From 2271f6c1ecf8a2d498fc9ca87a8b901f86115800 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 29 Sep 2026 04:07:35 -0400 Subject: [PATCH] [Fix] (Remote, P10 B): GL_KHR_parallel_shader_compile follows the client's compile switch - the caps mirror re-derives it on adoption, so a tcp server started with another MOBILEGL_ASYNC_SHADER_COMPILE no longer decides the client's string --- MobileGL/MG_Remote/Client/CapsMirror.cpp | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/MobileGL/MG_Remote/Client/CapsMirror.cpp b/MobileGL/MG_Remote/Client/CapsMirror.cpp index 2301e012..72bd14fe 100644 --- a/MobileGL/MG_Remote/Client/CapsMirror.cpp +++ b/MobileGL/MG_Remote/Client/CapsMirror.cpp @@ -36,8 +36,10 @@ #include // MG_Config::SplitTransportRequestedByConfig #include // MGPipeServerArm, D1c's role predicate #include +#include #include +#include #include namespace MobileGL::MG_Remote::Client { @@ -66,6 +68,36 @@ namespace MobileGL::MG_Remote::Client { "beat the handshake", what); } + + // P10 B: GL_KHR_parallel_shader_compile IS THE CLIENT'S EXTENSION, SO THE CLIENT DECIDES + // IT. Both backends put it in their list when THEIR process compiles asynchronously + // (BackendObject_DirectGLES.cpp / BackendObject_DirectVulkan.cpp, "MobileGL's own + // capability"), but under split the process that compiles is this one: the pool, its + // threads, glMaxShaderCompilerThreadsKHR and GL_MAX_SHADER_COMPILER_THREADS_KHR + // (GL_Getter.cpp) all live in the frontend, and the server only ever sees the archive. + // Taking the server's word advertised the string from the SERVER's configuration - + // under inproc and spawn the server inherits this process's environment and the two + // agree by accident; a tcp server is started on its own and they need not. Measured: + // AsyncCompileScenario.ExtensionStringMatchesTheConfiguration with + // MOBILEGL_ASYNC_SHADER_COMPILE=0 on the client and a default (async-on) tcp server + // read the string advertised and the thread count 0, on both backends. So the entry is + // re-derived here from this process's switch, on every adoption. + void ReconcileClientCompileExtensions(RendererInfo& renderer) { + Vector& extensions = renderer.RendererGLInfo.Extensions; + const auto found = + std::find(extensions.begin(), extensions.end(), E_GL_KHR_parallel_shader_compile); + const Bool advertised = found != extensions.end(); + const Bool compilesAsync = MG_Util::Async::AsyncShaderCompileEnabled(); + if (advertised == compilesAsync) return; + if (compilesAsync) { + extensions.push_back(E_GL_KHR_parallel_shader_compile); + } else { + extensions.erase(found); + } + MGLOG_D("MG_Remote client: GL_KHR_parallel_shader_compile %s - the server's list said the " + "opposite, and the compile pool it describes is this process's", + compilesAsync ? "advertised" : "withdrawn"); + } } // namespace void CapsMirror::Adopt(const MG_Pipe::MGPCaps& caps, const MG_Backend::FormatCapabilityCache& formats, @@ -80,6 +112,7 @@ namespace MobileGL::MG_Remote::Client { m_caps.RendererInfo = MG_Pipe::MGPBlobRef{}; m_formats = formats; m_renderer = renderer; + ReconcileClientCompileExtensions(m_renderer); m_apiVersion = apiVersion; m_backend = backend; ++m_generation;