Beispiel #1
0
        internal static unsafe void AllocatePool(out VkDeviceMemory NativeMemory, ref VkDevice device, ref VkPhysicalDevice pDevice, ref VkMemoryPropertyFlags memoryProperties, ref VkMemoryRequirements memoryRequirements, ulong size)
        {
            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = size,
            };

            Vortice.Vulkan.Vulkan.vkGetPhysicalDeviceMemoryProperties(pDevice, out var physicalDeviceMemoryProperties);

            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            NativeMemory = new VkDeviceMemory();

            Vortice.Vulkan.Vulkan.vkAllocateMemory(device, &allocateInfo, null, out NativeMemory);
        }
Beispiel #2
0
        public static VkMemoryAllocateInfo memoryAllocateInfo()
        {
            VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo();

            memAllocInfo.sType = VkStructureType.MemoryAllocateInfo;
            return(memAllocInfo);
        }
Beispiel #3
0
            public ChunkAllocator(VkDevice device, uint memoryTypeIndex, bool persistentMapped)
            {
                _device           = device;
                _memoryTypeIndex  = memoryTypeIndex;
                _persistentMapped = persistentMapped;
                _totalMemorySize  = persistentMapped ? PersistentMappedChunkSize : UnmappedChunkSize;

                VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New();

                memoryAI.allocationSize  = _totalMemorySize;
                memoryAI.memoryTypeIndex = _memoryTypeIndex;
                VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory);

                CheckResult(result);

                void *mappedPtr = null;

                if (persistentMapped)
                {
                    result = vkMapMemory(_device, _memory, 0, _totalMemorySize, 0, &mappedPtr);
                    CheckResult(result);
                }

                VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex, mappedPtr);

                _freeBlocks.Add(initialBlock);
            }
        public void Allocate(uint memoryTypeIndex)
        {
            if (imageMemoryBind.memory != VkDeviceMemory.Null)
            {
                return;
            }

            imageMemoryBind = new VkSparseImageMemoryBind();

            var allocInfo = new VkMemoryAllocateInfo();

            allocInfo.sType           = VkStructureType.MemoryAllocateInfo;
            allocInfo.allocationSize  = size;
            allocInfo.memoryTypeIndex = memoryTypeIndex;
            imageMemoryBind.memory    = Device.AllocateMemory(ref allocInfo);

            // Sparse image memory binding
            imageMemoryBind.subresource = new VkImageSubresource
            {
                aspectMask = VkImageAspectFlags.Color,
                mipLevel   = mipLevel,
                arrayLayer = layer,
            };

            imageMemoryBind.extent = extent;
            imageMemoryBind.offset = offset;
        }
Beispiel #5
0
 private bool TryAllocateDedicated(MemoryRequirements req, MemoryType memoryType)
 {
     unsafe
     {
         if (!Device.ExtensionEnabled(VkExtension.KhrDedicatedAllocation))
         {
             return(false);
         }
         var dedInfo = new VkMemoryDedicatedAllocateInfoKHR()
         {
             SType = VkStructureType.MemoryDedicatedAllocateInfoKhr,
             PNext = IntPtr.Zero
         };
         if (!req.DedicatedMemory.Value.SetOwnerOn(ref dedInfo))
         {
             return(false);
         }
         var info = new VkMemoryAllocateInfo()
         {
             SType           = VkStructureType.MemoryAllocateInfo,
             AllocationSize  = req.TypeRequirements.Size,
             MemoryTypeIndex = memoryType.TypeIndex,
             PNext           = new IntPtr(&dedInfo)
         };
         Handle = Device.Handle.AllocateMemory(&info, Instance.AllocationCallbacks);
         if (Handle == VkDeviceMemory.Null)
         {
             return(false);
         }
         DedicatedMemoryOwner = req.DedicatedMemory.Value;
         Capacity             = req.TypeRequirements.Size;
         return(true);
     }
 }
Beispiel #6
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 #7
0
        protected void allocateMemory()
        {
            VkMemoryAllocateInfo memInfo = VkMemoryAllocateInfo.New();

            memInfo.allocationSize  = memReqs.size;
            memInfo.memoryTypeIndex = Dev.GetMemoryTypeIndex(memReqs.memoryTypeBits, MemoryFlags);
            Utils.CheckResult(vkAllocateMemory(Dev.VkDev, ref memInfo, IntPtr.Zero, out vkMemory));
        }
        internal unsafe void AllocateOneTimeUploadBuffer(int size, out UploadBuffer uploadBuffer)
        {
            var bufferCreateInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                size  = (ulong)size,
                flags = VkBufferCreateFlags.None,
                usage = VkBufferUsageFlags.TransferSrc,
            };

            uploadBuffer = new UploadBuffer
            {
                size = size
            };

            vkCreateBuffer(NativeDevice, &bufferCreateInfo, null, out uploadBuffer.buffer);

            // figure out the memory type
            if (properType == uint.MaxValue)
            {
                VkMemoryPropertyFlags memoryProperties = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent;
                vkGetBufferMemoryRequirements(nativeDevice, uploadBuffer.buffer, out var memoryRequirements);
                vkGetPhysicalDeviceMemoryProperties(NativePhysicalDevice, out var physicalDeviceMemoryProperties);
                var typeBits = memoryRequirements.memoryTypeBits;
                for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
                {
                    if ((typeBits & 1) == 1)
                    {
                        // Type is available, does it match user properties?
                        var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                        if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                        {
                            properType = i;
                            break;
                        }
                    }
                    typeBits >>= 1;
                }
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                allocationSize  = (ulong)size,
                memoryTypeIndex = properType
            };

            fixed(VkDeviceMemory *nativeUploadBufferMemoryPtr = &uploadBuffer.memory)
            vkAllocateMemory(NativeDevice, &allocateInfo, null, nativeUploadBufferMemoryPtr);

            vkBindBufferMemory(NativeDevice, uploadBuffer.buffer, uploadBuffer.memory, 0);

            fixed(IntPtr *nativeUploadBufferStartPtr = &uploadBuffer.address)
            vkMapMemory(NativeDevice, uploadBuffer.memory, 0, (ulong)size, VkMemoryMapFlags.None, (void **)nativeUploadBufferStartPtr);
        }
Beispiel #9
0
        public override VkResult AllocateMemory(VkMemoryAllocateInfo pAllocateInfo, out VkDeviceMemory pMemory)
        {
            VkPreconditions.CheckRange(pAllocateInfo.allocationSize, 1, int.MaxValue, nameof(pAllocateInfo.allocationSize));
            VkPreconditions.CheckRange(pAllocateInfo.memoryTypeIndex != 0, nameof(pAllocateInfo.memoryTypeIndex));

            var ret = new SoftwareDeviceMemory(this, pAllocateInfo);

            m_DeviceMemory.Add(ret);
            pMemory = ret;
            return(VkResult.VK_SUCCESS);
        }
Beispiel #10
0
        protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements)
        {
            if (NativeMemory != VkDeviceMemory.Null)
            {
                return;
            }

            if (memoryRequirements.size == 0)
            {
                return;
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = memoryRequirements.size,
            };

            VkPhysicalDeviceMemoryProperties localProps;

            if (!gotProps)
            {
                gotProps = true;
                vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out physicalDeviceMemoryProperties);
            }
            localProps = physicalDeviceMemoryProperties;

            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < localProps.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&localProps.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            var result = vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, out NativeMemory);

            if (result != VkResult.Success)
            {
                string err = "Couldn't allocate memory: " + result + ", NativeMemory: " + NativeMemory + ", type: " + allocateInfo.memoryTypeIndex + ", size: " + memoryRequirements.size;
                Xenko.Core.ErrorFileLogger.WriteLogToFile(err);
                throw new Exception(err);
            }
        }
        public VkMemoryBlock Allocate(
            VkPhysicalDeviceMemoryProperties memProperties,
            uint memoryTypeBits,
            VkMemoryPropertyFlags flags,
            bool persistentMapped,
            ulong size,
            ulong alignment)
        {
            lock (_lock)
            {
                uint memoryTypeIndex = FindMemoryType(memProperties, memoryTypeBits, flags);

                ulong minDedicatedAllocationSize = persistentMapped
                    ? MinDedicatedAllocationSizeDynamic
                    : MinDedicatedAllocationSizeNonDynamic;

                if (size >= minDedicatedAllocationSize)
                {
                    VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New();
                    allocateInfo.allocationSize  = size;
                    allocateInfo.memoryTypeIndex = memoryTypeIndex;
                    VkResult allocationResult = vkAllocateMemory(_device, ref allocateInfo, null, out VkDeviceMemory memory);
                    if (allocationResult != VkResult.Success)
                    {
                        throw new VeldridException("Unable to allocate sufficient Vulkan memory.");
                    }

                    void *mappedPtr = null;
                    if (persistentMapped)
                    {
                        VkResult mapResult = vkMapMemory(_device, memory, 0, size, 0, &mappedPtr);
                        if (mapResult != VkResult.Success)
                        {
                            throw new VeldridException("Unable to map newly-allocated Vulkan memory.");
                        }
                    }

                    return(new VkMemoryBlock(memory, 0, size, memoryTypeBits, null, true));
                }
                else
                {
                    ChunkAllocatorSet allocator = GetAllocator(memoryTypeIndex, persistentMapped);
                    bool result = allocator.Allocate(size, alignment, out VkMemoryBlock ret);
                    if (!result)
                    {
                        throw new VeldridException("Unable to allocate sufficient Vulkan memory.");
                    }

                    return(ret);
                }
            }
        }
Beispiel #12
0
        void CreateDeviceMemory(ulong allocationSize, uint memoryTypeIndex)
        {
            var info = new VkMemoryAllocateInfo();

            info.sType           = VkStructureType.MemoryAllocateInfo;
            info.allocationSize  = allocationSize;
            info.memoryTypeIndex = memoryTypeIndex;

            Device.Commands.allocateMemory(Device.Native, ref info, Device.Instance.AllocationCallbacks, out deviceMemory);

            Size            = allocationSize;
            MemoryTypeIndex = memoryTypeIndex;
        }
        /**
         * Create a buffer on the device
         *
         * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer)
         * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent)
         * @param buffer Pointer to a vk::Vulkan buffer object
         * @param size Size of the buffer in byes
         * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over)
         *
         * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied
         */
        public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, vksBuffer buffer, ulong size, void *data = null)
        {
            buffer.device = _logicalDevice;

            // Create the buffer handle
            VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo();

            bufferCreateInfo.sType = BufferCreateInfo;
            bufferCreateInfo.usage = usageFlags;
            bufferCreateInfo.size  = size;
            {
                VkBuffer vkBuffer;
                vkCreateBuffer(_logicalDevice, &bufferCreateInfo, null, &vkBuffer);
                buffer.buffer = vkBuffer;
            }

            // Create the memory backing up the buffer handle
            VkMemoryRequirements memReqs;
            VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo();

            memAlloc.sType = MemoryAllocateInfo;
            vkGetBufferMemoryRequirements(_logicalDevice, buffer.buffer, &memReqs);
            memAlloc.allocationSize = memReqs.size;
            // Find a memory type index that fits the properties of the buffer
            memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
            {
                VkDeviceMemory memory;
                vkAllocateMemory(_logicalDevice, &memAlloc, null, &memory);
                buffer.memory = memory;
            }

            buffer.alignment           = memReqs.alignment;
            buffer.size                = memAlloc.allocationSize;
            buffer.usageFlags          = usageFlags;
            buffer.memoryPropertyFlags = memoryPropertyFlags;

            // If a pointer to the buffer data has been passed, map the buffer and copy over the data
            if (data != null)
            {
                buffer.map();
                Unsafe.CopyBlock(buffer.mapped, data, (uint)size);
                buffer.unmap();
            }

            // Initialize a default descriptor that covers the whole buffer size
            buffer.setupDescriptor();

            // Attach the memory to the buffer object
            return(buffer.bind());
        }
Beispiel #14
0
        private VkDeviceMemory CreateVulkanDeviceMemory()
        {
            _state.ThrowIfDisposedOrDisposing();

            VkDeviceMemory vulkanDeviceMemory;

            var memoryAllocateInfo = new VkMemoryAllocateInfo {
                sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
                allocationSize  = Size,
                memoryTypeIndex = GetMemoryTypeIndex(VulkanGraphicsDevice.VulkanGraphicsAdapter.VulkanPhysicalDevice, CpuAccess),
            };

            ThrowExternalExceptionIfNotSuccess(nameof(vkAllocateMemory), vkAllocateMemory(VulkanGraphicsDevice.VulkanDevice, &memoryAllocateInfo, pAllocator: null, (ulong *)&vulkanDeviceMemory));

            return(vulkanDeviceMemory);
            public ChunkAllocator(VkDevice device, uint memoryTypeIndex)
            {
                _device          = device;
                _memoryTypeIndex = memoryTypeIndex;

                VkMemoryAllocateInfo memoryAI = VkMemoryAllocateInfo.New();

                memoryAI.allocationSize  = _totalMemorySize;
                memoryAI.memoryTypeIndex = _memoryTypeIndex;
                VkResult result = vkAllocateMemory(_device, ref memoryAI, null, out _memory);

                CheckResult(result);

                VkMemoryBlock initialBlock = new VkMemoryBlock(_memory, 0, _totalMemorySize, _memoryTypeIndex);

                _freeBlocks.Add(initialBlock);
            }
Beispiel #16
0
        public static VulkanBuffer DynamicUniform <T>(VulkanContext ctx, int count) where T : struct
        {
            long size = Unsafe.SizeOf <T>() * count;

            VkBufferCreateInfo createInfo = new VkBufferCreateInfo
            {
                sType = VkStructureType.BufferCreateInfo,
                pNext = null,
                size  = (ulong)size,
                usage = VkBufferUsageFlags.UniformBuffer
            };

            VkBuffer buffer;
            VkResult result = vkCreateBuffer(ctx.Device, &createInfo, null, out buffer);

            result.CheckResult();

            VkMemoryRequirements memoryRequirements;

            vkGetBufferMemoryRequirements(ctx.Device, buffer, out memoryRequirements);

            vkGetPhysicalDeviceMemoryProperties(ctx.PhysicalDevice, out VkPhysicalDeviceMemoryProperties memoryProperties);

            uint memoryTypeIndex = BufferHelper.GetMemoryTypeIndex(memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, memoryProperties);

            // We require host visible memory so we can map it and write to it directly.
            // We require host coherent memory so that writes are visible to the GPU right after unmapping it.

            VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo()
            {
                sType           = VkStructureType.MemoryAllocateInfo,
                pNext           = null,
                allocationSize  = memoryRequirements.size,
                memoryTypeIndex = memoryTypeIndex
            };

            VkDeviceMemory memory;

            result = vkAllocateMemory(ctx.Device, &memAllocInfo, null, &memory);
            result.CheckResult();

            result = vkBindBufferMemory(ctx.Device, buffer, memory, 0);
            result.CheckResult();

            return(new VulkanBuffer(ctx.Device, ctx.GraphicsCommandPool, buffer, memory, count));
        }
Beispiel #17
0
        private void Setup()
        {
            disposed = false;
            VkImageCreateInfo image = VkImageCreateInfo.New();

            image.imageType = VkImageType.Image2D;
            image.format    = device.DepthFormat;
            image.extent    = new VkExtent3D()
            {
                width = swapchain.width, height = swapchain.height, depth = 1
            };
            image.mipLevels   = 1;
            image.arrayLayers = 1;
            image.samples     = VkSampleCountFlags.Count1;
            image.tiling      = VkImageTiling.Optimal;
            image.usage       = (VkImageUsageFlags.DepthStencilAttachment | VkImageUsageFlags.TransferSrc);
            image.flags       = 0;

            VkMemoryAllocateInfo mem_alloc = VkMemoryAllocateInfo.New();

            mem_alloc.allocationSize  = 0;
            mem_alloc.memoryTypeIndex = 0;

            VkImageViewCreateInfo depthStencilView = VkImageViewCreateInfo.New();

            depthStencilView.viewType                        = VkImageViewType.Image2D;
            depthStencilView.format                          = device.DepthFormat;
            depthStencilView.flags                           = 0;
            depthStencilView.subresourceRange                = new VkImageSubresourceRange();
            depthStencilView.subresourceRange.aspectMask     = (VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil);
            depthStencilView.subresourceRange.baseMipLevel   = 0;
            depthStencilView.subresourceRange.levelCount     = 1;
            depthStencilView.subresourceRange.baseArrayLayer = 0;
            depthStencilView.subresourceRange.layerCount     = 1;

            Util.CheckResult(vkCreateImage(device.device, &image, null, out vkImage));
            vkGetImageMemoryRequirements(device.device, vkImage, out VkMemoryRequirements memReqs);
            mem_alloc.allocationSize  = memReqs.size;
            mem_alloc.memoryTypeIndex = device.vulkanDevice.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
            Util.CheckResult(vkAllocateMemory(device.device, &mem_alloc, null, out vkMem));
            Util.CheckResult(vkBindImageMemory(device.device, vkImage, vkMem, 0));

            depthStencilView.image = vkImage;
            Util.CheckResult(vkCreateImageView(device.device, ref depthStencilView, null, out vkView));
        }
        /**
         * Create a buffer on the device
         *
         * @param usageFlags Usage flag bitmask for the buffer (i.e. index, vertex, uniform buffer)
         * @param memoryPropertyFlags Memory properties for this buffer (i.e. device local, host visible, coherent)
         * @param size Size of the buffer in byes
         * @param buffer Pointer to the buffer handle acquired by the function
         * @param memory Pointer to the memory handle acquired by the function
         * @param data Pointer to the data that should be copied to the buffer after creation (optional, if not set, no data is copied over)
         *
         * @return Success if buffer handle and memory have been created and (optionally passed) data has been copied
         */
        public VkResult createBuffer(VkBufferUsageFlagBits usageFlags, VkMemoryPropertyFlagBits memoryPropertyFlags, ulong size, VkBuffer *buffer, VkDeviceMemory *memory, void *data = null)
        {
            // Create the buffer handle
            VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo();

            bufferCreateInfo.sType       = BufferCreateInfo;
            bufferCreateInfo.usage       = usageFlags;
            bufferCreateInfo.size        = size;
            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;
            vkCreateBuffer(LogicalDevice, &bufferCreateInfo, null, buffer);

            // Create the memory backing up the buffer handle
            VkMemoryRequirements memReqs;
            VkMemoryAllocateInfo memAlloc = new VkMemoryAllocateInfo();

            memAlloc.sType = MemoryAllocateInfo;
            vkGetBufferMemoryRequirements(LogicalDevice, *buffer, &memReqs);
            memAlloc.allocationSize = memReqs.size;
            // Find a memory type index that fits the properties of the buffer
            memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
            vkAllocateMemory(LogicalDevice, &memAlloc, null, memory);

            // If a pointer to the buffer data has been passed, map the buffer and copy over the data
            if (data != null)
            {
                IntPtr mapped;
                vkMapMemory(LogicalDevice, *memory, 0, size, 0, &mapped);
                Unsafe.CopyBlock(mapped, data, (uint)size);
                // If host coherency hasn't been requested, do a manual flush to make writes visible
                if ((memoryPropertyFlags & VkMemoryPropertyFlagBits.HostCoherent) == 0)
                {
                    VkMappedMemoryRange mappedRange = new VkMappedMemoryRange();
                    mappedRange.memory = *memory;
                    mappedRange.offset = 0;
                    mappedRange.size   = size;
                    vkFlushMappedMemoryRanges(LogicalDevice, 1, &mappedRange);
                }
                vkUnmapMemory(LogicalDevice, *memory);
            }

            // Attach the memory to the buffer object
            vkBindBufferMemory(LogicalDevice, *buffer, *memory, 0);

            return(VkResult.Success);
        }
Beispiel #19
0
        void CreateBuffer(long size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, out VkBuffer buffer, out VkDeviceMemory memory)
        {
            var info = new VkBufferCreateInfo();

            info.size        = size;
            info.usage       = usage;
            info.sharingMode = VkSharingMode.Exclusive;

            buffer = new VkBuffer(device, info);

            var allocInfo = new VkMemoryAllocateInfo();

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

            memory = new VkDeviceMemory(device, allocInfo);
            buffer.Bind(memory, 0);
        }
Beispiel #20
0
        protected virtual void SetupDepthStencil()
        {
            VkImageCreateInfo image = VkImageCreateInfo.New();

            image.imageType = VkImageType._2d;
            image.format    = DepthFormat;
            image.extent    = new VkExtent3D()
            {
                width = Width, height = Height, depth = 1
            };
            image.mipLevels   = 1;
            image.arrayLayers = 1;
            image.samples     = VkSampleCountFlags._1;
            image.tiling      = VkImageTiling.Optimal;
            image.usage       = (VkImageUsageFlags.DepthStencilAttachment | VkImageUsageFlags.TransferSrc);
            image.flags       = 0;

            VkMemoryAllocateInfo mem_alloc = VkMemoryAllocateInfo.New();

            mem_alloc.allocationSize  = 0;
            mem_alloc.memoryTypeIndex = 0;

            VkImageViewCreateInfo depthStencilView = VkImageViewCreateInfo.New();

            depthStencilView.viewType                        = VkImageViewType._2d;
            depthStencilView.format                          = DepthFormat;
            depthStencilView.flags                           = 0;
            depthStencilView.subresourceRange                = new VkImageSubresourceRange();
            depthStencilView.subresourceRange.aspectMask     = (VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil);
            depthStencilView.subresourceRange.baseMipLevel   = 0;
            depthStencilView.subresourceRange.levelCount     = 1;
            depthStencilView.subresourceRange.baseArrayLayer = 0;
            depthStencilView.subresourceRange.layerCount     = 1;

            Util.CheckResult(vkCreateImage(Device, &image, null, out DepthStencil.Image));
            vkGetImageMemoryRequirements(Device, DepthStencil.Image, out VkMemoryRequirements memReqs);
            mem_alloc.allocationSize  = memReqs.size;
            mem_alloc.memoryTypeIndex = VulkanDevice.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal);
            Util.CheckResult(vkAllocateMemory(Device, &mem_alloc, null, out DepthStencil.Mem));
            Util.CheckResult(vkBindImageMemory(Device, DepthStencil.Image, DepthStencil.Mem, 0));

            depthStencilView.image = DepthStencil.Image;
            Util.CheckResult(vkCreateImageView(Device, ref depthStencilView, null, out DepthStencil.View));
        }
Beispiel #21
0
        private void CreateDepthImage(VkPhysicalDevice physicalDevice, uint width, uint height)
        {
            VkImageCreateInfo createInfo = VkImageCreateInfo.New();

            createInfo.imageType     = VkImageType.Image2D;
            createInfo.extent.width  = width;
            createInfo.extent.height = height;
            createInfo.extent.depth  = 1;
            createInfo.mipLevels     = 1;
            createInfo.arrayLayers   = 1;
            createInfo.format        = VkFormat.D32Sfloat;
            createInfo.tiling        = VkImageTiling.Optimal;
            createInfo.initialLayout = VkImageLayout.Undefined;
            createInfo.usage         = VkImageUsageFlags.DepthStencilAttachment;
            createInfo.sharingMode   = VkSharingMode.Exclusive;
            createInfo.samples       = VkSampleCountFlags.Count1;

            VkImage depthImage;

            Assert(vkCreateImage(device, &createInfo, null, &depthImage));

            VkMemoryRequirements memoryRequirements;

            vkGetImageMemoryRequirements(device, depthImage, &memoryRequirements);

            VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties();

            vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);

            VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New();

            allocateInfo.allocationSize  = memoryRequirements.size;
            allocateInfo.memoryTypeIndex = FDataBuffer <byte> .SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits,
                                                                                VkMemoryPropertyFlags.DeviceLocal);

            VkDeviceMemory depthImageMemory;

            Assert(vkAllocateMemory(device, &allocateInfo, null, &depthImageMemory));

            vkBindImageMemory(device, depthImage, depthImageMemory, 0);

            this.depthImage       = depthImage;
            this.depthImageMemory = depthImageMemory;
        }
        private VkDeviceMemory CreateVulkanDeviceMemory()
        {
            ThrowIfDisposedOrDisposing(_state, nameof(VulkanGraphicsMemoryBlock));

            VkDeviceMemory vulkanDeviceMemory;

            var collection   = Collection;
            var vulkanDevice = collection.Allocator.Device.VulkanDevice;

            var memoryAllocateInfo = new VkMemoryAllocateInfo {
                sType           = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
                allocationSize  = Size,
                memoryTypeIndex = collection.VulkanMemoryTypeIndex,
            };

            ThrowExternalExceptionIfNotSuccess(vkAllocateMemory(vulkanDevice, &memoryAllocateInfo, pAllocator: null, (ulong *)&vulkanDeviceMemory), nameof(vkAllocateMemory));

            return(vulkanDeviceMemory);
        }
        internal VkResult AllocateDeviceMemory()
        {
            VkMemoryAllocateInfo info = VkMemoryAllocateInfo.New();

            info.allocationSize  = max_size;
            info.memoryTypeIndex = memoryTypeIndex;

            VkResult result = vkAllocateMemory(device.device, &info, null, out vkDeviceMemory);

            if (result != VkResult.Success)
            {
                return(result);
            }

            if ((memoryPropertyFlags & VkMemoryPropertyFlags.HostVisible) != 0)
            {
                Map();
            }
            return(result);
        }
Beispiel #24
0
        protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties, VkMemoryRequirements memoryRequirements)
        {
            if (NativeMemory != VkDeviceMemory.Null)
            {
                return;
            }

            if (memoryRequirements.size == 0)
            {
                return;
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = memoryRequirements.size,
            };

            vkGetPhysicalDeviceMemoryProperties(GraphicsDevice.NativePhysicalDevice, out var physicalDeviceMemoryProperties);
            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            fixed(VkDeviceMemory *nativeMemoryPtr = &NativeMemory)
            vkAllocateMemory(GraphicsDevice.NativeDevice, &allocateInfo, null, nativeMemoryPtr);
        }
Beispiel #25
0
        public FDataBuffer(VkDevice device, VkPhysicalDevice physicalDevice, int length, VkBufferUsageFlags usage, VkSharingMode sharingMode)
        {
            this.device = device;

            VkBufferCreateInfo createInfo = VkBufferCreateInfo.New();

            size                   = (ulong)(sizeof(T) * length);
            createInfo.size        = size;
            createInfo.usage       = usage;
            createInfo.sharingMode = sharingMode;

            VkBuffer buffer = VkBuffer.Null;

            Assert(vkCreateBuffer(device, &createInfo, null, &buffer));
            this.Buffer = buffer;

            VkMemoryRequirements memoryRequirements = new VkMemoryRequirements();

            vkGetBufferMemoryRequirements(device, this.Buffer, &memoryRequirements);

            VkPhysicalDeviceMemoryProperties memoryProperties = new VkPhysicalDeviceMemoryProperties();

            vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);

            VkMemoryAllocateInfo allocateInfo = VkMemoryAllocateInfo.New();

            allocateInfo.allocationSize  = memoryRequirements.size;
            allocateInfo.memoryTypeIndex = SelectMemoryType(memoryProperties, memoryRequirements.memoryTypeBits,
                                                            VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent);

            VkDeviceMemory memory = new VkDeviceMemory();

            Assert(vkAllocateMemory(device, &allocateInfo, null, &memory));
            Memory = memory;

            Assert(vkBindBufferMemory(device, this.Buffer, memory, 0));

            spanLength = length;
        }
Beispiel #26
0
        private void createVertexBuffer()
        {
            VkBufferCreateInfo bufferInfo = new VkBufferCreateInfo();

            bufferInfo.sType       = VkStructureType.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
            bufferInfo.size        = Marshal.SizeOf(vertices[0]) * vertices.Length;
            bufferInfo.usage       = VkBufferUsageFlagBits.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
            bufferInfo.sharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE;

            VkResult result = Vulkan.vkCreateBuffer(device, bufferInfo, null, out vertexBuffer);

            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to create vertex buffer!", result);
            }

            VkMemoryRequirements memRequirements;

            Vulkan.vkGetBufferMemoryRequirements(device, vertexBuffer, out memRequirements);

            VkMemoryAllocateInfo allocInfo = new VkMemoryAllocateInfo();

            allocInfo.sType           = VkStructureType.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
            allocInfo.allocationSize  = memRequirements.size;
            allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VkMemoryPropertyFlagBits.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

            result = Vulkan.vkAllocateMemory(device, allocInfo, null, out vertexBufferMemory);
            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to allocate vertex buffer memory!", result);
            }

            Vulkan.vkBindBufferMemory(device, vertexBuffer, vertexBufferMemory, 0);

            byte[] data;
            Vulkan.vkMapMemory(device, vertexBufferMemory, 0, bufferInfo.size, 0, out data);
            MemoryCopyHelper.Copy(vertices, data, 0, bufferInfo.size);
            Vulkan.vkUnmapMemory(device, vertexBufferMemory);
        }
Beispiel #27
0
        private bool TryAllocateNormal(ulong capacity, MemoryType memoryType)
        {
            unsafe
            {
                var info = new VkMemoryAllocateInfo()
                {
                    SType           = VkStructureType.MemoryAllocateInfo,
                    AllocationSize  = capacity,
                    MemoryTypeIndex = memoryType.TypeIndex,
                    PNext           = IntPtr.Zero
                };
                Handle = Device.Handle.AllocateMemory(&info, Instance.AllocationCallbacks);
            }

            if (Handle == VkDeviceMemory.Null)
            {
                return(false);
            }
            DedicatedMemoryOwner = null;
            Capacity             = capacity;
            return(true);
        }
        protected unsafe void AllocateMemory(VkMemoryPropertyFlags memoryProperties)
        {
            vkGetBufferMemoryRequirements(nativeDevice, nativeUploadBuffer, out var memoryRequirements);

            if (memoryRequirements.size == 0)
            {
                return;
            }

            var allocateInfo = new VkMemoryAllocateInfo
            {
                sType          = VkStructureType.MemoryAllocateInfo,
                allocationSize = memoryRequirements.size,
            };

            vkGetPhysicalDeviceMemoryProperties(NativePhysicalDevice, out var physicalDeviceMemoryProperties);
            var typeBits = memoryRequirements.memoryTypeBits;

            for (uint i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++)
            {
                if ((typeBits & 1) == 1)
                {
                    // Type is available, does it match user properties?
                    var memoryType = *(&physicalDeviceMemoryProperties.memoryTypes_0 + i);
                    if ((memoryType.propertyFlags & memoryProperties) == memoryProperties)
                    {
                        allocateInfo.memoryTypeIndex = i;
                        break;
                    }
                }
                typeBits >>= 1;
            }

            vkAllocateMemory(NativeDevice, &allocateInfo, null, out nativeUploadBufferMemory);

            vkBindBufferMemory(NativeDevice, nativeUploadBuffer, nativeUploadBufferMemory, 0);
        }
Beispiel #29
0
        VkBuffer CreateBuffer(VkPhysicalDevice physicalDevice, VkDevice device, object values, VkBufferUsageFlagBits usageFlags, System.Type type)
        {
            var      array  = values as System.Array;
            var      length = (array != null) ? array.Length : 1;
            var      size   = System.Runtime.InteropServices.Marshal.SizeOf(type) * length;
            VkBuffer buffer;
            {
                UInt32 index = 0;
                var    info  = new VkBufferCreateInfo {
                    sType = VkStructureType.BufferCreateInfo
                };
                info.size               = (UInt64)size;
                info.usage              = usageFlags;
                info.sharingMode        = VkSharingMode.Exclusive;
                info.queueFamilyIndices = index;
                //VkBuffer buffer = device.CreateBuffer(ref info);
                vkAPI.vkCreateBuffer(device, &info, null, &buffer).Check();
                info.Free();
            }
            VkDeviceMemory       deviceMemory; // = device.AllocateMemory(ref allocInfo);
            VkMemoryRequirements memoryReq;

            //VkMemoryRequirements memoryReq = device.GetBufferMemoryRequirements(buffer);
            vkAPI.vkGetBufferMemoryRequirements(device, buffer, &memoryReq);
            var allocInfo = new VkMemoryAllocateInfo {
                sType = VkStructureType.MemoryAllocateInfo
            };

            {
                allocInfo.allocationSize = memoryReq.size;
                VkPhysicalDeviceMemoryProperties memoryProperties;
                vkAPI.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
                allocInfo.memoryTypeIndex = GetMemoryTypeIndex(memoryProperties, memoryReq,
                                                               VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent);
                vkAPI.vkAllocateMemory(device, &allocInfo, null, &deviceMemory).Check();
            }
            {
                IntPtr memPtr = IntPtr.Zero;
                vkAPI.vkMapMemory(device, deviceMemory, 0, (UInt64)size, 0, &memPtr).Check();

                if (type == typeof(float))
                {
                    System.Runtime.InteropServices.Marshal.Copy(values as float[], 0, memPtr, length);
                }
                else if (type == typeof(short))
                {
                    System.Runtime.InteropServices.Marshal.Copy(values as short[], 0, memPtr, length);
                }
                else if (type == typeof(AreaUniformBuffer))
                {
                    System.Runtime.InteropServices.Marshal.StructureToPtr(values, memPtr, false);
                    this.vkBuffer       = buffer;
                    this.vkDeviceMemory = deviceMemory;
                    this.uniformSize    = memoryReq.size;
                }

                vkAPI.vkUnmapMemory(device, deviceMemory);
            }
            vkAPI.vkBindBufferMemory(device, buffer, deviceMemory, 0).Check();

            return(buffer);
        }
Beispiel #30
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,
            VkImageUsageFlagBits imageUsageFlags = VkImageUsageFlagBits.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, &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 = new VkMemoryAllocateInfo();

            memAllocInfo.sType = 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 = new VkBufferCreateInfo();
                bufferCreateInfo.sType = BufferCreateInfo;
                bufferCreateInfo.size  = tex2D.GetTotalSize();
                // This buffer is used as a transfer source for the buffer copy
                bufferCreateInfo.usage       = VkBufferUsageFlagBits.TransferSrc;
                bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

                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,
                                                                    VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent);

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

                // Copy texture data into staging buffer
                IntPtr data;
                vkMapMemory(device.LogicalDevice, stagingMemory, 0, memReqs.size, 0, &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
                var  bufferCopyRegions = new List <VkBufferImageCopy>();
                uint offset            = 0;

                for (uint i = 0; i < mipLevels; i++)
                {
                    VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();
                    bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlagBits.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 = new VkImageCreateInfo();
                imageCreateInfo.sType         = ImageCreateInfo;
                imageCreateInfo.imageType     = VkImageType._2d;
                imageCreateInfo.format        = format;
                imageCreateInfo.mipLevels     = mipLevels;
                imageCreateInfo.arrayLayers   = 1;
                imageCreateInfo.samples       = VkSampleCountFlagBits._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 & VkImageUsageFlagBits.TransferDst) == 0)
                {
                    imageCreateInfo.usage |= VkImageUsageFlagBits.TransferDst;
                }
                {
                    VkImage vkImage;
                    vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &vkImage);
                    this.image = vkImage;
                }

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

                memAllocInfo.allocationSize = memReqs.size;

                memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits,
                                                                    VkMemoryPropertyFlagBits.DeviceLocal);
                {
                    VkDeviceMemory memory;
                    vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &memory);
                    this.deviceMemory = memory;
                }
                vkBindImageMemory(device.LogicalDevice, image, deviceMemory, 0);

                VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange();
                subresourceRange.aspectMask   = VkImageAspectFlagBits.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,
                    VkImageAspectFlagBits.Color,
                    VkImageLayout.Undefined,
                    VkImageLayout.TransferDstOptimal,
                    subresourceRange);

                // Copy mip levels from staging buffer
                fixed(VkBufferImageCopy *pointer = bufferCopyRegions.ToArray())
                {
                    vkCmdCopyBufferToImage(
                        copyCmd,
                        stagingBuffer,
                        image,
                        VkImageLayout.TransferDstOptimal,
                        (UInt32)bufferCopyRegions.Count,
                        pointer);
                }

                // Change texture image layout to shader read after all mip levels have been copied
                this.imageLayout = imageLayout;
                Tools.setImageLayout(
                    copyCmd,
                    image,
                    VkImageAspectFlagBits.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 = new VkSamplerCreateInfo();

            samplerCreateInfo.sType        = SamplerCreateInfo;
            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;
            {
                VkSampler vkSampler;
                vkCreateSampler(device.LogicalDevice, &samplerCreateInfo, null, &vkSampler);
                this.sampler = vkSampler;
            }

            // 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 = new VkImageViewCreateInfo();

            viewCreateInfo.sType      = ImageViewCreateInfo;
            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   = VkImageAspectFlagBits.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;
            {
                VkImageView vkImageView;
                vkCreateImageView(device.LogicalDevice, &viewCreateInfo, null, &vkImageView);
                this.view = vkImageView;
            }

            // Update descriptor image info member that can be used for setting up descriptor sets
            updateDescriptor();
        }