//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)); }
/** * 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); }
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); }