My application (with a modernish OpenGL >= 3.0 and an OpenGL ES 2.0 backend) renders more or less streaming data with up to millions of vertices with different vertex layouts and sizes (some simple, some quite big). Some data is indexed, some is not. I'm currently hitting the problem of draw calls and buffers (index and/or vertex) becoming too large, so I need to split them. I have a hard time understanding when and how I should correctly split draw calls. My questions:

  1. The limits GL_MAX_ELEMENTS_VERTICES and GL_MAX_ELEMENTS_INDICES, according to the docs, tell the application the maximum value for well-performing glDrawRangeElements calls. Why is this ONLY for glDrawRangeElements, why not glDrawRangeElementsBaseVertex or even glDrawElements?! This does not make sense to me, because glDrawRangeElements is more or less glDrawElements after all. Also I've see a couple of OpenGL implementations reliably crash when rendering indices above that limit, even with glDrawElements. On the other hand some stackoverflow answers say that the limits are not relevant anymore... What else should I use to decide how to split my draw calls then?
  2. What about glDrawArrays? Is there an upper limit (e.g. GL_MAX_ELEMENTS_VERTICES)?
  3. For the OpenGL ES 2.0 backend I require the extension "GL_OES_element_index_uint" to use indices above the 65k limit. What limits should I choose there for draw call size?
  4. I have decided to limit my IBO and VBO sizes to a certain limit (max. 64MB), as there's no way to ask OpenGL about what buffer size I can allocate, else than checking for GL_OUT_OF_MEMORY. That means I have to additionally split according to that buffer size (both IBO and VBO). Is there a better way to check buffer limits?
  5. What should be the preferred way to split draw calls? Make them small in the application already, then batch them when rendering? This will lead to lots of duplicate vertices in some case, which is not ideal.
    Splitting them in the render code can be complicated, because index data has to be analyzed, indices changed or memory copied, but in the end it is the only place where you can be sure all limits are respected...

I'd prefer reliable, stable solutions even if they provide lower performance. I'm targeting OpenGL Desktop hardware newer than ~2010 and Angle as a conversion layer from OpenGL ES 2.0 -> Direct3D in case of Remote Desktop connections.

  • \$\begingroup\$ I'm pretty sure you mean fallback instead of backend. Backend is used for the technology behind it, fallback is the emergency plan \$\endgroup\$ – Bálint Jun 15 '17 at 10:26
  • 2
    \$\begingroup\$ Well, I'm not a native speaker, so I'm not sure the word is correct. With backend I mean the final code that will do the rendering. My renderer can have different "output modules" aka backends. Currently it has one for Desktop OpenGL 3.0+ and one for OpenGL ES 2.0. \$\endgroup\$ – Bim Jun 15 '17 at 10:36
  • 1
    \$\begingroup\$ "Backend" sounds ok to me in this context. \$\endgroup\$ – HolyBlackCat Jun 15 '17 at 14:21
  • \$\begingroup\$ The max index count depends on what you use for indexing. If it's GL_UNSIGNED_SHORT, then 65536, if it's GL_UNSIGNED_INT, then 2^32. 64 Mb allows you to store approx. 16777216 / 3 vertices \$\endgroup\$ – Bálint Jun 15 '17 at 14:55
  • 1
    \$\begingroup\$ @Balint: I know about ushort vs. uint. I want to know about the implementation defined limits. The 64MB is just an arbitrary sanity limit, but maybe even that is too high. LCdMf: You probably talk about GLES2? All Desktop GL2-capable hardware should support 32-bit indices. It's in the standard. \$\endgroup\$ – Bim Jun 15 '17 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.