vkCmdCopyBuffer 对暂存缓冲区的传输没有影响
vkCmdCopyBuffer has no effect for transfer of staging buffer
对于使用 vulkan-hpp 和 Vulkan 内存分配器的 vulkan 渲染器,我正在尝试使用暂存缓冲区将顶点数据传输到 gpu。
在不使用中间暂存缓冲区的情况下,传输工作正常并且可以渲染网格
没有问题(只是用 VMA_MEMORY_USAGE_CPU_TO_GPU 创建了一个缓冲区)。
但是通过调用 vkCmdCopyBuffer,生成的 vertexBuffer 只包含 0(使用 NSight 检查)。
考虑到可能需要使用障碍进行同步我尝试了以下代码,但仍然有同样的问题。
也许需要将执行复制的命令缓冲区与后来的命令缓冲区绑定和从顶点缓冲区获取同步?尽管我在遇到的任何教程中都没有看到或提到过这一点。
// vulkan initialization
// VmaAllocator initialization
std::vector<Vertex> vertices = { /*filled*/ };
auto vertexBufferSize = vertices.size() * sizeof(Vertex);
vk::Buffer stagingBuffer;
auto ci = vk::BufferCreateInfo().
setUsage(vk::BufferUsageFlagBits::eTransferSrc).
setSharingMode(vk::SharingMode::eExclusive).
setSize(vertexBufferSize );
VmaAllocationCreateInfo allocationCI = {};
allocationCI.usage = VMA_MEMORY_USAGE_CPU_ONLY;
vmaCreateBuffer(allocator, (VkBufferCreateInfo*)&ci,
&allocationCI, (VkBuffer*)&stagingBuffer, &allocation, nullptr);
void* pVBufMem = nullptr;
vmaMapMemory(allocator, allocation, &pVBufMem);
std::memcpy(pVBufMem, vertices.size(), vertexBufferSize );
vmaUnmapMemory(allocator, allocation);
vk::Buffer vertexBuffer;
ci = vk::BufferCreateInfo().
setUsage(vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer).
setSharingMode(vk::SharingMode::eExclusive).
setSize(vertexBufferSize);
allocationCI = {};
allocationCI.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateBuffer(allocator, (VkBufferCreateInfo*)&ci,
&allocationCI, (VkBuffer*)&vertexBuffer, &allocation, nullptr);
// copy staging buffer to vertex buffer
auto allocCI = vk::CommandBufferAllocateInfo().
setCommandBufferCount(1).
setCommandPool(pool).
setLevel(vk::CommandBufferLevel::ePrimary);
auto cmd = device.allocateCommandBuffers(allocCI)[0];
cmd.begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
// barrier host write -> copyBuffer read
auto bufferMemoryBarrier = vk::BufferMemoryBarrier()
.setBuffer(stagingBuffer)
.setSize(vertexBufferSize)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryWrite)
.setDstAccessMask(vk::AccessFlagBits::eTransferRead)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
cmd.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {},
{ }, { bufferMemoryBarrier }, { });
cmd.copyBuffer(stagingBuffer, vertexBuffer, { 0, 0, vertexBufferSize });
// copyBuffer write -> vertex read
bufferMemoryBarrier = vk::BufferMemoryBarrier()
.setBuffer(vertexBuffer)
.setSize(vertexBufferSize)
.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
.setDstAccessMask(vk::AccessFlagBits::eVertexAttributeRead)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
cmd.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {},
{ }, { bufferMemoryBarrier }, { });
cmd.end();
auto submitInfo = vk::SubmitInfo().
setCommandBufferCount(1).
setPCommandBuffers(&cmdBuffer);
queue.submit({ submitInfo }, {});
queue.waitIdle();
已修复。 copybuffer 的第三个参数未正确初始化。正确的调用应该是这样的:
cmd.copyBuffer(stagingBuffer, vertexBuffer, {{ 0, 0, vertexBufferSize }});
行
cmd.copyBuffer(stagingBuffer, vertexBuffer, { 0, 0, vertexBufferSize });
实际上创建了三个不同的复制区域。
对于使用 vulkan-hpp 和 Vulkan 内存分配器的 vulkan 渲染器,我正在尝试使用暂存缓冲区将顶点数据传输到 gpu。 在不使用中间暂存缓冲区的情况下,传输工作正常并且可以渲染网格 没有问题(只是用 VMA_MEMORY_USAGE_CPU_TO_GPU 创建了一个缓冲区)。 但是通过调用 vkCmdCopyBuffer,生成的 vertexBuffer 只包含 0(使用 NSight 检查)。 考虑到可能需要使用障碍进行同步我尝试了以下代码,但仍然有同样的问题。
也许需要将执行复制的命令缓冲区与后来的命令缓冲区绑定和从顶点缓冲区获取同步?尽管我在遇到的任何教程中都没有看到或提到过这一点。
// vulkan initialization
// VmaAllocator initialization
std::vector<Vertex> vertices = { /*filled*/ };
auto vertexBufferSize = vertices.size() * sizeof(Vertex);
vk::Buffer stagingBuffer;
auto ci = vk::BufferCreateInfo().
setUsage(vk::BufferUsageFlagBits::eTransferSrc).
setSharingMode(vk::SharingMode::eExclusive).
setSize(vertexBufferSize );
VmaAllocationCreateInfo allocationCI = {};
allocationCI.usage = VMA_MEMORY_USAGE_CPU_ONLY;
vmaCreateBuffer(allocator, (VkBufferCreateInfo*)&ci,
&allocationCI, (VkBuffer*)&stagingBuffer, &allocation, nullptr);
void* pVBufMem = nullptr;
vmaMapMemory(allocator, allocation, &pVBufMem);
std::memcpy(pVBufMem, vertices.size(), vertexBufferSize );
vmaUnmapMemory(allocator, allocation);
vk::Buffer vertexBuffer;
ci = vk::BufferCreateInfo().
setUsage(vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer).
setSharingMode(vk::SharingMode::eExclusive).
setSize(vertexBufferSize);
allocationCI = {};
allocationCI.usage = VMA_MEMORY_USAGE_GPU_ONLY;
vmaCreateBuffer(allocator, (VkBufferCreateInfo*)&ci,
&allocationCI, (VkBuffer*)&vertexBuffer, &allocation, nullptr);
// copy staging buffer to vertex buffer
auto allocCI = vk::CommandBufferAllocateInfo().
setCommandBufferCount(1).
setCommandPool(pool).
setLevel(vk::CommandBufferLevel::ePrimary);
auto cmd = device.allocateCommandBuffers(allocCI)[0];
cmd.begin({ vk::CommandBufferUsageFlagBits::eOneTimeSubmit });
// barrier host write -> copyBuffer read
auto bufferMemoryBarrier = vk::BufferMemoryBarrier()
.setBuffer(stagingBuffer)
.setSize(vertexBufferSize)
.setSrcAccessMask(vk::AccessFlagBits::eMemoryWrite)
.setDstAccessMask(vk::AccessFlagBits::eTransferRead)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
cmd.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {},
{ }, { bufferMemoryBarrier }, { });
cmd.copyBuffer(stagingBuffer, vertexBuffer, { 0, 0, vertexBufferSize });
// copyBuffer write -> vertex read
bufferMemoryBarrier = vk::BufferMemoryBarrier()
.setBuffer(vertexBuffer)
.setSize(vertexBufferSize)
.setSrcAccessMask(vk::AccessFlagBits::eTransferWrite)
.setDstAccessMask(vk::AccessFlagBits::eVertexAttributeRead)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED);
cmd.pipelineBarrier(
vk::PipelineStageFlagBits::eAllCommands, vk::PipelineStageFlagBits::eAllCommands, {},
{ }, { bufferMemoryBarrier }, { });
cmd.end();
auto submitInfo = vk::SubmitInfo().
setCommandBufferCount(1).
setPCommandBuffers(&cmdBuffer);
queue.submit({ submitInfo }, {});
queue.waitIdle();
已修复。 copybuffer 的第三个参数未正确初始化。正确的调用应该是这样的:
cmd.copyBuffer(stagingBuffer, vertexBuffer, {{ 0, 0, vertexBufferSize }});
行
cmd.copyBuffer(stagingBuffer, vertexBuffer, { 0, 0, vertexBufferSize });
实际上创建了三个不同的复制区域。