3
$\begingroup$

When using Transform Feedback to capture the vertices generated by the primtive generation stage, we can use glDrawTransformFeedback to directly draw the generated data without the need for querying the number of generated primitives and thus without CPU-GPU synchronization, which is especially useful with geometry shaders generating a possibly unknown number of primitives.

However, in my case I'm not using the generated primitive data per-vertex, but per-instance (it's basically a classic GPU-based instance culling scenario). So I need to supply the number of generated primitives into the instance count parameter of glDraw...Instanced. But the various Transform Feedback rendering functions only ever use the primitive count as vertex count and never as instance count. Now this does require me to wait for the transform feedback to finish and get the result of the corresponding query object, thus instroducing a synchronization point.

I considered that I could also use the quite powerful Indirect Rendering functionality and together with a Query Buffer Object route the result of the transform feedback query directly into the instance count field of the draw indirect buffer. But this has the problem that I'm not only issuing a single glDraw...Instanced call, but multiple different ones (each with their own state, per-vertex attributes and draw parameters, but all with the same instance count and per-instance attributes). So I would actually have to scatter the query result into multiple drawing parameter sets (though, possibly in the same buffer), probably by use of a compute shader. But this just seems like overkill to me.

So my question is, is there any other less involved way to just use the number of primitives/vertices generated from transform feedback directly as the instance count in (preferably multiple different) instanced rendering commands without the need to explicitly query that count onto the CPU? In light of GPU-based scene culling techniques I can't imagine this to be a rare use-case (but maybe in that case you just have to go the way over indirect drawing commands anyway). I'm not afraid of using extensions if available, so maybe there's some obscure little extension that does exactly that? Or I'm just missing something else obvious here.

$\endgroup$
2
$\begingroup$

The complexity of this makes it seem like you don't really want to use transform feedback; you want to use a compute shader. Then, through indirect rendering and SSBOs, you can write whatever vertex commands data you want.

The idea is that you have some number of indirect rendering commands (one command per set of instances). And for each instance you create, the CS invocation needs to bump the instance count of each of those commands (atomically, of course).

Now, because there are state changes between the commands, you wouldn't be able to use a multi-draw indirect command. But by using indirect commands and a CS, you can at least keep all of the data on the GPU, without having to do things like buffer copies to multiple locations.

Transform feedback is merely an ad-hoc mechanism for something that modern OpenGL allows you to just do directly. If you need to broadcast the "primitive" count to multiple locations (or really, if you're doing anything besides rendering the feedbacked data), then you should be using a compute shader, not TF.

$\endgroup$
  • $\begingroup$ Thanks, and I guess it's reasonable advice. It just seemed too elaborate and I don't like to have entirely different approaches for 3 and 4 hardware when it's just a seemingly minor hurdle. $\endgroup$ – Christian Rau Jan 25 '18 at 18:18

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.