Vangoule
Vangoule

Reputation: 155

C++ OpenGL Threaded Terrain Crashing

enter image description here

What the aim is:

I'm relatively new to threading. I've been trying to make Quad-Tree rendered terrain which will render fast and efficiently. The amount of terrain which is currently rendered would lag the user majorly if it was all at the maximum detail. This is why I've used a QuadTree to render it. The engine also supports Input and Physics therefore I decided to use a rendering thread. This has caused lots of problems.

The problem('s): When i wasn't threading there was a bit of lag due to the other systems in the Engine. The main one that caused the lag is the loading and deletion of terrain in the QuadTree (I'm not even sure if this is the optimal way to do it.) Now, Rendering happens very fast and it doesn't seem to lag. When the camera is standing still the game runs fine. I left the game running for an hour and no crashes were found.

When terrain is loaded it uses several of the variables the rendering code uses. Namely, binding the buffers -

    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW);

This variable I believe is being accessed at the same time as the other thread. Which causes a crash. How does one fix this? I have tried using Mutexes but this doesn't seem to work. Where would I lock and unlock the mutex to fix this?

Another variable that seem to cause the same error are "IsLeaf".

Another crash (std::badAlloc) is caused after loading a lot of terrain. Even though it's beeing cleaned up. I assume this is due to my deletion code but I don't know whats wrong.

The way I currently add and delete the tiles is I check the range from the camera and delete/create the tile. I want to render the tile i'm on and the ones around it. However, this doesn't work when transitioning from one of the 4 main tiles. Creating by using the range doesn't work as it's the range to the center of the big tile rather than the smaller ones. I've also tried deleting the whole map every few seconds and this seems to work too but with more lag. Is there a better way to do the creation and destruction?

Between different resolutions there are gaps. Is there anyway to reduce these? Currently i render the tiles a little larger than they need to be but this doesn't help on major resolution changes.

If you have any idea how to fix one of these errors it'd be much appreciated.

The code (Too much to upload here)

http://pastebin.com/MwXaymG0

http://pastebin.com/2tRbqtEB

Upvotes: 1

Views: 848

Answers (1)

Andy Esser
Andy Esser

Reputation: 287

An OpenGL context can only be bound to one thread at a time (through wglMakeCurrent() on Windows).

Therefore you should not being using gl* functions across threads, even if you use Mutexes to secure access to certain variables in memory the calls will fail.

What I would suggest is to move your gl* calls into your rendering thread, however, have things such as terrain loading, frustum calculations, clipping etc in your other thread. The rendering thread just needs to check whether an object has new data and then perform the appropriate GL calls as part of it's update/render.

Upvotes: 5

Related Questions