diff --git a/.github/workflows/apk.yml b/.github/workflows/apk.yml index 0e1a188f..5bd213d3 100644 --- a/.github/workflows/apk.yml +++ b/.github/workflows/apk.yml @@ -216,6 +216,7 @@ jobs: trace_archive: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.tgz trace_file: trace.trace golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725.png + alternate_golden: tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png target_call: 110725 width: 854 height: 480 diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 20067bcd..1cdbeea6 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -744,7 +744,8 @@ namespace MobileGL::MG_Backend::DirectGLES { backendObj->SyncToBackend(currentProgram); } else { if (!backendObj->GetBackendProgramId() || - backendObj->GetSnormFallbackClampOutputMask() != g_snormFallbackClampOutputMask) { + backendObj->GetSnormFallbackClampOutputMask() != g_snormFallbackClampOutputMask || + backendObj->GetUnormFallbackClampOutputMask() != g_unormFallbackClampOutputMask) { backendObj->SyncToBackend(currentProgram); } } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index c7b7e551..e977a09a 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -1332,6 +1332,18 @@ namespace MobileGL::MG_Backend::DirectGLES { } } + static Bool IsUnormFormat(TextureInternalFormat format) { + switch (format) { + case TextureInternalFormat::R16: + case TextureInternalFormat::RG16: + case TextureInternalFormat::RGB16: + case TextureInternalFormat::RGBA16: + return true; + default: + return false; + } + } + static Bool IsSnormFallbackAttachment( const MG_State::GLState::FramebufferAttachmentObject& attachmentObject) { if (attachmentObject.IsTexture()) { @@ -1348,6 +1360,22 @@ namespace MobileGL::MG_Backend::DirectGLES { return false; } + static Bool IsUnormFallbackAttachment( + const MG_State::GLState::FramebufferAttachmentObject& attachmentObject) { + if (attachmentObject.IsTexture()) { + const auto& textureObject = attachmentObject.GetTexture(); + return textureObject && IsUnormFormat(textureObject->GetFormat()) && + TextureImpl::ShouldUseCaveatTextureFormat(textureObject->GetFormat(), textureObject->GetTarget()); + } + if (attachmentObject.IsRenderbuffer()) { + const auto& renderbufferObject = attachmentObject.GetRenderbuffer(); + return renderbufferObject && + IsUnormFormat(renderbufferObject->GetInternalFormat()) && + TextureImpl::ShouldUseCaveatRenderbufferFormat(renderbufferObject->GetInternalFormat()); + } + return false; + } + void BackendFramebufferObject::SyncToBackend( const SharedPtr& stateFBOObject, FramebufferTarget asTarget) { #ifdef TRACY_ENABLE @@ -1399,7 +1427,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } if (asTarget == FramebufferTarget::Draw) { - Uint32 clampOutputMask = 0; + Uint32 snormClampOutputMask = 0; + Uint32 unormClampOutputMask = 0; for (Uint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS && i < 32; ++i) { const auto frontendBuf = stateDrawBuffers[i]; if (frontendBuf < FramebufferAttachmentType::Color0 || @@ -1408,10 +1437,13 @@ namespace MobileGL::MG_Backend::DirectGLES { } const auto& attachmentObject = stateFBOObject->GetAttachment(frontendBuf); if (IsSnormFallbackAttachment(attachmentObject)) { - clampOutputMask |= (1u << i); + snormClampOutputMask |= (1u << i); + } else if (IsUnormFallbackAttachment(attachmentObject)) { + unormClampOutputMask |= (1u << i); } } - PrgramImpl::g_snormFallbackClampOutputMask = clampOutputMask; + PrgramImpl::g_snormFallbackClampOutputMask = snormClampOutputMask; + PrgramImpl::g_unormFallbackClampOutputMask = unormClampOutputMask; } // 2. Remap read buffer @@ -1527,6 +1559,7 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace PrgramImpl { Uint32 g_snormFallbackClampOutputMask = 0; + Uint32 g_unormFallbackClampOutputMask = 0; StateBackendObjectRegistry g_backendProgramObjects; BackendProgramObjectImpl::BackendProgramObjectImpl() { @@ -1572,6 +1605,7 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("Syncing program to backend. State program ID: %u, Backend ID: %u", stateProgramObject->GetExternalIndex(), m_backendProgramId); m_snormFallbackClampOutputMask = g_snormFallbackClampOutputMask; + m_unormFallbackClampOutputMask = g_unormFallbackClampOutputMask; // Detach all existing shaders GLint attachedCount = 0; @@ -1647,8 +1681,9 @@ namespace MobileGL::MG_Backend::DirectGLES { source = ForceFlatIntegerVaryings(source, glShaderType); source = EmulateBaseInstanceInVertexShader(std::move(source), glShaderType); source = ForceSupporterOutput(source); - source = ClampSnormFallbackOutputs(std::move(source), glShaderType, - m_snormFallbackClampOutputMask); + source = ClampNormFallbackOutputs(std::move(source), glShaderType, + m_snormFallbackClampOutputMask, + m_unormFallbackClampOutputMask); // Patch for Photon compiler precision issue String findStr = "1000000.0"; diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index 3fcfe7c3..59ee09ff 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -285,16 +285,19 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint GetBackendProgramId() const { return m_backendProgramId; } Uint GetBackendGlobalUBOId() const { return m_backendGlobalUBOId; } Uint32 GetSnormFallbackClampOutputMask() const { return m_snormFallbackClampOutputMask; } + Uint32 GetUnormFallbackClampOutputMask() const { return m_unormFallbackClampOutputMask; } private: Uint m_backendProgramId = 0; Uint m_backendGlobalUBOId = 0; Int m_baseInstanceUniformLocation = -1; Uint32 m_snormFallbackClampOutputMask = 0; + Uint32 m_unormFallbackClampOutputMask = 0; Bool m_isInitialized = false; }; extern Uint32 g_snormFallbackClampOutputMask; + extern Uint32 g_unormFallbackClampOutputMask; extern StateBackendObjectRegistry g_backendProgramObjects; } // namespace PrgramImpl diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index d4002920..7662e927 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -214,10 +214,12 @@ namespace MobileGL::MG_Backend::DirectGLES { return result; } - String ClampSnormFallbackOutputs(String glslCode, GLenum shaderType, Uint32 outputMask) { + String ClampNormFallbackOutputs(String glslCode, GLenum shaderType, Uint32 snormOutputMask, + Uint32 unormOutputMask) { #ifdef TRACY_ENABLE ZoneScopedC(TRACY_ZONECOLOR_BACKEND); #endif + const Uint32 outputMask = snormOutputMask | unormOutputMask; if (shaderType != GL_FRAGMENT_SHADER || outputMask == 0) { return glslCode; } @@ -226,14 +228,18 @@ namespace MobileGL::MG_Backend::DirectGLES { R"(layout\s*\(\s*location\s*=\s*([0-9]+)\s*\)\s*out\s+(?:(?:lowp|mediump|highp)\s+)?vec4\s+([A-Za-z_][A-Za-z0-9_]*)\s*;)"); std::sregex_iterator outputIt(glslCode.begin(), glslCode.end(), outputPattern); std::sregex_iterator outputEnd; - Vector outputNames; + struct OutputClamp { + String Name; + Bool Signed; + }; + Vector outputClamps; for (; outputIt != outputEnd; ++outputIt) { const Uint location = static_cast(std::stoul((*outputIt)[1].str())); if (location < 32 && (outputMask & (1u << location))) { - outputNames.push_back((*outputIt)[2].str()); + outputClamps.push_back({(*outputIt)[2].str(), static_cast(snormOutputMask & (1u << location))}); } } - if (outputNames.empty()) { + if (outputClamps.empty()) { return glslCode; } @@ -252,9 +258,10 @@ namespace MobileGL::MG_Backend::DirectGLES { --depth; if (depth == 0) { String clampLine; - for (const String& outputName : outputNames) { - clampLine += "\n " + outputName + " = clamp(" + outputName + - ", vec4(-1.0), vec4(1.0));"; + for (const OutputClamp& outputClamp : outputClamps) { + const String minValue = outputClamp.Signed ? "-1.0" : "0.0"; + clampLine += "\n " + outputClamp.Name + " = clamp(" + outputClamp.Name + + ", vec4(" + minValue + "), vec4(1.0));"; } clampLine += "\n"; glslCode.insert(pos, clampLine); diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index d032a500..484a8d0f 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -48,7 +48,8 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace PrgramImpl { String ProcessOutColorLocations(const String& glslCode); String ForceSupporterOutput(const String& glslCode); - String ClampSnormFallbackOutputs(String glslCode, GLenum shaderType, Uint32 outputMask); + String ClampNormFallbackOutputs(String glslCode, GLenum shaderType, Uint32 snormOutputMask, + Uint32 unormOutputMask); String ForceFlatIntegerVaryings(const String& glslCode, GLenum shaderType); String RemoveLayoutBinding(const String& glslCode); } // namespace PrgramImpl diff --git a/tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png b/tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png new file mode 100644 index 00000000..951f773e --- /dev/null +++ b/tools/trace_replay/fixtures/minecraft-1.21.4-fabric-iris-bsl-in-world.0000110725-mali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e644b5e9ca8b93f0587151ef9920a27596d7eda802e87efb4765b367c4a303e +size 606400