substituting textures while loading into memory

Started by
12 comments, last by Sneftel 15 years, 9 months ago
Hello, I have a bunch of texture data that spills over the memory limit on modern graphics cards. Currently it is apparent that they are loading in and out because of the pauses I see in rendering. In my case, it would be satisfactory to use a low resolution texture as a temporary placeholder until the full-resolution texture is loaded onto the card. (An effect similar to how "google maps" shows low-res tiles of the earth until the high-res one is downloaded) What I have found on this forum/internet so far has mostly been warnings not to meddle with texture memory management. Is what I described above a feasible thing to do with opengl? Additionally, what functions in opengl would expose loading/unloading of textures from the card's memory? The only thing I really would need to do is substitute a low-res texture (which would permanently reside in the texture memory) when the high-res one is not in the memory at the time. I wouldn't want to interfere with the loading/unloading of the high-res textures, just show a placeholder when appropriate so I can keep rendering without pauses while the texture loads into the memory. Thanks
Advertisement
That's kind of tough. If you calculate and see that the object is far then it can use a low resolution texture. So, you make 2 texture, low resolution with all mipmaps and high resolution with no mipmaps.

It won't be long for a newb to come and suggest glAreTexturesResident but this function gives TRUE always on some implementations.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
are u using texture compression?
perhaps also disable mipmaps for some tetxures (though this may incur a performance lose + only save ~33% memory)
I am using DXT1 compression for my textures so far. If I can get this substitution thing working (still no progress yet), then I actually plan to add over 500MB of additional DXT1 compressed textures to my program. I don't think I can solve my problem by trying to squeeze down my current textures...there is just too much data that I want to include.

The goal is to suffer no pauses while waiting for textures to load. If the texture that is needed is not available, then I would like to use a small "emergency" placeholder texture and keep rendering until the proper texture is ready to use.

If you are curious for some background on what I am doing, I am trying to make a geography like program with a 3D globe as its centerpiece. In the case that one is zoomed in quite close, you need high-res textures, but it only makes sense to bother loading them if you stay in one spot long enough. So if you are scrolling around quickly, I would rather have the scene keep rendering with poor images than freeze for each new tile on the earth that you scroll past.

(and yes I am aware of worldwind. I'm trying to investigate how it works, but the documentation is not that thorough and it's sdk is still beta)
DXT1...

When do you do the texture compression?
I do that with opengl calls right after I load the textures from file and before I start rendering. For easy of editing at the moment, I have my textures in .png format. I am able to load them into my program rather easily since I am using jogl. If I understand, I could save my files in DDS format already compressed. At some point I will look into this possibility, but this should be irrelevant to what I am aiming to do right now.

edit: I haven't looked into how this would be done in C, but these are the lines of jogl code for the compression:
TextureData tempData = TextureIO.newTextureData(file, true, null);
tempData.setInternalFormat(GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT);

I am confident that I am compressing the textures due to differences in program behavior when I omit the 2nd line.
Quote:Original post by dsr12
At some point I will look into this possibility, but this should be irrelevant to what I am aiming to do right now.


You are looking for performance (at least... performance related), right? So, you should do it right first, otherwise, it is meaningless to discuss performance. And, S3TC compression will definitely take a measurable time to completed.
And, if the texture has to be loaded from harddisk on the ride, pre-compressing the texture will save you even more processing time.
Let me clarify about what I seek help on. I do not need to improve the loading time for my program when it initializes. Perhaps I will have pre-compressed DDS files for my textures instead of .png in the future, but that isn't important for me right now. Spending time converting my files into compressed DDS and writing the code to load them doesn't do a single thing toward fixing my problem that I outlined in my first post.

What I need some guidance on is approaching the problem of eliminating pauses in the rendering as my textures are loaded into the video RAM in the course of my program's execution. If a given texture is not in the video ram (because all of them together cannot fit in there), my program essentially freezes up for a while until that texture is resident I presume. I do not know if there are canonical solutions for this, but as I said previously I would be interested in exploring the technique of showing a small substitute placeholder texture until I have the large texture available in the video RAM.

The first holdup for this, assuming it is a valid proposal, is being able to reliably determine if a texture is in the video memory. Given that glAreTexturesResident() does not always work, what other options are there?
Loading a texture takes time, what do you want to do, slowly load small portions of it, update/render the frame, and continue where you left off from loading the large texture? I would have suggested using OpenGL to lower the quality of the texture but that doesn't change how much memory is needed to store the image. Sorry I can't really help too much =
Also, for my texture manager, I have a little class Texture that has string path; and GLuint index;. I have a vector<Texture> that holds all the textures I've loaded. If the filepath already exists in the vector, it's already been loaded. If it hasn't, I glGenTextures, load the image, and push_back. When I want to bind it, I just loop through the texture array for the filepath texture I want and it returns its index. For deleting I just glDeleteTextures and erase that spot in the vector.
DXT5 will save you quite a bit of memory. You're likely running into issues of compressing the file already loaded into memory onto the card. What you want to do is make your textures as small as possible while retaining as much detail as possible. A higher level of compression will allow this, such as DXT5. Pre-compressing just makes life easier and loading of the data faster (have you verified it's not the file loading + in memory compression + uploading to the card that's the issue? Cause that is a lot of cycles wasted). But even if you do DXT5 compression on the fly you'd likely see less swapping from system memory to video memory period. Until you fill that "extra" space with more textures as you said you would lol.

Writing a .png -> .dds converter that does all files in a given directory should take an hour and then getting a .dds loader up and running should take less time. But skipping that doing the DXT5 in memory compression should help you save space.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

This topic is closed to new replies.

Advertisement