summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorMike <contact@mikelittman.me>2026-10-14 00:03:37 -0500
committerGitHub <noreply@github.com>2026-10-14 13:03:37 +0800
commit9cc783022a202a1d00b5dc8eaf01ffddbc9fa39f (patch)
tree9a5b23fb63c2e09d1815d913272f7a17f96750e4 /indra
parent1b7d456077ba61c987fc06561e30127a1cc18968 (diff)
Stop Apple OpenGL from waiting on a null fence (#34)
glFinish and glWaitSync both crash in GLDFenceRec::getStatus when the fence record is null. On Apple, flush texture uploads instead and do not call glFinish before deleting buffers.
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llimagegl.cpp52
-rw-r--r--indra/llrender/llvertexbuffer.cpp7
2 files changed, 34 insertions, 25 deletions
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 82bc00fe7a..b01c81fc28 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1855,31 +1855,41 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
// post a sync to the main thread (will execute before tex name swap lambda below)
// glFlush calls here are partly superstitious and partly backed by observation
// on AMD hardware
- glFlush();
- auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- glFlush();
- if (sync)
+ if (gGLManager.mIsApple)
{
- LL::WorkQueue::postMaybe(
- mMainQueue,
- [=]()
- {
- LL_PROFILE_ZONE_NAMED("cglt - wait sync");
- {
- LL_PROFILE_ZONE_NAMED("glWaitSync");
- glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
- }
- {
- LL_PROFILE_ZONE_NAMED("glDeleteSync");
- glDeleteSync(sync);
- }
- });
+ // Apple's GL/Metal translator faults in GLDFenceRec::getStatus
+ // (null fence, address 0x24) while executing glWaitSync.
+ // glFenceSync and glFinish both enqueue that wait. Flush the
+ // upload onto the serial OpenGL queue and let the main thread
+ // issue later commands behind it.
+ glFlush();
}
else
{
- // glFenceSync failed. glWaitSync(0) is dispatched to Apple's
- // OpenGL thread, which faults in GLDFenceRec::getStatus.
- glFinish();
+ glFlush();
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ if (sync)
+ {
+ LL::WorkQueue::postMaybe(
+ mMainQueue,
+ [=]()
+ {
+ LL_PROFILE_ZONE_NAMED("cglt - wait sync");
+ {
+ LL_PROFILE_ZONE_NAMED("glWaitSync");
+ glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ }
+ {
+ LL_PROFILE_ZONE_NAMED("glDeleteSync");
+ glDeleteSync(sync);
+ }
+ });
+ }
+ else
+ {
+ glFinish();
+ }
}
}
}
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index a827927809..6a885d2a09 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -317,14 +317,13 @@ static void delete_buffers(S32 count, GLuint* buffers)
{
if (gGLManager.mIsApple)
{
- // Apple's GL/Metal translator crashes in GLDFenceRec::getStatus
- // (null fence, fault at +0x24) when glDeleteBuffers waits on a
- // sync that was never created. Unbind and finish first.
+ // Unbind, then delete one name at a time. Do not glFinish():
+ // that drains a queued glWaitSync and faults in
+ // GLDFenceRec::getStatus when Apple's fence record is null.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
LLVertexBuffer::sGLRenderBuffer = 0;
LLVertexBuffer::sGLRenderIndices = 0;
- glFinish();
for (GLuint name : sFreeList[idx])
{
if (name)