From 2a0ae743a03cc8480e49ae510e51ca8b5c3fc5e7 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 21 Jul 2026 03:34:33 -0400 Subject: [PATCH] [Fix] (DirectGLES): glFinish before the glGetTexImage temp-FBO readback - Mali (tile-based) does not resolve a texture's render into memory when it is read back through a different (temp) FBO than the one it was rendered with - The cross-FBO glReadPixels raced the deferred tile resolve and returned pre-render clear contents - Distinct render targets read back byte-identical, so KHR-GLxx.glsl_noperspective failed on Mali-G715 (all four programs read as the clear colour) - glGetTexImage is already a CPU/GPU sync point so the extra drain is negligible; Adreno resolves eagerly and was unaffected --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 1bf839b1..b19dff69 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -4002,6 +4002,15 @@ namespace MobileGL::MG_Backend::DirectGLES { GLuint backendTexId = backendTextureIt->second->GetBackendTextureId(); MGLOG_D("GetTexImage: backend texture id = %u", backendTexId); + // Force pending rendering to complete before reading the texture back through the temp READ FBO. + // Tile-based GPUs (Mali) do not guarantee that a render into this texture through its own FBO has + // been resolved to memory when it is subsequently sampled through a *different* (temp) FBO: the + // cross-FBO glReadPixels below races the deferred tile resolve and returns the pre-render (clear) + // contents, so distinct render targets read back byte-identical (e.g. KHR-GLxx.glsl_noperspective + // fails on Mali-G715, all four programs reading as the clear colour). glGetTexImage is already a + // CPU/GPU sync point, so the extra drain is negligible; Adreno resolves eagerly and is unaffected. + g_GLESFuncs.glFinish(); + MGLOG_D("GetTexImage: Binding temporary FBO"); TempFBOBinder tempFBOBinder(true);