//private void Flush(UInt64 start, UInt64 length) {
        //	VkMappedMemoryRange memoryRange = VkMappedMemoryRange.New();
        //	memoryRange.memory = vkMemory;
        //	memoryRange.size = length;
        //	memoryRange.offset = start;

        //	Util.CheckResult(vkFlushMappedMemoryRanges(device.device, 1, ref memoryRange));
        //}


        private void Allocate()
        {
            if (usageHint == BufferMemoryUsageHint.Static)
            {
                bufferUsageFlags |= VkBufferUsageFlags.TransferDst;
            }

            // Create the buffer handle
            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo(bufferUsageFlags, size);

            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;
            Util.CheckResult(vkCreateBuffer(device.device, &bufferCreateInfo, null, out vkBuffer));

            // Create the memory backing up the buffer handle
            VkMemoryRequirements memReqs;

            vkGetBufferMemoryRequirements(device.device, vkBuffer, &memReqs);

            var hostVisible = usageHint == BufferMemoryUsageHint.Dynamic;

            memory = device.memoryAllocator.Allocate(memReqs, hostVisible);

            // Attach the memory to the buffer object
            Util.CheckResult(vkBindBufferMemory(device.device, vkBuffer, memory.vkDeviceMemory, memory.offset));
        }
Esempio n. 2
0
        /**
         * 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 VK_SUCCESS if buffer handle and memory have been created and (optionally passed) data has been copied
         */
        public VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, ulong size, VkBuffer *buffer, VkDeviceMemory *memory, void *data = null)
        {
            // Create the buffer handle
            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo(usageFlags, size);

            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;
            Util.CheckResult(vkCreateBuffer(LogicalDevice, &bufferCreateInfo, null, buffer));

            // Create the memory backing up the buffer handle
            VkMemoryRequirements memReqs;
            VkMemoryAllocateInfo memAlloc = Initializers.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);
            Util.CheckResult(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)
            {
                void *mapped;
                Util.CheckResult(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 & VkMemoryPropertyFlags.HostCoherent) == 0)
                {
                    VkMappedMemoryRange mappedRange = Initializers.mappedMemoryRange();
                    mappedRange.memory = *memory;
                    mappedRange.offset = 0;
                    mappedRange.size   = size;
                    vkFlushMappedMemoryRanges(LogicalDevice, 1, &mappedRange);
                }
                vkUnmapMemory(LogicalDevice, *memory);
            }

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

            return(VkResult.Success);
        }
Esempio n. 3
0
        private void TransferData(Image <Rgba32> tex2D)
        {
            using CommandBuffer copyCmd = device.GetCommandPool().Rent();

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

            copyCmd.Begin();

            // Create a host-visible staging buffer that contains the raw image data
            VkBuffer       stagingBuffer;
            VkDeviceMemory stagingMemory;


            var pixels    = tex2D.GetPixelSpan();
            var byteCount = (ulong)(pixels.Length * Unsafe.SizeOf <Rgba32>());

            VkBufferCreateInfo bufferCreateInfo = Initializers.bufferCreateInfo();

            bufferCreateInfo.size = byteCount;
            // This buffer is used as a transfer source for the buffer copy
            bufferCreateInfo.usage       = VkBufferUsageFlags.TransferSrc;
            bufferCreateInfo.sharingMode = VkSharingMode.Exclusive;

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

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

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

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

            // Copy texture data into staging buffer
            byte *data;

            Util.CheckResult(vkMapMemory(device.device, stagingMemory, 0, memReqs.size, 0, (void **)&data));

            fixed(Rgba32 *pixelDataPtr = &pixels[0])
            {
                Unsafe.CopyBlock(data, pixelDataPtr, (uint)byteCount);
            }

            vkUnmapMemory(device.device, stagingMemory);

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

            VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy();

            bufferCopyRegion.imageSubresource.aspectMask     = VkImageAspectFlags.Color;
            bufferCopyRegion.imageSubresource.mipLevel       = 0;
            bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
            bufferCopyRegion.imageSubresource.layerCount     = 1;
            bufferCopyRegion.imageExtent.width  = (uint)tex2D.Width;
            bufferCopyRegion.imageExtent.height = (uint)tex2D.Height;
            bufferCopyRegion.imageExtent.depth  = 1;
            bufferCopyRegion.bufferOffset       = offset;

            bufferCopyRegions.Add(bufferCopyRegion);

            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.vkCmd,
                image,
                VkImageAspectFlags.Color,
                VkImageLayout.Undefined,
                VkImageLayout.TransferDstOptimal,
                subresourceRange);

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

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

            copyCmd.End();
            device.FlushCommandBuffer(copyCmd);

            //device.flushCommandBuffer(copyCmd, copyQueue);

            // Clean up staging resources
            vkFreeMemory(device.device, stagingMemory, null);
            vkDestroyBuffer(device.device, stagingBuffer, null);
        }