Writing to an element VBO via geometry shader

Hello,
I would like to tessellate some geometry in the geometry shader. I realize geom shaders aren’t ideal for this, and that a new shader is likely to emerge as a “tessellation shader”, but for now, I am using the geometry shader, along with transform feedback. It would be nice to write out indices to an element VBO, in addition to geometry that I’m writing to the vertex attribute VBO, but it looks as though at the moment I can only write to a vertex attribute VBO, forcing me to use glDrawArrays() on the result. Is this correct, or is there some relatively straightforward way to write to the element VBO also, such that I can use glDrawElements() again? I didn’t see anything in the spec, but perhaps there is a good reason, or something. Thanks.

A simple tessellation with displacement mapping is easy with geometry shaders. I’ve wrote some examples http://lumina.sourceforge.net/index.php?id=29

The problem is the dynamic recursive tessellation, because the optimal output type are triangle stripes and not single triangles.

With the transform feedback it’s not a problem, because the geometry shader has only 2 cases to handle:
Triangle is to large: Tesselate into 4 or 9 new parts.
Triangle is to small: Don’t tessellate it.

The influence of the displacement map is depend on the distance of two vertices, so the a T intersection has no holes…

Originally posted by oc2k1:
[b] A simple tessellation with displacement mapping is easy with geometry shaders. I’ve wrote some examples http://lumina.sourceforge.net/index.php?id=29

The problem is the dynamic recursive tessellation, because the optimal output type are triangle stripes and not single triangles.

With the transform feedback it’s not a problem, because the geometry shader has only 2 cases to handle:
Triangle is to large: Tesselate into 4 or 9 new parts.
Triangle is to small: Don’t tessellate it.

The influence of the displacement map is depend on the distance of two vertices, so the a T intersection has no holes… [/b]
Thanks for your response, but it doesn’t have much to do with my question. I have a geometry shader doing displacement mapping, I would just like to be able to generate indexed primitives in the geometry shader, and output them directly to an element VBO, along with the vertex data I already output to a vertex attribute VBO. Then I could call glDrawElements() (or similar) using the resultant VBOs. Without an element VBO, I have to call glDrawArrays() directly, since I have no indices, and thus I can’t take advantage of the T&L cache, I store vertex data redundantly, etc.

It seems pretty clear that this isn’t something you can currently do (at least not easily). But I am still curious what other peoples’ thoughts are on the subject.

Without an element VBO, I have to call glDrawArrays() directly, since I have no indices, and thus I can’t take advantage of the T&L cache, I store vertex data redundantly, etc.
First, your second pass (likely) isn’t doing any T&L. So the post-T&L cache itself isn’t helping much. Any performance benefit would be from not reading so much from the buffer object.

Second, geometry shaders don’t really have the ability to do complicated things like triangle stripping. And they can’t do vertex reduction, where they detect that a vertex was already written and thus don’t write another.

Third, I don’t think geometry shaders will be able to do stuff like that in the near future. Maybe in the future when shaders have an actual stack and can do real recursion, we will see something like that. But the fundamental precept of all shaders of any kind is that they are independent of parallel operations. That is, two geometry shader instances running on separate primitives can exists. They cannot pass information between them, so it would be difficult to know a priori if a prior shader actually wrote a vertex or what that index would be.

Fourth, unless your tessellation is dynamic, it’s entirely possible to know beforehand what the vertex layout is going to be and create an index buffer for that.

Originally posted by Korval:
First, your second pass (likely) isn’t doing any T&L. So the post-T&L cache itself isn’t helping much. Any performance benefit would be from not reading so much from the buffer object.
Ah yes, that’s true about the T&L cache (thanks for pointing that out), but still, the difference in buffer sizes could be non-negligible for large geometry.

Second, geometry shaders don’t really have the ability to do complicated things like triangle stripping. And they can’t do vertex reduction, where they detect that a vertex was already written and thus don’t write another.
I realize geometry shaders aren’t ideal for this task, which is why I put the disclaimer in my original post. Despite this, they are working out quite nicely thus far in conjunction with transform feedback. It just seemed like it would be nice to be able to write out a pool of verts, plus some connectivity, rather than having to explicitly (re)write out all the vertices for each tessellated triangle. But I can see how this goes against the way the plumbing currently works for geometry shaders.

Third, I don’t think geometry shaders will be able to do stuff like that in the near future. Maybe in the future when shaders have an actual stack and can do real recursion, we will see something like that. But the fundamental precept of all shaders of any kind is that they are independent of parallel operations. That is, two geometry shader instances running on separate primitives can exists. They cannot pass information between them, so it would be difficult to know a priori if a prior shader actually wrote a vertex or what that index would be.
I agree. I can live with some redundancy, it would just be nice to reduce some of it within a given geometry shader run. Also, I’ve heard that there will possibly be a fourth shader type that is designed for this task, thus relieving the geometry shader of this particular abuse.

Fourth, unless your tessellation is dynamic, it’s entirely possible to know beforehand what the vertex layout is going to be and create an index buffer for that.
The tessellation is dynamic.