From c9d84e33c5e51075e9c6ec7374740fb314cc755c Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 16 Sep 2026 08:11:05 -0400 Subject: [PATCH] [Fix] (DirectGLES/Managers): under an active transport a resource_subdata that finds no twin MINTS one (GetOrCreateBufferResourceForHandle) so its bytes reach the server StagedShadowStore - the twin is otherwise lazy until the first draw (D-A2) and the reduced-path VBO bytes were lost, so the milestone frame rendered a shifted store; monolith keeps the lazy twin (R-11/ID-52 item 3) --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 48cca6f1..37f937a1 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -2093,6 +2093,21 @@ namespace MobileGL::MG_Backend::DirectGLES { const SizeT offset = static_cast(MG_Pipe::MGPipeSubDataBufferOffset(record)); const SizeT size = static_cast(MG_Pipe::MGPipeSubDataBufferSize(record)); auto* resource = FindBufferResourceForHandle(res); +#if MOBILEGL_BUILD_DISAGGREGATED + // R-11 / ID-52 item 3: under an ACTIVE TRANSPORT this record's bytes are the ONLY + // delivery of the buffer's content - the client sends no companion pointer and the + // server has no MappedData to fall back on. But the twin is created LAZILY at the + // first draw (Ops_H_Create is a no-op by D-A2), which is AFTER this record, so a + // subdata that finds no twin would return here and the bytes would be lost - the + // draw then uploads an empty/shifted store (TriangleScenario read a blue triangle + // before this). So under split the subdata MINTS the twin it needs to stage into. + // Monolith is untouched: the twin stays lazy there because the frontend object's + // MappedData is the source and nothing is lost by deferring the allocation (D-A2). + if (resource == nullptr && bytes != nullptr && + MG_Config::Transport != MG_Config::TransportMode::Monolith) { + resource = GetOrCreateBufferResourceForHandle(res); + } +#endif if (!resource) return; // M-2: UNDER pendingMutex, because this line runs BEFORE the CanTouchGLNow() // test below - i.e. on the arm D-A2 deliberately keeps reachable off the render