private void CreateView() { TextureTarget target = Target.Convert(); FormatInfo format = FormatTable.GetFormatInfo(_info.Format); PixelInternalFormat pixelInternalFormat; if (format.IsCompressed) { pixelInternalFormat = (PixelInternalFormat)format.PixelFormat; } else { pixelInternalFormat = format.PixelInternalFormat; } GL.TextureView( Handle, target, _parent.Handle, pixelInternalFormat, _firstLevel, _info.Levels, _firstLayer, _info.GetLayers()); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(target, Handle); int[] swizzleRgba = new int[] { (int)_info.SwizzleR.Convert(), (int)_info.SwizzleG.Convert(), (int)_info.SwizzleB.Convert(), (int)_info.SwizzleA.Convert() }; GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba); int maxLevel = _info.Levels - 1; if (maxLevel < 0) { maxLevel = 0; } GL.TexParameter(target, TextureParameterName.TextureMaxLevel, maxLevel); // TODO: This requires ARB_stencil_texturing, we should uncomment and test this. // GL.TexParameter(target, TextureParameterName.DepthStencilTextureMode, (int)_info.DepthStencilMode.Convert()); }
public unsafe TextureStorage( VulkanRenderer gd, PhysicalDevice physicalDevice, Device device, TextureCreateInfo info, float scaleFactor, Auto <MemoryAllocation> foreignAllocation = null) { _gd = gd; _device = device; _info = info; ScaleFactor = scaleFactor; var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format); var levels = (uint)info.Levels; var layers = (uint)info.GetLayers(); var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1); VkFormat = format; var type = info.Target.Convert(); var extent = new Extent3D((uint)info.Width, (uint)info.Height, depth); var sampleCountFlags = ConvertToSampleCountFlags((uint)info.Samples); var usage = DefaultUsageFlags; if (info.Format.IsDepthOrStencil()) { usage |= ImageUsageFlags.ImageUsageDepthStencilAttachmentBit; } else if (info.Format.IsRtColorCompatible()) { usage |= ImageUsageFlags.ImageUsageColorAttachmentBit; } if (info.Format.IsImageCompatible()) { usage |= ImageUsageFlags.ImageUsageStorageBit; } var flags = ImageCreateFlags.ImageCreateMutableFormatBit; // This flag causes mipmapped texture arrays to break on AMD GCN, so for that copy dependencies are forced for aliasing as cube. bool isCube = info.Target == Target.Cubemap || info.Target == Target.CubemapArray; bool cubeCompatible = gd.IsAmdGcn ? isCube : (info.Width == info.Height && layers >= 6); if (type == ImageType.ImageType2D && cubeCompatible) { flags |= ImageCreateFlags.ImageCreateCubeCompatibleBit; } if (type == ImageType.ImageType3D) { flags |= ImageCreateFlags.ImageCreate2DArrayCompatibleBit; } var imageCreateInfo = new ImageCreateInfo() { SType = StructureType.ImageCreateInfo, ImageType = type, Format = format, Extent = extent, MipLevels = levels, ArrayLayers = layers, Samples = sampleCountFlags, Tiling = ImageTiling.Optimal, Usage = usage, SharingMode = SharingMode.Exclusive, InitialLayout = ImageLayout.Undefined, Flags = flags }; gd.Api.CreateImage(device, imageCreateInfo, null, out _image).ThrowOnError(); if (foreignAllocation == null) { gd.Api.GetImageMemoryRequirements(device, _image, out var requirements); var allocation = gd.MemoryAllocator.AllocateDeviceMemory(physicalDevice, requirements, DefaultImageMemoryFlags); if (allocation.Memory.Handle == 0UL) { gd.Api.DestroyImage(device, _image, null); throw new Exception("Image initialization failed."); } _size = requirements.Size; gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError(); _allocationAuto = new Auto <MemoryAllocation>(allocation); _imageAuto = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image), null, _allocationAuto); InitialTransition(ImageLayout.Undefined, ImageLayout.General); } else { _foreignAllocationAuto = foreignAllocation; foreignAllocation.IncrementReferenceCount(); var allocation = foreignAllocation.GetUnsafe(); gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError(); _imageAuto = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image)); InitialTransition(ImageLayout.Preinitialized, ImageLayout.General); } }
public unsafe TextureStorage( VulkanGraphicsDevice gd, PhysicalDevice physicalDevice, Device device, TextureCreateInfo info, float scaleFactor, Auto <MemoryAllocation> foreignAllocation = null) { _gd = gd; _device = device; _info = info; ScaleFactor = scaleFactor; var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format); var levels = (uint)info.Levels; var layers = (uint)info.GetLayers(); var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1); VkFormat = format; var type = info.Target.Convert(); var extent = new Extent3D((uint)info.Width, (uint)info.Height, depth); var sampleCountFlags = ConvertToSampleCountFlags((uint)info.Samples); var usage = DefaultUsageFlags; if (info.Format.IsDepthOrStencil()) { usage |= ImageUsageFlags.ImageUsageDepthStencilAttachmentBit; } else if (info.Format.IsRtColorCompatible()) { usage |= ImageUsageFlags.ImageUsageColorAttachmentBit; } if (info.Format.IsImageCompatible()) { usage |= ImageUsageFlags.ImageUsageStorageBit; } var flags = ImageCreateFlags.ImageCreateMutableFormatBit; if (info.BlockWidth != 1 || info.BlockHeight != 1) { flags |= ImageCreateFlags.ImageCreateBlockTexelViewCompatibleBit; } bool cubeCompatible = info.Width == info.Height && layers >= 6; if (type == ImageType.ImageType2D && cubeCompatible) { flags |= ImageCreateFlags.ImageCreateCubeCompatibleBit; } if (type == ImageType.ImageType3D) { flags |= ImageCreateFlags.ImageCreate2DArrayCompatibleBit; } // System.Console.WriteLine("create image " + type + " " + format + " " + levels + " " + layers + " " + usage + " " + flags); var imageCreateInfo = new ImageCreateInfo() { SType = StructureType.ImageCreateInfo, ImageType = type, Format = format, Extent = extent, MipLevels = levels, ArrayLayers = layers, Samples = sampleCountFlags, Tiling = ImageTiling.Optimal, Usage = usage, SharingMode = SharingMode.Exclusive, InitialLayout = ImageLayout.Undefined, Flags = flags }; gd.Api.CreateImage(device, imageCreateInfo, null, out _image).ThrowOnError(); if (foreignAllocation == null) { gd.Api.GetImageMemoryRequirements(device, _image, out var requirements); var allocation = gd.MemoryAllocator.AllocateDeviceMemory(physicalDevice, requirements); if (allocation.Memory.Handle == 0UL) { gd.Api.DestroyImage(device, _image, null); throw new Exception("Image initialization failed."); } gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError(); _allocationAuto = new Auto <MemoryAllocation>(allocation); _imageAuto = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image), null, _allocationAuto); InitialTransition(ImageLayout.Undefined, ImageLayout.General); } else { var allocation = foreignAllocation.GetUnsafe(); gd.Api.BindImageMemory(device, _image, allocation.Memory, allocation.Offset).ThrowOnError(); _imageAuto = new Auto <DisposableImage>(new DisposableImage(_gd.Api, device, _image)); InitialTransition(ImageLayout.Preinitialized, ImageLayout.General); } }
public TextureView( VulkanGraphicsDevice gd, Device device, TextureCreateInfo info, TextureStorage storage, int firstLayer, int firstLevel) { _gd = gd; _device = device; Info = info; Storage = storage; FirstLayer = firstLayer; FirstLevel = firstLevel; gd.Textures.Add(this); var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format); var levels = (uint)info.Levels; var layers = (uint)info.GetLayers(); VkFormat = format; var type = info.Target.ConvertView(); var swizzleR = info.SwizzleR.Convert(); var swizzleG = info.SwizzleG.Convert(); var swizzleB = info.SwizzleB.Convert(); var swizzleA = info.SwizzleA.Convert(); if (info.Format == GAL.Format.R5G5B5A1Unorm || info.Format == GAL.Format.R5G5B5X1Unorm || info.Format == GAL.Format.R5G6B5Unorm) { var temp = swizzleR; swizzleR = swizzleB; swizzleB = temp; } else if (info.Format == GAL.Format.R4G4B4A4Unorm) { var tempR = swizzleR; var tempG = swizzleG; swizzleR = swizzleA; swizzleG = swizzleB; swizzleB = tempG; swizzleA = tempR; } var componentMapping = new ComponentMapping(swizzleR, swizzleG, swizzleB, swizzleA); var aspectFlags = info.Format.ConvertAspectFlags(info.DepthStencilMode); var aspectFlagsDepth = info.Format.ConvertAspectFlags(DepthStencilMode.Depth); var subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, layers); var subresourceRangeDepth = new ImageSubresourceRange(aspectFlagsDepth, (uint)firstLevel, levels, (uint)firstLayer, layers); unsafe Auto <DisposableImageView> CreateImageView(ComponentMapping cm, ImageSubresourceRange sr, ImageViewType viewType) { var imageCreateInfo = new ImageViewCreateInfo() { SType = StructureType.ImageViewCreateInfo, Image = storage.GetImageForViewCreation(), ViewType = viewType, Format = format, Components = cm, SubresourceRange = sr }; gd.Api.CreateImageView(device, imageCreateInfo, null, out var imageView).ThrowOnError(); return(new Auto <DisposableImageView>(new DisposableImageView(gd.Api, device, imageView), null, storage.GetImage())); } _imageView = CreateImageView(componentMapping, subresourceRange, type); // Framebuffer attachments and storage images requires a identity component mapping. var identityComponentMapping = new ComponentMapping( ComponentSwizzle.R, ComponentSwizzle.G, ComponentSwizzle.B, ComponentSwizzle.A); _imageViewIdentity = CreateImageView(identityComponentMapping, subresourceRangeDepth, type); // Framebuffer attachments also requires 3D textures to be bound as 2D array. if (info.Target == Target.Texture3D) { subresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, levels, (uint)firstLayer, (uint)info.Depth); _imageView2dArray = CreateImageView(identityComponentMapping, subresourceRange, ImageViewType.ImageViewType2DArray); } Valid = true; }