2

Looks like a driver bug, but I'm not sure ) Or maybe I do something wrong

In my application I use two different threads (and two shared contexts) to upload and render data.

The app sometimes crashes (probably when the workload is higher than average) when the main thread renders (glMultiDrawArraysIndirect), using buffers (the problem is with GL_DRAW_INDIRECT_BUFFER, I suppose) uploaded in another thread.

some simplified pseudocode:

Working thread:

{

    ...
    uploadContext->makeCurrent();
    glCreateBuffers(1, &tile.geometryBuf);
    glNamedBufferStorage(tile.geometryBuf, geometryBuffer.size(), geometryBuffer.constData(), 0);

    glCreateBuffers(1, &tile.indirectBuffer);
    glNamedBufferStorage(tile.indirectBuffer, indirectBuffer.size(), indirectBuffer.constData(), 0);

    glCreateBuffers(1, &tile.settingsBuffer);//);
    glNamedBufferStorage(tile.settingsBuffer, settingsBuffer.size(), settingsBuffer.constData(), 0);    

    //need this for syncronization between threads
    tile.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 
    glFlush();

    emit tileReady(tile); //send a signal to the main thread
}

Main thread:

{
    .....
    renderingContext->makeCurrent();
    ///sync
    GLenum waitReturn = glClientWaitSync(tile.sync, 0, 0);

    if (waitReturn != GL_ALREADY_SIGNALED && waitReturn != GL_CONDITION_SATISFIED)
        return;
    glDeleteSync(tile.sync);

    //binding should validate the buffer in rendering context according to specs (but seems that it doesn't)
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, tile.indirectBuffer);

    //vao is defined during initialization
    //now only change arrayVertexBuffer binding
    glVertexArrayVertexBuffer(vao, 0, tile.geometryBuf, 0, 2 * sizeof(float));
    glBindVertexArray(vao);

    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, tile.settingsBuffer);
    glMultiDrawArraysIndirect(GL_TRIANGLES, 0, tile.counts, 0);
    ....
}

So it crashes sometimes like this:

(Exception thrown at 0x000001CD7121F302 in viewer.exe: 0xC0000005: Access violation reading location 0x0000000000000100)

if I use debug mode there are no GL errors.

It does NOT crash if:

1) I use another GPU (Nvidia Geforce 980 Titan X)

or

2) I change glFlush() to glFinish() in the upload thread

or

3) I comment glMultiDrawArraysIndirect

or

4) Before rendering with GL_DRAW_INDIRECT_BUFFER I insert these lines of code:

glBindBuffer(GL_DRAW_INDIRECT_BUFFER, tile.indirectBuffer);
qint64 sz;
glGetBufferParameteri64v(GL_DRAW_INDIRECT_BUFFER, GL_BUFFER_SIZE, &sz);

(and it takes about 0.4 ms). It seems like there's no problem with SSBO and VertexArrayBuffer.

Config: Windows 10 Pro, 64 bit GeForce GTX 1060 driver version 416.81

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
simpetar
  • 39
  • 2
  • Are you sure `tile.sync` is always a valid value (i.e. even before it gets set in the worker thread)? I'd test it before calling `glClientWaitSync`. Also, why do you wait for `0` ns? I'd use `10` or more. – Ripi2 Dec 19 '18 at 17:30
  • I am not convinced that this is a driver bug (although it might be, of course). None of the variants you reported rule out a race condition or undefined behavior on your side, and without the relevant code, it is impossible to debug this. – derhass Dec 19 '18 at 23:02
  • @Ripi2, yes, sure, I test it. Actualy it's a queue of tiles and some tiles can even be empty. So, tile.sync is nullptr for them, and the rendering thread certainly checks for it. Also every other tile in the queue doesn't even exist in the rendering thread before the signal (emit) is done. I use 0 ns because i don't want to wait for completness, i just break and do other work until next call to this function. Why 10 ns, not 5, not 20? I prefer not to use magic numbers, when i don't need to. – simpetar Dec 20 '18 at 11:25
  • @derhass, the real code is too complicated to post it here. This is only a small part. Maybe you can suggest some other variants to test for debugging. – simpetar Dec 20 '18 at 11:31

0 Answers0