Jump to content
  • Advertisement
Sign in to follow this  
Batzer

Vulkan CPU Readback Synchronization

Recommended Posts

Hello everyone,

I'm currently trying to get CPU readback to work in Vulkan and I'm having issues getting the snychronization to work properly. I want to use the results of a subpass on the CPU. so what I do right now is copy the render target image to a staging buffer and map that buffer and simply memcpy the contents. My idea was to use a VkEvent to signal when the copy to the staging buffer has finished on the GPU so the CPU knows when to start copying valid data. However, I'm not sure if this the correct way to do it or if a VkFence is the correct choice here and if I need memory barriers or not. In addition, I of course want multiple staging buffers in flight at the same time so the CPU doesn't keep the GPU waiting and I'm not sure how to know which buffers are ready to be written to again.

I'm very new to low-level GPU programming and I keep getting my GPU to crash the system, so I would be very grateful if somebody could clear things up for me :)

Thanks!

Share this post


Link to post
Share on other sites
Advertisement

I seem to have gotten it to work now. I'm using N events that belong to N staging buffers. When staging buffer A is filled on the GPU then event A is signaled on the GPU as well. On the CPU I check if event B has been signaled already. If not then I either wait or just coninue without reading back the data, depending on if the buffer I'm trying to readback this frame will be overwritten the next frame by the GPU. This I have at max N frames delay when reading the data from the GPU, but can run everything at full speed without waiting too often. I'm pretty sure by now that the same behavior can be implemented by using fences, but it would be less fine-grained since events can be signaled at any time in a command buffer, and thus directly after the data is ready to be read.

Here is some pseudo-code:

renderSomeStuff();
commandBuffer.copyImageToBuffer(framebuffer, stagingBuffers[writeIndex]);
commandBuffer.signalEvent(events[writeIndex]);
writeIndex = (writeIndex + 1) % NumBuffers;

if (writeIndex == readIndex) {
	waitForEvent(events[readIndex]); // CPU side wait
}

if (events[readIndex].status == SIGNALED) {
	readback(stagingBuffers[readIndex]);
	events[readIndex].reset(); // CPU side reset
	readIndex = (readIndex + 1) % NumBuffers;
}

I'd still be grateful if somebody has a better solution!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!