[Fix] (Pipe): give each context's applier its own serial range so backend memos never match another context.

This commit is contained in:
2026-10-03 05:37:51 -04:00
parent 25a76c1b20
commit 393002a46e
2 changed files with 21 additions and 1 deletions
+6
View File
@@ -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<Uint64> 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;
+15 -1
View File
@@ -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