In-Order output from a geometry shader

Started by
4 comments, last by theremin 16 years, 10 months ago
So, I'm trying to implement fractal trees using L-Systems with as little CPU intervention as possible. Without getting too deep into the theory, I want to do the following using geometry shaders: Take array A of vertices: A = [a, b, c, d] Pass each vertex of the array to its own geometry shader thread, and stream the output into array B. Each input vertex will output some number of vertices. B = [a0, a1, a2, b, c0, c1, d] In this example, a became 3 verts, b remained 1 vert, c became 2 verts, and d remained 1. All of a's children must precede all of b's children, b's children must precede c's, etc. What's the best way to do this, with as little CPU intervention as possible?
Advertisement
(breaking this up to keep it readable)

If geometry shaders don't "just work" like that, here's a fact that may help:
It is possible to know the number of verts each particular vertex will output.

However, this doesn't help "d" know where to going unless it peeks at "c" "b" and "a".

I see that I could run through the verts in A with the CPU, keeping track of the cumulative offset, and use one draw call per vertex with the proper offset into B. However, this takes so much GPU-CPU synchronization I may as well do the whole thing on the CPU.

I'd like to get away with only one draw call on A.
It is my understanding (from practical experience and the official specs) that the stream out buffer stores the geometry in the exact same order in which it was appended from the geometry shader. You can verify this with PIX quite easily.

What do you mean by "geometry shader thread"? The micro-operations that a shader performs are run in parallel across the card's computing units automatically.

Niko Suni

Sorry, this is going to be my first geometry shader so I'm not up on the exact language. By "geometry shader thread," I meant each vertex will be processed in its own instance of the shader program; like each fragment of a triangle is processed by its own instance of a fragment shader.

In extreme pseudocode:
A = [a, b, c, d]GeometryShader(A) -> leads to 4 instances of shader...  shader(a) -> a0, a1, a2  shader(b) -> b  shader(c) -> c0, c1  shader(d) -> d-> stream output from shaders to buffer B

I'm concerned my output buffer is going to look like this:
B = [a0, b, d, a1, c0, a2, c1]

when I want this:
B = [a0, a1, a2, b, c0, c1, d]

[Edited by - theremin on May 24, 2007 4:48:13 PM]
I checked the SDK again, and found this:

Quote:
Microsoft DirectX SDK April 07, topic "Shader Stages (Direct3D 10)":

"Execution of a geometry shader instance is atomic from other invocations, except that data added to the streams is serial. The outputs of a given invocation of a geometry shader are independent of other invocations (though ordering is respected). A geometry shader generating triangle strips will start a new strip on every invocation."


If the graphics system respects this (and it should, by specification), then the order of the output geometry array corresponds exactly with the input order like I said - thus, your problem is non-existent.

That said, you can use PIX and verify this yourself. Just pass a primitive id from the VS to the GS and observe the resulting outputs to confirm that the output primitives are indeed in the correct order.

I'm not sure about the OpenGL implementation, though, haven't used GS from it yet.

Niko Suni

Confirmed: My problem was non-existent. I'm pumping in a huge amount of data, with varying output from each vertex, and it all comes out in order. This is using the NVidia's extensions for the OpenGL geometry shader.

Thanks a lot!

This topic is closed to new replies.

Advertisement