Water
Water

Reputation: 3675

Understanding binding/activating texture performance penalty in OpenGL

I'm unsure if what I'm doing is optimal or not.

I have three textures (two of which are array textures stacked with lots of information) and I do three rendering passes:

Therefore my code generally does something like this pseudo-code:

bindTexture(tex1);
drawLevel();
unbindTexture(tex1);  // Is this necessary if I just bind after anyways?

bindTexture(tex2);
drawEntities();
unbindTexture(tex2);

bindTexture(tex3);
drawHUD();
unbindTexture(tex3);

Since I recall seeing that were allowed up to 16 (or more) individual textures on GL_TEXTURE0, GL_TEXTURE1, ...etc, does that mean I can write my world textures to GL_TEXTURE0, entities to GL_TEXTURE1, and HUD to GL_TEXTURE2 and have no performance penalities, or very little? Or does even changing active textures carry a penalty that could be noticable?

I ask because I recall seeing that texture swapping is a taxing operation. Does this mean even if I change my active texture, it's still taxing? Or is it only taxing if you have more than 16 or so textures and keep pushing them to the GPU?

Is this wrong or slow?

I only need 3 textures, so if there's a most optimized way of doing this I'd be glad to learn it.

Assume I'm using core 3.3 and nothing like 4.5 (but if there's a better way of doing it in something like 4.2 or above, I'd be happy to hear those as well). It also should work on nvidia and AMD or any GPU released in the past 4-5 years as well.

EDIT: If you notice any weird concepts that I say which are wrong, correct me because I'm new to this. I'd much rather have someone be verbose in their answer for this reason.

Upvotes: 1

Views: 2555

Answers (1)

Xirema
Xirema

Reputation: 20396

I think there is a small amount of confusion regarding active textures in OpenGL. What OpenGL lets you do is have up to 16 Active Textures at the same time (edit: per shader stage). So you can have a single draw call reference up to 16 textures at once (and some implementations will allow more than 16).

There's no limit on the number of textures that you can create and have active in your program (except for the physical VRAM limit). More importantly, most OpenGL drivers are optimized around the assumption that you're going to bind a new texture (or possibly several) for every single draw call.

Changing active textures is a relatively expensive process, but not in the context in which you're using it. It would matter if, say, every single entity had multiple textures to reference, and each entity was a tiny object that wouldn't otherwise take much effort to render. It matters a lot less when you're literally bundling all your textures up into 3 "mega-textures" and only switching when moving from one set of objects to the next. In that context, the cost of switching textures is trivial and unworthy of attention.

I will say this looks a bit like a case of Premature Optimization, since putting in the effort of bundling everything together probably represents a workload footprint that might be outweighing the benefits you're getting from the final result, but that's a determination that you'll have to make for yourself.

But, TL;DR: there's nothing functionally or performance-wise wrong with your code.

Upvotes: 7

Related Questions