Gemotry Pass to cullin & Transform Feeedback Buffers

Hi!

I have been reading references about culling and assignment LOD instances using geometry pass with Transform Feedback, apparently its
“easy step” to do a very improve performs using GPU power.

Its very straightforward at this point, I set in some Tranform Feedback streams the mat4 tranforms vertex data, OK
But about khronos reference don´t tell a path how to use the vertex tranforms data captured in Transform Feedback streams,
Once the feedback operation is complete, the feedback object has a vertex count. This can be used for rendering purposes by binding

I’m obviously missing something, unless that i can mark exactly the instances to draw with glDrawTransformFeedbackInstanced
¿how i can set this?

I mean, e.g, if i have of total 5 instances, and when culling ends i only set to draw the instances n2 and n5, maybe I’m uninformed but I only set total count to draw instances.

Thx and greetings!

Ps. after read core 4.5 | and transform feeedback section, i continue with same doubt.

mountains-lod

I’ve done exactly what you’re talking about before (culling + LOD binning using transform feedback and a geometry shader), and it works very well.

What I did at the time (given available GL functionality, which has grown since then) is to use glDrawElementsIndirect() to launch the instanced batches serialized by the transform-feedback (stream-out) geometry shader. Basically the geometry shaders weren’t outputing vertices, but rather were outputing instance data (one per culled-in instance) to each of the LOD-specific instance buffers.

To use glDrawElementsIndirect(), you need to have the instance count in the buffer object along with the other draw call parameters. But the instance count comes from the number of items of data that you write out to each LOD buffer using the transform feedback (stream-out) geometry shader, right?

One option (a poor one) is to read back on the CPU the count of items serialized to each LOD buffer by the GPU. Then upload that from the CPU to the GPU to the correct offset into the GL_INDIRECT_BUFFER object containing the draw call parameters for the glDrawElementsIndirect() instanced draw call. This is not a good option, because it adds a big pipeline bubble during which the CPU and GPU are idle.

Another option (the one I chose at the time) was to have the geometry shader write out the count of items serialized to a specific LOD buffer to an atomic counter (1 per LOD). This atomic counter just happened to point directly to the byte offset in the GL_INDIRECT_BUFFER containing the draw call parameters for the glDrawElementsIndirect() draw call (specifically to the instance count member in the draw call parameters). So after the geometry shader ran, all of the indirect draw call buffers were populated with the correct instance counts, so you could launch those draw calls immediately. That worked well, but there are easier ways to accomplish this now that don’t involve gyrations with atomic counters.

Let me look that up and get back to you in a bit… I’ll update this post.

This extension provides one way to do this relay of the instance counts (from the geometry shader LOD buffer output written via transform feedback to the indirect draw call) more simply: ARB_indirect_parameters.

I think I have it!
I’m going to update my code and I’ll relate if finally works

Thanks so much Dark Photon!

Finally , don´t worked completely.
I can using glDrawElementsIndirect() with especific offSet provides from count of the streams feedback, but this is incomplete functionally for me, i will try explains :

I have an Buffer that is contains vertex and transform data elements instances from one chunck, and i get the frustum culling and select LOD using geometry pass with transforms feedback stream where in each stream contains the position Data about each instance that should by draw.

One more time, for example, simplifying it, I have 10 instances and after culling pass I must draw only 5 instances from these 10 : 2, 4, 5, 7, 9
And feedbacks streams contains the position about each it.

When i am trying glDrawElementsIndirect() after transform feedback, i can only set a unique offSet, and if i try draw now only can give instance 2, and I think that I am continue missing something.

should not be more easy? use the feedbacks streams data directly with the VAO buffer instances? how i bind streams data that contains the position with the VAO buffer that contains the vertex data of instance? and if response is that rebuild instance buffers, this will take 0.001 ms, it’s really worth it? It is very limiting!

[QUOTE=martel;1292490]I have 10 instances and after culling pass I must draw only 5 instances from these 10 : 2, 4, 5, 7, 9
And feedbacks streams contains the position about each…[/QUOTE]

Ok.

When i am trying glDrawElementsIndirect() after transform feedback, i can only set a unique offSet, and if i try draw now only can give instance 2, and I think that I am continue missing something.

I don’t understand what you mean by “unique offSet” here. The goal is to use the number of instances written by transform feedback to override the “primCount” in the indirect draw call.

If you’re using the old-school method I described of updating the “primCount” member directly in the transform feedback pass by mapping an atomic counter onto the “primCount” field in the indirect draw call parameters buffer (GL_DRAW_INDIRECT_BUFFER), then you could call glDrawElementsIndirect directly (or glMultiDrawElementsIndirect to launch the draws for all of the LODs in one API call, assuming they use the same pipeline state).

However, if you’re using the ARB_indirect_parameters technique, then you would be calling glMultiDrawElementsIndirectCount() as defined in the extension. My read is that this overrides the primCount in the GL_DRAW_INDIRECT_BUFFER buffer with the value in the GL_PARAMETER_BUFFER_ARB buffer. Now to get the number of primitives written by transform feedback into that GL_PARAMETER_BUFFER buffer before that, you can use ARB_query_buffer_object. This lets you retrieve the value into the buffer object bound to GL_QUERY_BUFFER.

Re the latter technique, now that I look at it, it appears you might be able to just use ARB_query_buffer_object to copy the number of primitives written by transform feedback directly onto the primCount field in the buffer you’d provide to glDrawElementsIndirect by binding its GL_DRAW_INDIRECT_BUFFER buffer to GL_PARAMETER_BUFFER for the copy. That’s worth considering. That said, I haven’t used either of these extensions myself, and I haven’t read them fully.

use the feedbacks streams data directly with the VAO buffer instances? how i bind streams data that contains the position with the VAO buffer that contains the vertex data of instance?

Wait. Let’s make sure we’re on the same page. Typically with hardware instancing, you’ve got a set of vertex attribute arrays defining the vertex positions/normals/colors/etc. that you need to render one single instance of a mesh around some local origin (lets call this “mesh” data). Then, you have a separate set of data (“instance variation” data) that defines properties which vary per instance. For example, if you were rendering a number of instances of a single mesh in your world at different positions, your instance variation data would typically contain an instance position. When rendering, in your vertex shader you would add the mesh position to the instance position to get a composite position for this vertex.

Now to your question. You could still have your VAOs contain bindings to the VBO that contains your “mesh” data because that isn’t changing. What “is” changing is the “instance variation” data and the number of instances. Both are going to be stored in buffer objects that aren’t going to be bound to vertex attribute or index buffer bind points, and thus are not stored in VAO state.

[QUOTE=Dark Photon;1292492]
Wait. Let’s make sure we’re on the same page. Typically with hardware instancing, you’ve got a set of vertex attribute arrays defining the vertex positions/normals/colors/etc. that you need to render one single instance of a mesh around some local origin (lets call this “mesh” data). Then, you have a separate set of data (“instance variation” data) that defines properties which vary per instance. For example, if you were rendering a number of instances of a single mesh in your world at different positions, your instance variation data would typically contain an instance position. When rendering, in your vertex shader you would add the mesh position to the instance position to get a composite position for this vertex.

Now to your question. You could still have your VAOs contain bindings to the VBO that contains your “mesh” data because that isn’t changing. What “is” changing is the “instance variation” data and the number of instances. Both are going to be stored in buffer objects that aren’t going to be bound to vertex attribute or index buffer bind points, and thus are not stored in VAO state.[/QUOTE]

I need process the transform array data provide from feedbaks streams, why they don´t are a regular transform data to bind VAO. I will try enyway with multiDrawElementsInstanced.

[QUOTE=martel;1292495]I need process the transform array data provide from feedbaks streams,
why they don´t are a regular transform data to bind VAO.[/QUOTE]

I don’t understand what you’re asking here. Are you asking why the arrays of data output by transform feedback streams (the instance variation data) are not bound with VAOs?

That’s because the only buffer bindings which are stored in Vertex Array Object (VAO) State (ignoring the legacy vertex attributes) are: GL_ELEMENT_ARRAY_BUFFER and the GL_ARRAY_BUFFER bindings active when you register your vertex attributes (e.g. with glVertexAttribPointer()). Other buffer binding points are not.

The only way these bindings can be stored in VAOs is if you take the buffer(s) containing transform feedback output, bind them to one of the above two buffer binding points, and (in the case of GL_ARRAY_BUFFER) actually register a vertex attribute with that binding active.

If you’re using the method of instancing where you pull in the instance data using gl_InstanceID in the shader, then you wouldn’t bind this instance variation data to a vertex attribute. However, if you’re using the “instanced arrays” form of instancing, where you bind the instance variation data to one or more vertex attributes and then setup the attribute divisor on them to advance through them only once per instance, then you would. I was assuming you were using the former form of instancing. Is this correct?

Srry, I have been traveling for work, but thank you very much for continuing to answer.

To assume that we are talking about the same thing I post here some code,

  • First to all I gen the Tranform Feedback Object and Buffer array to bind with him :


glGenBuffers(1, &Buffer);
glBindBuffer(GL_ARRAY_BUFFER, Buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Data_Max_Storage), 0, GL_STREAM_DRAW);

GLuint Feedback = 0;
glGenTransformFeedbacks(1, &Feedback);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, Feedback);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, Buffer);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

And then, I set that attributes will record on to buffer (mat4 and vec3), select INTERVELAVED mode to use with glDrawElementsIndirect()


const char* varyings[4] = { "InstanceMatrix", "colorVariation" `;
glTransformFeedbackVaryings(programHandle, 2, varyings,
GL_INTERLEAVED_ATTRIBS);

In Geometry Pass I have a simple implementantion LOD select;


layout(points) in;
layout(points, max_vertices = 1) out;


layout(stream=0) out mat4 instPosLOD0;
layout(stream=0) out vec3 colorVariation;
layout(stream=1) out mat4 instPosLOD1;
layout(stream=1) out vec3 colorVariation;

void main() {

  float distance = length(ModelViewMatrix * vec4(InstancePosition[0], 1.0));
  if ( distance < LodDistance.x ) {

    instPosLOD0= instanceMatrix[0];
    colorVariation0 = colorVariation[0];
    EmitStreamVertex(0);
    EmitStreamPrimitive(0);
  } else
  if ( distance < LodDistance.y ) {

    instPosLOD1= instanceMatrix[0];
    colorVariation1 = colorVariation[0];
    EmitStreamVertex(1);
    EmitStreamPrimitive(1);
  }
}

And DrawCalls of Feedback Process :


glEnable(GL_RASTERIZER_DISCARD);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TransformFeedback);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, countFromInstanceMatrix);
glEndTransformFeedback();
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glDisable(GL_RASTERIZER_DISCARD);

So here is the code that I have, ovbiously its wrongs, I tried to dedicate my free time to improve my knowledge of OpenGL core.

[ol]
[li]The GL_ARRAY_BUFFER what have I bind to Feedback Object, will be contain diferents VBO with InstanceMatrix and colorVariation attributes?;[/li][li] In wiki/Feedback#Captured_data_format says “Feedback objects record the number of vertices that they captured in a feedback operation.” to avoid use query object, glDrawTransformFeedbackStreamInstanced() it seems that it is better used than glDrawElementsIndirect()[/li][li] After feeedback process, how I can hadle the diferents VBO that sould contain each LOD level data?[/li][/ol]

my founts modern-opengl.pdf, glspec45.core.pdf and wiki/Transform_Feedback

UPDATED

In section 6.1 from glspec45.core.pdfDescribes how to use BindBufferRange to use with FeddbackStreams, I am triying set a offSet to use latter with glDrawElementsIndirect()

I’m not sure I understand your question. First, when talking about the output of transform feedback, I would refer to the buffer handle(s) the output is sent to. Output is sent to the buffer handle(s) bound to the GL_TRANSFORM_FEEDBACK_BUFFER buffer bind point(s). None of these should be bound as the GL_ARRAY_BUFFER when the transform feedback operation is performed (because they are the output buffer objects, not the input buffer objects).

On the topic of TF setup, I am puzzled by your code here. Your TF shader shows that you are outputting to 2 streams. However, you’re only binding a buffer object to receive TF output on stream 0 (i.e. GL_TRANSFORM_FEEDBACK_BUFFER[ 0 ]). Why?

  1. In wiki/Feedback#Captured_data_format says “Feedback objects record the number of vertices that they captured in a feedback operation.” to avoid use query object, glDrawTransformFeedbackStreamInstanced() it seems that it is better used than glDrawElementsIndirect()

Unless I’m missing something, I don’t think glDrawTransformFeedbackStreamInstanced() will do what you want.

You started this thread with a description and image from Rastergrid’s helpful GPU based dynamic geometry LOD blog post (he has several other related posts on instance culling and LOD binning).

Based on that, I assume you are trying to do LOD binning, and your shader code supports that theory.

Therefore, the TF output count is going to specify the number of instances to be rendered, not the number of vertices within each instance.

In contrast, glDrawTransformFeedbackStreamInstanced() sources the vertex count, not the number of instances, from the TF output count. Therefore, it doesn’t appear that it does what (I think) you want it to.

  1. After feeedback process, how I can hadle the diferents VBO that sould contain each LOD level data?

It depends on the method you choose for getting your TF output counts (1 for each stream) into the indirect draw call buffer(s). But in general:

[ol]
[li]copy the TF output counts into the proper locations (on top of the “instanceCount” members) in the indirect draw call buffer(s) (if you don’t write them there directly during TF), [/li][li]bind the buffer to the GL_INDIRECT_BUFFER buffer bind point, and then [/li][li]issue the indirect draw call (e.g. glMultiDrawArraysIndirect). [/li][/ol]

Also, a few questions:

[ol]
[li]In your “And DrawCalls of Feedback Process”, I don’t see you setting up the GL_ARRAY_BUFFER binding here before glDrawArrays(). Are you sure it is set properly at this point? The Transform Feedback object doesn’t capture the GL_ARRAY_BUFFER binding (and so doesn’t restore it when the TF object is bound). [/li][li]For glTransformFeedbackVaryings(), are you calling it before you link your glLinkProgram() for the transform feedback program? [/li][/ol]

[QUOTE=Dark Photon;1292551]
Also, a few questions:

[ol]
[li]In your “And DrawCalls of Feedback Process”, I don’t see you setting up the GL_ARRAY_BUFFER binding here before glDrawArrays(). Are you sure it is set properly at this point? The Transform Feedback object doesn’t capture the GL_ARRAY_BUFFER binding (and so doesn’t restore it when the TF object is bound). [/li][li]For glTransformFeedbackVaryings(), are you calling it before you link your glLinkProgram() for the transform feedback program? [/li][/ol][/QUOTE]

[ol]
[li]Yes, indeed, I was forgetting. (but there are still many things wrong).[/li][li]I am using glTransformFeedbackVaryings() between to load shader Programs and create FeedbackObject.[/li][/ol]

I thought I could use only a single buffer, selecting a INTERVELAVED mode.

As you can obviously verify I have a big mess of concepts, even so between all the documentation and your responses I can go enlightening everything, I think I’m close.


//
glBindBuffer(GL_ARRAY_BUFFER, Buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Data_Max_Storage), 0, GL_STREAM_DRAW);

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, Feedback);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, Buffer);
//

  1. When I create the transform feedback object that first that I made is bind him with a GL_ARRAY_BUFFER with a maximum size equivalent to all the information that may contain, leaving it empty, This is Right?[/li][li]I must use glBindBufferBase() for set each Stream in to a unique Buffer? I do not need to indicate how much space has each one?
    [QUOTE=Dark Photon;1292551]It depends on the method you choose for getting your TF output counts (1 for each stream) into the indirect draw call buffer(s). But in general:

    copy the TF output counts into the proper locations (on top of the “instanceCount” members) in the indirect draw call buffer(s) (if you don’t write them there directly during TF),
    bind the buffer to the GL_INDIRECT_BUFFER buffer bind point, and then
    issue the indirect draw call (e.g. glMultiDrawArraysIndirect).[/QUOTE]

  2. This includes using glMultiDrawElementsIndirectCount() from ARB_indirect_parameters?, when you says “(on top of the “instanceCount” members) in the indirect draw call buffer(s)” this means that I have to bind GL_INDIRECT_BUFFER with Tranform Feedback Object too?
    [srry if it sounds stupid]
  3. How I can made the output counts on geometry step to use with GL_INDIRECT_BUFFER?[/li][li]I can´t find examples codes / or exercises from 4.4Core about Transform Feedback, as a way to learn, would it be possible share some code that you have?

Well check the spec, but IIRC the way it works is (considering only 1 output stream): SEPARATE writes each TF output to its own separate buffer bind point, whereas INTERLEAVED interleaves them all into the same buffer (bound to a single buffer bind point). That’s for a single output stream. With multiple output streams, you have more flexibility and can interleave the outputs written to a each stream in their own buffer, but you still have each separate stream filling its own output buffer. So the buffer for each stream is bound to its own indexed buffer bind point (using glBindBufferBase or glBindBufferRange).

For reference, see Transform Feedback in the wiki. In particular, the Advanced Interleaving section.

Also check the OpenGL Spec. In particular, pg. 449 where it’s talking about when a program can fail to link due to a call to glTransformFeedbackVaryings(), it says one way this can happen is if: “the set of outputs to capture to any single binding point includes outputs from more than one vertex stream.” So your streams will be routed to the buffers bound to separate binding points, one per stream.

When I create the transform feedback object that first that I made is bind him with a GL_ARRAY_BUFFER with a maximum size equivalent to all the information that may contain, leaving it empty, This is Right?

If you’re talking about the buffer object which will contain the TF output, yes. You just need to allocate it (glBufferData). You don’t care what it contains as it’ll be overwritten.

  1. I must use glBindBufferBase() for set each Stream in to a unique Buffer? I do not need to indicate how much space has each one?

Or glBindBufferRange(), yes. See Buffer Binding on the Transform Feedback wiki page.

glBindBufferBase() binds the whole buffer, however big it is, for TF output. It is expected that you’ve already allocated storage to it (e.g. by calling glBufferData with it bound to a buffer bind point.

2 This includes using glMultiDrawElementsIndirectCount() from ARB_indirect_parameters?, when you says “(on top of the “instanceCount” members) in the indirect draw call buffer(s)” this means that I have to bind GL_INDIRECT_BUFFER with Tranform Feedback Object too?

I don’t understand what you’re asking here.

Separate in your mind what’s required for the transform feedback pass, and then what’s required for issuing an indirect draw call. You run TF first. That gives you a list of instances in each stream, and a number of instances written to each stream. …THEN… You’re going to issue an indirect draw call (or calls) that actually tell the GPU to draw with those instance lists.

All I was trying to say is it’s up to you how you communicate the number of instances written to a stream from the TF output pass -TO- the draw call parameters used by the indirect draw call. There are several possible ways. It’s up to you which way you go!

  1. How I can made the output counts on geometry step to use with GL_INDIRECT_BUFFER?

Don’t think in terms of buffer binding points. Those are just like hooks that you can hang buffer objects on if/when needed. Think in terms of your buffer objects and the contents that they have.

The buffer object bound to the GL_INDIRECT_BUFFER contains draw call parameters. These are the same parameters you’d provide in your CPU function call to a non-indirect draw call like (for instance) glDrawArraysInstanced(). To see exactly what the format is for glDrawArraysIndirect(), see the man page and look at the DrawArraysIndirectCommand struct. See the “primCount” member? That’s the number of instances. You need to use some method (such as one of those described above) to copy the number of instances written to a stream in the TF output pass into that “primCount” member. Once you get it in there, then you can bind that buffer object to the GL_INDIRECT_BUFFER and issue your indirect draw call. Does that make sense?

  1. I can´t find examples codes / or exercises from 4.4Core about Transform Feedback, as a way to learn, would it be possible share some code that you have?

I don’t have time to look through a lot of code, but if you post code snippets here with specific questions, I’m sure folks here will be able to help you clear up any confusion you might have. Before you do though, I would definitely read that Transform Feedback wiki page as well as the wiki section on Indirect rendering. If something is confusing, just ask!

OK, I’ve started from the simplest to make sure everything goes well but I’ve already had problems that should not be going step by step using wiki/Transform_Feedback + glspec46.pdf 13.3.1 Transform Feedback Objects.

Forgetting temporarily my goal of instance LOD Culling, I thought a simple enough objective : using a VBO that only contain one VEC4 positions attribute, and use transform feedback to divide it in two output streams and finally using glDrawTransformFeedbackStream() to render streams as a points.



const char* varyings[] = { "POS0", "POS1" };                                               // <- TWO OUTPUT STREAMS
glTransformFeedbackVaryings(idProgram, 2, varyings, GL_SEPARATE_ATTRIBS);                  //<- SEPARATE MODE TO GET OUTPUTS INTO SEPARATE BUFFERS 
glLinkProgram(idProgram);

//

glGenBuffers(1, &BUFFER0);
glBindBuffer(GL_ARRAY_BUFFER, BUFFER0);                                                    // <- FIRST BUFFER OUTPUT
glBufferData(GL_ARRAY_BUFFER, max_size_data, 0, GL_STREAM_DRAW);

glGenBuffers(1, &BUFFER1);
glBindBuffer(GL_ARRAY_BUFFER, BUFFER1);                                                    // <- SECOND BUFFER OUTPUT
glBufferData(GL_ARRAY_BUFFER, max_size_data, 0, GL_STREAM_DRAW);


glGenTransformFeedbacks(1, &feedbackObject);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedbackObject);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, BUFFER0);                                //
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, BUFFER1);                                // <- BIND BUFFERS 0 and 1


// AFTER BIND BUFFER INPUT (that contain VBO VEC4 positions)
glEnable(GL_RASTERIZER_DISCARD);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, feedbackObject);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, countPositions);
glEndTransformFeedback();
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glDisable(GL_RASTERIZER_DISCARD);


// NOW, AFTER BIND BUFFER0 TO RENDER IT AS A STREAM 0
glDrawTransformFeedbackStream(GL_POINTS, feedbackObject, 0);              


layout(points) in;
layout(points, max_vertices = 1) out;

layout(stream=0) out vec4 POS0;
layout(stream=1) out vec4 POS1;
void main()
{  
    if( gs_in[0].POS.x < 50.0) {                   // <- TO OBTAIN HALF IN TO EACH STREAM
                POS0 = gs_in[0].POS;
                EmitStreamVertex(0);
                EndStreamPrimitive(0);
     }else {
                POS1 = gs_in[0].POS;
                EmitStreamVertex(1);
                EndStreamPrimitive(1);
     }
} 

Interestingly, this code does work with ONLY one of streams if I made this changes :

glTransformFeedbackVaryings(idProgram, [b][u]1[/u][/b], varyings, GL_SEPARATE_ATTRIBS);

Obviously I am indicate only an single exit here, but its works, only half of positions are rendered as points. I’ve spent all night reviewing the documentation before putting this here.
What am I missing so that when I indicate 2 incices into set Varyings it don´t breaks?

In terms of getting you a TF geometry shader/program that does successfully output to multiple streams, try this:

[ul]
[li]Re: Still having problems with calling glTransformFeedbackVaryings [/li][/ul]
A few differences between my code and yours: 1) Using INTERLEAVED instead of SEPARATE, and 2) using “gl_NextBuffer” in the glTransformFeedbackVaryings() list to explicitly designate streams.

To your above code. Here, before the glDrawArrays:


glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, countPositions);
glEndTransformFeedback();

you didn’t show binding a buffer to GL_ARRAY_BUFFER (but you probably did based on the comment above this section) and didn’t show setting up your vertex attribute pointers and enables (glVertexAttribPointer / gl{Enable,Disable}VertexAttribArray). I realize you are just showing an excerpt above so you may have this in your actual source code. If not, add this.

You also didn’t show binding your TF program (glUseProgram), but you almost certainly have that in your actual code since you’ve seen this working in some cases.

[QUOTE=Dark Photon;1292560]In terms of getting you a TF geometry shader/program that does successfully output to multiple streams, try this:

[ul]
[li]Re: Still having problems with calling glTransformFeedbackVaryings [/li][/ul][/QUOTE]

I am using a GTX1080Ti, I set/get max_stream_outputs. I think it’s relevant.

I made the changes and it still does not work, only I can draw stream 0 (the half of all points) but when i am trying stream 1 I don’t get any in screen. I’m confused anyway, why could not I use separate mode for this example?

Okey, after a few relaxing days I have recreated everything from scratch and it has worked, at least using the old CPU query techniques, Y but at least I can do culling + LOD now. if Dark Photon read this, It will be pulling the hair again thinking something like “but if I gave the key to this noob in first replys to avoid CPU -> GPU sync!!”.

I really am able to use INDIRECT_BUFFER, but as much as I review ARB_query_buffer_object I do not see how the example they provide with code (From example 4) to update primCount in indirect buffer :


glGetQueryObjectuiv (queryId, GL_QUERY_RESULT, 
                            BUFFER_OFFSET (offsetof (DrawArraysIndirectCommand, primCount)));

This line code do not make sense to me, among other things when I try this, returns error “DrawArraysIndirectCommand not defined”.
Apart, I would not know how to adapt it to be useful for some streams.

Excellent!

I really am able to use INDIRECT_BUFFER, but as much as I review ARB_query_buffer_object I do not see how the example they provide with code (From example 4) to update primCount in indirect buffer :

Reading through the extension (ARB_query_buffer_object), I see that they’ve provided an example of exactly what you’re looking for. It looks like you found that too (just under: “Example 4: Using transform feedback query result to fill indirect draw buffer”).

glGetQueryObjectuiv (queryId, GL_QUERY_RESULT,
BUFFER_OFFSET (offsetof (DrawArraysIndirectCommand, primCount)));

This line code do not make sense to me, among other things when I try this, returns error “DrawArraysIndirectCommand not defined”.

offsetof() is a macro defined in stddef.h / cstddef which returns the offset of a field within a struct (or class, or union) type or variable. See the link: offsetof()

DrawArraysIndirectCommand is a struct type that is defined in the OpenGL Spec under the description of the [gl]DrawArraysIndirect command (search for DrawArraysIndirect; the spec leaves off the leading gl and GL_ prefixes on everything). You can also find this structure definition in the OpenGL man pages and the wiki. For instance: glDrawArraysIndirect. Copy that structure definition into your source code, and then this should compile.

If you’re missing the BUFFER_OFFSET() macro definition, it’s:


#define BUFFER_OFFSET(i) ((void*)(i))

I’m sorry dark photon, just I come here to say that ASK about DrawArraysIndirectCommand I realized that it was a stupid question, srry about that!.

Now I have that :



#include <stddef.h>
#define BUFFER_OFFSET(i) ((void*)NULL + (i))


{...}

		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, _gIndirectBuffer);
		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(vDrawCommand), vDrawCommand, GL_DYNAMIC_COPY);

		glBindBuffer(GL_QUERY_BUFFER, _gIndirectBuffer);
		glGetQueryObjectuiv(0, GL_QUERY_RESULT, BUFFER_OFFSET(offsetof(struct vDrawCommand, primCount)));

vDrawCommand is the buffer_indirect struct, even so BUFFER_OFFSET return “argument void* not compatible with parameter GLint*

What happens if I use

#define BUFFER_OFFSET(i) ((GLuint*)NULL + (i))

if I use it that way, it executes but does not replace the primCount value parameter from INDIRECT_BUFFER

	
	vDrawCommand[0].count = (GLsizei)_mesh.indices.size();
		vDrawCommand[0].primCount = 10;
		vDrawCommand[0].firstIndex = 0;
		vDrawCommand[0].baseVertex = 0;
		vDrawCommand[0].baseInstance = 0;

For the test I fill parameters before gens/bind INDIRECT_BUFFER,

Ignore the last message,

IT WORKS!!! IT WORKS!!! :smiley:

But doing tests only works for the stream 0, would you tell me what would be the logic for N streams? (now I was trying to capture 2 streams in to 2 querys objects)

No problem. There’s a first time for everything.

#define BUFFER_OFFSET(i) ((void*)NULL + (i))

…BUFFER_OFFSET return “argument void* not compatible with parameter GLint*

That’s not a good definition for BUFFER_OFFSET. Instead you should use.


#define BUFFER_OFFSET(i) ((void*)(i))

Why do I say that? Yours is semantically different than mine, resulting in a different answer.

For the one I quoted, “i” is treated as a byte offset, so what you get is the value “i” cast to a void * type.

For yours, since the cast operator is higher precedence than the + operator, you end up with NULL (typically the value 0) cast to a “void *” type being added to an integer. This is invalid, because “void *” has no fundamental type size that it’s pointing to, causing the error you were getting.