From 3dc6a1b6dbde7e3c5f7bab5c8d507baf82a24a41 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Tue, 4 Aug 2026 09:40:15 -0400 Subject: [PATCH] [Fix] (MG_Impl, DirectGLES): answer the texture-gather offset limit queries glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET) and its GL_MAX_ counterpart fell through to the default arm of the getter and raised GL_INVALID_ENUM, leaving the caller's variable untouched - KHR-GL40.texture_gather.api-enums read back the uninitialised 32764 that happened to be on its stack and failed on the error alone. Both are core state from GL 4.0 (table 23.53) and from ES 3.1 (table 20.40), so the value is simply the host driver's, probed alongside the other limits in FillInGLESCapabilities and carried to the getter through DynamicBackendParameters. The probe result is widened to the -8/+7 core minimums rather than trusted blindly: a driver that leaves the out-parameter alone (no ES 3.1, or an enum it ignores) would otherwise hand us a range narrower than GL 4.0 requires MobileGL to advertise, and the shaders the CTS builds assume the guaranteed range regardless. --- MobileGL/MG_Backend/BackendObject.h | 4 ++++ .../DirectGLES/BackendObject_DirectGLES.cpp | 2 ++ MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp | 6 ++++++ MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp | 12 ++++++++++++ MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h | 2 ++ 5 files changed, 26 insertions(+) diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 14014b3c..38c211fb 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -288,6 +288,10 @@ namespace MobileGL { Int MaxIntegerSamples = 1; Int MaxSamples = 1; Int MaxSampleMaskWords = 1; + // GL_MIN/MAX_PROGRAM_TEXTURE_GATHER_OFFSET. Defaults are the GL 4.0 core + // minimums, which every ES 3.1 driver also guarantees. + Int MinProgramTextureGatherOffset = -8; + Int MaxProgramTextureGatherOffset = 7; Int MaxTextureImageUnits = 32; Int MaxVertexTextureImageUnits = 32; Int MaxComputeTextureImageUnits = 32; diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index a8cea1b5..98c0d163 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -1072,6 +1072,8 @@ namespace MobileGL::MG_Backend::DirectGLES { m_dynamicParameters.MaxIntegerSamples = m_GLESCapabilities.MaxIntegerSamples; m_dynamicParameters.MaxSamples = m_GLESCapabilities.MaxSamples; m_dynamicParameters.MaxSampleMaskWords = m_GLESCapabilities.MaxSampleMaskWords; + m_dynamicParameters.MinProgramTextureGatherOffset = m_GLESCapabilities.MinProgramTextureGatherOffset; + m_dynamicParameters.MaxProgramTextureGatherOffset = m_GLESCapabilities.MaxProgramTextureGatherOffset; // Clamp the advertised sampler limits the same way the DirectVulkan backend does: per-stage // GL_MAX_TEXTURE_IMAGE_UNITS must never exceed host-side fixed arrays sized off it (e.g. // Minecraft's 128-entry Blaze3D GlStateManager.TEXTURES[], iterated by Iris), and the combined diff --git a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp index f9a4e11f..853cd179 100644 --- a/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp +++ b/MobileGL/MG_Impl/GLImpl/Getter/GL_Getter.cpp @@ -1912,6 +1912,12 @@ namespace MobileGL::MG_Impl::GLImpl { case GL_MAX_SAMPLE_MASK_WORDS: *params = dynamicParameters.MaxSampleMaskWords; break; + case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET: + *params = dynamicParameters.MinProgramTextureGatherOffset; + break; + case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET: + *params = dynamicParameters.MaxProgramTextureGatherOffset; + break; case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: *params = static_cast(GetIndexedBufferQueryPointCount(BufferTarget::ShaderStorage)); break; diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp index ff73b843..2e367d80 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp @@ -916,6 +916,10 @@ namespace MobileGL::MG_Util::BackendLoader { GLfloat minFragmentInterpolationOffset = -0.5f; GLfloat maxFragmentInterpolationOffset = 0.4375f; GLint fragmentInterpolationOffsetBits = 4; + // Core minimums of both APIs (GL 4.6 table 23.53, ES 3.1 table 20.40); the probe + // below only ever widens them. + GLint minProgramTextureGatherOffset = -8; + GLint maxProgramTextureGatherOffset = 7; glesFuncs.glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, aliasedLineWidthRange); glesFuncs.glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, smoothLineWidthRange); glesFuncs.glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &smoothLineWidthGranularity); @@ -944,6 +948,12 @@ namespace MobileGL::MG_Util::BackendLoader { // single test case. 1 is a spec-legal value (the minimum required), so cap // to what is actually implemented instead of forwarding the raw driver limit. maxSampleMaskWords = std::min(maxSampleMaskWords, 1); + glesFuncs.glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &minProgramTextureGatherOffset); + glesFuncs.glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &maxProgramTextureGatherOffset); + // A driver that leaves the probe untouched (pre-ES 3.1, or an ignored enum) must not + // drag the advertised range below what GL 4.0 requires of us. + minProgramTextureGatherOffset = std::min(minProgramTextureGatherOffset, -8); + maxProgramTextureGatherOffset = std::max(maxProgramTextureGatherOffset, 7); glesFuncs.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureImageUnits); glesFuncs.glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits); glesFuncs.glGetIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &maxComputeTextureImageUnits); @@ -1027,6 +1037,8 @@ namespace MobileGL::MG_Util::BackendLoader { caps.MaxIntegerSamples = maxIntegerSamples; caps.MaxSamples = maxSamples; caps.MaxSampleMaskWords = maxSampleMaskWords; + caps.MinProgramTextureGatherOffset = minProgramTextureGatherOffset; + caps.MaxProgramTextureGatherOffset = maxProgramTextureGatherOffset; caps.MaxTextureImageUnits = maxTextureImageUnits; caps.MaxVertexTextureImageUnits = maxVertexTextureImageUnits; caps.MaxComputeTextureImageUnits = maxComputeTextureImageUnits; diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h index 45ba3ed3..9971140f 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h @@ -1102,6 +1102,8 @@ namespace MobileGL { Int MaxIntegerSamples = 1; Int MaxSamples = 1; Int MaxSampleMaskWords = 1; + Int MinProgramTextureGatherOffset = -8; + Int MaxProgramTextureGatherOffset = 7; Int MaxTextureImageUnits = 32; Int MaxVertexTextureImageUnits = 32; Int MaxComputeTextureImageUnits = 32;