[Fix] (MG_Backend/DirectGLES, MG_Test/Backend): advertise 32 fragment texture units

- Iris budgets a whole program's samplers against GL_MAX_TEXTURE_IMAGE_UNITS;
  the ES driver's 16 per stage left iterationT with no pipeline on Espryt
- report min(32, max(per-stage, combined)) so unit numbers stay legal
- add CapabilityLimitsTest for the Adreno, narrow and wide cases
This commit is contained in:
2026-10-18 15:55:03 -04:00
parent c4eb620982
commit b4b2ccfe7b
3 changed files with 56 additions and 1 deletions
@@ -1832,8 +1832,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
// 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
// limit must stay within our texture-unit state array capacity.
//
// The fragment limit is raised to the desktop value (32) even where the ES driver counts 16
// per stage: Iris sizes its WHOLE-PROGRAM unit budget off this query (vertex and fragment
// samplers share it, and it refuses the next sampler as soon as the budget is full), so 16
// leaves shader packs such as iterationT without a pipeline at all. Unit NUMBERS up to the
// driver's combined limit are legal in every stage, and a stage that really samples more
// textures than the driver allows still fails at link with the driver's own log.
m_dynamicParameters.MaxTextureImageUnits =
std::min(m_GLESCapabilities.MaxTextureImageUnits,
std::min(std::max(m_GLESCapabilities.MaxTextureImageUnits, m_GLESCapabilities.MaxCombinedTextureImageUnits),
static_cast<Int>(MG_State::GLState::TextureState::MAX_PER_STAGE_TEXTURE_IMAGE_UNITS));
m_dynamicParameters.MaxVertexTextureImageUnits =
std::min(m_GLESCapabilities.MaxVertexTextureImageUnits,
@@ -57,6 +57,11 @@ target_link_libraries(
)
include(GoogleTest)
add_executable(CapabilityLimitsTest CapabilityLimitsTest.cpp)
target_include_directories(CapabilityLimitsTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(CapabilityLimitsTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
gtest_discover_tests(CapabilityLimitsTest DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit)
add_executable(ContextEpochTest ContextEpochTest.cpp)
target_include_directories(ContextEpochTest PRIVATE ${MGL_ROOT}/include ${MGL_ROOT}/MobileGL)
target_link_libraries(ContextEpochTest PRIVATE MobileGLTestMain ${LINK_LIBRARIES})
@@ -0,0 +1,43 @@
// MobileGL - MobileGL/MG_Test/Backend/DirectGLES/CapabilityLimitsTest.cpp
// Copyright (c) 2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#include <gtest/gtest.h>
#include <MG_Backend/DirectGLES/BackendObject_DirectGLES.h>
#include <MG_State/GLState/TextureState/TextureState.h>
using namespace MobileGL;
// Iris budgets every program's samplers (vertex and fragment together) against
// GL_MAX_TEXTURE_IMAGE_UNITS, so an ES driver's 16-per-stage answer leaves shader packs without a
// pipeline. The fragment limit reports the desktop value whenever the driver's combined limit can
// number that many units, and never more than the combined limit or the per-stage cap.
TEST(DirectGLESCapabilityLimits, AdvertisesDesktopFragmentTextureUnitsWhenCombinedLimitAllows) {
constexpr Int kPerStageCap = MG_State::GLState::TextureState::MAX_PER_STAGE_TEXTURE_IMAGE_UNITS;
MG_Backend::DirectGLES::BackendObject_DirectGLES backend;
MG_External::GLESCapabilities adreno;
adreno.MaxTextureImageUnits = 16;
adreno.MaxVertexTextureImageUnits = 16;
adreno.MaxCombinedTextureImageUnits = 96;
backend.ApplyGLESCapabilitiesForTesting(adreno);
EXPECT_EQ(backend.GetDynamicParameters().MaxTextureImageUnits, kPerStageCap);
EXPECT_EQ(backend.GetDynamicParameters().MaxVertexTextureImageUnits, 16);
EXPECT_EQ(backend.GetDynamicParameters().MaxCombinedTextureImageUnits, 96);
MG_External::GLESCapabilities narrowCombined;
narrowCombined.MaxTextureImageUnits = 16;
narrowCombined.MaxCombinedTextureImageUnits = 20;
backend.ApplyGLESCapabilitiesForTesting(narrowCombined);
EXPECT_EQ(backend.GetDynamicParameters().MaxTextureImageUnits, 20);
MG_External::GLESCapabilities wide;
wide.MaxTextureImageUnits = 64;
wide.MaxCombinedTextureImageUnits = 192;
backend.ApplyGLESCapabilitiesForTesting(wide);
EXPECT_EQ(backend.GetDynamicParameters().MaxTextureImageUnits, kPerStageCap);
}