What's the best way to sample one point from a texture using Vulkan?

Viewed 94

I've read through this question but it seems the solution to that is to draw a full-screen quad. Sampling a texture shouldn't involve vertex input or the rasteriser at all, it's just reading a value from a buffer/image. I want to do screen picking and I've thought about a couple of ways to do this, but they all involve first rasterising the scene objects onto a picking buffer and writing the object ID's. With the help of the depth buffer the final value should be the topmost object. After the first part of rendering into the picking buffer/image is done I then need to sample the value at the mouse coordinates/position. I can either read the entirety of the picking buffer back to host and sample it in my C++ code or I can have a shader that specifically samples an image at a particular point. Can this be done in a compute shader? I send in a point value and the shader samples the texture. There shouldn't be any need for the graphics pipeline to simply sample an image.

1 Answers

You can use vkCmdCopyImage or vkCmdCopyImageToBuffer to copy a pixel's worth of image data to CPU-accessible memory. Of course, it's not that simple.

Each queue has its own rules about the granularity of image copies. Indeed, some queues can forbid you from copying anything less than an entire mipmap level. So you may have to copy more than you're interested in and pick out the exact data you intended.

And as with everything else in Vulkan, there needs to be some sort of memory barrier between the process which generated the data and the transfer operation. And since this is a command, it gets recorded into a command buffer that you have to submit. And after submissions, you'll need synchronization (and possibly invalidation) between the transfer operation and the host operation which tries to read the data. This could be an event (for fine-grained control) that the host checks or a fence.

And of course, this has to be after the render pass is over.

Can this be done in a compute shader?

Yes, you could do that. Assuming that your implementation allows you to have SSBOs that are stored in host-accessible memory. But you'll still have to deal with all of the synchronization this entails.

This would be particularly useful if your queue forces you to copy entire mipmap levels.

Related