Beyond Porting: How Modern OpenGL Can Radically Reduce Driver Overhead (Steam Dev Days 2014)

Steamworks Development · 59K views · 2014 · 51:14

Open on YouTube

Computer graphics & renderingSoftware performance & optimizationGame programming & enginestalk

Why Stack Overflow recommends it

Stack Overflow users link it when explaining which OpenGL state changes (programs, vertex formats, buffer bindings, uniforms) are expensive and why batching and shared buffers help.

Recommended by 2 people across 4 different months, 2014 to 2022.

What it is

A Steam Dev Days 2014 talk by NVIDIA's Cass Everitt and John McDonald on modern OpenGL extensions that cut driver overhead. It covers where GL performance goes, how to profile it, and techniques like bindless rendering and MultiDraw commands, with a ranking of how costly different state changes are.

Cited in 1 Wikipedia article, including Mantle (API).

What people said

Strong rec LJᛃ · 2014-10 · Stack Overflow · on “Use single vertex buffer or many?”

The GPU is a state machine, switching states is expensive(even more when done through WebGL because of the additional layer of checks introduced by the WebGL implementation) so binding vertex buffers is expensive. Its good practice to reduce API calls to a minimum. Even when having multiple distinct objects you still want to use a single vertex buffer and use the offset parameter of the drawArrays or drawElements methods. Here is a list of API calls ordered by decreasing expensiveness(top is most expensive): FrameBuffer Program Texture binds Vertex format Vertex bindings Uniform updates For more information on this you can watch this great talk Beyond Porting: How Modern OpenGL can Radically

Recommends Nicol Bolas · 2015-12 · Stack Overflow · on “How taxing are OpenGL glDrawElements() calls compared to basic logic code?”

The cost of glDrawElements (or any other OpenGL rendering command [LINK] ) cannot really be estimated. This is because its cost depends a great deal on what OpenGL state you changed between draw calls. The cost of calling an OpenGL state changing function (basically, any OpenGL function that isn't a glGet of some form or a glDraw of some form) will be relatively quick. But it will make the next draw call slower. This video on OpenGL performance [this video] shows which state changes are more costly at draw time than others. The really good part starts around 31 minutes in. Draw calls are relatively fast if you haven't changed any OpenGL state between draw calls. Different pieces of state have dif

Recommends Nicol Bolas · 2016-02 · Stack Overflow · on “How should you efficiently batch complex meshes?”

You are focused on the wrong things. In two ways. First, there's no reason you can't stick all of the mesh's vertex data into a single buffer object. Note that this has nothing to do with batching. Remember: batching is about the number of draw calls , not the number of buffers you use. You can render 400 draw calls out of the same buffer. This "maximum size" that you seem to want to have is a fiction , based on nothing from the real world. You can have it if you want. Just don't expect it to make your code faster. So when rendering this mesh, there is no reason to be switching buffers at all. Second, batching is not really about the number of draw calls (in OpenGL). It's really about the co

Recommends Nicol Bolas · 2021-02 · Stack Overflow · on “Should shader programs be shared in OpenGL”

Changing uniform values is much cheaper than changing programs . The AZDO presentation [this video] made it clear that changing programs is something that, if you care about performance in large-scale rendering operations, should be done relatively sparingly.

Cites Nicol Bolas · 2015-12 · Stack Overflow · on “Rendering multiple objects with OpenGL shaders”

@RetoKoradi: Well, NVIDIA and AMD seem to have data (~32 minutes) [this video] that says that vertex format changes are more expensive than vertex bindings (aka: buffer bindings). So I'll go with what they say. Also, on GCN-based AMD hardware, changing vertex formats requires modifications to the vertex shader, since GCN-hardware doesn't actually have vertex pulling hardware.

Cites Nicol Bolas · 2016-04 · Stack Overflow · on “OpenGL batching and disabling objects”

Batching requires putting all of your data in one buffer, but batching is not limited to that. Batching is about reducing the number of draw calls. Putting your data in one buffer is necessary for that, but not sufficient. Putting all of your vertex data in one buffer alone has performance advantages, relative to having to switch buffers and vertex formats. You don't need to go all the way to batching everything into a single draw call to improve performance over using a buffer for each individual object. In OpenGL, as discussed in this video [this video] , the primary cost of multiple draw calls isn't the draw call itself. It's the state changes you usually do between draw calls. You've put your

Cites Nicol Bolas · 2017-11 · Stack Overflow · on “Performance gain of glColorMask()/glDepthMask() on modern hardware?”

@lisyarus: "Why" is essentially irrelevant. It is a well understood fact of OpenGL performance development [this video] . And there's nothing you can do to change its performance characteristics. All you can do is avoid FBO changes as best your algorithm allows.

Cites Nicol Bolas · 2019-01 · Stack Overflow · on “Cost of glUniform1ui”

In the taxonomy of state change performance [this video] , updating a uniform is the least costly thing you can do. Changing UBO bindings is more expensive. So you should prefer uniform updates once per object to UBO binding per object. However, since you are using ES 3.1, which features SSBOs, it might be better to use them rather than UBOs, simply due to the amount of stuff you can access from an SSBO compared to a UBO.

Cites Nicol Bolas · 2021-05 · Stack Overflow · on “How can I pass a single value in a VBO to every vertex?”

It is possible to set a stride to be 0. You just have to use the vertex attrib binding API [LINK] . The stride set by glBindVertexBuffer can be 0 and it has the expected meaning (since there is no way to determine what a tightly packed stride ought to be from the available parameters). However, if you're doing this for performance, this isn't particularly helpful. To switch to a different value in the VBO, you have to issue a glBindVertexBuffer call, which is going to be about as expensive as a glProgramUniform call. Indeed, according to NVIDIA's AZDO presentation [this video] , changing uniforms is cheaper than vertex buffer bindings. If you want to beat the cost of uniform updates, then you're

Cites Nicol Bolas · 2021-06 · Stack Overflow · on “OpenGL best practice for putting two different mesh in the same vertex VBO”

The purpose of batching [LINK] is to improve performance by minimizing state changes between draw calls (batching reduces them to 0, since there is nothing between draw calls). However, there are degrees of performance improvement, and not all state changes are equal. On the scale of the costs of state changes [this video] , changing program uniforms is the least expensive state change. That's not to say that it's meaningless, but you should consider how much effort you really want to spend compared to the results you get out of it. Especially if you're not pushing hardware as fast as possible. VAO changes (non-buffer-only changes, that is) are among the more expensive state changes, so you gaine