[Feat] (Pipe): land the P2 contract - real storage for the three swallowed capabilities, the render-state chunk table and its subset hash, the in-process applier, the slot allocator, the subsystem bitmask and the residual ratchet down to 8

- FramebufferSrgb, DepthClamp and TextureCubeMapSeamless get real storage. All three fell
  to SetCapability's "not supported currently" arm and IsCapabilityEnabled's default:
  glEnable was swallowed and glIsEnabled lied, so DirectGLES' sRGB block and the
  DirectVulkan read points consumed a constant. The three Bools land in the three
  alignment bytes at [581, 584) between ColorMasks and ClearColor, so
  sizeof(RenderStateParameters) stays 1168 and NO existing offset moves - Espryt's
  kBlendSpanBegin/kBlendSpanEnd (312/536) and the whole chunk table depend on that.
- MGPipeRenderStateSpans.{h,cpp}: the pipeline/dynamic split, written in exactly one place.
  The rule is the only rule - a byte is pipeline state iff a public RenderState setter that
  calls BumpVersions() writes it - which makes G7's "the subset hash moves iff
  m_pipelineStateVersion moves" true by construction. 16 boundaries, all offsetof or
  sizeof, alternating dynamic/pipeline: 8 dynamic chunks / 772 bytes and 7 pipeline chunks
  / 396 bytes, partitioning [0, 1168) exactly, asserted at compile time.
  MGPipeComputePipelineSubsetHash is XXH64 over the seven pipeline chunks, seeded with a
  table version so a chunk-table change invalidates every persisted key.
- The pipeline subset is now a strict SUPERSET of the 24 members ComputePipelineStateHash
  hashed: 44 members, adding sample coverage, the front face, the provoking vertex, the
  scissor-test mask, the back polygon mode, eleven capability bools the hash never read and
  the three above. Demoting those setters to ++m_version instead would have changed
  MG_State semantics in the PULL build for the push path's sake. The hash runs only when
  m_pipelineStateVersion moves, which is exactly when Magma re-hashed before.
- PipeApply.{h,cpp}: the in-process applier, the server half of the P2 calls. The server's
  working RenderStateParameters IS PipeInputs::m_renderState, which is why DirectGLES'
  SyncRenderState is not one line changed and why the verify comparator stops being a
  tautology. Per-context CSO store indexed by slot, gen-validated; the residual block's
  capability bits are compared against the assembled block, so a capability a later call
  takes over and forgets to carry is Fatal{PipeResidualDiverged}.
  MGPipeDeriveRenderStateFields is a declared STUB - its 29 derivations are commit c1.
- SlotAllocator.{h,cpp}: the client's per-kind {slot, gen} allocator, free list plus
  high-water, first allocatable slot 1, gen bumping only on slot REUSE, a debug assert on
  gen wrap, the composite ShaderCso band held back, and a lifetimeId -> slot map per kind so
  a GL name never enters a key. In the contract because both Track H slices need it.
- ResidualValueBlock 1248 -> 8 bytes, one Uint64 of capability bits.
  RenderStateParameters retired to create/bind_render_state and set_dynamic_state, Pack to
  set_pixel_pack_state, the patch quintet to set_patch_state. gen_pipe.py now emits the
  member-by-member offsetof assertions the ratchet comment always promised.
- gen_pipe.py: PIPELINE_STATE_MEMBERS grows to the 44-member set in declaration order and
  PipeSpanTable.inc's "deliberately absent" block records the answers instead of the
  questions; Coverage.def gains MGP_COVERAGE_EMITTED_LIST (34 rows) and PipeFilled.inc
  gains kMGPipeFieldEmittedBy[], which is what lets the residual fill loop skip a field a
  P2 call now supplies. One more --self-test negative control covers the new list.
- MOBILEGL_PIPE_PUSH becomes a per-subsystem bitmask with named bits (0..6 migrated at P2,
  bit 63 the CSO-content-addressing negative control), defaulting to 0x7f in a push build
  and staying 0 in a pull build. New CMake option MOBILEGL_PIPE_LEGACY_MEMOS, ON, forced ON
  when MOBILEGL_PIPE_PUSH=OFF where it is the only arm. New Features.PipeHandleAbaControl
  under MOBILEGL_PIPE_PUSH, negative control C for HandleRecycleScenario.
- PipeStats gains CallClass::{RenderStateCsoMints, RenderStateCsoBinds} (csom / csob on the
  summary line), and they are PUSH-ONLY: growing the enum in the pull build would resize
  the counter arrays, the name table and FormatWindowLine for two counters that could never
  leave zero, and G1 admits no such resize.
- Four MG_Test/Pipe stubs plus their CMake registration, so the packages that own their
  contents never touch MG_Test/Pipe/CMakeLists.txt.

G1, pull build, symbol_report --threshold 0: 0 added, 0 removed, 0 renamed, 4 resized, and
every resize is attributed:
  RenderState::RenderState()                       1700 -> 1848 (+148)  the three {}
  RenderState::SetCapability(CapabilityInput,bool)   850 ->  927  (+77)  three switch arms
  RenderState::IsCapabilityEnabled(CapabilityInput)  239 ->  268  (+29)  three switch arms
  _GLOBAL__sub_I_DirectGLES.cpp                     1340 -> 1331   (-9)  the static
    initialiser of DirectGLES.cpp's `static RenderStateParameters
    g_syncedRenderStateParameters` re-scheduling around the three new default-initialised
    members. A shrink, and the only unforeseen entry; it is a direct consequence of the
    struct gaining members and touches no interface.
This commit is contained in:
2026-09-06 07:45:07 -04:00
parent 4826806881
commit 9c6a8a25d8
30 changed files with 1826 additions and 130 deletions
@@ -317,9 +317,11 @@ namespace MobileGL {
SET_CAPABILITY(ColorLogicOp, enabled);
SET_CAPABILITY(DebugOutput, enabled);
SET_CAPABILITY(DebugOutputSynchronous, enabled);
SET_CAPABILITY(DepthClamp, enabled);
SET_CAPABILITY(DepthTest, enabled);
SET_CAPABILITY(CullFace, enabled);
SET_CAPABILITY(Dither, enabled);
SET_CAPABILITY(FramebufferSrgb, enabled);
SET_CAPABILITY(LineSmooth, enabled);
SET_CAPABILITY(Multisample, enabled);
SET_CAPABILITY(PolygonOffsetFill, enabled);
@@ -335,6 +337,7 @@ namespace MobileGL {
SET_CAPABILITY(SampleMask, enabled);
SET_CAPABILITY(SampleShading, enabled);
SET_CAPABILITY(StencilTest, enabled);
SET_CAPABILITY(TextureCubeMapSeamless, enabled);
SET_CAPABILITY(ProgramPointSize, enabled);
case CapabilityInput::Blend: {
Bool stateChanged = false;
@@ -378,7 +381,9 @@ namespace MobileGL {
++m_version;
break;
}
default: // not supported currently
// Every CapabilityInput now has storage; the arm is a backstop for a value
// outside the enum, not a silent swallow of a real glEnable.
default:
break;
}
#undef SET_CAPABILITY
@@ -392,9 +397,11 @@ namespace MobileGL {
RETURN_CAPABILITY(ColorLogicOp);
RETURN_CAPABILITY(DebugOutput);
RETURN_CAPABILITY(DebugOutputSynchronous);
RETURN_CAPABILITY(DepthClamp);
RETURN_CAPABILITY(DepthTest);
RETURN_CAPABILITY(CullFace);
RETURN_CAPABILITY(Dither);
RETURN_CAPABILITY(FramebufferSrgb);
RETURN_CAPABILITY(LineSmooth);
RETURN_CAPABILITY(Multisample);
RETURN_CAPABILITY(PolygonOffsetFill);
@@ -410,6 +417,7 @@ namespace MobileGL {
RETURN_CAPABILITY(SampleMask);
RETURN_CAPABILITY(SampleShading);
RETURN_CAPABILITY(StencilTest);
RETURN_CAPABILITY(TextureCubeMapSeamless);
RETURN_CAPABILITY(ProgramPointSize);
case CapabilityInput::Blend:
return m_parameters.BlendStates[0].Enabled;
@@ -169,11 +169,16 @@ namespace MobileGL {
// not evict a cached pipeline. Keeping one counter for both made a glViewport call
// knock the next draw off the pipeline memo AND the draw fast path.
Uint16 m_pipelineStateVersion = 0;
RenderStateParameters m_parameters;
// Value-initialised, PADDING INCLUDED. The MGPipe CSO key is a byte-range
// hash over RenderStateParameters and the residual block's trip wire is a
// byte-level compare, so indeterminate padding would make a CSO handle
// reproducible only within one context and would make the trip wire
// meaningless. Costs one .text resize of this constructor.
RenderStateParameters m_parameters{};
// Pixel Store
PixelStoreParameters m_pixelStorePackParameters;
PixelStoreParameters m_pixelStoreUnpackParameters;
PixelStoreParameters m_pixelStorePackParameters{};
PixelStoreParameters m_pixelStoreUnpackParameters{};
};
} // namespace GLState
} // namespace MG_State