Files
MobileGL/docs/Disaggregated/notes/recovered/wf4/part2.md
T
swung0x48 aba329cc53 [Docs] (Disaggregated): P6's plan and contract draft; the working notes move from a local directory into the repository
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.
2026-09-18 23:31:39 -04:00

25 KiB
Raw Blame History


2. The non-pGLContext paths by which a backend reaches frontend objects

pGLContext is the only MG_State:: global the backends touch (§0, "other MG_State globals: 0"). Every other reach is one of the five shapes below. P1 cannot succeed by rewriting only the 278 arrow sites: the accessors return references to live frontend objects, and the backends then call ~200 distinct methods on those objects.

2.1 The one static cache of a frontend pointer

MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp:142-155 — the only place a raw GLContext* is stored across calls:

142:    using FbBindingSlot =
143:        std::remove_reference_t<decltype(MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw))>;
144:    static const MG_State::GLState::GLContext* g_fbSlotCacheContext = nullptr;
145:    static Array<FbBindingSlot*, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fbSlotCache = {};
146:    static inline FbBindingSlot& GetFramebufferBindingSlotFast(FramebufferTarget target) {
147:        MG_State::GLState::GLContext* ctx = MG_State::pGLContext.get();
148:        if (ctx != g_fbSlotCacheContext) { ... &ctx->GetFramebufferBindingSlot(...) ... }

It caches interior pointers into the GLContext object (the by-value binding-slot members), keyed on the raw context address. Under P1 this cache has no meaning across a pipe boundary — the slots are not addressable from the backend at all. Its five call sites are the hot framebuffer path and each is a GetFramebufferBindingSlot read that the arrow-site table does not list (they read through the cache, not through pGLContext):

call site enclosing function verb path what it reads
DirectGLES/DirectGLES.cpp:1611 SyncNeccessaryTextures texture op (draw/dispatch) draw FBO binding slot
DirectGLES/DirectGLES.cpp:1905 SyncCurrentFBO framebuffer sync slot for target
DirectGLES/DirectGLES.cpp:2743 SyncCurrentProgram program/uniform sync draw FBO binding slot
DirectGLES/DirectGLES.cpp:2858 BindCurrentFBO framebuffer sync slot for target
DirectGLES/DirectGLES.cpp:2933 ForceBindCurrentFBO framebuffer sync slot for target

Each of those five also reads the slot's version (BindingSlot::GetVersion()) at DirectGLES.cpp:1614, 1917, 2745, 2936 — a value block P1 must carry alongside the handle.

There are no other GLContext&/GLContext* parameters or local aliases anywhere in MG_Backend: grep -rn 'GLContext\s*[&*]' --include=*.cpp --include=*.h returns exactly the one line 144 above once pGLContext matches are excluded.

2.2 SharedPtr<MG_State::GLState::…> in signatures and members (the "handle-ify" surface)

177 lines. The ones that matter structurally are the table-level ones (they are the verb signatures themselves) and the member-level ones (backend containers that own or weakly hold frontend objects across frames).

Table-level (these five GLFunctionsTable entries take frontend objects by handle today):

declaration file:line
ClearNamedFramebufferfv(const SharedPtr<FramebufferObject>&, …) BackendObject.h:158
ClearNamedFramebufferfi(const SharedPtr<FramebufferObject>&, …) BackendObject.h:160
ClearNamedFramebufferiv(const SharedPtr<FramebufferObject>&, …) BackendObject.h:162
ClearNamedFramebufferuiv(const SharedPtr<FramebufferObject>&, …) BackendObject.h:164
BlitNamedFramebuffer(const SharedPtr<FramebufferObject>& read, const SharedPtr<FramebufferObject>& draw, …) BackendObject.h:168-169
GetTextureImage(const SharedPtr<ITextureObject>&, …) BackendObject.h:186
CopyImageSubData(const CopyImageEndpoint& src, …, const CopyImageEndpoint& dst, …) where CopyImageEndpoint is {SharedPtr<ITextureObject> Texture; SharedPtr<RenderbufferObject> Renderbuffer;} BackendObject.h:33-38, BackendObject.h:176-180

Their per-backend mirrors: DirectGLES/DirectGLES.h:60,62,64,66,70,71; DirectVulkan/DirectVulkan.h:36,38,40,42,76,77,101; DirectVulkan/Renderer/VulkanRenderer.h:184,186,188,190,195,196,256,1400.

Member-level (backend state that outlives a verb and holds frontend objects):

holder file:line what it holds
UniformManager::m_fallbackTexture2D Renderer/UniformManager.h:305 SharedPtr<ITextureObject> — a synthesised frontend texture the backend itself created
UniformManager::m_fallbackMultisampleTextures Renderer/UniformManager.h:308 UnorderedMap<Uint32, SharedPtr<ITextureObject>>
UniformManager::m_unboundStorageImageTextures Renderer/UniformManager.h:317 UnorderedMap<Uint64, SharedPtr<ITextureObject>>
VkClearManager::m_aliveObjects Renderer/VkClearManager.h:167 unordered_map<TextureIdentity, WeakPtr<ITextureObject>>
VkTextureManager::m_aliveObjects Renderer/VkTextureManager.h:725 unordered_map<TextureIdentity, WeakPtr<ITextureObject>>
VkRenderPassManager attachment records Renderer/VkRenderPassManager.h:45,51,330,359 WeakPtr<ITextureObject> / WeakPtr<RenderbufferObject>
VulkanRenderer blit/clear helper programs Renderer/VulkanRenderer.h:378,379,380,388 SharedPtr<ProgramObject> + two SharedPtr<SamplerObject> the backend constructs itself
DirectGLES raw-depth-fetch sampler DirectGLES/DirectGLES.cpp:55 (static SharedPtr<SamplerObject> g_rawDepthFetchSamplerState), built at DirectGLES.cpp:150-160 same pattern: backend-authored frontend object

The last two rows are the P1 trap: these are frontend objects created by the backend, so under disaggregation the server has no frontend to create them in. They need either a server-local equivalent or a client-side create call.

2.3 The twin registries and the owner-keyed memos

DirectGLES/Managers.h:271 template <typename StateObject, typename BackendObject> class StateBackendObjectRegistry — hash map keyed on the raw frontend object pointer (using BackendMap = UnorderedMap<StateObject*, Entry>;, Managers.h:284), each Entry holding {BackendPtr backend; StateWeakPtr stateRef;} (Managers.h:280-283). Liveness is decided by entry.stateRef.expired() (Managers.h:318, Managers.h:339).

Six instances, all reached by the draw path:

registry declared keyed on
VertexArrayImpl::g_backendVertexArrayObjects Managers.h:803-804 VertexArrayObject*
TextureImpl::g_backendTextureObjects Managers.h:1124-1125 ITextureObject*
FramebufferImpl::g_backendFramebufferObjects Managers.h:1215-1216 FramebufferObject*
PrgramImpl::g_backendProgramObjects Managers.h:1733-1734 ProgramObject*
SamplerImpl::g_backendSamplerObjects Managers.h:1833-1834 SamplerObject*
RenderbufferImpl::g_backendRenderbufferObjects Managers.h:1860-1861 RenderbufferObject*

On top of them, DirectGLES/DirectGLES.cpp:83-115 class TwinLookupMemo — a direct-mapped memo whose slot is {StateObject* key; WeakPtr<StateObject> owner; BackendObject* twin;} (DirectGLES.cpp:100-104), indexed by Fibonacci-hashing the frontend heap address (DirectGLES.cpp:108-112), validated by OwnerEquals (DirectGLES.cpp:62-65, a weak_ptr::owner_before pair test). Three instances: g_vaoTwinLookupMemo (DirectGLES.cpp:122-123), g_programTwinLookupMemo (DirectGLES.cpp:124-125), g_fboTwinLookupMemo (DirectGLES.cpp:130-131); looked up at DirectGLES.cpp:1204, 2767, 2872 and stored at 1212, 2775, 2877.

Both mechanisms are pointer-identity based and cannot survive a process/thread split. P1 has to replace "frontend heap address + weak_ptr owner equality" with the wire handle plus a lifetime id. The good news is that the frontend already exposes exactly that: GetLifetimeId() (§2.4).

2.4 Lifetime-id and version reads (the memo keys P1 must carry over the wire)

39 GetLifetimeId() reads:

object kind sites
program DirectGLES/DirectGLES.cpp:3333, 3349; DirectVulkan/DirectVulkan.cpp:163; Renderer/UniformManager.cpp:482, 696, 2272, 2384, 2732; Renderer/VulkanRenderer.cpp:6044, 6484, 6524, 6577, 6648, 6962
texture Renderer/UniformManager.cpp:656, 1746, 1792; Renderer/VkClearManager.cpp:155, 197, 251, 368, 459; Renderer/VkRenderPassManager.cpp:642; Renderer/VkTextureManager.cpp:235, 733
sampler Renderer/UniformManager.cpp:654, 1747, 1793
VAO Renderer/VertexInputStateFactory.cpp:48 (via attr.Buffer, actually a buffer); Renderer/VulkanRenderer.cpp:3552, 6107, 6384, 6965
FBO Renderer/VkRenderPassManager.cpp:844, 869; Renderer/VulkanRenderer.cpp:6112, 6968
buffer DirectGLES/Managers.cpp:2678; Renderer/VertexInputStateFactory.cpp:48

36 version reads:

version sites what it gates
BindingSlot::GetVersion() (framebuffer slot) DirectGLES/DirectGLES.cpp:1614, 1917, 2745, 2936 the FBO-sync short-circuit (g_fboSyncedSlotVersions)
BindingSlot::GetVersion() (VAO index-buffer slot) DirectGLES/Managers.cpp:2307 element-array rebind
BufferObject::GetChangeSerial() DirectGLES/Managers.cpp:794, 1078, 1151, 1163, 1203, 1238, 1245, 1283, 1468, 1553, 1580, 1581, 2679; Renderer/VkBufferManager.cpp:697; Renderer/VulkanRenderer.cpp:3849 every buffer upload/re-upload decision on both backends
ITextureObject::GetContentVersion() DirectGLES/Managers.cpp:3649, 3776, 3826, 4731; Managers.h:1012; Renderer/VkTextureManager.cpp:1646, 1755; Renderer/VulkanRenderer.cpp:6293, 7016 texture upload short-circuit + the draw-time content-sum memo
SamplerObject::GetVersion() DirectGLES/Managers.cpp:4756, 8534; Managers.h:1016; Renderer/UniformManager.cpp:655; Renderer/VkSamplerManager.cpp:401 sampler twin re-sync
ITextureObject::GetShapeVersion() Renderer/VkTextureManager.cpp:1647, 1756 image recreate decision
ITextureObject::GetTextureParamsVersion() 14 sites, e.g. DirectGLES/Managers.cpp:3647, 3777, 3847 texture-parameter re-push
ProgramObject::GetBackendStateVersion() / GetLinkVersion() / GetImageUnitVersion() / GetUBOContentVersion() / GetBlockBindingVersion() DirectGLES/DirectGLES.cpp:3335, 3350, 3540, 2798, 2799, 3715, 3401; Renderer/UniformManager.cpp:2273; DirectVulkan/DirectVulkan.cpp:165 program twin re-sync + UBO re-upload
VertexArrayObject::GetConfigVersion() DirectGLES/DirectGLES.cpp:1258, 2962; DirectGLES/Managers.cpp:2306 VAO re-emit
FramebufferObject::GetObjectVersion() DirectGLES/DirectGLES.cpp:1615, 1918, 2937 FBO twin re-sync

2.5 BufferBackendOps — the reverse (frontend → backend) immediate-op table

Declared MobileGL/MG_State/GLState/BufferState/BufferObject.h:76-123; seven function pointers: Respecify, SubData, ResidentSubData, FlushMappedRange, OnDestroy, AcquirePersistentMap, ReadbackFromGpu. Every one takes BufferObject& — a frontend object by reference, and the callee reads the frontend shadow through it.

backend table registered unregistered
DirectGLES g_glesBufferBackendOps (DirectGLES/Managers.cpp:1351-1361, all seven filled, each wrapped in a …Tracked shim that bumps the buffer-mutation epoch) Managers.cpp:1374-1379 RegisterBufferBackendOps(), called from DirectGLES/BackendObject_DirectGLES.cpp:849 and DirectGLES/DirectGLES.cpp:10063 Managers.cpp:1381-1392, also from OnBackendContextDestroyed (Managers.cpp:1397)
DirectVulkan g_vulkanBufferBackendOps (Renderer/VkBufferManager.cpp:106-113, six filled — ResidentSubData is left null) Renderer/VkBufferManager.cpp:132 inside VkBufferManager::Initialize Renderer/VkBufferManager.cpp:139-141 inside Shutdown

The epoch the GLES shims maintain (Managers.cpp:1362-1372, CurrentBufferMutationEpoch / BumpBufferMutationEpoch) is itself a frontend-write-visibility signal the draw path memos read.

2.6 Backend → frontend writes (not pulls, but the same coupling, and P1 must not miss them)

These are calls the backend makes that mutate a frontend object. They are the mirror image of the pull sites and a pipe with only a pull direction will silently drop them:

method on frontend object sites
BufferObject::MarkGpuWritten() DirectGLES/DirectGLES.cpp:510, 1828; Renderer/UniformManager.cpp:1074, 1230
BufferObject::SetBackendResource() DirectGLES/Managers.cpp:1015, 1482; Renderer/VkBufferManager.cpp:297 (+1)
BufferObject::EnsureGpuResidentStorage() Renderer/UniformManager.cpp:1072, 1228; Renderer/VulkanRenderer.cpp:11326
BufferObject::WritebackFromBackend() DirectGLES/Managers.cpp:1279
ITextureObject::AllocateStorage() / MarkStorageDirty() / TruncateMipmapLevels() / SetInternalFormat() / SetSamples() / SetFixedSampleLocations() DirectGLES/DirectGLES.cpp:6326, 6327; Renderer/UniformManager.cpp:1484, 1489, 1490, 1496, 1497, 1498, 1625, 1628, 1635
ProgramObject::SetDrawID() / SetBaseVertex() / SetBaseInstance() / SetViewportPassMask() DirectGLES/DirectGLES.cpp:3683, 3689, 3677, 3813
ProgramObject::AttachShader() / Link() / MarkUBOContentDirty() / SetBackendHashMemo() Renderer/VulkanRenderer.cpp:4233, 4234, 4235, 4313, 4315, 4665, 8564; Renderer/ProgramFactory.cpp:3448
VertexArrayObject::SetBackendHashMemo() / SetBackendStateMemo() / SetBackendAuxMemo() Renderer/VertexInputStateFactory.cpp:60, 78, 83
SamplerObject::SetWrapS/T/R, SetMinFilter, SetMagFilter, SetMipmapMode, SetLodRange Renderer/VulkanRenderer.cpp:4270-4276
GLContext::RecordError() 6 sites, §3 accessor RecordError
GLContext::InvalidateCompileEnv() 2 sites, §3 accessor InvalidateCompileEnv

2.7 Frontend-object method surface reached through the pulled references

Counted by receiver-name heuristic over MG_Backend/** (excludes comment lines). This is the size of the "handle + value block" problem P1 inherits once the arrow sites are replaced:

frontend class distinct methods called call sites top methods
BufferObject 16 169 GetSize 50, MappedData 42, SyncPersistentMappedRange 20, GetChangeSerial 15, GetBackendResource 11, SyncGpuWrites 6
ITextureObject 38 411 GetExternalIndex 147, GetTarget 48, GetFormat 47, GetTextureParamsVersion 14, GetStorageType 11, IsTextureView 11, GetLifetimeId 10
ProgramObject 56 275 GetExternalIndex 69, GetLifetimeId 14, GetLinkStatus 14, GetUBOSize 14, GetUniformLocation 12, GetUniformSamplerOrImageUnitIndex 10
FramebufferObject 9 115 GetAttachment 39, GetExternalIndex 19, IsDefaultFramebuffer 18, GetDrawBuffers 16, GetReadBuffer 8, GetObjectVersion 7
SamplerObject 26 52 GetVersion 5, GetAllSamplerParameters 3, then one-per-parameter getters (GetWrapS/T/R, GetMinFilter, …)
VertexArrayObject 12 40 GetIndexBufferBindingSlot 11, GetAttribute 6, GetConfigVersion 6, GetBackendHashMemo 4, GetLifetimeId 4

Total ≈ 1062 method calls on frontend objects across 157 distinct methods. MGPResourceDesc, MGPProgramDesc, MGPSamplerDesc, MGPFramebufferState and MGPVertexElements in MG_Pipe/PipeFields.def are the intended replacements; the field lists there are visibly narrower than this surface, which is the second thing P1 has to reconcile.


3. (a) The PipeInputs accessor surface

Return types are from MobileGL/MG_State/GLState/Core.h (the GLContext class body starts at Core.h:61). "sites" is the count from §0.2; full site lists are in §1.

3.1 Accessors that return a handle to a frontend object (must become an MGPipeHandle)

accessor signature (Core.h) sites verb paths served
GetBufferBindingSlot BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget) — Core.h:78 29 draw (indirect/parameter), dispatch (indirect), readback (PixelPack), buffer op (SyncBoundBuffer)
GetBufferBindingPoint BindingSlotRange1D<BufferObject>& GetBufferBindingPoint(BufferTarget, Uint) — Core.h:79 9 buffer op (SSBO/UBO/atomic), xfb, program/uniform sync (descriptor)
GetFramebufferBindingSlot BindingSlot<FramebufferObject>& GetFramebufferBindingSlot(FramebufferTarget) — Core.h:473 19 (+5 via the fast cache, §2.1) framebuffer sync, clear, blit, readback, draw, pipeline build
GetTextureUnitObject TextureUnit& GetTextureUnitObject(Int) — Core.h:120 19 texture op, program/uniform sync (descriptor)
GetImageTextureBinding ImageTextureBinding& GetImageTextureBinding(Int) (+ const overload) — Core.h:121-122 7 texture op (image unit), program/uniform sync (storage image/texel)
GetBoundVertexArray const SharedPtr<VertexArrayObject>& GetBoundVertexArray() — Core.h:102 12 vertex sync, draw
GetProgramForDraw const SharedPtr<ProgramObject>& GetProgramForDraw() — Core.h:174 7 draw, program/uniform sync
GetProgramForDispatch const SharedPtr<ProgramObject>& GetProgramForDispatch() — Core.h:179 3 dispatch
GetProgramObject const SharedPtr<ProgramObject>& GetProgramObject(Uint) — Core.h:159 3 program/uniform sync (ShaderStorageBlockBinding, GetBackendProgramId)
GetTextureObject const SharedPtr<ITextureObject>& GetTextureObject(Uint) — Core.h:110 1 texture op (VkTextureManager::SyncTextureAndGetDescriptor liveness check)
GetTransformFeedbackProgram const SharedPtr<ProgramObject>& GetTransformFeedbackProgram() const — Core.h:329 3 xfb
GetCurrentVertexAttribute const CurrentVertexAttributeValue& GetCurrentVertexAttribute(Uint) — Core.h:106 2 vertex sync

The four in bold below return a reference to a mutable slot, not a value, so a PipeInputs accessor cannot simply copy them: GetBufferBindingSlot, GetBufferBindingPoint, GetFramebufferBindingSlot, GetTextureUnitObject. Every call site immediately follows with .GetBoundObject(), .GetRange(), .GetVersion() or .GetSamplerObject(); those are the value blocks P1 must materialise. PipeFields.def already models them as MGPVertexBuffer, MGPIndexBuffer, MGPIndirectBuffers, MGPBufferRange, MGPShaderBuffers, MGPBoundView, MGPSamplerViews, MGPImageView, MGPFramebufferState.

3.2 Accessors that return a plain value (a PipeInputs field can hold them verbatim)

accessor return type (Core.h line) sites
GetActiveTextureUnit Int (146) 8
GetBlendColor const FloatVec4& (278) 1
GetBlendEquationIndexed void(Uint, BlendEquation&, BlendEquation&) — out-params (255) 1
GetBlendFuncIndexed void(Uint, BlendFactor&×4) — out-params (250) 1
GetBufferBindingPointCount constexpr SizeT(BufferTarget) (80) 3
GetTouchedBufferBindingPointCount SizeT(BufferTarget) (86) 2
GetClampReadColor GLenum (235) 1
GetClearColor const FloatVec4& (272) 1
GetClearDepth Float (274) 1
GetClearStencil Uint32 (276) 1
GetColorMaskIndexed BoolVec4(Uint) (270) 6
GetCullFaceMode CullFaceMode (294) 1
GetDepthFunc DepthTestFunc (259) 1
GetDepthMask Bool (261) 5
GetDepthRangeIndexed const FloatVec2&(Uint) (282) 1
GetLineWidth Float (211) 1
GetLogicOp LogicOperation (257) 1
GetMaxTouchedTextureUnit Int (126) 1
GetMinSampleShadingValue Float (289) 1
GetPatchDefaultInnerLevel const FloatVec2& (219) 3
GetPatchDefaultOuterLevel const FloatVec4& (217) 3
GetPatchVertices Uint (215) 3
GetPixelStoreParameters PixelStoreParameters(Bool isUnpack) (292) 6 (all with isUnpack=false)
GetPolygonModeFront GLenum (237) 1
GetPolygonOffsetFactor Float (222) 1
GetPolygonOffsetUnits Float (223) 1
GetPrimitiveRestartIndex Uint32 (240) 3
GetProvokingVertexMode ProvokingVertexMode (298) 1
GetRenderStateParameters const RenderStateParameters& (205) 11
GetScissorBox const IntVec4& (300) 3
GetStencilState const StencilFaceState&(StencilFace) (266) 8
GetViewport IntVec4 (207) 1
GetViewportIndexed const FloatVec4&(Uint) (209) 1
IsCapabilityEnabled Bool(CapabilityInput) (242) 29
IsCapabilityEnabledIndexed Bool(CapabilityInput, Uint) (244) 1
IsTransformFeedbackActive Bool (325) 5
IsTransformFeedbackPaused Bool (326) 2
HasOpenTransformFeedbackSpan Bool(Uint64 lifetimeId) (450) — NOT in PipeFilled.inc 1
ValidateProgramName Bool(Uint) const (157) — pseudo-call kClientResolved 3

The 14 distinct CapabilityInput values the 30 capability reads ask for (P1's CapabilityBits block, which PipeFields.def already names in MGP_FIELDS_ResidualValueBlock): FramebufferSrgb, RasterizerDiscard, PrimitiveRestart, PrimitiveRestartFixedIndex, Multisample, SampleMask, CullFace, DepthTest, PolygonOffsetFill, ColorLogicOp, StencilTest, SampleShading, ScissorTest, Blend (only via IsCapabilityEnabledIndexed).

3.3 Accessors that return a version / generation counter (memo keys)

accessor return type (Core.h line) sites memo it keys
GetPipelineStateVersion Uint (204) 3 Vulkan pipeline cache + fast-path snapshot
GetRenderStateParametersVersion Uint (202) 2 GLES render-state shadow, Vulkan dynamic-state tail
GetTextureBindGeneration Uint64 (130) 5 per-draw sampled-texture set
GetSamplingResolutionGeneration Uint64 (136) 9 mipmap-completeness re-resolve
GetTextureContextId Uint64 (143) 6 disambiguates a recreated context at the same address
GetTransformFeedbackGeneration Uint64 (334) 1 xfb counter-buffer rebind
GetTransformFeedbackCapturedVertices Uint64 (357) 1 GLES scatter-capture record count
GetTransformFeedbackPausedPrimitiveCounter Uint64 (349) 2 xfb primitives-written query
GetBoundTransformFeedbackLifetimeId Uint64 (441) — NOT in PipeFilled.inc 1 Vulkan xfb counter-slot ownership

3.4 Non-read accessors (reverse channel / client-resolved)

accessor signature sites Coverage.def classification
RecordError void(ErrorCode, UniquePtr<ErrorInfo>) — Core.h:66 6 kReverseChannel
InvalidateCompileEnv void() — Core.h:506 2 kClientResolved
ValidateProgramName Bool(Uint) const — Core.h:157 3 kClientResolved

3.5 Reconciliation with PipeFilled.inc's 61 fields

fields in PipeFilled.inc (generated/PipeFilled.inc:28-90, asserted at :92) 61
distinct accessors read by the backends on this tree 61 (+.get())
in PipeFilled.inc but never read by a backend 1 — GetBoundTransformFeedbackName (PipeFilled.inc:32)
read by a backend but absent from PipeFilled.inc 2 — GetBoundTransformFeedbackLifetimeId, HasOpenTransformFeedbackSpan
corrected field count for P1 62

Additional structural gaps that PipeInputs-as-generated does not model, all of which have real sites:

  1. .get() on the context itself (DirectGLES.cpp:147) has no accessor to map to; the whole GetFramebufferBindingSlotFast cache (DirectGLES.cpp:142-155, 5 call sites) must be deleted or rebuilt on handles.
  2. Slot version reads (BindingSlot::GetVersion(), 5 sites, §2.4) ride on GetFramebufferBindingSlot/GetBoundVertexArray and are not separate fields today; MGP_FIELDS_MGPBindRenderState has a Version and MGP_FIELDS_MGPFramebufferState has a ContentHash, but no field carries a framebuffer binding-slot version.
  3. GetBufferBindingSlot is polymorphic over BufferTarget — Coverage.def:37-42 already flags this ("its rows split across set_vertex_buffers, set_index_buffer, set_indirect_buffers and set_shader_buffers once the inventory carries the target argument (P1)"). The five targets actually asked for are DrawIndirect (13 sites), Parameter (4), PixelPack (7), DispatchIndirect (1), plus a runtime target parameter at DirectGLES.cpp:518 (SyncBoundBuffer, called with DrawIndirect @:664 and DispatchIndirect @:691).
  4. GetBufferBindingPoint is likewise polymorphic: TransformFeedback (3), ShaderStorage (1), AtomicCounter (1), Uniform (2), plus a runtime target/bufferTarget at DirectGLES.cpp:370 and UniformManager.cpp:1194.