views:

790

answers:

6

This is a very vague problem, so please feel free to clarify anything about this project.

I'm working on a very large application, and recently a very perplexing bug has cropped up regarding the texturing. Some of the textures that we are loading are being loaded - I've stepped through the code, and it runs - but all OpenGL renders for those textures is a weird Pink/White striped texture.

What would you suggest to even begin debugging this situation?

  • The project is multithreaded, but a mutex makes sure all OpenGL calls are not interrupted by anything else.
  • Some textures are being loaded, some are not. They're all loaded in the exact same way.
  • I've made sure that all textures exist
  • The "pink/white" textures are definitely loaded in memory - they become visible shortly after I load any other texture into OpenGL.

I'm perplexed, and have no idea what else can be wrong. Is there an OpenGL command that can be called after glTexImage that would force the texture to become useable?

Edit: It's not about the commands failing, it's mainly a timing issue. The pink/white textures show up for a while, until more textures are loaded. It's almost as if the textures are queued up, and the queue just pauses at some time.

Next Edit: I got the glIntercept log working correctly, and this is what it outputted (before the entire program crashed)

http://freetexthost.com/1kdkksabdg

Next Edit: I know for a fact the textures are loaded in OpenGL memory, but for some reason they're not rendering in the program themselves.

A: 

Check the size and compression of those images you use as textures. i think opengl texture size has to be a power of 2 ...

jose
OpenGL supports NPOT textures assuming your graphics card does. Most cards made in the last 6-7 years or so support NPOT textures.
Ron Warholic
They don't have to be, that's a suggestion for most older video cards. That said, in my case it's a timing issue, as the textures do eventually load properly.
Andrei Krotkov
Not if you have the ARB_texture_non_power_of_two extension, and it is pretty common now.
Trillian
+3  A: 

If your texture is colored incorrectly most likely you're loading the wrong order of RGB. Make sure in your glTexImage2D you're using the right enums for your image format. Make sure the number of components is correct and that you're getting the order of your RGB pixels in the format argument right.

Although probably not related to your textures showing up wrong, OpenGL doesn't support multithreaded draws so make sure you're not doing any drawing work on a different thread than the one that owns the context.

Edit: Do you have a reference renderer so you can verify the image pixels are being loaded as expected? I would strongly recommend writing a small routine to load then immediately save the pixels to a file so you can be sure that you're getting the right texture results.

Ron Warholic
The pixels are being loaded, but not being updated into OpenGL until multiple draws requesting that picture exist. The reason I know this is that the pink/white textures are replaced by the actual texture requested, but only after more textures are loaded. The reason I know it's not the loading is because the same pink/white texture is consistent - it shows up the same way in ALL textures that didn't load properly, for whatever reason.
Andrei Krotkov
What is your threading set up? You're not calling any gl*** functions out of thread correct?
Ron Warholic
Give glIntercept a try, it replaces your opengl32.dll with one that logs the call history to a file. Make sure your calls are happening in the correct order.
Ron Warholic
Also what happens when you create a texture in the code (just make an all red/green image) and load that, does it still show up as pink/white for a time? I'm thinking the pink/white texture is just what's in memory at that location until the load operation actually occurs.
Ron Warholic
glIntercept causes our program to crash without ever displaying a single thing...
Andrei Krotkov
Are you using the fixed function pipeline? glIntercept really shouldn't crash so it might be an indicator you're calling a function in a way that you shouldn't be (cross thread or out of context).
Ron Warholic
I believe the error it gave before crashing was that functions were being called out of context - unfortunately that's very old code that I wasn't on the project for, so I have no idea why it doesn't explode on the normal OpenGL dlls.
Andrei Krotkov
Curious, have you tried the glFlush as suggested by Mr. Berna? Otherwise I can only speculate that you have context ownership issues since there really isn't much other explanation for the behaviour you're seeing.
Ron Warholic
I got the glIntercept output from the program - there's a few interesting jumps, but which ones are harmful, and which ones are harmless? Is loading textures inside display lists frowned upon? Inside quads? Between glGetString calls?
Andrei Krotkov
It all depends unfortunately--the only surefire way to check is to head over to opengl.org and read the documentation on each suspect function. At the least I do know it's illegal to call many operations between a glBegin() and glEnd(). There are additional limitation for display lists as well.
Ron Warholic
+1  A: 

When you say:

The project is multithreaded, but a mutex makes sure all OpenGL calls are not interrupted by anything else.

This doesn't sound like strong enough protection to me: remember that OpenGL is a state machine with a large amount of internal state. You need to make sure the OpenGL state is what you expect it to be when you are making your calls, and that certain sequences of calls don't get interrupted with by calls from other threads.

I'm no expert on OpenGL thread-safety, but this seems to me where your problem might lie.

Autopulated
Well stated - the direction I'm taking to try to resolve it is to get it working with GLTrace, to see if it would give more information. Which state variables would affect when a texture would be available?
Andrei Krotkov
+1  A: 

Check your texture coordinates. If they are set wrong, you can see just one or two texels mapped to entire primitives. Remember, OpenGL is a state machine. Check if you're changing the texture coordinate state at the wrong time. You may be setting the texture coordinates at a later point in your code, then when you get back to redrawing these elements the state is acceptable for mapping your texture to the code.

If it is merely a timing issue where the texture loading OpenGL calls aren't executed in time, and your threading code is correct, try adding a call to glFlush() after loading the textures. glFlush() causes all pending OpenGL commands to execute.

Mr. Berna
The first part is definitely not the problem, as the texture coordinates are never actually changed between them working and not. Are there any side effects to calling glFlush in the middle of a render loop?
Andrei Krotkov
I have no idea why adding glFlush worked, but it did, so you get the accepted! I would love to know why, though. It also sped up the program like fivefold.
Andrei Krotkov
What was almost certainly happening was that you were seeing the buffering delay for the glTexImage2D--it was reading memory that had not been initialized for several frames due to the way your draw calls are set up. This is typically only a big problem if you're using display lists since they are compiled and may do things in a way you don't expect.
Ron Warholic
I wasn't aware there was any delay on glTexImage2D - it seems like a blocking function in all of its' behaviors.
Andrei Krotkov
Read the documentation on glFlush--even the glFlush call itself may not block for the entirety of processing! http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml
Ron Warholic
In OpenGL's client/server model, the main program, the client, issues commands that are then passed to the OpenGL server. All OpenGL commands can be non-blocking, meaning you can issue a new command or continue with your main program's execution before OpenGL completes the last command. glFlush says to OpenGL, "Do everything I've told you to do so far before starting to work on anything else." Because GPUs are parallel processors, OpenGL implementations can be multithreaded on the GPU. The texture loading code was doing its thing on one thread, while OpenGL continued to execute commands.
Mr. Berna
A: 

You can't load a texture in a thread and use it in other different thread because you will see a beautiful white texture. To do this possible you must load the OpenGL context in between differents threads before use any OpenGL function.

jfcalvo
A: 

If you are using GLIntercept to check your code, ensure to enable: ThreadChecking = True; in the gliConfig.ini file.

Viewing the log it seems that quite a few OpenGL calls are being main outside the main context.

Damian Trebilco