Jump to content

  • Log In with Google      Sign In   
  • Create Account

Drawing in one draw call vertex buffer with different programs


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 Zebratov   Members   -  Reputation: 117

Like
0Likes
Like

Posted 08 July 2014 - 06:39 AM

Hi all, 

 

I am trying to figure out how to implement the following concept with modern OpenGL API (4.3)

 

I have a vertex buffer which has a regular vertex array, But I need half of its data to process with ShaderProgram A,

and another half - with ShaderProgram B.

 

Currently what I do is creating two different VAOs with vertex attribute pointers pointing to related parts of the vertex array.

But in this case I must issue 2 draw calls -one per VAO.

Can I do it with a single draw call?

 

P.S: I thought of primitive restart,but AFAIK it doesn't switch shaders on each restart.

 

Thanks!



Sponsor:

#2 L. Spiro   Crossbones+   -  Reputation: 14258

Like
0Likes
Like

Posted 08 July 2014 - 11:31 AM

Can I do it with a single draw call?

No.
You have already found the solution.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#3 SeanMiddleditch   Members   -  Reputation: 7166

Like
0Likes
Like

Posted 08 July 2014 - 11:46 AM

Yeah, either you have to combine your shaders (and then only if you can make a shader that will run on GPU efficiently, e.g. with a minimum a branching or dynamic loops), or just suck it up and use two draw calls.

Remember, multiple draw calls _is not a problem_, so long as they don't scale linearly with the number of objects in your scene! You can easily have hundreds of draw calls even on mobile devices. It's better to have a system that always needs 57 draw calls to render any scene (whether it has 1 object or 10,000) than it is to need "only" 1 draw call per object (meaning you'd only ever be able to have a few hundred objects in a scene at once on low-end devices).

Look into instancing or deferred approaches to help ensure you only use one draw call per material to the extent possible.

#4 Zebratov   Members   -  Reputation: 117

Like
0Likes
Like

Posted 10 July 2014 - 02:37 AM

Thanks for the help.

 

And It is possible, using the new 

  • GL_ARB_multi_draw_indirect
  • "Approaching Zero Driver Overhead"


#5 Hodgman   Moderators   -  Reputation: 31809

Like
0Likes
Like

Posted 10 July 2014 - 06:37 AM

Thanks for the help.
 
And It is possible, using the new 

  • GL_ARB_multi_draw_indirect
  • "Approaching Zero Driver Overhead"
Those still have one shader per each draw call.
You can't use two different programs within one call, ever.

#6 Zebratov   Members   -  Reputation: 117

Like
0Likes
Like

Posted 10 July 2014 - 09:21 AM

 

Thanks for the help.
 
And It is possible, using the new 

  • GL_ARB_multi_draw_indirect
  • "Approaching Zero Driver Overhead"
Those still have one shader per each draw call.
You can't use two different programs within one call, ever.

 

By implementing an übershader .. and using shader subroutines, which are the GLSL equivalent of function pointers. These can be formed into arrays and different implementations of the subroutine can have entirely different behavior.



#7 Hodgman   Moderators   -  Reputation: 31809

Like
2Likes
Like

Posted 10 July 2014 - 05:05 PM

That kind of ubershader is still one program though ;-)

Also, I would recommend only ever using that approach if you're desperate to reduce CPU-side overhead. That technique allows you to drastically reduce the amount of gl* calls that the CPU has to make, but it's also likely to cause a huge amount of overhead on the GPU-side - so you're wasting GPU-time in order to gain CPU-time.
If your game is GPU-bound, then you'd be better off making more draw calls with non-uber shaders ;)

#8 mhagain   Crossbones+   -  Reputation: 8277

Like
3Likes
Like

Posted 11 July 2014 - 03:17 AM

Currently what I do is creating two different VAOs with vertex attribute pointers pointing to related parts of the vertex array.

 

Just to address this part, you don't need this kind of set up at all.  You can do it with a single VAO and a single set of attrib pointers, but still with two draw calls, so it takes away some of the overhead.

 

So, say you're using glDrawArrays: look at the documentation for that and you'll see that it has a first parameter.  Let's assume that you have 200 vertices, and you want the first 100 drawn with ShaderProgramA, the second 100 with ShaderProgramB.  Your code is:

 

glBindVertexArray (LetsUseASingleVAOHere);

glUseProgram (ShaderProgramA);

glDrawArrays (GL_TRIANGLES, 0, 100);

glUseProgram (ShaderProgramB);

glDrawArrays (GL_TRIANGLES, 100, 100);

 

Similarly with glDrawElements you can see that it has a pointer parameter, (GLvoid *indices), as well as a count parameter, so again rather than using two sets of attrib pointers, you just use a single set and then adjust the parameters of your draw call to specify which range of the buffers to draw.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS