Which is Faster?

Started by
15 comments, last by Sir Sapo 18 years, 10 months ago
I hear that it is really expensive to switch textures in an OpenGL program which got me thinking about optimizing my tile engine. Lets say I have 300 tiles in a level and each tile can have one of 30 textures binded to it. Would this way be faster than binding the same textures 300 times? I have a for loop that binds one of the 30 textures, looks through all the tiles and only draws the ones that are supposed to have that texture bound to them, and then moves on to the next texture and repeats the process. My writing sucks so I'll write some code too:


for(int tex = 0; tex < 30; tex ++)
{
glBindTexture(GL_TEXTURE_2D , textures[tex]);

for(int tile = 0; tile < 300; tile ++)
{
if(Tiles[tile]->getTexture() == tex)
Tiles[tile]->RenderTile();
}


}




Would this even make a measurable effect on the speed of my game if I'm only doing this 300 times anyway?
My Current Project Angels 22 (4E5)
Advertisement
Quote:Original post by Sir Sapo
I hear that it is really expensive to switch textures in an OpenGL program which got me thinking about optimizing my tile engine.

Lets say I have 300 tiles in a level and each tile can have one of 30 textures binded to it. Would this way be faster than binding the same textures 300 times? I have a for loop that binds one of the 30 textures, looks through all the tiles and only draws the ones that are supposed to have that texture bound to them, and then moves on to the next texture and repeats the process.

My writing sucks so I'll write some code too:

*** Source Snippet Removed ***

Would this even make a measurable effect on the speed of my game if I'm only doing this 300 times anyway?



Sorting by texture and/or minimizing texture switching usually does help. Just how much in your case, you'll have to profile and find out [smile].

btw your loop would be more efficient if you sorted your tiles by texture instead of the nested loop like that. Something like the following then.

tex = 0;for(int tile = 0; tile < 300; tile ++){   if(Tiles[tile]->getTexture() != tex)   {      glBindTexture(GL_TEXTURE_2D , Tiles[tile]->getTexture());      tex = Tiles[tile]->getTexture();   }   Tiles[tile]->RenderTile();}


executes 300 times instead of 9000 :) but for maximum efficiency sort the tiles before hand by their textures (above will work without sorting aswell but not as efficiently).

HTH
Thanks for the help.
My Current Project Angels 22 (4E5)
Quote:I hear that it is really expensive to switch textures in an OpenGL program


It is only really expensive if you have modified the texture since you last drew it, or if you're binding more textures during a frame than fits in your graphics cards' VRAM (after framebuffer, Z buffer, double buffer etc are subtracted).

In OpenGL version 1.0, about ten years ago, there were no texture objects, and the texture had to be uploaded to the card each time you wanted to use it -- really quite expensive. Display lists were usually used to "hint" to the driver that it could cache that texture. However, as of texture objects, in OpenGL 1.1, that hasn't been an issue. It's long dead and buried.

Binding a new vertex program, or even worse, fragment program, is likely to cause a far bigger stall in your pipeline than switching textures. Pipe stalls == fewer pixels processed == lower frame rate, if that's your limiting factor.
enum Bool { True, False, FileNotFound };
Even if the texture is sitting in the graphics cards VRAM the GPU has to do a fair amount of work when the texture is changed. Caches are flushed, data has to be shifted about, states setup etc.

So, yes, while a shader change is more expensive texture changes can hurt as well which is why its advised to minmise them.
Quote:Original post by hplus0603
Binding a new vertex program, or even worse, fragment program, is likely to cause a far bigger stall in your pipeline than switching textures.


Eh in OpenGL, you can only bind Program Objects which consist of both Vertex and Pixel Shaders, and from the fact that after linking a program object, modifying the original vertex/pixel shaders does not affect the already linked Program Object, am i right to conclude that for OpenGL atleast, sorting by vertex/pixel shaders is of no use and you should instead sort by Program Objects? Because it appears to me that the driver makes a copy of the program object upon linking which is why changes made to the original vertex/pixel shaders do not affect it.

Quote:Original post by GamerSg
Quote:Original post by hplus0603
Binding a new vertex program, or even worse, fragment program, is likely to cause a far bigger stall in your pipeline than switching textures.


Eh in OpenGL, you can only bind Program Objects which consist of both Vertex and Pixel Shaders, and from the fact that after linking a program object, modifying the original vertex/pixel shaders does not affect the already linked Program Object, am i right to conclude that for OpenGL atleast, sorting by vertex/pixel shaders is of no use and you should instead sort by Program Objects? Because it appears to me that the driver makes a copy of the program object upon linking which is why changes made to the original vertex/pixel shaders do not affect it.

You're probably right if you're talking about GLSL Program Objects, but IIRC with the previous shader extensions you could bind just a fragment program or just a vertex program.
Quote:Original post by OrangyTang
IIRC with the previous shader extensions you could bind just a fragment program or just a vertex program.


You are also able to not include either vertex-, or fragment-shader in GLSL program-object. Not to be picky about it, but I couldn't resist ;)

ch.

What if you were to compile your textures into one file?
I suppose having 30 textures in one file is quite large, but what if you had 10 textures in 3 files? It'd probably be even better to logically spearate the tiles with other like tiles. Say, have all the grass textures in one "master grass texture file"?

Then, you could do 3 passes, one with each of the "master texture files" bound. Depending on the texture that needs to be drawn, you could simply alter the texture coordinates of the quad you draw.
Quote:
What if you were to compile your textures into one file?
I suppose having 30 textures in one file is quite large, but what if you had 10 textures in 3 files? It'd probably be even better to logically spearate the tiles with other like tiles. Say, have all the grass textures in one "master grass texture file"?

Then, you could do 3 passes, one with each of the "master texture files" bound. Depending on the texture that needs to be drawn, you could simply alter the texture coordinates of the quad you draw.


The only problem I see with that is that there will be ugly-looking grid lines at the edges of the quads, at least that's what I've experienced when using multiple parts of one image as multiple textures. If anyone can tell me how to fix that, please let me know, its handy.
My Current Project Angels 22 (4E5)

This topic is closed to new replies.

Advertisement