Geometry programs

Slightly offtopic : DirectX next was proposing something like this and that’s why I decided to post it here - OpenGL needs a counter-weapon [Razz]
Still, I’m very eager to know how they design it

Yea I know. That’s why I made this very same suggestions while ago.
If tesselation programs get into GPUs, the research will be done by MS, NV, ATI and university profs and grads. Exposing the functionality is then trivial.

The real work lies in designing the chip and making sure it’s worthwhile.

I’m pretty sure some years will pass before this idea becomes reality.

I’ve got a funny problem here, I wanted to post but I get

Sorry, we do not permit this HTML tag: Parenthesis in HTML tag

error. I don’t have any HTML in my post at all!

Use the code tag. You probably wrote square brackets, curly brackets or “bigger than” or “smaller than” sign.

Ok, I’ll try to bring my final idea together :slight_smile:

First of all, accessing an arbitrary array can be emulated via texture lookup with nearest filtering.
For my approach to work we’ll need:

  • unified memory model(textures and vertex data are areas of memory). Partially granted with GL 2.0, VBO and PBO
  • integer textures and integer datatypes within the GPU
  • full memory access within the shaders(for arrays and textures)
  • other will be added

We add two shader targets: primitive assembly shader and vertex assembly shader. The vertex assembly shader is a function that takes some arguments(the number and types of the arguments can be restricted to some minimal values) and outputs general vertex attributes – they will be then send to the vertex shader. An example:

uniform Vector3f vertices[];

attribute Vector3f position;
attribute Vector3f normal;
attribute Vector2f texcoord;


void main(float i, v) {
 position = ...
 normal  = ...
 texcoord = ...
}

A primitive assembly shader has a task of producing primitives. It has a special built-in function Vertex(…) that return values of datatype Vertex. Vertex( … ) has the same arguments as the main() of the bound vertex assembly shader and the return value uniquely identifies the produces vertex data(as output by vertex primitive shader).
Another built-in functions are glBegin(int primitive_type), glEnd() and glYieldVertex(Vertex v). It is reasonable to restrict primitive type to GL_PONT_SPRITE, GL_LINE and GL_TRIANGLE. Other triangle types can be output as triangles

Example(only an example, it doesn’t do anything meaningful :slight_smile: ):

uniform int N;
uniform int M;

void main() {

glBegin(GL_TRIANGLES);

for(int v = 0; v < N; v++)
 for(int i = 0; i < M; i++) {
  Vertex v1 = Vertex(i/M, v/N);
 glYieldVertex(v1);
}

 glEnd();
}

Putting it all together:

it it taken by default, that vertex assembly shader has higher latency then the primitive assembly shader(as it has to do more work). It would be meaningful to have only one fast unit to process the primitive assembly shader but to split the vertex generation onto multiple units. The vertex handle returned by Vertex() function will grant a simple but effective cashing mechanism(the nice think about it – it would be fully user-dependent, no or just simple dedicated hardware needed to support it). Such architecture will be most flexible but also most performance-friendly. Moreover, any WGF 2.0 DirectX Next compliant hardware with unified shader architecture would be compatible with my approach(it will only need an additional unit as primitive assembly shader) as shader units could be used to implement the vertex generation.

The possible usage can be almost everything related to surface generation. Notice that this mechanism will replace OpenGL geometry specifying functions as it can implement all functions like glDrawElements or glDrawArray

Well, something like that :slight_smile: I’m looking forward to your critics :slight_smile:

p.s. hey thanks v-man - it worked out! :wink:

Zengar, your vertex assembly shader looks very much like a regular vertex shader. I don’t see the point there.
Currently, vertex shader hw can have integers and can access textures, as you may know already.

What causes it to execute?

In the primitive assemly stage, what causes it to get called?

These are important points you don’t explain or somehow I missed it.

Sorry about the late reply. About the post where I mumbled “vertex program” a number of times, I’ll just straigthen out T101’s question mark. Yes, GP must obviously be placed before VP. If for nothing else to be able to be implemented in software.

V-man however adds a question I find interesting: “What causes it to execute?”.

Assuming we have a remote server able to do this (be it a gfx card or a remote server over GLX), we’d first have to send it one of two things. either a precompiled blob (to some kind of platform-independent bytecode, making the language very rigid and hard to extend during these testing/prototyping stages) or the plaintext GP. I’m at least initially in favor of the latter and completely against the former.

We’d then have to have a way to execute them. Now, what mechanism is most closely resemble these steps? To me, display lists seems to be the best match to model this new functionality from.

So we’d need three new functions, as I see it currently:

  • Generate new name (to be able to e.g. replace an existing GP with some new code).
  • Upload GP to server.
  • Execute GP.

As this is brand new functionality, I suggest new entry points (I don’t take this lightly, but the added functionality validates, even neccessitates the addition of entry points I think).

One thing I still find possibly missing is the ability to send along some extra data to the server with the “execute” call. Say we want to tell the GP “LOD level 3, using textures 4711, 42 and 7” (whatever that means is up to the GP and application).

One could argue “put that data in a vertex stream, or a texture or…”. But they would still be only emulators of a function call argument list, and they would likely be very slow compared to the potentially short-lived and per/frame data we want to send the GP.

The only solution I see to this is to use a vector version of the execute call, with … GLuint’s? Naturally then comes the argv/argc paradigm (even if by different names) for the GP itself.

I don’t know, I’m just throwing around some ideas that struck me and seemed to make sense at the time of writing.

Originally posted by tamlin:
But they would still be only emulators of a function call argument list, and they would likely be very slow compared to the potentially short-lived and per/frame data we want to send the GP.
No. There is a fundamental difference between passing function call arguments or setting uniforms and using an input data stream.

Uniform variables and function call arguments are very similar. You can easily emulate parameters by setting a uniform and you can just pass more parameters instead of using uniforms, so they are functionally equivalent.

Input streams are another story. You send lots of similar data that could potentially be processed in parallel. It could also benefit from something similar to vertex arrays. It’s nothing you can archieve with only parameters and uniforms, and you can’t realize parameters and uniforms with an input stream, so these two are completely different.

Also I don’t see why function call arguments would be any faster or slower then any other method. After all it’s just a syntactical difference if I write it in parenthesis next to main or with the uniform keyword above main.

Originally posted by Overmind:
You can easily emulate parameters by setting a uniform and you can just pass more parameters instead of using uniforms, so they are functionally equivalent.
You’re right. I was thinking of potential benefits from ease-of-use for callers. Perhaps the uniform mechanism is better.

However, reusing that for GP’s would put GP ID’s in the same namespace as other program ID’s. OK, GLuint is likely more than enough to hold more program ID’s of all possible different types from here to kningdom come, so namespace exhaustion isn’t likely a concern. I still have dubts it’s really healthy putting GP programs in the same namespace, though.

Maybe I’m just overly cautious. Anyway, I’m really just throwing ideas into the air to see if any ends up useful. Thanks for the feedback.

Sorry for a long pause, I was at vacations

Originally posted by V-man:
[b]
In the primitive assemly stage, what causes it to get called?

These are important points you don’t explain or somehow I missed it.[/b]
The vertex shader cat’s executed when an assemly program invokes the Vertex(…) function.
The assemly program can e invoked by an new command like glPrimitiveAssemly(…). If a primitive assemlby program is bound than the execution will be transferred to it, otherwise an error will occure

A use case I have not seen mentioned for Geometry programs is instancing. Such a program could generate a single instance at a time when passed the required positional/rotational data. It could generate thousands of instances at once if supplied with a block of memory (a texture for you pixel shader coders). It could even procedurally generate a user-supplied number of objects each with its own skeletal pose, rotation, etc. (You can design an algorithm that will produce repeatable results across frames.)

The generation of trees, plants, grass, and other foilage would be made much more efficient this way. You could have millions (billions? depends on the hardware acceleration) of such objects with zero memory or host-to-GPU overhead.

-Raystonn