16

Does it make any sense to use drawElements instead of drawArrays if I'm not going to share any vertices?

If I understood correctly, with drawElements I have to use multiple drawcalls if the index array exceeds ~65k elements because of the uInt16 limitation of the indexbuffer ( in webgl ).

So could one say as a rule of thumb:

No shared vertices, use drawArrays because its just one big drawCall.

If shared vertices, use drawElements because GPU bandwith could be saved and this would result in better performance than drawArrays also if there are multiple drawcalls required?

genpfault
  • 51,148
  • 11
  • 85
  • 139
supernova
  • 3,814
  • 3
  • 22
  • 37
  • 3
    The `OES_element_index_uint` extension is supported by 95.5% of webgl capable browsers, allowing you to use uInt32 indices. – LJᛃ Jan 22 '15 at 13:29

1 Answers1

20

The advantage of glDrawElements() is in theory simple: you use fewer vertexes, and you get to use the post-T&L cache. The penalty is that you have to use an index array and cache locality might be worse.

Comparisons are complicated by the fact that the post-T&L cache will vary in size depending on (for example) how old your graphics card is. Newer cards might have huge caches, older cards might have smaller ones.

However, if you are not sharing any vertexes between primitives, then there is no advantage to glDrawElements() whatsoever, and you should use glDrawArrays().

In more complicated scenarios, when you are comparing the cost of additional draw calls (with glDrawElements()) against the cost of extra vertex data and more vertex shader invocations (with glDrawArrays()), I would want to profile.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • So if I dont share any vertices is glDrawElements slower because I have to call bindBuffer and drawElements more often or does this depend solely on the graphics card I am using? – supernova Jan 21 '15 at 20:15
  • 3
    Let's say you are drawing 1000 triangles, and the vertex array is 8 bytes per vertex. With `glDrawArrays()`, you have to transfer 24000 bytes to the renderer. With `glDrawElements()`, you have to transfer 30000 bytes to the renderer: 24000 bytes of vertex data, and 6000 bytes of index data. – Dietrich Epp Jan 21 '15 at 20:19
  • thanks, I'm going to profile it to make sure whats better for my usecase. – supernova Jan 21 '15 at 20:20
  • That's usually a good idea, but if no vertexes are shared, it's a foregone conclusion. – Dietrich Epp Jan 21 '15 at 20:21
  • 1
    I did tests and at least with my card (gtx 760) drawElements was actually faster than drawArrays.. at 60 million vertices with ~800 drawcalls i got 35 fps where with drawArrays i had ~140 drawcalls and roughly 30 fps - I read a comment about this drawArrays vs drawElements and someone said that if an index is provided it does lift some work of the vertex shader - what exactly was he talking about? – supernova Jan 23 '15 at 10:44
  • whats the difference between vertices and triangles here, in my case I dont share any vertices. – supernova Jan 23 '15 at 10:55
  • @supernova oh sorry my fault. I didnt read your question well. – Entity Black Jan 23 '15 at 13:05
  • You should think who is your project audience. For example I do webgl for mobile devices, result can be very different without quite new gtx 760. "it does lift some work of the vertex shader" - I guess it was simply ment V program can read attribute value from memory instead of directly from buffer. Then VS shader should be faster. https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics-pipeline-2011-part-3/ – Entity Black Jan 23 '15 at 13:18
  • @supernova I think the index related vertex shader efficiency with drawElements was mentioned because, on one hand, you can have a more compact geometry representation (it won't make drawing faster, but can reduce the buffer update time), and on the other, the T&L cache can reuse vertex shader computations if the vertex was already processed recently as part of an adjacent triangle: https://www.opengl.org/wiki/Post_Transform_Cache – Robert Monfera Oct 23 '16 at 15:53