The three reverse MGPipeCallbacks entries become the SERVER session's producer callbacks
(Reserve + fill the head + copy the payload inline + PublishEvents; the host pointer never
reaches the wire), installed at Accept and uninstalled at Close, a second installation
over a claimed entry being Fatal{RoleViolation, callback-double-install}. Producers wired:
buffer writeback (the mapped bytes are copied into the record's inline tail instead of a
raw pointer in MGPBlobRef::Offset), GPU-written (Magma's three direct MarkGpuWritten
bypasses are routed through the callback), surface-changed (the backend posts
MGPSurfaceInfo; the client consumer replays the allocate/format writes against
pDefaultFramebufferInfo on the GL thread, where R3's ownership always was), and
kEventGlError = 4 for PipeInputs::RecordError (ordering stays P9's).
PipeInputs::InvalidateCompileEnv's forward is deleted with an active transport - R-12's
caps re-publication already does its job. The consumer's monolith guard is replaced by
the three segment arms (kSegEvent resolves through the session's SegmentTable;
kMGHostSpanSegNone is monolith-only and Fatal{ProtocolCorruption} on the wire; anything
else the same), and DrainEventRing calls the client consumers BY NAME, never through the
global table. Overflow is Fatal{EventRingOverflow} - P5c's events are lossless, P9 owns
the drop policy. Monolith arms keep the pre-P5c expressions character for character.
Evidence: unit 2139/2139 (incl. the new kEventGlError round-trip), integration-split
107/107, monolith GPU subset 24/24; negative control executed - a writeback blobref
reverted to the raw-pointer shape turns DirectGLES.Split.AtomicCounterScenario.
SubDataAfterDispatchSurvivesAnImmediateReadback red with Fatal{ProtocolCorruption,
OnBufferWriteback.Seg}. CONTRACT-P5C sections 1, 4.
- EGL swap semantics make the presented colour buffer's content undefined at
its next acquire (EGL_BUFFER_DESTROYED, the implementation default) and
every ancillary depth/stencil buffer's content undefined after ANY swap,
yet the default-FBO render pass reloaded both with LOAD_OP_LOAD every
frame; SwapchainObject now tracks per-image content validity (defined when
a pass stores into the attachment, invalidated at present) and the
render-pass manager turns an undefined attachment's tile load into
LOAD_OP_DONT_CARE with initialLayout=UNDEFINED, keyed into both hashes so
the cached LOAD variants cannot be hit by mistake
- the default framebuffer's depth attachment is now attached ON DEMAND: a
draw with depth test and stencil test both disabled (GL: a disabled test
neither reads nor writes its buffer), and no pending depth/stencil clear,
resolves to a depth-less pass flavour, dropping the D24S8 tile load AND
store outright - MC 26.2 renders its GUI into its own FBO and only ever
blits colour to the default framebuffer, so its swapchain pass carried a
full-screen depth round-trip for nothing
- the flavour only escalates: an active depth-full pass absorbs depth-less
draws unchanged, while a depth-using draw against a depth-less pass
resolves to an incompatible entry and splits, its depth loading DONT_CARE
(the content was undefined all along); the depth-less flavour is folded
into ComputeHash and the per-draw fast-path memo so the two flavours can
never alias
Moves snapshot capture entirely into the apitrace retrace layer (glReadPixels + PNG encode). Drops the MOBILEGL_PRESENT_DUMP_PATH / MOBILEGL_PRESENT_STATS / MOBILEGL_PRESENT_DUMP_CALL / MOBILEGL_PRESENT_CURRENT_CALL / MOBILEGL_TRACE_CURRENT_CALL_OVERRIDE plumbing from Config, ConfigLoader, VulkanRenderer (GetPresentedDumpPixel/WritePresentedDumpPpm + present-stats readback), the EGL/GLX/Android ws shims, and the Android trace_replay_core PPM reader.
DirectVulkan ReadPixels on the default framebuffer now remaps raw swapchain pixels (top-left origin, preTransform-rotated) to GL orientation (bottom-left origin) so the retrace snapshot matches the golden; SwapchainObject also resizes the default-FBO stencil attachment to the swapchain extent to fix GL_INVALID_FRAMEBUFFER_OPERATION under the glReadPixels completeness check.
- Memoize the program content hash on ProgramObject (keyed by the backend
state version + compile flags; relinking and binding changes invalidate
it) and the vertex-input hash on VertexArrayObject (keyed by a new
aggregate config version bumped by every attribute mutation). Full-SPIRV
XXH64 hashing fell from 13.7% to 1.4% of the render thread.
- ProgramObject also gains a link version and a global-UBO content version
(bumped by uniform writes and on relink, wrap-safe around the backends'
"never uploaded" sentinel) for backends to gate uploads and link caches.
- Reuse member scratch vectors in SetupDraw, UploadAndBindVertexBuffers,
GetOrCreatePipeline and BindProgramUniformBuffers instead of allocating
per draw (~12% of render-thread time was in the allocator).
- Replace hot-path dynamic_cast with AsMipmapTexture (storage-type tag +
static_cast); TextureObjectMipmap is the only Mipmap-tagged branch.
- Register/prune texture aliases only when a new (texture, lifetimeId)
identity appears instead of scanning the entire alive map on every
sampled-texture sync.
- Make the fallback VkPresentModeKHR log strings report the actual mode.
Vanilla render-thread share of libMobileGL dropped from 48% to 35% on
DirectVulkan (simpleperf, Adreno 830).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>