Vertex Shader Scatter via gl_VertexIDOut and Transform Feedback

Hello there.

I am just wondering if it isn’t trivially possible to implement functionality to scatter an output vertex to some arbitrary position into a transform feedback bound buffer via a vertex shader for OpenGL 3 Core?!

I use TF currently like this:


// Single vertex shader with transform feedback, pseudo:
in in_vert ;
out out_vert ;

void main()
{
    // maps input_buffer[gl_VertexID] -> output_buffer[gl_VertexID]
    out_vert = in_vert ;
}

This means, I map input vertices with gl_VertexID to the output buffer where that vertex is placed on index gl_VertexID.
That just works fine.

Now the question is, wouldn’t it be possible to do something like this


// Single vertex shader with transform feedback, pseudo:
in in_vert ;
out out_vert ;

int f( int id ){... do some mapping... }

void main()
{
    // default: gl_VertexIDOut = gl_VertexID
    gl_VertexIDOut = f(gl_VertexID) ;
    // maps input_buffer[gl_VertexID] -> output_buffer[gl_VertexIDOut]
    out_vert = in_vert ;
}

So that the currently processed vertex does not go to position gl_VertexID but to position gl_VertexIDOut.
That would also be coincident with gl_PrimitiveIDIn and gl_PrimitiveID.

I use texture buffers a lot and there would be tons of applications which could use that functionality because those application are not requiring the rasterizer nor any fragment shader invocation.

If such thing would be possible, that would be GPGPU like hell :wink: or maybe totally like :doh:

So long.

To get random writes, the only thing is GL4 hardware feature: GL_ARB_shader_storage_buffer_object found in GL core 4.3 and above. As for GL3, not that I know of.

Now the question is, wouldn’t it be possible to do something like this

Um, no.

That would require:

1: That a vertex shader knows that it’s writing to transform feedback, rather than to the rasterizer. They don’t. At link time, they know that they can write to TF, but it’s perfectly legal to use shaders with TF params without actually storing the values.

2: That TF makes any form of sense when writing arbitrarily to the buffer, rather than in incrementing values. It doesn’t. How would you even know how many primitives had been collected into a feedback buffer if you have random writes? Indeed, what does random vertex writing even mean? Remember: TF writes primitives, not vertices. So unless you’re drawing GL_POINTS (and only a GS can enforce that), it doesn’t make sense to randomly write anything. Vertex shaders operate on vertices, not primitives.

To get random writes, the only thing is GL4 hardware feature: GL_ARB_shader_storage_buffer_object found in GL core 4.3 and above.

Nonsense. Image Load/Store does random writes just fine. SSBOs are really just a nicer-looking form of buffer texture load stores.

In my opinion, that would make a lot of sense unless you dont know the mapping. You are just thinking too … linear, Alfonse. But you are right, Im just talking about points. So it would be:

  • use GL_POINTS as data items
  • disable raster
  • set TF buffer

Since I dont have any further understanding of the technical aspect within the GL, I just leave it by that. I was just curious.

No, you are thinking too… non-sense. Transform feedback is what it is. It is not scattered write functionality. ARB_shader_image_load_store and ARB_shader_storage_buffer_object is scattered write functionality.
Transform feedback is meant to feed back transformed primitives. Makes sense, right?

Alfhonse is right, GL_ARB_shader_image_store allows one to get random writes to a buffer object via imageBuffer types. Wonder what caused that brain fart of mine.

No, you are thinking too… non-sense. Transform feedback is what it is. It is not scattered write functionality. ARB_shader_image_load_store and ARB_shader_storage_buffer_object is scattered write functionality.
Transform feedback is meant to feed back transformed primitives. Makes sense, right?

Now, that statement is like no statement. You could even have written nothing. Would be as good as that.

Except Alfonse, the other posters dont really contribute to the discussion, since those posters, except Alfonse, dont read the original post. I can not see any point in it where I am talking about ARB_shader_image_load_store. So much to that. You just want to ++Posts :wink:

Ok, since there are always people who claim to know everything best, like aqnuep, can someone explain a bit more precisely, why it matters for the vertex shader know about that it is writing into a tf buffer? All the vertex shader is doing, is to pass through the vertices. From input to output. Now, where is the difference in having the vertex shader put a vertex to a specific position?

If that doesnt make sense, than something like a load/store would also make no sense. It would be exactly the same but doable with transform feedback.

Only because you can not image use-cases for that doen’t mean it “makes no sense”. That is all I want to say.

My biggest concern is that too many people post too much crap. Like aqnuep. I just wanted to participate is a discussion about what would be possible and not about telling people that they are stupid, because something does “make no sense”. I will not post anything here anymore. Those two liners are, thinking knowing everything make me ill. Or people like aqnuep. Putting “Disclaimers” in their foot-line about what crapy things they are posting is only “personal profile”. Now that “Disclaimer” makes no sense in what so ever. This is like a disclaimer of an 10 year old, like your posts.

Ok, since there are always people who claim to know everything best, like aqnuep, can someone explain a bit more precisely, why it matters for the vertex shader know about that it is writing into a tf buffer? All the vertex shader is doing, is to pass through the vertices. From input to output. Now, where is the difference in having the vertex shader put a vertex to a specific position?

If the operations were performed by a CPU, you’d be right. But they are not. Indeed, transform feedback started at GL3, not GL2. It essentially comes down to the issue of what is fixed function and what is programmable on a GPU. There are plenty of bits on a GPU that are not programmable:

[ul]
[li]Rasterization. One can specify to rasterize triangles, lines and point sprites. The rasterizer is a very fixed funtional bit of jazz.[/li][li]Texturing. For texture filtering, one can specify nearest vs bilinear, with mipmaps or not and how to apply them along with anisotropic filtering [and the latter does not have formally defined spec, just a hint system].[/li][li]Blending. Lots of hardware has dedicated bits to do blending that have very fixed-function capability[/li][/ul]

Although the hardware is quite programmable, lots of bits of it are fixed function.

About your idea, what you essentially want is the ability to specify a value and an offset into the buffer where to write the value. As for why GL3 hardware cannot do it, it comes down to what GL3 GPU one is talking about. My bet is that transform feedback is like a switch; under normal jazz, the values are buffered some and then sent to the rasterizer, under transform feedback the buffer writes to a buffer object and likely the little bits of hardware that do the actual writing are not very flexible. Going further, by knowing that the writes to the buffer object are continuous, that makes flushing it back to VRAM (or RAM for unified) loads easier too; it is oodles easier to implement it so that it performs better. Perfect candidate for hardware implementation: simple and by making it fixed faster.

Going further, when I look at the evolution of the hardware capabilities: GL2 to GL3 to GL4, a great of the advances have come in more flexible memory access. GL3 through transform feed back gave ability to feedback values from GL back to buffers and both texture buffer and uniform buffer objects gave more flexible read access from buffer objects [where as before they could only be used as attribute sources]. GL4 generation hardware gave the ability for random writes to texture and buffer objects; before where and how to write was very predictable: buffer objects only could be written by transform feedback or by setting the data by the CPU and textures by setting the data by CPU or rendering to them…now full blown random access.

As a side note, GL_ARB_shader_image_store and the buffer object one need to be used with care; poor use of them can have unpleasant effects on performance.

I think it is worth saying: most GL3 hardware supports a real GPGPU solution like OpenCL or CUDA. If you want GPGPU scatter-writes, use one of the existing solutions.

noopnoop, I didn’t know you are such a great expert of OpenGL, so please enlighten me how your “scattered transform feedback” would interwork with different primitive types, features like GL_PRIMITIVES_GENERATED and GL_TRANSFORM_FEEDBACK_PRIMITIVES queries, or with glDrawTransformFeedback, because I’m apparently too ignorant to comprehend it.

Also, I’m sorry for incorrectly taking the definition of transform feedback from the OpenGL specification, my bad:

In transform feedback mode, attributes of the vertices of transformed primitives passed to the transform feedback stage are written out to one or more buffer objects.

Finally, I want to apologize for directing you to check ARB_shader_image_load_store and ARB_shader_storage_buffer_object if you are interested in scattered write functionality, apparently you also know those features better than me, because I thought those features are already in OpenGL and allow scattered writes from the vertex shader.

All the vertex shader is doing, is to pass through the vertices. From input to output. Now, where is the difference in having the vertex shader put a vertex to a specific position?

Where is the difference? You just said the difference; it’s right there in your post.

Currently, vertex shaders pass vertices “from input to output”. This means that they have no knowledge of a “specific position”. All they know is that they received a set of inputs, and will be writing a set of outputs. They neither know nor care where those outputs are going. The “position” of a vertex is defined by the rendering pipeline.

So if a VS is going to write to a “specific position”, the VS now must have the concept of a position. Which it currently does not.

There is a reason why VS’s can’t generate vertices, why they can’t cull vertices. Why the only thing a VS can do is transform a vertex “from input to output”. That’s what a VS is for. For other things, we have Geometry Shaders.

If that doesnt make sense, than something like a load/store would also make no sense. It would be exactly the same but doable with transform feedback.

… what?

You know that Image Load/Store is not actually possible on OpenGL 3.x-class hardware, right? That’s a feature of 4.x hardware. So you seem to be arguing with yourself, since you want this scattered write TF feature in 3.x hardware… where it generally isn’t possible.

Also, his “makes no sense” isn’t about the idea of scattered writes itself; it’s about the idea of scattered writes using Transform Feedback. Scattered writing is good functionality, when needed. But scattered writes have no place in transform feedback.

Only because you can not image use-cases for that doen’t mean it “makes no sense”. That is all I want to say.

Um, no. It makes no sense because it makes no sense. It runs contrary to the basic functioning of the rendering pipeline.

I am going to port gasoline on this fire… just for fun. There is a way, sort of, to do random write transform feedback with even GL2 generation jazz, but it kind of feels silly:
[ol]
[li]Render to MRT point sprites of radius so that exactly one pixel is hit[/li][li]Specify “where” in the buffer objects one wishes to write by in the vertex shader setting the value of gl_Position[/li][li]Read back the values from the MRT color buffers into one’s buffer objects[/li][/ol]

Essentially, “render points” to color buffers, each color buffer packing an output of the vertex shader to stage. The color buffer should be GL_RGBA32F (or GL_RGB32F, GL_RG32F or GL_R32F). Then do glReadPixel with a buffer object bound to GL_PIXEL_PACK_BUFFER to read the values into a buffer object. You’ll have to be very careful about the value you set gl_Position as to make sure only one pixel is hit and exactly where you want it to be read into the buffer object after the “render”, but this should work, and I have memory that this was a strategy at one point in time too.

I admit that this feels awkward though.