Textures size issue / openGL ES / impossible to generate mipmaps

Started by
4 comments, last by billouparis 12 years, 11 months ago
Hello,

I'm rather a newbie with openGL / openGL ES.
I have one application with lots of objects being rendered in the same scene, and with lots of texture maps based on images.

When i'm rendering my scene with 50 objects (all using different textures), the performances are alright (30 ms),
when rendering 1 more object (so 51 objects), then suddenly I get a drop in performances (500ms), only for one more object added to the scene!

I have very large texture images, like 10 textures are 1024x1024, some are 512x512, and very few are 128x128 or 256x256.
If I reduce the size of the very large textures to 512x512 instead of 1024x1024, then the performances for 51 objects are again ok (30ms). Which basically solves my problem,
but I would really like to understand why there is this drop in performances for only one more texture to draw.

I have also tried to use mipmap textures, by calling the following methods:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture( GL_TEXTURE_2D, textures[indexTextureBuffer] );
glGenerateMipmap(GL_TEXTURE_2D);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexImage2D (GL_TEXTURE_2D, 0,
GL_RGBA, image2.width(), image2.height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, image2.bits());

but this previous code though compiles alright, but then I have a crash when running the application. So I removed the line glGenerateMipmap(GL_TEXTURE_2D);
and changed the two following lines back to:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);


I understand I have a problem with large size texture images, but what I don't understand is why it happens so suddenly, with such a drop in performances when I simply add a texture image (even if it is a large one, there are already other large textures in use), and why my issue is not progressive?
Can somebody point me to some article that could explain this issue to me, so I can understand what openGL is doing at this moment that could explain this drop in performance?

Thank you,
Bill
Advertisement
If you run the card out of texture memory, your OpenGL driver will start trying to swap textures.

If you try and use one which is currently not on the card, it'll throw one out (the least recently used probably) and upload a copy again.

Performance obviously takes a hit because the upload can take a while. This is why it's fast and then suddenly slower. You'll find it'll probably plateau at that point, because the LRU replacement when you're drawing will nastily tend to throw out the very next needed texture so you'll have to upload all the textures.

Image if have space for 3 textures and you draw A then B then C in a frame, followed by A B C next time and so on. Everything is OK. If you try and add a fourth, D, then your drawing sequence might be A B C... then D -- at which point A will be turfed out, D uploaded. Next frame starts, you request A... which needs uploading. B is the least recently used, despite it being the next one you want...

You could probably help the driver out by noticing textures which are only distantly visible and downsizing them. You can resend them with a larger scale when the objects get closer again.
Hello Katie,

from what I read here and there I kinda come to the same conclusion you exposed in your post, thank you so much for detailing the mechanism that may occur.

Now I still need to go further and dig deeper to find answers to the following questions:

1 - how can I know the total amount of texture RAM managed by my GPU,

2 - how can I update the total amound of texture RAM managed by my GPU,

3 - what about texture units, what are they used for exactly, how could they help me in getting better performances,

4 - where is this texture RAM, is it simply a partition of my current board RAM, or has the GPU his own RAM. If it is only a partition, why can't my GPU basically access other part of my RAM, or why does the upload/swapping require so much time, since all my texture images are loaded into RAM in the first place?

5 - why can't I simply use mimaps in openGL ES 2.0?

6 - if I was to use different image sizes for the same texture and use them depending on the distance of the objects on the screen, how can I know this distance to be able to bind the right texture?

Thank you,
Bill
5 - why can't I simply use mimaps in openGL ES 2.0?[/quote]
For mipmapping you should be using:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

The only valid values for GL_TEXTURE_MAG_FILTER are GL_LINEAR or GL_NEAREST; GL_TEXTURE_MIN_FILTER is where you set your mipmapping param.

http://www.opengl.or...exParameter.xml

You're also calling glGenerateMipmap before you specify your texture; move it to after your glTexImage2D call and it should work.

1 - how can I know the total amount of texture RAM managed by my GPU[/quote]
Generally you can't. If texture swapping is a problem for your program (and it might not be if you fix your mipmapping as your driver should only swap in the levels required rather than the full texture) then there are a few other things you can do.

To expand on Katie's example, if you're drawing 16 objects with textures A, B, C, D, depending on the structure of your program, you might be using textures in the following order: A B C D A B C D A B C D A B C D. This will really make the problem a lot worse, so to resolve that you group your objects by texture and draw them in AAAA BBBB CCCC DDDD order. You still get swapping, but you've hugely reduced the number of times per frame that it happens. That's just one example with one solution; other solutions available to you include using texture compression, and breaking really large texture atlasses into smaller ones (swapping in a 256x256 texture will require less overhead and make it less likely that another texture needs to be swapped out to make room for it).

6 - if I was to use different image sizes for the same texture and use them depending on the distance of the objects on the screen, how can I know this distance to be able to bind the right texture[/quote]
I would recommend that you walk away from this idea right now. Fix your mipmapping first (see above) and let the hardware do the job. If nothing else, doing it in software will be horribly inefficient, won't look as good (mipmapping does a bit more than just selecting a downsized texture), and the state changes required will kill your performance.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Really? I thought this would be a neat wheeze.

(Not that I've tried it, tho)

For mipmapping you should be using:glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

The only valid values for GL_TEXTURE_MAG_FILTER are GL_LINEAR or GL_NEAREST; GL_TEXTURE_MIN_FILTER is where you set your mipmapping param.

http://www.opengl.or...exParameter.xml

You're also calling glGenerateMipmap before you specify your texture; move it to after your glTexImage2D call and it should work.


Hello mhagain, and thank you for your answers.
I tried the solution with mipmapping, unfortunately it really does not work for me.
I changed the position of my glGenerateMipmap function call, which allowed me to get rid of the crash I had, which is a good thing.
I used the glTexParameteri function parameters you suggested too.
But the result is quite messy, my textures are not rendered correctly anylonger, there are part of texture missing, or completely mixed up.
Also the rendering performance is very slow, even when I'm using smaller textures that worked without using mipmap.
Maybe I forgot to set another state or something?

Bill
I think I found the problem with my mipmaps, apparently I have to call the glGenerateMipmap just after binding the textures when rendering also, am I right?
Bill

This topic is closed to new replies.

Advertisement