Beispiel #1
0
        /// <summary>
        /// create host visible linear image without command from path
        /// </summary>
        public static Image Load(Device dev,
                                 string path, VkFormat format      = VkFormat.Undefined, bool reserveSpaceForMipmaps = true,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                 VkImageTiling tiling    = VkImageTiling.Linear,
                                 VkImageType imageType   = VkImageType.Image2D,
                                 VkImageUsageFlags usage = VkImageUsageFlags.Sampled)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }

            int    width, height, channels;
            IntPtr imgPtr = Stb.Load(path, out width, out height, out channels, 4);

            if (imgPtr == IntPtr.Zero)
            {
                throw new Exception($"File not found: {path}.");
            }

            long size      = width * height * 4;
            uint mipLevels = reserveSpaceForMipmaps ? (uint)Math.Floor(Math.Log(Math.Max(width, height))) + 1 : 1;

            Image img = new Image(dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);

            img.Map();
            unsafe {
                System.Buffer.MemoryCopy(imgPtr.ToPointer(), img.MappedData.ToPointer(), size, size);
            }
            img.Unmap();

            Stb.FreeImage(imgPtr);

            return(img);
        }
Beispiel #2
0
        void CreateImage(int width, int height,
                         VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties,
                         out VkImage image, out VkDeviceMemory memory)
        {
            var info = new VkImageCreateInfo();

            info.imageType     = VkImageType._2D;
            info.extent.width  = width;
            info.extent.height = height;
            info.extent.depth  = 1;
            info.mipLevels     = 1;
            info.arrayLayers   = 1;
            info.format        = format;
            info.tiling        = tiling;
            info.initialLayout = VkImageLayout.Undefined;
            info.usage         = usage;
            info.sharingMode   = VkSharingMode.Exclusive;
            info.samples       = VkSampleCountFlags._1_Bit;

            image = new VkImage(device, info);

            var req = image.Requirements;

            var allocInfo = new VkMemoryAllocateInfo();

            allocInfo.allocationSize  = req.size;
            allocInfo.memoryTypeIndex = FindMemoryType(req.memoryTypeBits, properties);

            memory = new VkDeviceMemory(device, allocInfo);

            image.Bind(memory, 0);
        }
Beispiel #3
0
        internal static VkImageUsageFlags VdToVkTextureUsage(TextureUsage vdUsage)
        {
            VkImageUsageFlags vkUsage = VkImageUsageFlags.None;

            vkUsage = VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc;
            bool isDepthStencil = (vdUsage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil;

            if ((vdUsage & TextureUsage.Sampled) == TextureUsage.Sampled)
            {
                vkUsage |= VkImageUsageFlags.Sampled;
            }
            if (isDepthStencil)
            {
                vkUsage |= VkImageUsageFlags.DepthStencilAttachment;
            }
            if ((vdUsage & TextureUsage.RenderTarget) == TextureUsage.RenderTarget)
            {
                vkUsage |= VkImageUsageFlags.ColorAttachment;
            }
            if ((vdUsage & TextureUsage.Storage) == TextureUsage.Storage)
            {
                vkUsage |= VkImageUsageFlags.Storage;
            }

            return(vkUsage);
        }
Beispiel #4
0
        /// <summary>
        /// Create a new Image.
        /// </summary>
        /// <remarks>Initial layout will be automatically set to Undefined if tiling is optimal and Preinitialized if tiling is linear.</remarks>
        /// <param name="device">The logical device that create the image.</param>
        /// <param name="format">format and type of the texel blocks that will be contained in the image</param>
        /// <param name="usage">bitmask describing the intended usage of the image.</param>
        /// <param name="_memoryPropertyFlags">Memory property flags.</param>
        /// <param name="width">number of data in the X dimension of the image.</param>
        /// <param name="height">number of data in the Y dimension of the image.</param>
        /// <param name="type">value specifying the basic dimensionality of the image. Layers in array textures do not count as a dimension for the purposes of the image type.</param>
        /// <param name="samples">number of sample per texel.</param>
        /// <param name="tiling">tiling arrangement of the texel blocks in memory.</param>
        /// <param name="mipsLevels">describes the number of levels of detail available for minified sampling of the image.</param>
        /// <param name="layers">number of layers in the image.</param>
        /// <param name="depth">number of data in the Z dimension of the image</param>
        /// <param name="createFlags">bitmask describing additional parameters of the image.</param>
        /// <param name="sharingMode">value specifying the sharing mode of the image when it will be accessed by multiple queue families.</param>
        /// <param name="queuesFamillies">list of queue families that will access this image (ignored if sharingMode is not CONCURRENT).</param>
        public Image(Device device, VkFormat format, VkImageUsageFlags usage, VkMemoryPropertyFlags _memoryPropertyFlags,
                     uint width, uint height,
                     VkImageType type               = VkImageType.Image2D, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
                     VkImageTiling tiling           = VkImageTiling.Optimal, uint mipsLevels          = 1, uint layers = 1, uint depth = 1,
                     VkImageCreateFlags createFlags = 0, VkSharingMode sharingMode                    = VkSharingMode.Exclusive, params uint[] queuesFamillies)
            : base(device, _memoryPropertyFlags)
        {
            info.imageType     = type;
            info.format        = format;
            info.extent.width  = width;
            info.extent.height = height;
            info.extent.depth  = depth;
            info.mipLevels     = mipsLevels;
            info.arrayLayers   = layers;
            info.samples       = samples;
            info.tiling        = tiling;
            info.usage         = usage;
            info.initialLayout = (tiling == VkImageTiling.Optimal) ? VkImageLayout.Undefined : VkImageLayout.Preinitialized;
            info.sharingMode   = sharingMode;
            info.flags         = createFlags;

            this.queueFalillies = queuesFamillies;
            lastKnownLayout     = info.initialLayout;

            Activate();
        }
Beispiel #5
0
        /// <summary>
        /// create host visible linear image without command from data pointed by IntPtr pointer containing full image file (jpg, png,...)
        /// </summary>
        public static Image Load(Device dev,
                                 IntPtr bitmap, ulong bitmapByteCount, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
                                 VkFormat format = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                 VkImageTiling tiling  = VkImageTiling.Linear, bool generateMipmaps = false,
                                 VkImageType imageType = VkImageType.Image2D)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }
            if (generateMipmaps)
            {
                usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
            }

            using (StbImage stbi = new StbImage(bitmap, bitmapByteCount)) {
                uint mipLevels = generateMipmaps ? ComputeMipLevels(stbi.Width, stbi.Height) : 1;

                Image img = new Image(dev, format, usage, memoryProps, (uint)stbi.Width, (uint)stbi.Height, imageType,
                                      VkSampleCountFlags.SampleCount1, tiling, mipLevels);

                img.Map();
                stbi.CoptyTo(img.MappedData);
                img.Unmap();

                return(img);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Create and Activate a new frabuffer for the supplied RenderPass.
        /// </summary>
        /// <param name="_renderPass">Render pass.</param>
        /// <param name="_width">Width.</param>
        /// <param name="_height">Height.</param>
        /// <param name="views">Array of image views. If null and not in unused state, attachment image and view will be automatically created from the
        /// supplied renderpass configuration.</param>
        public FrameBuffer(RenderPass _renderPass, uint _width, uint _height, params Image[] views)
            : this(_renderPass, _width, _height)
        {
            for (int i = 0; i < views.Length; i++)
            {
                Image v = views[i];
                if (v == null)
                {
                    //automatically create attachment if not in unused state in the renderpass
                    VkAttachmentDescription ad          = renderPass.Attachments[i];
                    VkImageUsageFlags       usage       = 0;
                    VkImageAspectFlags      aspectFlags = 0;

                    Utils.QueryLayoutRequirements(ad.initialLayout, ref usage, ref aspectFlags);
                    Utils.QueryLayoutRequirements(ad.finalLayout, ref usage, ref aspectFlags);
                    foreach (SubPass sp in renderPass.SubPasses)
                    {
                        //TODO:check subpass usage
                    }

                    v = new Image(renderPass.Dev, ad.format, usage, VkMemoryPropertyFlags.DeviceLocal,
                                  _width, _height, VkImageType.Image2D, ad.samples, VkImageTiling.Optimal, 1, createInfo.layers);
                    v.SetName($"fbImg{i}");
                    v.CreateView(VkImageViewType.ImageView2D, aspectFlags);
                }
                else
                {
                    v.Activate();                     //increase ref and create handle if not already activated
                }
                attachments.Add(v);
            }
            Activate();
        }
Beispiel #7
0
        /// <summary>
        /// Load bitmap into Image with stagging and mipmap generation if necessary
        /// and usage.
        /// </summary>
        public static Image Load(Device dev, Queue staggingQ, CommandPool staggingCmdPool,
                                 string path, VkFormat format      = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
                                 VkImageTiling tiling    = VkImageTiling.Optimal, bool generateMipmaps = true,
                                 VkImageType imageType   = VkImageType.Image2D,
                                 VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }
            if (tiling == VkImageTiling.Optimal)
            {
                usage |= VkImageUsageFlags.TransferDst;
            }
            if (generateMipmaps)
            {
                usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
            }

            using (StbImage stbi = new StbImage(path)) {
                uint mipLevels = generateMipmaps ? ComputeMipLevels(stbi.Width, stbi.Height) : 1;

                Image img = new Image(dev, format, usage, memoryProps, (uint)stbi.Width, (uint)stbi.Height, imageType,
                                      VkSampleCountFlags.SampleCount1, tiling, mipLevels);

                img.load(staggingQ, staggingCmdPool, stbi.Handle, generateMipmaps);

                return(img);
            }
        }
Beispiel #8
0
 public static extern VkResult GetPhysicalDeviceImageFormatProperties(
     VkPhysicalDevice physicalDevice,
     VkFormat format,
     VkImageType type,
     VkImageTiling tiling,
     VkImageUsageFlags usage,
     VkImageCreateFlags flags,
     IntPtr pImageFormatProperties
     );
Beispiel #9
0
 public static extern void GetPhysicalDeviceSparseImageFormatProperties(
     VkPhysicalDevice physicalDevice,
     VkFormat format,
     VkImageType type,
     VkSampleCountFlags samples,
     VkImageUsageFlags usage,
     VkImageTiling tiling,
     ref uint pPropertyCount,
     IntPtr pProperties
     );
Beispiel #10
0
 public RenderTexture(uint width, uint height, uint layers, VkFormat format, VkImageUsageFlags usage,
                      VkSampleCountFlags samples = VkSampleCountFlags.Count1, SizeHint sizeHint = SizeHint.None)
 {
     this.extent          = new VkExtent3D(width, height, 1);
     this.layers          = layers;
     this.format          = format;
     this.imageUsageFlags = usage;
     this.samples         = samples;
     this.sizeHint        = sizeHint;
     Create();
 }
Beispiel #11
0
        /// <summary>
        /// create host visible linear image without command from byte array
        /// </summary>
        public static Image Load(Device dev,
                                 byte[] bitmap, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
                                 VkFormat format = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                 VkImageTiling tiling  = VkImageTiling.Linear, bool generateMipmaps = false,
                                 VkImageType imageType = VkImageType.Image2D)
        {
            Image img = Load(dev, bitmap.Pin(), (ulong)bitmap.Length, usage, format, memoryProps, tiling, generateMipmaps,
                             imageType);

            bitmap.Unpin();
            return(img);
        }
Beispiel #12
0
        /// <summary>
        /// Load image from byte array containing full image file (jpg, png,...)
        /// </summary>
        public static Image Load(Device dev, Queue staggingQ, CommandPool staggingCmdPool,
                                 byte[] bitmap, VkFormat format    = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
                                 VkImageTiling tiling    = VkImageTiling.Optimal, bool generateMipmaps = true,
                                 VkImageType imageType   = VkImageType.Image2D,
                                 VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst)
        {
            Image img = Load(dev, staggingQ, staggingCmdPool, bitmap.Pin(), (ulong)bitmap.Length, format, memoryProps, tiling, generateMipmaps,
                             imageType, usage);

            bitmap.Unpin();
            return(img);
        }
Beispiel #13
0
        public AttachmentInfo(StringID id, SizeHint sizeHint, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlags samples = VkSampleCountFlags.Count1)
        {
            this.id               = id;
            this.SizeHint         = sizeHint;
            this.Usage            = usage;
            attachmentDescription = new VkAttachmentDescription(format, samples);

            if (Device.IsDepthFormat(format))
            {
                ClearValue = new VkClearDepthStencilValue(1, 0);
            }
            else
            {
                ClearValue = new VkClearColorValue(0, 0, 0, 1);
            }
        }
Beispiel #14
0
        public static void CreateImage(
            VkDevice device,
            VkPhysicalDeviceMemoryProperties physicalDeviceMemProperties,
            VkDeviceMemoryManager memoryManager,
            uint width,
            uint height,
            uint depth,
            uint arrayLayers,
            VkFormat format,
            VkImageTiling tiling,
            VkImageUsageFlags usage,
            VkMemoryPropertyFlags properties,
            out VkImage image,
            out VkMemoryBlock memory)
        {
            VkImageCreateInfo imageCI = VkImageCreateInfo.New();

            imageCI.imageType     = VkImageType.Image2D;
            imageCI.extent.width  = width;
            imageCI.extent.height = height;
            imageCI.extent.depth  = depth;
            imageCI.mipLevels     = 1;
            imageCI.arrayLayers   = arrayLayers;
            imageCI.format        = format;
            imageCI.tiling        = tiling;
            imageCI.initialLayout = VkImageLayout.Preinitialized;
            imageCI.usage         = usage;
            imageCI.sharingMode   = VkSharingMode.Exclusive;
            imageCI.samples       = VkSampleCountFlags.Count1;

            VkResult result = vkCreateImage(device, ref imageCI, null, out image);

            CheckResult(result);

            vkGetImageMemoryRequirements(device, image, out VkMemoryRequirements memRequirements);
            VkMemoryBlock memoryToken = memoryManager.Allocate(
                physicalDeviceMemProperties,
                memRequirements.memoryTypeBits,
                properties,
                false,
                memRequirements.size,
                memRequirements.alignment);

            memory = memoryToken;
            result = vkBindImageMemory(device, image, memory.DeviceMemory, memory.Offset);
            CheckResult(result);
        }
Beispiel #15
0
        public AttachmentInfo(uint width, uint height, uint layers, VkFormat format, VkImageUsageFlags usage,
                              VkSampleCountFlags samples = VkSampleCountFlags.Count1)
        {
            this.Width            = width;
            this.Height           = height;
            this.Layers           = layers;
            this.Usage            = usage;
            attachmentDescription = new VkAttachmentDescription(format, samples);

            if (Device.IsDepthFormat(format))
            {
                ClearValue = new VkClearDepthStencilValue(1, 0);
            }
            else
            {
                ClearValue = new VkClearColorValue(0, 0, 0, 1);
            }
        }
Beispiel #16
0
        /// <summary>
        /// Import vkImage handle into a new Image class, handle will be preserve on destruction.
        /// </summary>
        public Image(Device device, VkImage vkHandle, VkFormat format, VkImageUsageFlags usage, uint width, uint height)
            : base(device, VkMemoryPropertyFlags.DeviceLocal)
        {
            info.imageType     = VkImageType.Image2D;
            info.format        = format;
            info.extent.width  = width;
            info.extent.height = height;
            info.extent.depth  = 1;
            info.mipLevels     = 1;
            info.arrayLayers   = 1;
            info.samples       = VkSampleCountFlags.SampleCount1;
            info.tiling        = VkImageTiling.Optimal;
            info.usage         = usage;

            handle   = vkHandle;
            imported = true;

            state = ActivableState.Activated;
            references++;            //increment ref because it is bound to swapchain
        }
Beispiel #17
0
        /// <summary>
        /// create host visible linear image without command from data pointed by IntPtr pointer containing full image file (jpg, png,...)
        /// </summary>
        public static Image Load(Device dev,
                                 IntPtr bitmap, ulong bitmapByteCount, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
                                 VkFormat format = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                 VkImageTiling tiling  = VkImageTiling.Linear, bool generateMipmaps = false,
                                 VkImageType imageType = VkImageType.Image2D)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }

            int    width, height, channels;
            IntPtr imgPtr = Stb.Load(bitmap, (int)bitmapByteCount, out width, out height, out channels, 4);

            if (imgPtr == IntPtr.Zero)
            {
                throw new Exception($"STBI image loading error.");
            }

            uint mipLevels = generateMipmaps ? (uint)Math.Floor(Math.Log(Math.Max(width, height))) + 1 : 1;

            if (generateMipmaps)
            {
                usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
            }

            long  size = width * height * 4;
            Image img  = new Image(dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);

            img.Map();
            unsafe {
                System.Buffer.MemoryCopy(imgPtr.ToPointer(), img.MappedData.ToPointer(), size, size);
            }
            img.Unmap();

            Stb.FreeImage(imgPtr);

            return(img);
        }
Beispiel #18
0
        /// <summary>
        /// Check if specified image usage is supported for the given physical image format.
        /// </summary>
        /// <returns><c>true</c>, if usage is supported</returns>
        /// <param name="usage">bitmask of intend usage for an image.</param>
        /// <param name="phyFormatSupport">Physical format feature bitmask as returned by `GetFormatProperties` of PhysicalDevice</param>
        public static bool CheckFormatIsSupported(VkImageUsageFlags usage, VkFormatFeatureFlags phyFormatSupport)
        {
            if (usage.HasFlag(VkImageUsageFlags.TransferSrc) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.TransferSrc))
            {
                return(false);
            }
            if (usage.HasFlag(VkImageUsageFlags.TransferDst) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.TransferSrc))
            {
                return(false);
            }
            if (usage.HasFlag(VkImageUsageFlags.Sampled) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.SampledImage))
            {
                return(false);
            }
            if (usage.HasFlag(VkImageUsageFlags.Storage) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.StorageImage))
            {
                return(false);
            }
            if (usage.HasFlag(VkImageUsageFlags.ColorAttachment) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.ColorAttachment))
            {
                return(false);
            }
            if (usage.HasFlag(VkImageUsageFlags.DepthStencilAttachment) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.DepthStencilAttachment))
            {
                return(false);
            }

            /*if (usage.HasFlag (VkImageUsageFlags.TransientAttachment) ^ phyFormatSupport.HasFlag (VkFormatFeatureFlags.))
             *      return false;*/
            if (usage.HasFlag(VkImageUsageFlags.InputAttachment) & !phyFormatSupport.HasFlag(VkFormatFeatureFlags.SampledImage))
            {
                return(false);
            }

            /*if (usage.HasFlag (VkImageUsageFlags.ShadingRateImageNV) ^ phyFormatSupport.HasFlag (VkFormatFeatureFlags.TransferSrc))
             *      return false;
             * if (usage.HasFlag (VkImageUsageFlags.FragmentDensityMapEXT) ^ phyFormatSupport.HasFlag (VkFormatFeatureFlags.TransferSrc))
             *      return false;*/
            return(true);
        }
Beispiel #19
0
        public static Texture Create(uint width, uint height, VkImageViewType imageViewType, uint layers, VkFormat format, uint levels = 0, VkImageUsageFlags additionalUsage = VkImageUsageFlags.None)
        {
            Texture texture = new Texture
            {
                extent    = new VkExtent3D(width, height, 1),
                layers    = layers,
                mipLevels = (levels > 0) ? levels : (uint)NumMipmapLevels(width, height),
            };

            VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | additionalUsage;

            if (texture.mipLevels > 1)
            {
                usage |= VkImageUsageFlags.TransferSrc; // For mipmap generation
            }

            texture.image     = Image.Create(width, height, (imageViewType == VkImageViewType.ImageCube || imageViewType == VkImageViewType.ImageCubeArray) ? VkImageCreateFlags.CubeCompatible : VkImageCreateFlags.None, layers, texture.mipLevels, format, VkSampleCountFlags.Count1, usage);
            texture.imageView = ImageView.Create(texture.image, imageViewType, format, VkImageAspectFlags.Color, 0, Vulkan.RemainingMipLevels, 0, layers);
            texture.sampler   = new Sampler(VkFilter.Linear, VkSamplerMipmapMode.Linear, VkSamplerAddressMode.ClampToBorder, texture.mipLevels, Device.Features.samplerAnisotropy == true);
            texture.UpdateDescriptor();
            return(texture);
        }
Beispiel #20
0
        /// <summary>
        /// Load bitmap into Image with stagging and mipmap generation if necessary
        /// and usage.
        /// </summary>
        public static Image Load(Device dev, Queue staggingQ, CommandPool staggingCmdPool,
                                 string path, VkFormat format      = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
                                 VkImageTiling tiling    = VkImageTiling.Optimal, bool generateMipmaps = true,
                                 VkImageType imageType   = VkImageType.Image2D,
                                 VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }

            int    width, height, channels;
            IntPtr imgPtr = Stb.Load(path, out width, out height, out channels, 4);

            if (imgPtr == IntPtr.Zero)
            {
                throw new Exception($"File not found: {path}.");
            }

            uint mipLevels = generateMipmaps ? (uint)Math.Floor(Math.Log(Math.Max(width, height))) + 1 : 1;

            if (tiling == VkImageTiling.Optimal)
            {
                usage |= VkImageUsageFlags.TransferDst;
            }
            if (generateMipmaps)
            {
                usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
            }

            Image img = new Image(dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);

            img.load(staggingQ, staggingCmdPool, imgPtr, generateMipmaps);

            Stb.FreeImage(imgPtr);

            return(img);
        }
Beispiel #21
0
        /// <summary>
        /// create host visible linear image without command from path
        /// </summary>
        public static Image Load(Device dev,
                                 string path, VkImageUsageFlags usage = VkImageUsageFlags.Sampled, bool reserveSpaceForMipmaps = true, VkFormat format = VkFormat.Undefined,
                                 VkMemoryPropertyFlags memoryProps    = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                 VkImageTiling tiling = VkImageTiling.Linear, VkImageType imageType = VkImageType.Image2D)
        {
            if (format == VkFormat.Undefined)
            {
                format = DefaultTextureFormat;
            }

            using (StbImage stbi = new StbImage(path)) {
                uint mipLevels = reserveSpaceForMipmaps ? ComputeMipLevels(stbi.Width, stbi.Height) : 1;

                Image img = new Image(dev, format, usage, memoryProps, (uint)stbi.Width, (uint)stbi.Height, imageType,
                                      VkSampleCountFlags.SampleCount1, tiling, mipLevels);

                img.Map();
                stbi.CoptyTo(img.MappedData);
                img.Unmap();

                return(img);
            }
        }
Beispiel #22
0
        public Image(Device device, VkFormat format, VkImageUsageFlags usage, VkMemoryPropertyFlags _memoryPropertyFlags,
                     uint width, uint height,
                     VkImageType type               = VkImageType.Image2D, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
                     VkImageTiling tiling           = VkImageTiling.Optimal, uint mipsLevels          = 1, uint layers = 1, uint depth = 1,
                     VkImageCreateFlags createFlags = 0)
            : base(device, _memoryPropertyFlags)
        {
            info.imageType     = type;
            info.format        = format;
            info.extent.width  = width;
            info.extent.height = height;
            info.extent.depth  = depth;
            info.mipLevels     = mipsLevels;
            info.arrayLayers   = layers;
            info.samples       = samples;
            info.tiling        = tiling;
            info.usage         = usage;
            info.initialLayout = (tiling == VkImageTiling.Optimal) ? VkImageLayout.Undefined : VkImageLayout.Preinitialized;
            info.sharingMode   = VkSharingMode.Exclusive;
            info.flags         = createFlags;

            Activate(); //DONT OVERRIDE Activate in derived classes!!!!
        }
Beispiel #23
0
 internal extern static Result vkGetPhysicalDeviceImageFormatProperties(IntPtr physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, ref VkImageFormatProperties pImageFormatProperties);
Beispiel #24
0
 internal extern static void vkGetPhysicalDeviceSparseImageFormatProperties(IntPtr physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling, ref UInt32 pPropertyCount, [In, Out] VkSparseImageFormatProperties[] pProperties);
Beispiel #25
0
        public static ReadOnlySpan <VkSparseImageFormatProperties> vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling)
        {
            uint propertyCount = 0;

            vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &propertyCount, null);

            ReadOnlySpan <VkSparseImageFormatProperties> properties = new VkSparseImageFormatProperties[propertyCount];

            fixed(VkSparseImageFormatProperties *propertiesPtr = properties)
            {
                vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &propertyCount, propertiesPtr);
            }

            return(properties);
        }
Beispiel #26
0
        /**
         * Load a 2D texture including all mip levels
         *
         * @param filename File to load (supports .ktx and .dds)
         * @param format Vulkan format of the image data stored in the file
         * @param device Vulkan device to create the texture on
         * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
         * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT)
         * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
         * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false)
         *
         */
        public void loadFromFile(
            string filename,
            VkFormat format,
            vksVulkanDevice device,
            VkQueue copyQueue,
            VkImageUsageFlags imageUsageFlags = VkImageUsageFlags.Sampled,
            VkImageLayout imageLayout         = VkImageLayout.ShaderReadOnlyOptimal,
            bool forceLinear = false)
        {
            KtxFile tex2D;

            using (var fs = File.OpenRead(filename))
            {
                tex2D = KtxFile.Load(fs, false);
            }

            this.device = device;
            width       = tex2D.Header.PixelWidth;
            height      = tex2D.Header.PixelHeight;
            if (height == 0)
            {
                height = width;
            }
            mipLevels = tex2D.Header.NumberOfMipmapLevels;

            // Get device properites for the requested texture format
            VkFormatProperties formatProperties;

            vkGetPhysicalDeviceFormatProperties(device.PhysicalDevice, format, out formatProperties);

            // Only use linear tiling if requested (and supported by the device)
            // Support for linear tiling is mostly limited, so prefer to use
            // optimal tiling instead
            // On most implementations linear tiling will only support a very
            // limited amount of formats and features (mip maps, cubemaps, arrays, etc.)
            bool useStaging = !forceLinear;

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            // Use a separate command buffer for texture loading
            VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true);

            if (useStaging)
            {
                // Create a host-visible staging buffer that contains the raw image data
                VkBuffer       stagingBuffer;
                VkDeviceMemory stagingMemory;

                VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();
                bufferCreateInfo.size = tex2D.GetTotalSize();
                // This buffer is used as a transfer source for the buffer copy
                bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
                bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

                Util.CheckResult(vkCreateBuffer(device.LogicalDevice, &bufferCreateInfo, null, &stagingBuffer));

                // Get memory requirements for the staging buffer (alignment, memory type bits)
                vkGetBufferMemoryRequirements(device.LogicalDevice, stagingBuffer, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;
                // Get memory type index for a host visible buffer
                memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

                Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &stagingMemory));
                Util.CheckResult(vkBindBufferMemory(device.LogicalDevice, stagingBuffer, stagingMemory, 0));

                // Copy texture data into staging buffer
                byte *data;
                Util.CheckResult(vkMapMemory(device.LogicalDevice, stagingMemory, 0, memReqs.size, 0, (void **)&data));
                byte[] pixelData = tex2D.GetAllTextureData();
                fixed(byte *pixelDataPtr = &pixelData[0])
                {
                    Unsafe.CopyBlock(data, pixelDataPtr, (uint)pixelData.Length);
                }

                vkUnmapMemory(device.LogicalDevice, stagingMemory);

                // Setup buffer copy regions for each mip level
                NativeList <VkBufferImageCopy> bufferCopyRegions = new NativeList <VkBufferImageCopy>();
                uint offset = 0;

                for (uint i = 0; i < mipLevels; i++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
                    bufferCopyRegion.imageSubresource.mipLevel       = i;
                    bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
                    bufferCopyRegion.imageSubresource.layerCount     = 1;
                    bufferCopyRegion.imageExtent.width  = tex2D.Faces[0].Mipmaps[i].Width;
                    bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height;
                    bufferCopyRegion.imageExtent.depth  = 1;
                    bufferCopyRegion.bufferOffset       = offset;

                    bufferCopyRegions.Add(bufferCopyRegion);

                    offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes;
                }

                // Create optimal tiled target image
                VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                imageCreateInfo.imageType     = VkImageType._2d;
                imageCreateInfo.format        = format;
                imageCreateInfo.mipLevels     = mipLevels;
                imageCreateInfo.arrayLayers   = 1;
                imageCreateInfo.samples       = VkSampleCountFlags._1;
                imageCreateInfo.tiling        = VkImageTiling.Optimal;
                imageCreateInfo.sharingMode   = VkSharingMode.Exclusive;
                imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                imageCreateInfo.extent        = new VkExtent3D {
                    width = width, height = height, depth = 1
                };
                imageCreateInfo.usage = imageUsageFlags;
                // Ensure that the TRANSFER_DST bit is set for staging
                if ((imageCreateInfo.usage & VkImageUsageFlags.TransferDst) == 0)
                {
                    imageCreateInfo.usage |= VkImageUsageFlags.TransferDst;
                }
                Util.CheckResult(vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, out image));

                vkGetImageMemoryRequirements(device.LogicalDevice, image, &memReqs);

                memAllocInfo.allocationSize = memReqs.size;

                memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
                Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, out deviceMemory));
                Util.CheckResult(vkBindImageMemory(device.LogicalDevice, image, deviceMemory, 0));

                VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
                subresourceRange.aspectMask   = VkImageAspectFlags.Color;
                subresourceRange.baseMipLevel = 0;
                subresourceRange.levelCount   = mipLevels;
                subresourceRange.layerCount   = 1;

                // Image barrier for optimal image (target)
                // Optimal image will be used as destination for the copy
                Tools.setImageLayout(
                    copyCmd,
                    image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.Undefined,
                    VkImageLayout.TransferDstOptimal,
                    subresourceRange);

                // Copy mip levels from staging buffer
                vkCmdCopyBufferToImage(
                    copyCmd,
                    stagingBuffer,
                    image,
                    VkImageLayout.TransferDstOptimal,
                    bufferCopyRegions.Count,
                    bufferCopyRegions.Data);

                // Change texture image layout to shader read after all mip levels have been copied
                this.imageLayout = imageLayout;
                Tools.setImageLayout(
                    copyCmd,
                    image,
                    VkImageAspectFlags.Color,
                    VkImageLayout.TransferDstOptimal,
                    imageLayout,
                    subresourceRange);

                device.flushCommandBuffer(copyCmd, copyQueue);

                // Clean up staging resources
                vkFreeMemory(device.LogicalDevice, stagingMemory, null);
                vkDestroyBuffer(device.LogicalDevice, stagingBuffer, null);
            }
            else
            {
                throw new NotImplementedException();

                /*
                 * // Prefer using optimal tiling, as linear tiling
                 * // may support only a small set of features
                 * // depending on implementation (e.g. no mip maps, only one layer, etc.)
                 *
                 * // Check if this support is supported for linear tiling
                 * Debug.Assert((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != 0);
                 *
                 * VkImage mappableImage;
                 * VkDeviceMemory mappableMemory;
                 *
                 * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();
                 * imageCreateInfo.imageType = VkImageType._2d;
                 * imageCreateInfo.format = format;
                 * imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 };
                 * imageCreateInfo.mipLevels = 1;
                 * imageCreateInfo.arrayLayers = 1;
                 * imageCreateInfo.samples = VkSampleCountFlags._1;
                 * imageCreateInfo.tiling = VkImageTiling.Linear;
                 * imageCreateInfo.usage = imageUsageFlags;
                 * imageCreateInfo.sharingMode = VkSharingMode.Exclusive;
                 * imageCreateInfo.initialLayout = VkImageLayout.Undefined;
                 *
                 * // Load mip map level 0 to linear tiling image
                 * Util.CheckResult(vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &mappableImage));
                 *
                 * // Get memory requirements for this image
                 * // like size and alignment
                 * vkGetImageMemoryRequirements(device.LogicalDevice, mappableImage, &memReqs);
                 * // Set memory allocation size to required memory size
                 * memAllocInfo.allocationSize = memReqs.size;
                 *
                 * // Get memory type that can be mapped to host memory
                 * memAllocInfo.memoryTypeIndex = device.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);
                 *
                 * // Allocate host memory
                 * Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &mappableMemory));
                 *
                 * // Bind allocated image for use
                 * Util.CheckResult(vkBindImageMemory(device.LogicalDevice, mappableImage, mappableMemory, 0));
                 *
                 * // Get sub resource layout
                 * // Mip map count, array layer, etc.
                 * VkImageSubresource subRes = new VkImageSubresource();
                 * subRes.aspectMask = VkImageAspectFlags.Color;
                 * subRes.mipLevel = 0;
                 *
                 * VkSubresourceLayout subResLayout;
                 * void* data;
                 *
                 * // Get sub resources layout
                 * // Includes row pitch, size offsets, etc.
                 * vkGetImageSubresourceLayout(device.LogicalDevice, mappableImage, &subRes, &subResLayout);
                 *
                 * // Map image memory
                 * Util.CheckResult(vkMapMemory(device.LogicalDevice, mappableMemory, 0, memReqs.size, 0, &data));
                 *
                 * // Copy image data into memory
                 * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size());
                 *
                 * vkUnmapMemory(device.LogicalDevice, mappableMemory);
                 *
                 * // Linear tiled images don't need to be staged
                 * // and can be directly used as textures
                 * image = mappableImage;
                 * deviceMemory = mappableMemory;
                 * imageLayout = imageLayout;
                 *
                 * // Setup image memory barrier
                 * vks::tools::setImageLayout(copyCmd, image, VkImageAspectFlags.Color, VkImageLayout.Undefined, imageLayout);
                 *
                 * device.flushCommandBuffer(copyCmd, copyQueue);
                 */
            }

            // Create a defaultsampler
            VkSamplerCreateInfo samplerCreateInfo = VkSamplerCreateInfo.New();

            samplerCreateInfo.magFilter    = VkFilter.Linear;
            samplerCreateInfo.minFilter    = VkFilter.Linear;
            samplerCreateInfo.mipmapMode   = VkSamplerMipmapMode.Linear;
            samplerCreateInfo.addressModeU = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.addressModeV = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.addressModeW = VkSamplerAddressMode.Repeat;
            samplerCreateInfo.mipLodBias   = 0.0f;
            samplerCreateInfo.compareOp    = VkCompareOp.Never;
            samplerCreateInfo.minLod       = 0.0f;
            // Max level-of-detail should match mip level count
            samplerCreateInfo.maxLod = (useStaging) ? (float)mipLevels : 0.0f;
            // Enable anisotropic filtering
            samplerCreateInfo.maxAnisotropy    = 8;
            samplerCreateInfo.anisotropyEnable = True;
            samplerCreateInfo.borderColor      = VkBorderColor.FloatOpaqueWhite;
            Util.CheckResult(vkCreateSampler(device.LogicalDevice, &samplerCreateInfo, null, out sampler));

            // Create image view
            // Textures are not directly accessed by the shaders and
            // are abstracted by image views containing additional
            // information and sub resource ranges
            VkImageViewCreateInfo viewCreateInfo = VkImageViewCreateInfo.New();

            viewCreateInfo.viewType   = VkImageViewType._2d;
            viewCreateInfo.format     = format;
            viewCreateInfo.components = new VkComponentMapping {
                r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A
            };
            viewCreateInfo.subresourceRange = new VkImageSubresourceRange {
                aspectMask = VkImageAspectFlags.Color, baseMipLevel = 0, levelCount = 1, baseArrayLayer = 0, layerCount = 1
            };
            // Linear tiling usually won't support mip maps
            // Only set mip map count if optimal tiling is used
            viewCreateInfo.subresourceRange.levelCount = (useStaging) ? mipLevels : 1;
            viewCreateInfo.image = image;
            Util.CheckResult(vkCreateImageView(device.LogicalDevice, &viewCreateInfo, null, out view));

            // Update descriptor image info member that can be used for setting up descriptor sets
            updateDescriptor();
        }
Beispiel #27
0
 public IReadOnlyList<VkSparseImageFormatProperties> GetSparseImageFormatProperties(VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage,
     VkImageTiling tiling)
 {
     int count;
     Direct.GetPhysicalDeviceSparseImageFormatProperties(Handle, format, type, samples, usage, tiling, &count, (VkSparseImageFormatProperties*)0);
     var resultArray = new VkSparseImageFormatProperties[count];
     fixed (VkSparseImageFormatProperties* pResultArray = resultArray)
     {
         Direct.GetPhysicalDeviceSparseImageFormatProperties(Handle, format, type, samples, usage, tiling, &count, pResultArray);
         return resultArray;
     }
 }
        /**
         * Load a 2D texture including all mip levels
         *
         * @param filename File to load (supports .ktx and .dds)
         * @param format Vulkan format of the image data stored in the file
         * @param device Vulkan device to create the texture on
         * @param copyQueue Queue used for the texture staging copy commands (must support transfer)
         * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT)
         * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
         * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false)
         *
         */
        public void FromTextureAsset(
            TextureAsset asset,
            GraphicsDevice device,
            VkImageUsageFlags imageUsageFlags = VkImageUsageFlags.Sampled,
            VkImageLayout imageLayout         = VkImageLayout.ShaderReadOnlyOptimal)
        {
            VkFormat format = VkFormat.Undefined;

            KtxFile tex2D = asset.GetTexture();

            format = GlFormatToVulkanFormat.vkGetFormatFromOpenGLInternalFormat(tex2D.Header.GlInternalFormat, tex2D.Header.GlFormat, tex2D.Header.GlType);

            width  = tex2D.Header.PixelWidth;
            height = tex2D.Header.PixelHeight;
            if (height == 0)
            {
                height = width;
            }
            mipLevels = tex2D.Header.NumberOfMipmapLevels;

            this.imageLayout = imageLayout;
            this.format      = format;
            this.device      = device;

            // Get device properites for the requested texture format
            VkFormatProperties formatProperties;

            vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, out formatProperties);

            VkMemoryAllocateInfo memAllocInfo = Initializers.memoryAllocateInfo();
            VkMemoryRequirements memReqs;

            // Create optimal tiled target image
            VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo();

            imageCreateInfo.imageType     = VkImageType.Image2D;
            imageCreateInfo.format        = format;
            imageCreateInfo.mipLevels     = mipLevels;
            imageCreateInfo.arrayLayers   = 1;
            imageCreateInfo.samples       = VkSampleCountFlags.Count1;
            imageCreateInfo.tiling        = VkImageTiling.Optimal;
            imageCreateInfo.sharingMode   = VkSharingMode.Exclusive;
            imageCreateInfo.initialLayout = VkImageLayout.Undefined;
            imageCreateInfo.extent        = new VkExtent3D {
                width = width, height = height, depth = 1
            };
            imageCreateInfo.usage = imageUsageFlags;
            // Ensure that the TRANSFER_DST bit is set for staging
            if ((imageCreateInfo.usage & VkImageUsageFlags.TransferDst) == 0)
            {
                imageCreateInfo.usage |= VkImageUsageFlags.TransferDst;
            }
            Util.CheckResult(vkCreateImage(device.device, &imageCreateInfo, null, out image));

            vkGetImageMemoryRequirements(device.device, image, &memReqs);

            memAllocInfo.allocationSize = memReqs.size;

            memory = device.memoryAllocator.Allocate(memReqs.size, memReqs.alignment, memReqs.memoryTypeBits, false);
            Util.CheckResult(vkBindImageMemory(device.device, image, memory.vkDeviceMemory, memory.offset));

            //memAllocInfo.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
            //Util.CheckResult(vkAllocateMemory(device.device, &memAllocInfo, null, out deviceMemory));
            //Util.CheckResult(vkBindImageMemory(device.device, image, deviceMemory, 0));

            TransferDataKtx(tex2D);

            CreateSampler();

            CreateView();

            // Update descriptor image info member that can be used for setting up descriptor sets
            UpdateDescriptor();
        }
Beispiel #29
0
        public static Image Load(Queue staggingQ, CommandPool staggingCmdPool, string ktxPath, VkImageUsageFlags usage = VkImageUsageFlags.Sampled,
                                 VkMemoryPropertyFlags memoryProperty = VkMemoryPropertyFlags.DeviceLocal, bool generateMipmaps = true,
                                 VkImageTiling tiling = VkImageTiling.Optimal)
        {
            Image img = null;

            using (Stream ktxStream = File.Open(ktxPath, FileMode.Open, FileAccess.Read)) {
                using (BinaryReader br = new BinaryReader(ktxStream)) {
                    if (!br.ReadBytes(12).AreEquals(ktxSignature))
                    {
                        throw new KtxException("Not a ktx file: " + ktxPath);
                    }

                    UInt32 endianness            = br.ReadUInt32();
                    UInt32 glType                = br.ReadUInt32();
                    UInt32 glTypeSize            = br.ReadUInt32();
                    UInt32 glFormat              = br.ReadUInt32();
                    UInt32 glInternalFormat      = br.ReadUInt32();
                    UInt32 glBaseInternalFormat  = br.ReadUInt32();
                    UInt32 pixelWidth            = br.ReadUInt32();
                    UInt32 pixelHeight           = br.ReadUInt32();
                    UInt32 pixelDepth            = Math.Min(1, br.ReadUInt32());
                    UInt32 numberOfArrayElements = br.ReadUInt32();             //only for array text, else 0
                    UInt32 numberOfFaces         = br.ReadUInt32();             //only for cube map, else
                    UInt32 numberOfMipmapLevels  = Math.Min(1, br.ReadUInt32());
                    UInt32 bytesOfKeyValueData   = br.ReadUInt32();

                    VkFormat vkFormat = GLHelper.vkGetFormatFromOpenGLInternalFormat(glInternalFormat);
                    if (vkFormat == VkFormat.Undefined)
                    {
                        vkFormat = GLHelper.vkGetFormatFromOpenGLFormat(glFormat, glType);
                        if (vkFormat == VkFormat.Undefined)
                        {
                            throw new KtxException("Undefined format: " + ktxPath);
                        }
                    }

                    VkFormatFeatureFlags phyFormatSupport = (tiling == VkImageTiling.Linear) ?
                                                            staggingQ.Dev.phy.GetFormatProperties(vkFormat).linearTilingFeatures :
                                                            staggingQ.Dev.phy.GetFormatProperties(vkFormat).optimalTilingFeatures;

                    uint requestedMipsLevels = numberOfMipmapLevels;
                    if (numberOfMipmapLevels == 1)
                    {
                        requestedMipsLevels = (generateMipmaps && phyFormatSupport.HasFlag(VkFormatFeatureFlags.BlitSrc | VkFormatFeatureFlags.BlitDst)) ?
                                              (uint)Math.Floor(Math.Log(Math.Max(pixelWidth, pixelHeight))) + 1 : 1;
                    }

                    if (tiling == VkImageTiling.Optimal)
                    {
                        usage |= VkImageUsageFlags.TransferDst;
                    }
                    if (generateMipmaps)
                    {
                        usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
                    }

                    VkImageCreateFlags createFlags = 0;

                    VkImageType imgType =
                        (pixelWidth == 0) ? throw new KtxException("pixelWidth must be > 0") :
                              (pixelHeight == 0) ? imgType = VkImageType.Image1D :
                                                             (pixelDepth == 0) ? imgType = VkImageType.Image2D : imgType = VkImageType.Image3D;


                    VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1;

                    if (numberOfFaces > 1)
                    {
                        if (imgType != VkImageType.Image2D)
                        {
                            throw new KtxException("cubemap faces must be 2D textures");
                        }
                        createFlags           = VkImageCreateFlags.CubeCompatible;
                        samples               = VkSampleCountFlags.SampleCount1;
                        numberOfArrayElements = numberOfFaces;
                    }
                    else
                    {
                        numberOfFaces = 1;
                        if (numberOfArrayElements == 0)
                        {
                            numberOfArrayElements = 1;
                        }
                    }

                    if (imgType != VkImageType.Image3D)
                    {
                        pixelDepth = 1;
                    }

                    img = new Image(staggingQ.Dev, vkFormat, usage, memoryProperty, pixelWidth, pixelHeight, imgType, samples,
                                    tiling, requestedMipsLevels, numberOfArrayElements, pixelDepth, createFlags);

                    byte[] keyValueDatas = br.ReadBytes((int)bytesOfKeyValueData);


                    if (memoryProperty.HasFlag(VkMemoryPropertyFlags.DeviceLocal))
                    {
                        ulong staggingSize = img.AllocatedDeviceMemorySize;


                        using (HostBuffer stagging = new HostBuffer(staggingQ.Dev, VkBufferUsageFlags.TransferSrc, staggingSize)) {
                            stagging.Map();

                            CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer();
                            cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit);
                            img.SetLayout(cmd, VkImageAspectFlags.Color,
                                          VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal,
                                          VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.Transfer);

                            List <VkBufferImageCopy> buffCopies = new List <VkBufferImageCopy> ();

                            VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy {
                                imageExtent      = img.CreateInfo.extent,
                                imageSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, img.CreateInfo.arrayLayers, 0)
                            };

                            ulong bufferOffset = 0;
                            uint  imgWidth     = img.CreateInfo.extent.height;
                            uint  imgHeight    = img.CreateInfo.extent.width;

                            for (int mips = 0; mips < numberOfMipmapLevels; mips++)
                            {
                                UInt32 imgSize = br.ReadUInt32();

                                bufferCopyRegion.bufferImageHeight = imgWidth;
                                bufferCopyRegion.bufferRowLength   = imgHeight;
                                bufferCopyRegion.bufferOffset      = bufferOffset;

                                if (createFlags.HasFlag(VkImageCreateFlags.CubeCompatible))
                                {
                                    IntPtr ptrFace = img.MappedData;
                                    bufferCopyRegion.imageSubresource.layerCount = 1;
                                    for (uint face = 0; face < numberOfFaces; face++)
                                    {
                                        bufferCopyRegion.imageSubresource.baseArrayLayer = face;
                                        Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize);
                                        buffCopies.Add(bufferCopyRegion);
                                        uint faceOffset = imgSize + (imgSize % 4);
                                        ptrFace      += (int)faceOffset;                                   //cube padding
                                        bufferOffset += faceOffset;
                                        bufferCopyRegion.bufferOffset = bufferOffset;
                                    }
                                }
                                else
                                {
                                    Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData, (int)imgSize);
                                    buffCopies.Add(bufferCopyRegion);
                                }
                                bufferOffset += imgSize;
                                imgWidth     /= 2;
                                imgHeight    /= 2;
                            }
                            stagging.Unmap();
                            Vk.vkCmdCopyBufferToImage(cmd.Handle, stagging.handle, img.handle, VkImageLayout.TransferDstOptimal,
                                                      (uint)buffCopies.Count, buffCopies.Pin());
                            buffCopies.Unpin();

                            if (requestedMipsLevels > numberOfMipmapLevels)
                            {
                                img.BuildMipmaps(cmd);
                            }
                            else
                            {
                                img.SetLayout(cmd, VkImageAspectFlags.Color,
                                              VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal,
                                              VkPipelineStageFlags.Transfer, VkPipelineStageFlags.AllGraphics);
                            }

                            cmd.End();

                            staggingQ.Submit(cmd);
                            staggingQ.WaitIdle();

                            cmd.Free();
                        }

                        //for (int mips = 0; mips < numberOfMipmapLevels; mips++) {
                        //UInt32 imgSize = br.ReadUInt32 ();

                        /*VkImageBlit imageBlit = new VkImageBlit {
                         *      srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, numberOfArrayElements, (uint)mips - 1),
                         *      srcOffsets_1 = new VkOffset3D((int)pixelWidth >> (mips - 1), (int)pixelHeight >> (mips - 1),1),
                         *      dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, numberOfArrayElements, (uint)mips),
                         *      dstOffsets_1 = new VkOffset3D ((int)pixelWidth >> mips, (int)pixelHeight >> mips, 1),
                         * };*/
                        //for (int layer = 0; layer < numberOfArrayElements; layer++) {
                        //for (int face = 0; face < numberOfFaces; face++) {
                        //for (int slice = 0; slice < pixelDepth; slice++) {

                        /*for (int y = 0; y < pixelHeight; y++) {
                         *      for (int x = 0; x < pixelWidth; x++) {
                         *              //Uncompressed texture data matches a GL_UNPACK_ALIGNMENT of 4.
                         *      }
                         * }*/
                        //}
                        //Byte cubePadding[0-3]
                        //}
                        //}
                        //Byte mipPadding[0-3]
                        //}
                    }
                }
            }

            return(img);
        }
Beispiel #30
0
        public static Image Load(Queue staggingQ, CommandPool staggingCmdPool, string ktxPath, VkImageUsageFlags usage = VkImageUsageFlags.Sampled,
                                 VkMemoryPropertyFlags memoryProperty = VkMemoryPropertyFlags.DeviceLocal, bool generateMipmaps = true,
                                 VkImageTiling tiling = VkImageTiling.Optimal)
        {
            Image img = null;

            using (Stream ktxStream = File.Open(ktxPath, FileMode.Open, FileAccess.Read)) {
                using (BinaryReader br = new BinaryReader(ktxStream)) {
                    if (!br.ReadBytes(12).AreEquals(ktxSignature))
                    {
                        throw new KtxException("Not a ktx file: " + ktxPath);
                    }

                    UInt32 endianness            = br.ReadUInt32();
                    UInt32 glType                = br.ReadUInt32();
                    UInt32 glTypeSize            = br.ReadUInt32();
                    UInt32 glFormat              = br.ReadUInt32();
                    UInt32 glInternalFormat      = br.ReadUInt32();
                    UInt32 glBaseInternalFormat  = br.ReadUInt32();
                    UInt32 pixelWidth            = br.ReadUInt32();
                    UInt32 pixelHeight           = br.ReadUInt32();
                    UInt32 pixelDepth            = Math.Max(1, br.ReadUInt32());
                    UInt32 numberOfArrayElements = br.ReadUInt32();             //only for array text, else 0
                    UInt32 numberOfFaces         = br.ReadUInt32();             //only for cube map, else 1
                    UInt32 numberOfMipmapLevels  = Math.Max(1, br.ReadUInt32());
                    UInt32 bytesOfKeyValueData   = br.ReadUInt32();

                    VkFormat vkFormat = GLHelper.vkGetFormatFromOpenGLInternalFormat(glInternalFormat);
                    if (vkFormat == VkFormat.Undefined)
                    {
                        vkFormat = GLHelper.vkGetFormatFromOpenGLFormat(glFormat, glType);
                        if (vkFormat == VkFormat.Undefined)
                        {
                            throw new KtxException("Undefined format: " + ktxPath);
                        }
                    }
                    VkFormatProperties   formatProperties = staggingQ.Dev.phy.GetFormatProperties(vkFormat);
                    VkFormatFeatureFlags phyFormatSupport = (tiling == VkImageTiling.Linear) ?
                                                            formatProperties.linearTilingFeatures :
                                                            formatProperties.optimalTilingFeatures;

                    uint requestedMipsLevels = numberOfMipmapLevels;
                    if (numberOfMipmapLevels == 1)
                    {
                        requestedMipsLevels = (generateMipmaps && phyFormatSupport.HasFlag(VkFormatFeatureFlags.BlitSrc | VkFormatFeatureFlags.BlitDst)) ?
                                              (uint)Math.Floor(Math.Log(Math.Max(pixelWidth, pixelHeight))) + 1 : 1;
                    }

                    if (tiling == VkImageTiling.Optimal)
                    {
                        usage |= VkImageUsageFlags.TransferDst;
                    }
                    if (generateMipmaps)
                    {
                        usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
                    }

                    VkImageCreateFlags createFlags = 0;

                    VkImageType imgType =
                        (pixelWidth == 0) ? throw new KtxException("pixelWidth must be > 0") :
                              (pixelHeight == 0) ? imgType = VkImageType.Image1D :
                                                             (pixelDepth == 1) ? imgType = VkImageType.Image2D : imgType = VkImageType.Image3D;


                    VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1;

                    if (numberOfFaces > 1)
                    {
                        if (imgType != VkImageType.Image2D)
                        {
                            throw new KtxException("cubemap faces must be 2D textures");
                        }
                        createFlags           = VkImageCreateFlags.CubeCompatible;
                        samples               = VkSampleCountFlags.SampleCount1;
                        numberOfArrayElements = numberOfFaces;
                    }
                    else
                    {
                        numberOfFaces = 1;
                        if (numberOfArrayElements == 0)
                        {
                            numberOfArrayElements = 1;
                        }
                    }

                    if (!Image.CheckFormatIsSupported(usage, phyFormatSupport))
                    {
                        throw new Exception($"Unsupported image format: {vkFormat}, {tiling}, {usage}");
                    }

                    img = new Image(staggingQ.Dev, vkFormat, usage, memoryProperty, pixelWidth, pixelHeight, imgType, samples,
                                    tiling, requestedMipsLevels, numberOfArrayElements, pixelDepth, createFlags);

                    byte[] keyValueDatas = br.ReadBytes((int)bytesOfKeyValueData);

                    uint blockW, blockH;
                    bool isCompressed = vkFormat.TryGetCompressedFormatBlockSize(out blockW, out blockH);
                    uint blockSize    = blockW * blockH;

                    if (memoryProperty.HasFlag(VkMemoryPropertyFlags.DeviceLocal))
                    {
                        ulong staggingSize = img.AllocatedDeviceMemorySize;
                        Console.WriteLine($"KtxStream size = {ktxStream.Length}, img Allocation = {img.AllocatedDeviceMemorySize}");

                        using (HostBuffer stagging = new HostBuffer(staggingQ.Dev, VkBufferUsageFlags.TransferSrc, staggingSize)) {
                            stagging.Map();

                            PrimaryCommandBuffer cmd = staggingCmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit);
                            img.SetLayout(cmd, VkImageAspectFlags.Color,
                                          VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal,
                                          VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.Transfer);

                            List <VkBufferImageCopy> buffCopies = new List <VkBufferImageCopy> ();

                            VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy {
                                imageExtent      = img.CreateInfo.extent,
                                imageSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, img.CreateInfo.arrayLayers, 0)
                            };

                            ulong bufferOffset = 0;
                            uint  imgWidth     = img.CreateInfo.extent.width;
                            uint  imgHeight    = img.CreateInfo.extent.height;

                            for (int mips = 0; mips < numberOfMipmapLevels; mips++)
                            {
                                UInt32 imgSize = br.ReadUInt32();

                                bufferCopyRegion.bufferRowLength   = imgWidth;
                                bufferCopyRegion.bufferImageHeight = imgHeight;

                                if (isCompressed && (imgWidth % blockW > 0 || imgHeight % blockH > 0))
                                {
                                    bufferCopyRegion.bufferRowLength   += blockW - imgWidth % blockW;
                                    bufferCopyRegion.bufferImageHeight += blockH - imgHeight % blockH;
                                }
                                bufferCopyRegion.bufferOffset = bufferOffset;
                                bufferCopyRegion.imageSubresource.mipLevel = (uint)mips;
                                bufferCopyRegion.imageExtent.width         = imgWidth;
                                bufferCopyRegion.imageExtent.height        = imgHeight;

                                if (createFlags.HasFlag(VkImageCreateFlags.CubeCompatible))
                                {
                                    //TODO:handle compressed formats
                                    for (uint face = 0; face < numberOfFaces; face++)
                                    {
                                        Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize);
                                        uint faceOffset = imgSize + (imgSize % 4);                                        //cube padding
                                        bufferOffset += faceOffset;
                                    }
                                    buffCopies.Add(bufferCopyRegion);
                                    bufferCopyRegion.bufferOffset = bufferOffset;
                                }
                                else if (isCompressed && (imgWidth % blockW > 0 || imgHeight % blockH > 0))
                                {
                                    for (int line = 0; line < imgHeight; line++)
                                    {
                                        Marshal.Copy(br.ReadBytes((int)imgWidth), 0, stagging.MappedData + (int)bufferOffset, (int)imgWidth);
                                        bufferOffset += bufferCopyRegion.bufferRowLength;
                                    }
                                    buffCopies.Add(bufferCopyRegion);
                                }
                                else
                                {
                                    Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize);
                                    buffCopies.Add(bufferCopyRegion);
                                    bufferOffset += imgSize;
                                }

                                if (isCompressed && bufferOffset % blockSize > 0)
                                {
                                    bufferOffset += blockSize - bufferOffset % blockSize;
                                }

                                imgWidth  /= 2;
                                imgHeight /= 2;
                            }
                            stagging.Unmap();

                            Vk.vkCmdCopyBufferToImage(cmd.Handle, stagging.handle, img.handle, VkImageLayout.TransferDstOptimal,
                                                      (uint)buffCopies.Count, buffCopies.Pin());
                            buffCopies.Unpin();

                            if (requestedMipsLevels > numberOfMipmapLevels)
                            {
                                img.BuildMipmaps(cmd);
                            }
                            else
                            {
                                img.SetLayout(cmd, VkImageAspectFlags.Color,
                                              VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal,
                                              VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
                            }

                            cmd.End();

                            staggingQ.Submit(cmd);
                            staggingQ.WaitIdle();

                            cmd.Free();
                        }
                    }
                    else
                    {
                    }
                }
            }

            return(img);
        }
Beispiel #31
0
        public unsafe static Image Create(uint width, uint height, VkImageCreateFlags flags, uint layers, uint levels,
                                          VkFormat format, VkSampleCountFlags samples, VkImageUsageFlags usage)
        {
            var imageType  = height == 1 ? width > 1 ? VkImageType.Image1D : VkImageType.Image2D : VkImageType.Image2D;
            var createInfo = new VkImageCreateInfo
            {
                sType         = VkStructureType.ImageCreateInfo,
                flags         = flags,
                imageType     = imageType,
                format        = format,
                extent        = new VkExtent3D(width, height, 1),
                mipLevels     = levels,
                arrayLayers   = layers,
                samples       = samples,
                tiling        = VkImageTiling.Optimal,
                usage         = usage,
                sharingMode   = VkSharingMode.Exclusive,
                initialLayout = VkImageLayout.Undefined
            };

            Image image = new Image(ref createInfo);

            return(image);
        }