potential nvidia null VBO pointer crash fix
This commit is contained in:
+31
-7
@@ -69,6 +69,17 @@ public class GLBuffer implements AutoCloseable
|
|||||||
protected boolean bufferStorage;
|
protected boolean bufferStorage;
|
||||||
protected boolean isMapped = false;
|
protected boolean isMapped = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locking on the render thread isn't great, but is needed due to an inconsistent
|
||||||
|
* race condition where VBOs can be marked as deleted outside the render thread. <br><br>
|
||||||
|
*
|
||||||
|
* But, due to being a read-write lock the chance of freezing
|
||||||
|
* the render thread is very low
|
||||||
|
* and since this is a stamped lock, the optimistic read time is basically zero.
|
||||||
|
* (The optimistic lock time doesn't even appear in the profiler).
|
||||||
|
*/
|
||||||
|
public final StampedLock renderStampLock = new StampedLock();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==============//
|
//==============//
|
||||||
@@ -142,14 +153,27 @@ public class GLBuffer implements AutoCloseable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
|
||||||
|
|
||||||
// mark the old data is invalid before deleting to prevent a rare race condition
|
long writeStamp = 0;
|
||||||
// where the queued on render thread task runs before the ID is cleared
|
try
|
||||||
this.id = 0;
|
{
|
||||||
this.size = 0;
|
// lock to prevent the render thread from accessing the buffer's ID
|
||||||
|
// while we are removing it
|
||||||
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
writeStamp = renderStampLock.writeLock();
|
||||||
|
|
||||||
|
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
||||||
|
|
||||||
|
// mark the old data is invalid before deleting to prevent a rare race condition
|
||||||
|
// where the queued on render thread task runs before the ID is cleared
|
||||||
|
this.id = 0;
|
||||||
|
this.size = 0;
|
||||||
|
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
renderStampLock.unlock(writeStamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private static void destroyBufferIdNow(int id)
|
private static void destroyBufferIdNow(int id)
|
||||||
{
|
{
|
||||||
|
|||||||
+35
-23
@@ -341,33 +341,45 @@ public class GlDhTerrainShaderProgram extends GlShaderProgram implements IDhApiS
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't render empty sections
|
|
||||||
if (vbo.getVertexCount() == 0)
|
// for lock information please view the lock's javadocs
|
||||||
|
long vboReadStamp = vbo.renderStampLock.readLock();
|
||||||
|
long iboReadStamp = vbo.getQuadIBO().renderStampLock.readLock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
continue;
|
// don't render empty sections
|
||||||
|
if (vbo.getVertexCount() == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't render deleted VBOs (this will crash the driver/game)
|
||||||
|
if (vbo.getId() == 0
|
||||||
|
|| vbo.getQuadIBO().getId() == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||||
|
int indexCount = (int) (vbo.getVertexCount() * 1.5);
|
||||||
|
|
||||||
|
vbo.bind();
|
||||||
|
vbo.getQuadIBO().bind();
|
||||||
|
|
||||||
|
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
||||||
|
GL32.glDrawElements(
|
||||||
|
GL32.GL_TRIANGLES,
|
||||||
|
indexCount,
|
||||||
|
vbo.getQuadIBO().getGlType(), 0);
|
||||||
|
|
||||||
|
vbo.unbind();
|
||||||
|
vbo.getQuadIBO().unbind();
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
// don't render deleted VBOs (this will crash the driver/game)
|
|
||||||
if (vbo.getId() == 0
|
|
||||||
|| vbo.getQuadIBO().getId() == 0)
|
|
||||||
{
|
{
|
||||||
continue;
|
vbo.renderStampLock.unlock(vboReadStamp);
|
||||||
|
vbo.getQuadIBO().renderStampLock.unlock(iboReadStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
|
||||||
int indexCount = (int)(vbo.getVertexCount() * 1.5);
|
|
||||||
|
|
||||||
vbo.bind();
|
|
||||||
vbo.getQuadIBO().bind();
|
|
||||||
|
|
||||||
GlDhMetaRenderer.INSTANCE.shaderProgramForThisFrame.bindVertexBuffer(vbo.getId());
|
|
||||||
GL32.glDrawElements(
|
|
||||||
GL32.GL_TRIANGLES,
|
|
||||||
indexCount,
|
|
||||||
vbo.getQuadIBO().getGlType(), 0);
|
|
||||||
|
|
||||||
vbo.unbind();
|
|
||||||
vbo.getQuadIBO().unbind();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
Submodule coreSubProjects updated: e465ef5325...d9f3b31cc5
Reference in New Issue
Block a user