CPU Readback Synchronization

Started by
1 comment, last by Batzer 5 years ago

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!

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!

This topic is closed to new replies.

Advertisement