From 0db666897ec16561ecab5ad1f89b5b60f0b2be6e Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 27 Aug 2026 05:47:27 -0400 Subject: [PATCH] [Fix] (DirectGLES): key the border-colour sync memo on the authoritative representation, not just the float one --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 10 ++++++++++ MobileGL/MG_Backend/DirectGLES/Managers.h | 9 ++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index d4caa7f0..92616ba7 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -4613,9 +4613,15 @@ namespace MobileGL::MG_Backend::DirectGLES { // 1132396544, the bit pattern of that float. glTexParameterIiv/Iuiv are ES 3.2 core // beside GL_TEXTURE_BORDER_COLOR itself, so they sit behind the same capability gate; // the entry-point null check covers a driver that advertises the extension without them. + // The redundancy filter has to look at the AUTHORITATIVE representation, not just the + // float one: two integer borders that differ above 2^24 (16777216 and 16777217, say) + // collapse onto the same float, so a float-only comparison would skip the second sync and + // leave the driver holding the first value forever. const auto borderColorForm = stateTextureObject->GetBorderColorForm(); if (!isMultisampleTarget && g_GLESCapabilities.SupportsTextureBorderClamp && (m_cacheBorderColor != stateTextureObject->GetBorderColor() || + m_cacheBorderColorI != stateTextureObject->GetBorderColorI() || + m_cacheBorderColorUI != stateTextureObject->GetBorderColorUI() || m_cacheBorderColorForm != borderColorForm)) { if (borderColorForm == BorderColorForm::Int && g_GLESFuncs.glTexParameterIiv) { const auto& borderColorI = stateTextureObject->GetBorderColorI(); @@ -4634,6 +4640,8 @@ namespace MobileGL::MG_Backend::DirectGLES { g_GLESFuncs.glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColorArray); } m_cacheBorderColor = stateTextureObject->GetBorderColor(); + m_cacheBorderColorI = stateTextureObject->GetBorderColorI(); + m_cacheBorderColorUI = stateTextureObject->GetBorderColorUI(); m_cacheBorderColorForm = borderColorForm; DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); @@ -7941,6 +7949,8 @@ namespace MobileGL::MG_Backend::DirectGLES { m_cacheSamplerParameters.maxAnisotropy = samplerParams.maxAnisotropy; } if (m_cacheSamplerParameters.borderColor != samplerParams.borderColor || + m_cacheSamplerParameters.borderColorI != samplerParams.borderColorI || + m_cacheSamplerParameters.borderColorUI != samplerParams.borderColorUI || m_cacheSamplerParameters.borderColorForm != samplerParams.borderColorForm) { // Same gate as the texture-side border colour above, and the same reason for // branching on the form: an integer border colour must reach the driver through diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index 0fb83025..82ed1c7d 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -1050,10 +1050,13 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint16 m_syncedShapeParamsVersion = 0; SamplerParameters m_cacheSamplerParameters; UintVec2 m_cacheLodRange = {0, 1000}; + // All three representations plus the form, because none of them alone identifies the + // border colour the driver texture is holding: two integer borders can share one float + // (anything differing above 2^24), and a Float -> Int transition can leave every number + // unchanged while still needing a different driver entry point. FloatVec4 m_cacheBorderColor = {0.0f, 0.0f, 0.0f, 0.0f}; - // Which border-colour entry point the driver texture last received. Cached beside the - // value because a Float -> Int transition can leave the numbers unchanged (the derived - // representations are kept in step) while still needing a different driver call. + IntVec4 m_cacheBorderColorI = {0, 0, 0, 0}; + UintVec4 m_cacheBorderColorUI = {0, 0, 0, 0}; BorderColorForm m_cacheBorderColorForm = BorderColorForm::Float; Vec4 m_cacheSwizzleParams = {TextureSwizzleParam::Red, TextureSwizzleParam::Green, TextureSwizzleParam::Blue, TextureSwizzleParam::Alpha};