Access Violation when rendering VAO/VBO loaded in background thread

Started by bunkerbewohner, July 26, 2012, 00:16:18

Previous topic - Next topic

bunkerbewohner

Hello there!

I just started playing around with LWJGL this week. But I used to work with OpenGL and C++ years ago. So far everything worked just perfectly.

But now I'm trying to load resources in a background thread. Unfortunately, as soon as I call glDrawArrays on the loaded VBO the program terminates with an Access Violation.

I created a small test case in my current project (written in Scala):
object TestCaseSharedDrawable extends App {

  // Just a Thread that accepts a list of things to be loaded and a callback
  class BackgroundLoader(ls: List[Loadable], callback: ()=>Unit) extends Thread {
    val drawable = new SharedDrawable(Display.getDrawable)

    // Loads all the loadables and calls the callback afterwards
    override def run() {
      // Set OpenGL context for current thread
      drawable.makeCurrent()

      // Load all the loadables
      for (l <- ls) l.load()

      // wait a bit before calling it quits
      Thread.sleep(1000)
      callback()
    }

    def done() {
      drawable.destroy()
    }
  }

  // Init LWJGL / Display
  Display.setTitle("Shared Drawable Test Case")
  Display.setDisplayMode(new DisplayMode(800, 600))
  Display.create()
  GL11.glViewport(0, 0, 800, 600)
  GL11.glClearColor(1f, 0f, 0f, 0)

  // Declare a simple green quad spanning the whole screen
  val vbuffer = VertexBuffer(Quad((-1f,-1f,0f), (1f,1f,0f), (0f,1f,0f,1f)))
  val shader = new Shader("fragment.glsl", "vertex.glsl")
  var loaded = false
  val loader = new BackgroundLoader(List(vbuffer,shader), () => loaded = true)

  // Process command line args
  if (args.length > 0 && args(0) == "single") loader.run() // single threaded loading
  else if (args.length > 0 && args(0) == "multi") loader.start() // background thread for loading
  else loader.start() // default = background thread for loading

  // Game loop just clears the screen and renders the vbuffer as soon as it is loaded
  while (!Display.isCloseRequested) {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT)

    if (loaded)
      vbuffer.render(shader)

    Display.update()
  }

  loader.done()
  Display.destroy()
}


I *think* the rendering and loading code itself, which is hidden behind the load() and render() calls in the example, is not important. However, if you want to check it out, the test "suite" can be downloaded here: https://dl.dropbox.com/u/8671192/Misc/LWJGL-SharedDrawableTest.zip

It contains the executable jar along with two .bat files for the single threaded version (which works) and that one with the background thread (which breaks). Also the most relevant code is included.

I'd be grateful for some hints how to fix this or where the problem lies. I'm aware of possible alternative solutions, but I really want to get the shared context multi-threaded solution to work.

P.S. I executed the BackgroundLoadTest that ships with LWJGL and it works properly. But that's what I took as an example for the background loader anyway. My program crashes on glDrawArrays, which that test doesn't use. As soon as I find the time I will try to extend the test with drawing vertex buffer objects to see if that produces the same result.


Thank you very much for all replies in advance!