5

I'm developing an iPad app that uses large textures in OpenGL ES. When the scene first loads I get a large black artifact on the ceiling for a few frames, as seen in the picture below. It's as if higher levels of the mipmap have not yet been filled in. On subsequent frames, the ceiling displays correctly.

This problem only began showing up when I started using mipmapping. One possible explanation is that the glGenerateMipmap() call does its work asynchronously, spawning some mipmap creation worker (in a separate process, or perhaps in the GPU) and returning.

Is this possible, or am I barking up the wrong tree?

Higher mipmap levels don't exist

brainjam
  • 18,863
  • 8
  • 57
  • 82

3 Answers3

3

Within a single context, all operations will appear to execute strictly in order. However, in your most recent reply, you mentioned using a second thread. To do that, you must have created a second shared context: it is always illegal to re-enter an OpenGL context. If already using a shared context, there are still some synchronization rules you must follow, documented at http://developer.apple.com/library/ios/ipad/#DOCUMENTATION/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithOpenGLESContexts/WorkingwithOpenGLESContexts.html

Frogblast
  • 1,671
  • 10
  • 9
  • Indeed, that clue does explain the problem. `glGenerateMipMaps`, like every other GL call, is guaranteed to be complete before the next GL operation occurs, subject to the caveat that OpenGL is not thread safe and a single context can't be used simultaneously on multiple threads. – Tommy Mar 17 '12 at 06:02
2

It should be synchronous; OpenGL does not in itself have any real concept of threading (excepting the implicit asynchronous dialogue between CPU and GPU).

A good way to diagnose would be to switch to GL_LINEAR_MIPMAP_LINEAR. If it's genuinely a problem with lower resolution mip maps not arriving until later then you'll see the troublesome areas on the ceiling blend into one another rather than the current black-or-correct effect.

A second guess, based on the output, would be some sort of depth buffer clearing issue.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • Good diagnostic suggestion. I'm currently using GL_LINEAR_MIPMAP_NEAREST. – brainjam Mar 15 '12 at 20:23
  • turns out your suggestion helped me solve the problem. Mipmap generation indeed seems asynchronous. – brainjam Mar 16 '12 at 18:49
  • You should report that to Apple; it's a bug per my reading of the specification. Allan Schaffer is the head OpenGL guy and always seems super-nice at WWDC things if you're looking for someone to email directly. – Tommy Mar 16 '12 at 19:04
  • Can you point at what it is in your reading of the specification that makes this a bug? Otherwise I'd be on shaky ground reporting a bug. – brainjam Mar 16 '12 at 19:15
  • I am far from an expert on OpenGL, but the implementation seems to be consistent with http://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf, Sections C.2, C.2.1 – brainjam Mar 16 '12 at 19:25
  • What is being described is a race condition, so it would be contrary to the invariance rules established in Appendix A, amongst other issues. You're guaranteed to get the same output for the same sequence of GL calls, not for the same sequence and timing of GL calls. So e.g the CPU is allowed to take, say, a 30 second break between calls and the output should still be identical. – Tommy Mar 16 '12 at 19:55
1

I followed @Tommy's suggestion and switched to GL_LINEAR_MIPMAP_LINEAR. Now the black-or-correct effect changed to a fade between correct and black.

I guess that although we all know that OpenGL is a pipeline (and therefore asynchronous unless you are retrieving state or explicity synchronizing), we tend to forget it. I certainly did in this case, where I was not drawing, but loading and setting up textures.

Once I confirmed the nature of the problem, I added a glFinish() after loading all my textures, and the problem went away. (Btw, my draw loop is in the foreground and my texture loading loop - because it is so time consuming and would impair interactivity - is in the background. Also, since this may vary between platforms, I'm using iOS5 on an iPad 2)

brainjam
  • 18,863
  • 8
  • 57
  • 82
  • Thank you for following up with your solution. I've been having a similar problem with similarly weird results for a couple of months now. Following your solution of adding a glFinish() after generating the mipmaps fixed everything. Man, what a relief to finally have that fixed! – John Stephen Jun 18 '14 at 21:27
  • I am experiencing the same issue under OSX 10.10.5! Not only that, simple glTexSubImage2D also seems to be async and I must glFlush()/glFinish() else I have artifacts! – user362515 Aug 28 '15 at 15:18