mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-10 19:43:23 +09:00
Two things land together: the plan and contract draft P6 needs before it starts, and the
working notes that until now existed on exactly one machine.
1. P6's plan and contract draft (neither started; not one line of code)
docs/Disaggregated/P6-SPAWN-PLAN.md the package plan
docs/Disaggregated/P6-CONTRACT-DRAFT.md the contract draft (moves to
MG_Remote/CONTRACT-P6.md when c6 lands)
The three findings that mattered, all written into the documents:
a. P6 is SMALLER than its roadmap cell suggests. The transport primitives are already in
the tree and already tested: SocketDoorbell including hangup detection and the two
lost-wakeup fences (Doorbell.cpp:211-360, four cases in FdPassingTest), SCM_RIGHTS fd
passing, ShmSegment::Adopt, and the SurfaceOp / WindowKind schema already defined in
protocol.fbs. inproc uses a real second shm mapping rather than an alias, and
SessionRings.h:22-28 says that was done so today is not the first time it runs. P6 is
assembly plus a control plane plus a process, not "write a socket transport".
b. The evidence for "P6 is only a transport swap" has EXPIRED. It was bought by P5c, whose
audit found 59 direct memory accesses in a tree that already looked clean. P5e changed
the tree again. So the first package, a6, is a read-only audit that writes no code, and
every contract row that depends on it is marked PENDING a6 rather than decided in
advance.
c. P6 does not get a game running on the phone. ANativeWindow* is meaningless in the child,
and protocol.fbs:186-196's own comment says Android transfers the window out of band -
that band is P12. P6 lands pbuffer / surfaceless / offscreen, which is what HeadlessGL,
the split-equivalent lane and trace replay need, and which is exactly what P6's own exit
gate measures. A real window reaching the server is a named refusal. This gets its own
section because "P6 is done" would otherwise read as "the game runs now".
The contract adds rule G: a role may not name a process-local handle. It extends P5c's
rule E (a role may not name the other role's memory) from memory to identity - EGLDisplay /
EGLSurface / EGLContext / ANativeWindow* / fd number / pid / mapped address either cross as
a token this contract defines or they do not cross, and a descriptor crosses only through
SCM_RIGHTS, where the kernel renumbers it.
What P5e left for P6 gets its own section. The latch semantics are already designed
(ARCHITECTURE.md:504) and are copied unchanged. What is new is that after run-ahead the
client no longer waits while the peer process can DIE: the client holds records that were
published and will never be applied, and Android's freezer suspends the child without
closing anything. So slow and dead must be distinguishable WITHOUT a timeout threshold.
That is P6's only new design; everything else is carriage. It shares a predicate with E1's
outstanding re-specification (ID-122), and the two should be designed together.
Two gates carried over from P5e's lessons: G2 requires integration-spawn's test-name set to
match integration-split's name for name, because a differing set means the lane is quietly
running less; and the arm-proof gate requires every entry to record the child pid and
transport=spawn in its OWN private log - ID-124 established that this kind of false green
really happens, and a spawn lane that actually ran monolith would pass every other gate.
S2's shape must be settled before it is written, and the document says why: E1 is the
cautionary case.
2. The working notes move into the repository (docs/Disaggregated/notes/, 415 .md files)
ROADMAP / CURRENT_STAGE_PROGRESS / MEASUREMENTS cite ruling numbers, audit line numbers and
the provenance of gate figures from ~/w7/notes/, a directory that exists on one machine and
is under no version control. A record cited hundreds of times that lives only locally is not
a record, so it moves in whole, with its directory structure intact.
Only .md moves. Scripts, run logs, census and gate result JSON, patches, APKs and nm dumps
stay where they are: they are evidence DATA rather than documents - large, regenerated per
run, and mostly carrying absolute paths and device serials that mean something only on the
machine that produced them. The mapping and this split are written in
docs/Disaggregated/notes/README.md.
Two exceptions are recorded there too: P6's BRIEF has been promoted to a first-class
document and keeps no copy under notes/, so the two cannot drift apart; and recovered/ holds
material salvaged from failed workflow runs, which may duplicate the like-named phase
directories and is kept because a few of those were the only complete version at the time.
CI's citation lint takes docs/Disaggregated/*.md only (non-recursive), and notes/ is
deliberately outside it: those notes' file:line citations were written against their own
code heads, and resolving them against today's HEAD would fail wholesale - which is not an
error, it is their correct state as a historical record. To check one, use the revision it
declares (--rev).
3. Inconsistencies fixed in passing
- README.md's status line still said P5e was in progress while the stage table already said
closed.
- CURRENT_STAGE_PROGRESS's next-step item 1 still listed the exit gate as pending, though
(a) and (b) were run in the previous commit; rewritten to closed plus the one item that
actually remains (E1).
- ROADMAP's P6 row still had the pre-phase plan in three of its cells; it now carries the
package order, the scope boundary and the two new gates.
Checked with check_doc_citations.py: 125 citations across docs/Disaggregated/*.md, 0 problems.
255 lines
39 KiB
Markdown
255 lines
39 KiB
Markdown
# P5e audit — apply-thread reads of client-owned memory on the DirectGLES inproc draw path
|
||
|
||
Repo head `2fde7034` (`feat/disaggregated`). Read-only static audit; no build, no run.
|
||
|
||
Legend — paths: `D` = `MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp`, `M` = `MobileGL/MG_Backend/DirectGLES/Managers.cpp`, `ST` = `MobileGL/MG_Backend/DirectGLES/SlotTables.h`, `PA` = `MobileGL/MG_Remote/Server/PipeApplier.cpp`, `AP` = `MobileGL/MG_Pipe/PipeApply.cpp/.h`, `MT` = `MobileGL/MG_Pipe/MGPipeTypes.h`, `PI` = `MobileGL/MG_Backend/MGPipe/PipeInputs.h`, `MD` = `MobileGL/MG_Backend/DirectGLES/MultiDraw.cpp`.
|
||
Kinds: `LIVE` = dereference of a client object/field; `PROBE` = `GetLifetimeId()` + `MGPipeSlots().FindByLifetimeId`; `MINT` = `MGPipeSlots().Acquire(...)`; `ROW-O` = `gPipeInputs` BARRIER_PULLED row holding a raw pointer/SharedPtr into the live `GLContext`; `ROW-V` = BARRIER_PULLED copied-value row.
|
||
Arm: `rec` = runs when `MG_Config::Transport != Monolith` with all `MOBILEGL_PIPE_PUSH` bits; `leg` = legacy/monolith arm only; `both` = no transport branch.
|
||
Freq: `draw` = every draw/dispatch; `memo` = only on memo miss / clean-probe open; `rare` = config change / error / special-feature path.
|
||
"Dup" = pushed record or `MGPipeApplierState` field (`AP:PipeApply.h`) already carrying the same information; `none` = nothing pushed covers it.
|
||
|
||
Sink map (all sinks are in `PA`; bodies read no `MG_State` — every client read is one level down in the callee): `OnDrawVbo` PA:430 → the 19 draw entries (`D:6705`-`D:7295`), all of which call `PrepareForDraw` (D:4762) first; `OnClear` PA:168 → `Clear` D:6180 / `ClearBufferfi` D:10045 / `ClearBufferfv` D:10091 / `ClearBufferiv` D:10104 / `ClearBufferuiv` D:10120; `OnBlit` PA:232 → `BlitFramebuffer` D:8322; `OnLaunchGrid` PA:670 → `DispatchCompute` D:9610 / `DispatchComputeIndirect` D:9618 → `PrepareForCompute` D:6118; `OnGenerateMipmap` PA:915 → `GenerateMipmap` D:9559; `OnCopyFramebufferToTexture` PA:931 → `CopyTexImage2D` D:9256 / `CopyTexSubImage2D` D:9373. `AP` (`PipeApply.cpp`, 38 `MGPipeApply*` entries) contains **zero** client-owned reads — no `pGLContext`, no `MGPipeSlots()` probe, no `MGB_CTX->`.
|
||
|
||
## VAO / vertex
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 1 | D:4770 | `PrepareForDraw` | `MGB_CTX->GetBoundVertexArray()` — SharedPtr to client VAO | ROW-O | draw | both | `BoundVertexElements` (AP:594) |
|
||
| 2 | D:1617 → ST:436-446 | `VertexArrayImpl::ResolveVaoTwin` | `Find(vao.get())` → `HandleOf` → `MGPipeSlots().FindByLifetimeId` | PROBE | draw (memo hit at ST:444 skips) | rec (slot arm) | `BoundVertexElements` |
|
||
| 3 | D:1618 → ST:247-248 | `ResolveVaoTwin` | `GetOrCreate(vao)` → `MGPipeSlots().Acquire` | MINT | rare | rec | none (first-touch only) |
|
||
| 4 | D:1626, D:1629-1634 | `ResolveVaoTwin` | legacy memo/registry keyed on frontend heap address + `stateRef` weak_ptr | LIVE | draw | leg | none |
|
||
| 5 | D:4775 | `PrepareForDraw` | `currentVAO->GetConfigVersion()` | LIVE | draw | both | none (server has `VertexBuffersSerial`/`ContentSerial` only) |
|
||
| 6 | D:1653 → M:4881 | `SyncCurrentVAO` | client VAO handed to `SyncToBackend` | LIVE handoff | draw | both; handle arm diverts to `SyncToBackendFromApplier` M:5160 (zero client reads) | `VertexElementsCso` record (AP:487) |
|
||
| 7 | M:4919-5104 | `BackendVertexArrayObject::SyncToBackend` | `GetConfigVersion`, index slot, `GetAllAttributeVersions`/`GetAllAttributes`, per-attrib `Enabled/Divisor/IsBgra/Offset/Stride/Type/...` | LIVE | draw | leg only | `MGPVertexAttribWire`/`MGPVertexBindingPointWire` (MT:389-400) |
|
||
| 8 | M:5479-5544 | `SyncFloat64AttributeAsFloat32` | `attrib.*`, `bufferObject->MappedData()` — client shadow bytes; `NarrowDoubleStreamToFloat32` reads them | LIVE | rare | leg | none |
|
||
| 9 | D:1669 | `SyncCurrentVertexAttributeValues` | `GetBoundVertexArray()` | ROW-O | draw | both | `BoundVertexElements` |
|
||
| 10 | D:1683, D:1688, D:1700 | `SyncCurrentVertexAttributeValues` | `vao->GetConfigVersion()`, `vao->GetAttribute(location).Enabled`; `GetCurrentVertexAttribute(location)` | LIVE + ROW-V | draw / memo | both | `SetVertexAttribDefaults` (AP:1600) for :1700; none for :1683/:1688 |
|
||
| 11 | D:6449, D:6451, D:6459 | `BoundElementArrayBuffer` | `GetBoundVertexArray()`, VAO index slot `GetBoundObject()`, `EnsureBufferResource` | ROW-O + LIVE + PROBE | per indexed draw | both | `IndexBuffer` (AP:620) |
|
||
| 12 | D:6724, D:6731 | `DrawArrays` | `GetBoundVertexArray()` + registry `Find(currentVAO.get())` → the one true per-draw `MGPipeSlots().FindByLifetimeId` from the apply thread | ROW-O + PROBE | every DrawArrays | both | `BoundVertexElements` |
|
||
| 13 | D:6768, D:6777 | `MultiDrawArrays` | same pair, per sub-draw | ROW-O + PROBE | per sub-draw | both | `BoundVertexElements` |
|
||
| 14 | M:5372-5449 | `SyncClientSideAttributesForDrawArrays` | `GetAllAttributes()`, `attrib.Offset` reinterpreted as client-memory pointer, client array bytes uploaded | LIVE | VAOs with client-side arrays | both | none (client-memory vertex data) |
|
||
| 15 | MD:96 | `BoundIndexBuffer` | `MGB_CTX->GetBoundVertexArray()` | ROW-O | per multi-draw element call | both | `BoundVertexElements` |
|
||
|
||
## Buffers
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 16 | D:897 | `SyncNeccessaryBuffers` | `currentVAOObject->GetIndexBufferBindingSlot().GetBoundObject()` | LIVE | every indexed draw | both | `IndexBuffer` (AP:620) |
|
||
| 17 | D:907 → M:2922-2941 | `SyncNeccessaryBuffers` | `HandleOfBuffer(possibleIBO.get())` → `MGPipeSlots().FindByLifetimeId` | PROBE | every indexed draw | rec | `IndexBuffer.Res` |
|
||
| 18 | D:911 → M:3109-3151 | `IsBufferDrawCleanByHandle` | server-only under split; `frontend->IsMapped()` at M:3147 is monolith-only | LIVE (monolith) | memo | both | resource record `Serial`/`HasLiveHostWrites` |
|
||
| 19 | D:915, D:932 | `SyncNeccessaryBuffers` | `EnsureBufferResource(possibleIBO)` | PROBE | rare | rec | `IndexBuffer.Res` |
|
||
| 20 | D:926, D:928, D:934 | `SyncNeccessaryBuffers` | `memo->iboFrontend == possibleIBO.get()` — client address compare | LIVE | every indexed draw | leg | `IndexBuffer.Res` |
|
||
| 21 | D:842 | `SyncNeccessaryBuffers` | `currentVAOObject->GetAttribute(entry.attribIndex).Buffer` | LIVE | rare (clean-probe fail) | both | `VertexBuffers` window (AP:598-600) |
|
||
| 22 | D:857-861 | `SyncNeccessaryBuffers` | `GetAllAttributes()`, per-attrib `Enabled`/`Buffer` | LIVE | memo | leg-memo path | `VertexElementsCso` + `VertexBuffers` |
|
||
| 23 | D:864, D:874 | `SyncNeccessaryBuffers` | stored raw client `BufferObject*`, `EnsureBufferResource(bufferObject)` | LIVE + PROBE | memo | both | buffer handle in `VertexBuffers` |
|
||
| 24 | D:736, D:746-753, D:763, D:766-770 | `SyncVaoAttributeBuffersByHandle` | memo-miss full walk: `GetAllAttributes`, `attrib.Buffer`, stores client pointer + `HandleOfBuffer` | LIVE + PROBE | memo | rec | `VertexBuffers`/`VertexElementsCso` |
|
||
| 25 | M:3158 | `IsBufferDrawClean` | `HandleOfBuffer(frontend)` | PROBE | every probe | rec | resource record |
|
||
| 26 | M:3163, M:3175, M:3179, M:3180 | `IsBufferDrawClean` | `frontend->GetBackendResource/IsMapped/GetSize/GetChangeSerial` | LIVE | every probe | leg | resource record |
|
||
| 27 | M:3444 | `EnsureBufferResource` | `HandleOfBuffer(bufferObject.get())` | PROBE | per bound VBO/IBO/SSBO/UBO/atomic/XFB/PBO per draw | rec | the handle in each pushing record |
|
||
| 28 | M:3452 | `EnsureBufferResource` | `bufferObject->GetExternalIndex()` | LIVE | error arm only | both | none |
|
||
| 29 | M:3221, M:3340, M:3393 | `EnsureBufferResourceForHandle` | `bufferObject->MappedData()/SyncPersistentMappedRange()/HasDefinedContent()` — **monolith-only**; under an active transport this function is client-free | LIVE | — | leg | `ServerStaged()` shadow + resource record |
|
||
| 30 | M:2953 | `MarkBufferGpuWritten` | `HandleOfBuffer(bufferObject.get())` before the reverse announcement | PROBE | per SSBO per draw | rec | none (reverse direction) |
|
||
| 31 | M:2950 | `MarkBufferGpuWritten` | `bufferObject->MarkGpuWritten()` — client **write** | LIVE | per SSBO per draw | leg | none |
|
||
| 32 | M:3083 | `GetBufferResource` | `bufferObject->GetBackendResource()` (called per UBO per draw from D:5472) | LIVE | draw | both | none |
|
||
| 33 | D:962, D:5987, D:6077, D:6511, D:6930-6931, D:7082-7083 | indirect/restart helpers | client `GetBufferBindingSlot(DrawIndirect/Parameter)` + `MappedData()` — all behind `Transport == Monolith`; record arms (D:373, D:951-956, D:6534-6536, D:6889-6927, D:7043-7079) read applier handles + server staged shadows only | ROW-O + LIVE | indirect draws | leg | `VerbIndirectBuffer`/`VerbIndirectParameterBuffer` (AP:742-743) |
|
||
| 34 | M:5364-5468 | see #14 | client-side attribute bytes | LIVE | rare | both | none |
|
||
|
||
## Textures / samplers
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 35 | D:1899-1913 | `UnitBindingsUnchanged` | `GetTextureUnitObject(unit)` (raw `TextureUnit*` into client array), `GetAllBindingSlots()`, `GetBoundObject()->GetLifetimeId()`, sampler `GetLifetimeId()` | ROW-O + LIVE | memo | rec walk arm | `BoundSamplerViews`/`BoundSamplerStates` windows (AP:673-681) |
|
||
| 36 | D:1871-1885 | `CaptureUnitBindings` | same tables, captures lifetime ids | ROW-O + LIVE | memo | rec | same |
|
||
| 37 | D:1934-1940, D:1947-1953 | legacy twins of the above | same + `WeakPtr` owner checks | LIVE | memo | leg | same |
|
||
| 38 | D:2346 → D:2136, D:2356, D:2359-2361 | `SyncNeccessaryTextures` served path | `entry.slot->get()` — borrowed pointer **into a client binding slot**; `*entry.slot` ITextureObject handed to twin sync | LIVE | **every draw, per list entry** | both | `BoundSamplerViews` |
|
||
| 39 | D:2374-2376 | `SyncNeccessaryTextures` rebuild | `GetTextureUnitObject(index)`, slots, `GetBoundObject()` | ROW-O | memo | both | `BoundSamplerViews` |
|
||
| 40 | D:2379-2381 | `SyncNeccessaryTextures` | `IsUndefinedDefaultTexture(...)`, probe + `SyncTextureObjectToBackend` mint | LIVE + PROBE/MINT | memo | both | texture resource handle |
|
||
| 41 | D:2405-2406, D:2408-2409 | `SyncNeccessaryTextures` draw-FBO half | `GetFramebufferBindingSlotChecked(Draw).GetBoundObject()`, slot `GetVersion()`, `currentFBO->GetObjectVersion()` | ROW-O + LIVE | **every draw** | both | `BoundFramebuffer[Draw]` + `FramebufferRecord` (AP:646,524) |
|
||
| 42 | D:2438-2447 | `SyncNeccessaryTextures` | replay of memoised `*entry.slot` through `IsDrawSyncClean` | LIVE | memo | both | `BoundSamplerViews` |
|
||
| 43 | D:2450-2459 | `SyncNeccessaryTextures` | `currentFBO->GetAllAttachmentObjects()`, `attachment.GetTexture()` + mint | LIVE + MINT | memo | both | `MGPFramebufferState` (MT:750) |
|
||
| 44 | D:2246-2247, D:2252, D:2258-2259 | `SyncReadFramebufferTextureAttachments` | read-FBO slot `GetBoundObject()`, pointer compare, versions | ROW-O + LIVE | every draw (PUSH) | both | `BoundFramebuffer[Read]` |
|
||
| 45 | D:2285, D:2290-2296 | same | `PairingsIntact` + replay to `SyncTextureParamsToBackend`/`SyncBuiltinSamplerToBackend`/`SyncMipmapsToBackend` | LIVE | memo | both | sampler-view/params records |
|
||
| 46 | D:2303-2308 | same | `readFBO->GetAllAttachmentObjects()`, `GetTexture()` + mint | LIVE + MINT | memo | both | `MGPFramebufferState` |
|
||
| 47 | D:1736, D:1738 | `SyncTextureObjectToBackend` | `g_backendTextureObjects.Find(textureObject.get())` / `GetOrCreate(textureObject)` | PROBE + MINT | per texture sync | both | texture resource handle |
|
||
| 48 | D:1781, D:1790, D:1797-1799 | `SyncTextureObjectToBackend` | re-resolution tail Find/GetOrCreate | PROBE + MINT | per call | both | same |
|
||
| 49 | D:1758, D:1760-1762, D:1771-1772 | `SyncTextureObjectToBackend` | client SharedPtr handed into `BackendTextureObject::Sync*` (deep reads at M:5816/7049/8554/8802) | LIVE | per sync | both | pushed params/mipmap records |
|
||
| 50 | D:4861, D:4876-4877 | `ResolveAndBindUnitTextures` | `GetTextureUnitObject(unit)`, `GetAllBindingSlots()`, `GetBoundObject()` | ROW-O | memo | both | `BoundSamplerViews` |
|
||
| 51 | D:4883, D:4885, D:4888 | same | `IsUndefinedDefaultTexture`, `GetExternalIndex()`, `GetTarget()` | LIVE | memo | both | none |
|
||
| 52 | D:4914-4918 | same | `textureUnit.GetSamplerObject()` ×2, `textureObject->GetSamplerObject()`, `SamplesAsIncompleteTexture` | LIVE | memo | both | `BoundSamplerStates` |
|
||
| 53 | D:4928, D:4945-4946 | same | `Find(textureObject.get())`; clear pass reads `bindingSlot.GetTarget()` | PROBE + LIVE | memo | both | view handle |
|
||
| 54 | D:5157, D:5159-5160 | `BindCurrentUnitSamplers` legacy arm | `GetTextureUnitObject(unit).GetSamplerObject()` | ROW-O + LIVE | memo | leg | `BoundSamplerStates` |
|
||
| 55 | D:4999, D:5003, D:5015, D:5018 | `ResolveUnitSamplerBackend` | `HandleOf(samplerObject.get())` probe, `OwnerEquals` weak memo, `Find` | PROBE + LIVE | per non-CSO sampler per draw | rec | `BoundSamplerStates` |
|
||
| 56 | D:5626 | `BindCurrentProgramWithResources` | `g_backendSamplerObjects.GetOrCreate(samplerObject)` | MINT | rare | leg-in-rec fallback | `BoundSamplerStates` |
|
||
| 57 | D:5633-5637, D:5639 | same | `SyncToBackend(samplerObject, ...)` — client SamplerObject | LIVE | memo | both | `SamplerCsos` record (AP:501) |
|
||
| 58 | D:5573, D:5577-5580, D:5591-5595 | same | `GetLodBias()`, binding-slot reads, `texture2D->GetSamplerObject()/GetFormat()` | LIVE | memo | both | none (LOD-bias/depth-fetch fixups) |
|
||
| 59 | D:9564-9566, D:9568-9570 | `GenerateMipmap` | `GetTextureUnitObject(unitIndex)` (client array), slot `GetBoundObject()`, `texture->GetFormat()` | ROW-O + LIVE | every mipmap | both (rec arm too) | `MGPMipPlan.Res` (MT:1382) covers identity only |
|
||
| 60 | D:9162, D:9217 | `GenerateDepth/ColorTexture2DMipmap` | `HandleOf(texture.get())` | PROBE | rare | rec | `VerbMipRes` (AP:739) |
|
||
| 61 | D:9484-9548 | `GenerateThreeChannelFloatMipmapOnCpu` | `GetFormat`, `AsMipmapTexture`, `GetMipmapLevelCount/TexelSize`, `MapMipmapData` — client shadow bytes read+written, `MarkStorageDirty` | LIVE | rare | both | none |
|
||
| 62 | D:9580, D:9584-9585, D:9591, D:9603 | `GenerateMipmap` | `texture->GetFormat()/GetTarget()` | LIVE | every mipmap | both | resource record `Desc` |
|
||
| 63 | D:8839, D:8861-8897 | `ScopedDetachedTextureFramebufferAttachments` | `Find(texture.get())` probe; **unmemoised walk of every live twin's client FBO**: `GetAllAttachmentObjects`, `GetTexture`, `GetTextureUploadTarget`, `IsLayered`, `GetTextureLevel` | PROBE + LIVE | rare (per mipmap) | both | none |
|
||
| 64 | D:8472 | `UpdateTextureBindingAtTarget` | `GetTextureUnitObject(unit)` | ROW-O | every copy-tex | both | `MGPCopyFromFramebuffer.Dst` (MT:1639) covers the handle |
|
||
| 65 | D:9302-9312, D:9416+ | `CopyTexImage2D`/`CopyTexSubImage2D` legacy arm | unit binding slot `GetBoundObject()`, `Find(textureObject.get())`, `GetFormat()` | ROW-O + LIVE + PROBE | every copy-tex | leg | `VerbCopyTexDst` (AP:737) |
|
||
| 66 | M:5884, M:7089, M:8483, M:8719 | texture `HandleOf` probes | `g_backendTextureObjects.HandleOf` → allocator probe | PROBE | memo/feature paths | rec | resource handle |
|
||
| 67 | M:9261, M:9318 | `SyncAttachmentObject` | `GetOrCreate(stateTextureObject)` / `GetOrCreate(renderbufferObject)` | MINT | FBO attach walk | leg | attachment record |
|
||
|
||
## Framebuffers / attachments
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 68 | D:3019, D:3021, D:3032 | `FramebufferRecordMatchesBinding` (from `SyncCurrentFBO` rec arm D:3112-3113) | `GetFramebufferBindingSlotChecked(target).GetBoundObject()` — **client slot, every record-arm draw, per target**; `pDefaultFramebufferInfo->defaultFBO`; `HandleOf(bound.get())` at D:3032 is monolith-gated | ROW-O + LIVE | draw | rec | `BoundFramebuffer` + `FramebufferSerial` (AP:646,652) |
|
||
| 69 | D:3178-3179, D:3186 | `SyncCurrentFBO` rec arm | `slot.GetBoundObject()` on serial miss; `currentFBO` handoff | ROW-O + LIVE | memo | rec | `FramebufferRecords` (AP:524) |
|
||
| 70 | D:3227-3228 | `SyncCurrentFBO` rec arm | `NoteStateForHandle(record.Fbo, currentFBO)` — **stores the client FBO into the twin table** | LIVE | per handle sync | rec | — |
|
||
| 71 | D:3269 → M:10044 | `SyncCurrentFBO` rec arm | `backendObj->SyncToBackend(currentFBO, target)` walks the frontend FBO | LIVE | memo | rec | `MGPFramebufferState` |
|
||
| 72 | D:3305-3306, D:3317-3319, D:3336, D:3349, D:3358, D:3360, D:3367-3369, D:3373 | `SyncCurrentFBO` legacy arm | slot + `GetBoundObject()`, versions, `defaultFBO`, `Find`/`GetOrCreate` mint, `SyncReadBufferToBackend`, `SyncToBackend` | ROW-O + LIVE + PROBE/MINT | draw | leg | same records |
|
||
| 73 | D:4568, D:4580-4581, D:4592, D:4600, D:4602 | `BindCurrentFBO` legacy arm (record arm D:4528-4565 is client-free: applier record + `FindByHandle`) | slot, `GetBoundObject()`, `defaultFBO`, `Find`, weak-owner memo | ROW-O + LIVE + PROBE | draw | leg | `BoundFramebufferRecord` |
|
||
| 74 | D:4720-4721, D:4734-4736 | `ForceBindCurrentFBO` | `GetFramebufferBindingSlotChecked(target).GetBoundObject()` + versions + `fbo.get()` — **unconditional on both arms**; memoises the frontend pointer at D:4736 | ROW-O + LIVE | every call (clear/blit/DSA) | both | `BoundFramebuffer` |
|
||
| 75 | D:4630, D:4646-4647, D:4655 | `SyncAndBindFramebufferObject` | `defaultFBO` compare, `Find`/`GetOrCreate` mint, `SyncToBackend` | LIVE + PROBE/MINT | rare | both | `MGPFramebufferState` |
|
||
| 76 | D:4700, D:4705 | `SyncAndBindFramebufferByHandle` | `StateForHandle(fbo)` returns the **recorded client FBO** (server-side weak note from #70); `SyncToBackend(stateObj, target)` walks it | LIVE | rare (named blit) | rec | handle itself is server |
|
||
| 77 | D:8357-8359 | `BlitFramebuffer` named arm | `FramebufferImpl::pDefaultFramebufferInfo->defaultFBO` | LIVE | rare | rec | none |
|
||
| 78 | D:8407-8410 | `BlitFramebuffer` bound arm | `GetFramebufferBindingSlot(Read/Draw).GetBoundObject()` ×2 — **both client FBOs, every bound blit** | ROW-O + LIVE | every bound blit | both | none (`MGPBlit` null-handle form carries no FBO identity) |
|
||
| 79 | D:8210-8302 | `BlitLayeredDestinationAspects` | `GetDrawBuffers()`, `GetReadBuffer()`, `GetAttachment(...)`, `IsLayered/GetTextureLevel/GetTextureLayer`, `GetTexture()`, `GetFormat()/GetSamples()`, `GetTarget()` + `SyncTextureObjectToBackend` probe/mint | LIVE + PROBE/MINT | every blit | both | none (attachment detail not in `MGPBlit`) |
|
||
| 80 | D:6284, D:6288-6291 | `Clear` | `GetFramebufferBindingSlot(Draw).GetBoundObject()` + `GetExternalIndex/GetObjectVersion/GetDrawBuffers()` — **debug-log only** | ROW-O + LIVE | dbg | both | — |
|
||
| 81 | M:10054, M:10119, M:10121, M:10216, M:10283-10284 | `BackendFramebufferObject::SyncToBackend` | `stateFBOObject->GetExternalIndex/GetDrawBuffers/GetAttachment/GetAllAttachmentObjects/GetAllFramebufferAttachmentVersions` | LIVE | per FBO sync | both (entered from #71/#75/#76) | `MGPFramebufferState` |
|
||
| 82 | M:9938, M:9872, M:9886 | `SyncReadBufferToBackend` | `GetReadBuffer()`, `GetExternalIndex()` | LIVE | per FBO sync | both | `MGPFramebufferState` |
|
||
| 83 | M:9862, M:10101 | same / `SyncToBackend` | `HandleOf(stateFBOObject)` — monolith branch only | PROBE | per sync | leg | FBO handle |
|
||
| 84 | D:4386-4399 | `SyncCurrentProgram` (FBO half) | `GetFramebufferBindingSlotChecked(Draw)`, `slot.GetBoundObject()/GetVersion()`, `drawFBO->GetObjectVersion()`, `drawFBO->GetDrawBuffers()` | ROW-O + LIVE | draw (memo-guarded at D:4390) | both | `BoundFramebufferRecord(Draw)` + `MGPFramebufferState.DrawBuffers` |
|
||
|
||
## Images
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 85 | D:2650-2653 | `SyncImageTextureBinding` | `GetImageTextureBinding(unit)` (client array), `binding.Texture`, `IsWritableImageBufferTexture` (`Texture->GetStorageType()`) | ROW-O + LIVE | memo/rare | both | `BoundShaderImages` window (AP:683-686) |
|
||
| 86 | D:2660, D:2671 | same | `SyncTextureObjectToBackend(imageBinding.Texture, true)` probe/mint; `imageBinding.Texture.get()` identity via `HandleOf` D:2634 | PROBE/MINT + LIVE | memo | both | `MGPImageView` |
|
||
| 87 | D:2672-2675 | same | legacy arm reads `imageBinding.Layered/Layer/Level/Format` (rec arm reads the `MGPImageView` record) | LIVE | memo | leg | `MGPImageView` |
|
||
| 88 | D:2682, D:2723-2724, D:2736, D:2744 | same | `GetTarget()`, `GetFormat()`, `imageBinding.Access` | LIVE | memo | both | `MGPImageView` |
|
||
| 89 | D:2767, D:2773-2774 | `MarkWritableImageBufferTexturesGpuWritten` | `GetImageTextureBinding(unit)`, downcast to `TextureObjectBuffer*`, `GetBufferBindingSlot().GetBoundObject()` | ROW-O + LIVE | every draw when writable image-buffer units exist | both | `BoundShaderImages` |
|
||
| 90 | M:10849 | `BoundImageUnitFormat` (via `ImageUnitFormatsStillMatch`, D:4472) | `MGB_CTX->GetImageTextureBinding(unit).Format` | ROW-O | programs with format-less image units | both | `MGPImageView.Format` |
|
||
|
||
## Programs / shader state
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 91 | D:4781 | `PrepareForDraw` | `MGB_CTX->GetProgramForDraw()` — SharedPtr to client ProgramObject | ROW-O | draw | both | `DrawProgram` (AP:691) |
|
||
| 92 | D:6126 | `PrepareForCompute` | `MGB_CTX->GetProgramForDispatch()` | ROW-O | every dispatch | both | `DispatchProgram` (AP:692) |
|
||
| 93 | D:4339 | `SyncCurrentProgram` | `currentProgram->GetLinkStatus()/GetSpirvStatus()` | LIVE | draw | both | `ShaderCsos` record (AP:503) |
|
||
| 94 | D:4415-4416 | `SyncCurrentProgram` | `g_backendProgramObjects.Find(currentProgram.get())` → `HandleOf` probe; `GetOrCreate(currentProgram)` mint | PROBE + MINT | draw | rec | `DrawProgram` handle |
|
||
| 95 | D:4425-4429 | `SyncCurrentProgram` | `g_programTwinLookupMemo.Lookup(currentProgram)`; address-keyed `Find`/`GetOrCreate` mint | LIVE + MINT | draw | leg | `DrawProgram` |
|
||
| 96 | D:4457-4459 | `SyncCurrentProgram` | `currentProgram->GetLinkVersion()/GetImageUnitVersion()` | LIVE | draw | both | `ShaderCso` serials |
|
||
| 97 | D:4463-4464 → M:10821 | `SyncCurrentProgram` | `ComputeShaderStorageBlockBindingSignature(*currentProgram)` → `ProgramObject::GetShaderStorageBlockBindingOverrides()` | LIVE | draw (early-out on empty map) | both | none (overrides not pushed) |
|
||
| 98 | D:4507 | `SyncCurrentProgram` | `twin->SyncToBackend(currentProgram)` — full client ProgramObject handoff | LIVE | memo | both | `CreateShaderState` record |
|
||
| 99 | D:4242, D:4274-4313 | `ResolveGlobalConstantsRecord` | `HandleOf(program)` probe; `program->GetUBOSize()` compares | PROBE + LIVE | every draw with a default UBO | rec | `SetGlobalConstants` record (AP:3010) |
|
||
| 100 | D:5257, D:5279-5282 | `BindCurrentTextures` | `programKey = currentProgram.get()`; `GetLifetimeId()`, `GetBackendStateVersion()`, `GetLinkStatus()` | LIVE | draw | both | `DrawProgram` |
|
||
| 101 | D:5320, D:5333, D:5337 | `BindCurrentProgramWithResources` | `GetLinkStatus()/GetSpirvStatus()`, `currentProgram.get()`, `Find` probe | LIVE + PROBE | draw | both | `DrawProgram` |
|
||
| 102 | D:5349, D:5372-5373 | same | `GetUBOSize()`, `GetUBOContentVersion()` | LIVE | every draw with UBO | both | `ShaderCso.Desc.GlobalUboSize` + `GlobalConstantsSerial` |
|
||
| 103 | D:5380, D:5382, D:5425-5430 | same | `currentProgram->MapUBO()` — client shadow bytes (legacy fallback of the ring path); `GetUBOSize()` for upload | LIVE | ring-miss only | both | `GlobalConstants` bytes |
|
||
| 104 | D:5463 | same | `currentProgram->GetUniformBlockBinding(i)` | LIVE | per UBO per draw | both | `ShaderCso.Desc` |
|
||
| 105 | D:5522, D:5546 | same | `GetBackendStateVersion()`, `GetUniformSamplerOrImageUnitIndex(location)` | LIVE | memo | both | `ShaderCso` records |
|
||
| 106 | D:1672, D:1701 | `SyncCurrentVertexAttributeValues` | `program->GetActiveAttributeLocationMask()`, `program->GetAttribType(location)` | LIVE | draw | both | none |
|
||
| 107 | D:5679, D:5683-5692 | `GetCurrentBackendProgram` | `GetProgramForDraw()` + stash-miss `Find(currentProgram.get())` probe | ROW-O + PROBE | per indirect sub-draw | both | `DrawProgram` |
|
||
| 108 | D:5733-5740 | `CurrentProgramMayNeedPerSubDrawBuiltins` | `currentProgram->GetLinkVersion()` | LIVE | per sub-draw query | both | `ShaderCso` serial |
|
||
| 109 | D:6157, D:10023, D:6152, D:10022 | `GetBackendProgramId` / `ShaderStorageBlockBinding` | `GetProgramObject(...)`, `ValidateProgramName(...)` — frontend name-table probe | LIVE | API-driven, not per draw | both | none |
|
||
| 110 | M:12954 | `BackendProgramObjectImpl::SyncToBackend` | `HandleOf(stateProgramObject)` | PROBE | per program sync/relink | rec | `ShaderCso` handle |
|
||
|
||
## Binding-point tables
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 111 | D:510-511 | `SyncBufferBindingPoints` | `GetBufferBindingPoint(target, i)` — raw pointer into the live GLContext array; `point.GetBoundObject()` SharedPtr to client BufferObject | ROW-O + LIVE | per touched SSBO per draw; per UBO+SSBO per dispatch | **both — no arm switch** | `MGPShaderBuffers` record (MT:910) |
|
||
| 112 | D:517, D:524, D:526, D:529-530 | same | `EnsureBufferResource(obj)` probe; `point.GetRange()`; `obj->GetSize()` | PROBE + LIVE | per bound point | both | buffer handle + range in record |
|
||
| 113 | D:602, D:605 | `MarkShaderStorageBuffersGpuWritten` | touched count; `GetBufferBindingPoint(ShaderStorage,i).GetBoundObject()` | ROW-V + ROW-O/LIVE | **every draw** | both | `MGPShaderBuffers` |
|
||
| 114 | D:569-570, D:575, D:583, D:585, D:588-589 | `SyncTransformFeedbackBindingPoints` | TF binding point, `GetBoundObject()`, ensure probe, `GetRange()`, `GetSize()` | ROW-O + LIVE + PROBE | rare (capture span open) | both | none |
|
||
| 115 | D:621, D:628, D:630, D:636, D:642-648, D:658-660 | `SyncAtomicCounterBuffers` | count; `GetBufferBindingPoint(AtomicCounter, ...)`, `GetBoundObject()`, ensure, `GetRange()`, `GetSize()`, `MarkBufferGpuWritten` | ROW-V/O + LIVE + PROBE | rare (programs with atomic counters) | both | none |
|
||
| 116 | D:669, D:675 | `SyncBoundBuffer` | `GetBufferBindingSlot(target).GetBoundObject()`, ensure probe | ROW-O + LIVE + PROBE | monolith indirect paths | leg | `VerbIndirectBuffer`/`VerbDispatchIndirectBuffer` |
|
||
| 117 | D:5464-5466 | `BindCurrentProgramWithResources` | `GetBufferBindingPoint(Uniform, binding)`, `GetBoundObject()`, `GetRange()` | ROW-O + LIVE | per UBO per draw | both | none (UBO bindings not pushed as records) |
|
||
| 118 | D:5472-5479 | same | `GetBufferResource(bufferObj.get())`, `IsBufferDrawClean`, `EnsureBufferResource(bufferObj)` | LIVE + PROBE | per UBO (epoch-stamped) | both | buffer handle |
|
||
|
||
## XFB
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 119 | D:1387 | `StartPendingTransformFeedback` | `MGB_CTX->GetTransformFeedbackProgram()` | ROW-O | span start | both | none (`TransformFeedback*` context values are pushed, the program row is not) |
|
||
| 120 | D:1405, D:1407-1415, D:1417 | same | `program->GetTransformFeedbackBufferCount()`, TF binding points, `GetBoundObject()`, ensure probe, `GetRange()`, `GetSize()`; pushes the client `SharedPtr<BufferObject>` into `xfb.targets` | LIVE + ROW-O + PROBE | span start | both | none |
|
||
| 121 | D:1427, D:1434, D:1439, D:1463, D:1497 | same | `NeedsScatteredTransformFeedbackCapture()`, `GetTransformFeedbackStride/PackedStride/BufferMode()` | LIVE | span start | both | none |
|
||
| 122 | D:1138, D:1295 | `ReadbackCapturedRanges` / `ScatterCapturedRecords` | `HandleOfBuffer(target.buffer.get())` | PROBE | span end | rec | buffer handle (carried in `xfb.targets`, but stored as SharedPtr) |
|
||
| 123 | D:1174, D:1191, D:1310, D:1342 | same | `IsBackendPersistentMapped()`, `WritebackFromBackend(...)`, `MappedData()` | LIVE | span end | leg | none |
|
||
| 124 | D:1247, D:1282, D:1312 | `ScatterCapturedRecords` | `program->GetTransformFeedbackPackedStride/Stride/Varyings()` | LIVE | span end | both | none |
|
||
|
||
## Misc
|
||
|
||
| # | site | function | what is read | kind | freq | arm | dup |
|
||
|---|---|---|---|---|---|---|---|
|
||
| 125 | PA:742-743 | `ServerVerbSink::OnResourceCopyRegion` | `gPipeInputs.GetTextureObject(SrcGlName/DstGlName)` — BARRIER_PULLED sticky-forward frontend name-table probe returning `SharedPtr<ITextureObject>` (`FieldOwnership.def:151`) | ROW-O | per `CopyImageSubData` | both | `MGPCopyRegion.Src/Dst` handles (MT:1302); the GL names are the declared P5b debt |
|
||
| 126 | PA:591 | `OnDrawVbo` | `MGPipeHostBytes(*userIndices)` — SEG_STAGE bytes under split; client pointer under monolith | ROW-V (split: server bytes) | `kDrawHasUserIndices` arm only | both | record tail |
|
||
| 127 | D:11761, D:11765, D:12192, D:12196, D:10232, D:11214, D:11451 | readback helpers (`ReadPixels`, `GetTexImage`, `StoreReadbackRowsToClient`, ...) | pack-PBO `GetBufferBindingSlot` + ensure | ROW-O + PROBE | readback paths | both | `MGPReadbackInfo` (MT:1388) |
|
||
| 128 | MD:909, MD:930 | `MultiDrawImpl::DrawElementsBatch` | `BoundIndexBuffer()` (client EBO), `BoundIndexBufferId()` | LIVE | per multi-draw | both | `IndexBuffer` (AP:620) |
|
||
|
||
## (a) Scope construction sites
|
||
|
||
`MGPipeFrontendKeyedRegistryScope` (exempts `MGPipeSlots()` from the apply-thread `Fatal{RoleViolation}`, `MobileGL/MG_Impl/Pipe/SlotAllocator.cpp:29`). Production sites: D:1609 (`ResolveVaoTwin`, VAO twin resolve, every draw) · D:1734 (`SyncTextureObjectToBackend`) · D:2588 (`ResolveShaderImageRecord`, image-seam identity) · D:3303 (`SyncCurrentFBO`, legacy half) · D:4236 (`ResolveGlobalConstantsRecord`) · D:4329 (`SyncCurrentProgram`, whole function) · D:4585 (`BindCurrentFBO`) · D:4926 (`ResolveAndBindUnitTextures`) · D:4993 (`ResolveUnitSamplerBackend`) · D:5328 (`BindCurrentTextures`) · D:5689 (`GetCurrentBackendProgram`) · D:6166 (`GetBackendProgramId`) · D:6729 (`DrawArrays`) · D:6775 (`MultiDrawArrays`) · D:8837 (`ScopedDetachedTextureFramebufferAttachments`) · D:9161 / D:9216 (mipmap depth/color) · D:9695 (`SyncRenderbufferObjectToBackend`) · D:10029 (`ShaderStorageBlockBinding`) · D:11884 (`GetTexImage`) · M:256 (`OnFrontendStateObjectDestroyed`, NoSession arm only) · M:4544 (`HandleOfSamplerViewForTexture`) · M:5882 (`RequireImageBindableStorage`) · M:7087 (`SyncMipmapsToBackend`) · M:8481 (`ResolvePushedBuiltinSampler`) · M:8717 (`ResolvePushedTextureParams`) · M:9256 / M:9310 (`SyncAttachmentObject`, legacy arm) · M:9709 (`SyncAttachmentSurface` RBO cross-check) · M:10382 / M:10403 (debug-only verification block in `BackendFramebufferObject::SyncToBackend`) · M:12949 (`BackendProgramObjectImpl::SyncToBackend`) · M:13273 (`BackendSamplerObject::SyncToBackend`) · M:13570 (`BackendRenderbufferObject::SyncToBackend`). Tests: `MobileGL/MG_Test/Wire/RemoteClientTest.cpp:1883, :1903`.
|
||
|
||
`MGPipeReverseAnnouncementScope`: `MobileGL/MG_Impl/Pipe/ResourceTracker.h:723` (`MGPipeAnnounceBufferGpuWritten`) · M:2938 (`BufferImpl::HandleOfBuffer`) · test at `RemoteClientTest.cpp:1885`. Definitions: `MobileGL/MG_Impl/Pipe/SlotAllocator.h:199-233`.
|
||
|
||
## (b) Frontend objects/pointers held across records by the apply thread
|
||
|
||
| site | storage | what |
|
||
|---|---|---|
|
||
| D:67 | `g_rawDepthFetchSamplerState` | SharedPtr to a frontend `SamplerObject` created and retained by the backend for process life |
|
||
| D:1027, D:1054 (in `g_xfbObjects` D:1064) | `XfbObjectState::targets[].buffer`, `scatterProgram` | SharedPtrs to frontend `BufferObject`/`ProgramObject` pinned across a capture span |
|
||
| D:117-121; instances D:138, D:140, D:146 | `TwinLookupMemo` ×3 (VAO/program/FBO) | raw frontend key + `WeakPtr` owner (legacy arm) |
|
||
| D:1847/1849, D:1926/1928 (in `g_observedUnitBindings` D:1959) | `UnitBindingsSnapshot::legacySlotObjects`/`legacySamplerObject` | WeakPtrs to frontend textures/samplers |
|
||
| D:2127-2131 (in `g_unitTextureSyncList` D:2140) | `UnitTextureSyncEntry` | borrowed pointer into a frontend binding slot + raw `ITextureObject*` |
|
||
| D:2151-2152, D:2235-2236 | `g_fboTextureSyncList`, `g_readFboTextureSyncList` + raw `FramebufferObject*` keys | draw/read FBO attachment sync lists |
|
||
| D:4097-4098 | `g_currentDrawFrontendProgram`/`g_currentDrawBackendProgram` | per-draw program/twin stash |
|
||
| D:4107 | `g_broadcastMemoFbo` | raw `const FramebufferObject*` memo key |
|
||
| D:4978-4985 | `g_unitSamplerLookupMemos` | per-unit `WeakPtr` frontend sampler + handle key |
|
||
| D:5220-5235 | `g_resolvedTextureBindingMemos` | frontend `ProgramObject` as `const void*` key + bound-texture copies |
|
||
| D:5588-5592 | `rawDepthSamplerObject` | pointer into frontend `TextureUnit` storage (transient per sampler pass) |
|
||
| `Managers.h:1223/1254/1278` | `BackendVertexArrayObject::ResolvedDrawBuffers::Entry::frontend`, `iboFrontend` | raw client `BufferObject*` per-VAO memo |
|
||
| `Managers.h:1378` | `BackendVertexArrayObject::m_syncedIndexBufferObject` | raw `BufferObject*` |
|
||
| `Managers.h:2054` / M:10453 | `g_fboSyncedObjects[2]` | raw `FramebufferObject*` per target (compare-only) |
|
||
| `Managers.h:320-324`; registries at 1423/1818/1943/2540/2678/2819 | legacy `StateBackendObjectRegistry::m_entries` | raw frontend address key + `StateWeakPtr` |
|
||
| ST:156-167, ST:362-378 | `BackendSlotTable::Entry::stateRef`; `NoteStateForHandle`/`StateForHandle` | per-handle frontend `WeakPtr`/SharedPtr note |
|
||
| PI:807, PI:812-814 | `m_boundVertexArray`, `m_programForDispatch`, `m_programForDraw`, `m_transformFeedbackProgram` | SharedPtrs to frontend objects inside `gPipeInputs` (BARRIER_PULLED rows) |
|
||
| PI:808-811, PI:815 | `m_bufferBindingSlot[15]`, `m_bufferBindingPointBase[15]`, `m_framebufferBindingSlot[2]`, `m_imageTextureBindingBase`, `m_textureUnitBase` | raw pointers into frontend tables inside `gPipeInputs` |
|
||
|
||
## (c) `MGB_CTX->` accessors used from `MG_Backend/DirectGLES` whose `FieldOwnership.def` row is BARRIER_PULLED
|
||
|
||
Under `MOBILEGL_PIPE_PUSH`, `MGB_CTX` = `&gPipeInputs` (`MobileGL/MG_Pipe/PipeInputsSwitch.h:17-27`); BARRIER_PULLED object rows dereference the live GLContext through the pointer bases at PI:807-815.
|
||
|
||
| accessor | call sites |
|
||
|---|---|
|
||
| `GetFramebufferBindingSlot` / `GetFramebufferBindingSlotChecked` | D:182, D:197, D:6284, D:8408-8409; M:9397, M:9775 |
|
||
| `GetBufferBindingSlot` | D:401, D:669, D:962, D:6852, D:6930-6931, D:7009, D:7082-7083, D:7263, D:7312, D:10232, D:11214, D:11451, D:11761, D:12192; `Utils.cpp:2353`; MD:88 |
|
||
| `GetBufferBindingPoint` | D:510, D:569, D:605, D:628, D:1407, D:5464 |
|
||
| `GetBufferBindingPointCount` | D:621 |
|
||
| `GetBoundVertexArray` | D:1669, D:4770, D:6449, D:6724, D:6768; MD:96 |
|
||
| `GetTextureUnitObject` | D:1871, D:1899, D:1934, D:1947, D:2374, D:4861, D:5157, D:5562, D:8472, D:9302, D:9416, D:9564, D:11874 |
|
||
| `GetImageTextureBinding` | D:2650, D:2767; M:10849 |
|
||
| `GetProgramForDraw` | D:4781, D:5308, D:5679, D:5734 |
|
||
| `GetProgramForDispatch` | D:6126 |
|
||
| `GetTransformFeedbackProgram` | D:1387 |
|
||
| `GetProgramObject` / `ValidateProgramName` | D:6157, D:10023 / D:6152, D:10022 |
|
||
| `RecordError` | D:8804; M:13668 |
|
||
|
||
(`GetTouchedBufferBindingPointCount`, `GetActiveTextureUnit`, `GetCurrentVertexAttribute`, `GetPrimitiveRestartIndex`, `GetRenderStateParameters*`, `GetViewport`, `IsCapabilityEnabled`, `IsTransformFeedbackActive/Paused`, `GetPatch*`, `GetTransformFeedbackCapturedVertices`, `GetMaxTouchedTextureUnit` are RECORD-SUPPLIED; `GetTextureContextId`/`GetTextureBindGeneration`/`GetSamplingResolutionGeneration`/`GetPixelStoreParameters(false)` are APPLIER_DERIVED — server-owned, not listed.)
|
||
|
||
## What would have to change for the apply thread to read only server-owned memory
|
||
|
||
**VAO/vertex.** The bound-VAO row (`GetBoundVertexArray`) must become a handle read of `BoundVertexElements` plus the `VertexElementsCso` record; `GetConfigVersion()` compares must be replaced by the applier's own `VertexBuffersSerial`/`IndexBufferSerial`/`ContentSerial`. The `DrawArrays`/`MultiDrawArrays` entry-path probe (#12/#13) and `SyncClientSideAttributesForDrawArrays` (#14) have no pushed equivalent for client-side arrays — those draws would need the client-array bytes staged with the record or the path refused under split. The legacy memo/registry arm (#4, #7, #8) dies with the legacy arm.
|
||
|
||
**Buffers.** Every `HandleOfBuffer` probe on the hot path (#17, #25, #27, #30) is redundant with handles already present in `IndexBuffer`, the `VertexBuffers` window, and the shader-buffer records; the sync lists must key on handles and drop the stored raw frontend pointers. `GetBufferResource`/`GetBackendResource` (#32) needs a handle-keyed twin lookup. The reverse announcement `MarkBufferGpuWritten` (#30/#31) must consume the record-side handle instead of probing the client allocator per SSBO per draw.
|
||
|
||
**Textures/samplers.** The memoised sync lists must stop borrowing pointers into client binding slots (#38); the unit windows already exist as `BoundSamplerViews`/`BoundSamplerStates` records, so the per-draw key check, the rebuild walk (#35-#40), and `ResolveAndBindUnitTextures` (#50-#53) can all run on handle arrays. Frontend-keyed `Find`/`GetOrCreate` (#47-#48, #55, #66) becomes `FindByHandle`/`GetOrCreateByHandle`. `GenerateMipmap`'s unit/slot resolution (#59) must take the texture from `VerbMipRes` only; the CPU-mip shadow path (#61) and the unkeyed all-twin detach sweep (#63) need staged shadow bytes and a handle-keyed affected-FBO list respectively.
|
||
|
||
**Framebuffers/attachments.** The record arm of `SyncCurrentFBO` must stop validating the pushed record against the live binding slot (#68) — the record's own `Gen`/serial is the truth; the slot read at #69, the `NoteStateForHandle` SharedPtr stash (#70), and the `SyncToBackend(currentFBO)` walk (#71, #81, #82) must be replaced by applying `MGPFramebufferState` directly. `ForceBindCurrentFBO` (#74) needs a handle-keyed force-bind. The bound-form blit (#78, #79) must carry FBO handles and attachment descriptors in `MGPBlit` (or a companion record), since today nothing pushed identifies the two framebuffers or their attachments.
|
||
|
||
**Images.** `GetImageTextureBinding` rows (#85-#90) are already duplicated by the `BoundShaderImages` window (`MGPImageView` records); the apply path needs to read the window + serial and drop the live binding read, the `binding.Texture` dereference, and the `HandleOf` identity check, including the format-less-image `BoundImageUnitFormat` lookup.
|
||
|
||
**Programs/shader state.** The program rows (#91, #92) become `DrawProgram`/`DispatchProgram` handle reads; twin identity resolves by handle, eliminating #94/#95. Version checks (#96, #102, #108) map to `ShaderCso` serials; the per-draw `GetShaderStorageBlockBindingOverrides` signature (#97) and the attribute mask/type reads (#106) need to be baked into the `ShaderCso` record at create/relink time. `MapUBO` fallback bytes (#103) already have the `GlobalConstants` record as the pushed arm. The name-table probes (#109) are API-driven and can stay latency-bound or be handle-translated at emit.
|
||
|
||
**Binding-point tables.** This family has no transport branch at all: `SyncBufferBindingPoints`, `MarkShaderStorageBuffersGpuWritten`, `SyncAtomicCounterBuffers`, and the per-UBO loop read the live GLContext arrays on every draw/dispatch (#111-#118). The SSBO side is partly covered by `MGPShaderBuffers`; UBO and atomic-counter bindings need equivalent pushed windows (handle + range per index) so the loops iterate applier state, and `EnsureBufferResource` becomes handle-keyed throughout.
|
||
|
||
**XFB.** Capture setup (#119-#121) reads the TF program row and TF binding points live; the record arm needs the TF program handle and the captured-target list pushed at `BindStreamOutput`/begin, with `xfb.targets` storing handles instead of client SharedPtrs. The span-end readback probes (#122) then resolve by handle; the legacy writeback arm (#123) is monolith-only and unaffected.
|
||
|
||
**Misc.** `OnResourceCopyRegion`'s sticky-forward name-table probe (#125) must resolve `MGPCopyRegion.Src/Dst` handles instead of the GL names. Readback pack-PBO reads (#127) need the pack buffer handle in `MGPReadbackInfo`-class records. The multi-draw EBO reads (#128) fold into the `IndexBuffer` handle. The two deliberate leaks (`gPipeInputs`, PI:818-835; `MGPipeSlots()`, `SlotAllocator.cpp:370-381`) and every frontend-pointer memo in list (b) must be retired or converted to handle keys before the R-1 barrier can be removed.
|