From 393002a46e0432bb04b2b1667869a9d6aec79d8f Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 3 Oct 2026 02:25:58 -0400 Subject: [PATCH] [Fix] (Pipe): give each context's applier its own serial range so backend memos never match another context. --- MobileGL/MG_Pipe/PipeApply.cpp | 6 ++++++ MobileGL/MG_Pipe/PipeApply.h | 16 +++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Pipe/PipeApply.cpp b/MobileGL/MG_Pipe/PipeApply.cpp index d917d063..a5cc73a1 100644 --- a/MobileGL/MG_Pipe/PipeApply.cpp +++ b/MobileGL/MG_Pipe/PipeApply.cpp @@ -669,6 +669,12 @@ namespace MobileGL::MG_Pipe { thread_local Uint64 t_applierCachedGeneration = 0; } // namespace + Uint64 MGPipeNextApplierSerialBase() { + // Constant-initialized, so the default applier's static construction may already use it. + static std::atomic appliers{0}; + return (appliers.fetch_add(1, std::memory_order_relaxed) + 1) << 40; + } + MGPipeApplierState& MGPipeApplier() { const MGPipeApplierKeyResolver resolve = g_applierKeyResolver; if (resolve == nullptr) return g_defaultApplier; diff --git a/MobileGL/MG_Pipe/PipeApply.h b/MobileGL/MG_Pipe/PipeApply.h index 71e52c2b..39f9b7e4 100644 --- a/MobileGL/MG_Pipe/PipeApply.h +++ b/MobileGL/MG_Pipe/PipeApply.h @@ -938,6 +938,15 @@ namespace MobileGL::MG_Pipe { }; + // P14: where a new applier's working-state serials start. Each applier (one per served context) + // gets a range of its own, 2^40 values wide, so no two appliers ever answer with the same serial: + // the backends key process-wide memos on these serials (a texture sync list on ContextSerial and + // SamplerViewsSerial, the synced framebuffer binding on FramebufferSerial, ...), and one apply + // thread serves every context of its session. With every applier counting from 0, two contexts + // at the same point of their lives answered the same keys, and a draw in one replayed the memo + // the other had built - its own textures went unsynced and it sampled them empty. + Uint64 MGPipeNextApplierSerialBase(); + // ===================================================================================== // P14 S5: ONE CONTEXT'S APPLIER = ITS OWN WORKING STATE + ITS SHARE GROUP'S RECORDS. // ===================================================================================== @@ -981,7 +990,12 @@ namespace MobileGL::MG_Pipe { TextureResources(objects.TextureResources), RenderbufferResources(objects.RenderbufferResources), SamplerCsos(objects.SamplerCsos), SamplerViewCsos(objects.SamplerViewCsos), ShaderCsos(objects.ShaderCsos), CompositeShaderCsos(objects.CompositeShaderCsos), - FramebufferRecords(objects.FramebufferRecords) {} + FramebufferRecords(objects.FramebufferRecords) { + const Uint64 base = MGPipeNextApplierSerialBase(); + VertexBuffersSerial = IndexBufferSerial = FramebufferSerial = SamplerViewsSerial = base; + SamplerStatesSerial = ShaderImagesSerial = ProgramBindingSerial = ShaderBuffersSerial = base; + TextureShutterSerial = ContextSerial = base; + } // ---- THE THREE FRAMEBUFFER ACCESSORS (ID-19(b)/(d)). They are functions rather than // members because the storage moved under them and their callers must not have to know