Files
MobileGL/MobileGL/MG_State
swung0x48 3594f03c4e [Refactor] (State, Magma): take the backend's raw pointers out of the frontend VAO - the hash and state memos become the factory's own per-slot fields
- P2 D12.5 (ARCHITECTURE.md 9.5). VertexArrayObject carried three `mutable` memos for the
  backend: a content hash, a raw pointer into VertexInputStateFactory's heap-allocated
  cache entry plus that cache's eviction epoch, and two aux words. A frontend state object
  holding the backend's pointer is what P2 retires - under split the backend is in another
  process and its cache entry has no address a client could store.
- The hash and state memos move into a slot-indexed table the FACTORY owns, keyed on the
  VAO's {slot, gen} and guarded by exactly the same config version, so nothing is
  recomputed more often than it was. Fixed and direct-mapped for the same reason m3's
  VaoDrawMemo table is: nothing frees a VertexElementsCso slot in P2, so a grow-on-demand
  table would keep one entry per VAO ever created. 2048 x 48 B is 96 KB.
- The AUX memo is deleted rather than moved, as the brief says: its two words already live
  in VulkanRenderer::VaoDrawMemo (layoutHash / layoutAuxMasks) and GetBackendAuxMemo has no
  live reader anywhere in the tree - the only writer was the line this commit stops
  executing.
- The eviction-epoch dance shrinks with them. The PROCESS-WIDE s_evictionEpochSource exists
  because the memos live on frontend VAOs and therefore outlive the factory; the handle
  arm's table dies with the factory, so a per-instance counter is enough there. The epoch
  itself stays - it guards the POINTEE, which is still a cache entry a frame boundary can
  erase, and moving the memo does not change that. (The brief reads as if a slot-indexed
  table removes the need for an epoch; it removes the need for a process-wide one.)
- The three draw-path readers that asked the VAO "is your content hash already memoized?"
  now ask whichever side owns the memo, through a force-inlined wrapper so the PULL build's
  two loads stay two loads.
- All three accessors and their storage are kept under MOBILEGL_PIPE_LEGACY_MEMOS rather
  than deleted from the file, because that is the arm the pre-handle A/B runs (D14) and
  because a pull build forces the option ON, where G1 admits no change at all. Configuring
  with -DMOBILEGL_PIPE_LEGACY_MEMOS=OFF is what makes the deletion real, and that build
  compiles clean - which is the check that nothing else still reaches for them.
- Verification: pull symbol_report --threshold 0 is 0 added / 0 removed / 0 renamed with
  the contract's four resizes and no fifth; ctest -L unit 1489/1489 in both the pull and
  the push build; ctest -L integration-gpu -R DirectVulkan 432/432 under the default
  bitmask and 432/432 under MOBILEGL_PIPE_PUSH=0. The LEGACY_MEMOS=OFF build compiles but
  cannot RUN on this tree, and that is the D14 gate working rather than a defect: no
  tracker binds a render-state CSO here, so the handle arm has no key and
  Fatal{PipeLegacyMemosDisabled} fires at the first draw instead of the memo quietly
  aliasing every render state onto one entry. Re-run it once p2/tracker has landed.
2026-09-07 23:18:09 -04:00
..