1
\$\begingroup\$

for a vulkan renderer using vulkan-hpp and Vulkan Memory Allocator I am trying to transfer vertex data to the gpu using a staging buffer. Without using an intermediary staging buffer the transfer works and the meshes can be rendered with no problems (just a single buffer created with VMA_MEMORY_USAGE_CPU_TO_GPU). But with the call to vkCmdCopyBuffer the resulting vertexBuffer only contains 0s (checked with NSight). Thinking that synchronisation using barriers might be required I tried the following code, but still have the same problem.

Maybe there is a need to synchronize the command buffer doing the copy with the later command buffer binding and sourcing from the vertex buffer? Although I didnt see this done or mentioned in any tutorials I came across.

// 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();
\$\endgroup\$
1
\$\begingroup\$

It is fixed. The third argument to copybuffer was not being correctly initialized. The correct call should be like this:

cmd.copyBuffer(stagingBuffer, vertexBuffer, {{ 0, 0, vertexBufferSize }});

The line

cmd.copyBuffer(stagingBuffer, vertexBuffer, { 0, 0, vertexBufferSize });

actually creates three distinct copy regions.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.