From 41e45f7d480333ee58fbf5c50f580e8ef55a7ba7 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Tue, 4 Aug 2026 09:40:28 -0400 Subject: [PATCH] [Fix] (MG_Impl): let an indexed buffer bind reach the generic binding point too BindBufferBase and BindBufferRange bind the buffer to the indexed point AND to the generic binding point of the same target (GL 4.6 core 6.1.1); only the indexed half was implemented. Applications lean on the second half constantly, because it is what makes the set-up idiom work: glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER, size, nullptr, GL_DYNAMIC_DRAW); With the generic point left at 0 the glBufferData raised GL_INVALID_OPERATION and the buffer kept its zero size, so the later glMapBufferRange over it failed the offset+length bound and returned nullptr. The whole KHR-GL40.texture_gather group verifies its result through exactly that sequence and dereferences the map's return value without checking it, so 51 of its 75 cases took the process down with a SIGSEGV inside the test. Unbinding propagates the same way: buffer 0 clears both points. --- MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp index 4143ce81..d7472ca5 100644 --- a/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Buffer/GL_Buffer.cpp @@ -1366,6 +1366,7 @@ namespace MobileGL::MG_Impl::GLImpl { if (buffer == 0) { point.Bind(nullptr); point.SetRange(Range1D(0, 0)); + GetBufferBindingSlot(bufferTarget).Bind(nullptr); return; } @@ -1384,6 +1385,12 @@ namespace MobileGL::MG_Impl::GLImpl { } else { point.ClearRange(); } + // The indexed bind also binds to the generic binding point of the same target + // (GL 4.6 core 6.1.1). Callers rely on it: the texture_gather tests set up their + // SSBO with BindBufferBase and then size it through glBufferData on the generic + // target alone, which would otherwise raise GL_INVALID_OPERATION and leave the + // buffer with no storage. + GetBufferBindingSlot(bufferTarget).Bind(bufferObject); } void BindBufferRange_State(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) { @@ -1407,6 +1414,7 @@ namespace MobileGL::MG_Impl::GLImpl { if (buffer == 0) { point.Bind(nullptr); point.SetRange(Range1D(0, 0)); + GetBufferBindingSlot(bufferTarget).Bind(nullptr); return; } @@ -1424,6 +1432,8 @@ namespace MobileGL::MG_Impl::GLImpl { } else { point.ClearRange(); } + // Also the generic binding point, exactly as BindBufferBase (GL 4.6 core 6.1.1). + GetBufferBindingSlot(bufferTarget).Bind(bufferObject); } /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */