示例#1
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();
        }
示例#2
0
 public static extern VkResult GetPhysicalDeviceImageFormatProperties(
     VkPhysicalDevice physicalDevice,
     VkFormat format,
     VkImageType type,
     VkImageTiling tiling,
     VkImageUsageFlags usage,
     VkImageCreateFlags flags,
     IntPtr pImageFormatProperties
     );
示例#3
0
文件: Image.cs 项目: Svengali/vk.net
        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!!!!
        }
示例#4
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);
        }
示例#5
0
 internal extern static Result vkGetPhysicalDeviceImageFormatProperties(IntPtr physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, ref VkImageFormatProperties pImageFormatProperties);
示例#6
0
文件: ktx.cs 项目: Svengali/vk.net
        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);
        }
示例#7
0
文件: ktx.cs 项目: jpbruyere/vke.net
        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);
        }
 public VkImageFormatProperties GetImageFormatProperties(VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags)
 {
     using (var prop = new Marshalled <VkImageFormatProperties>()) {
         Instance.Commands.getPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, prop.Address);
         return(prop.Value);
     }
 }