- set_vertex_attrib_defaults hard-coded MGPAttribValue::ValueClass to 0 for every attribute
and always sent the FLOAT view's four words. A CurrentVertexAttributeValue is one value in
three views and GLContext converts numerically between them, so those bytes cannot
reproduce the frontend value: glVertexAttrib4f(loc, 1.5f, ..) leaves 1 in intValue and
0x3FC00000 in floatValue, and every glVertexAttribI4i/ui default was wrong too
- GLContext now records which view each glVertexAttrib* write filled directly
(GetCurrentVertexAttributeClass, push-only) and the payload carries that class and THAT
class's own words. It is kept beside the value rather than inside it because
CurrentVertexAttributeValue is mirrored into PipeInputs and compared there by a memcmp
whose size assertion lives in a file this package does not own
- MGPipeFillAttribValue is the flattening, in one named place, so TrackerAttribPayload can
pin it: the old defect turns three of its four cases red
- the applier (package A's) still memcpys the four words into all three views regardless of
ValueClass, so the emitter now CHECKS: it compares the mirror the applier wrote against the
frontend's value and, when they differ, copies the field itself and says so once. That
closes the window the old code left wrong - a glVertexAttrib* write followed by a verb
whose class does not read the field, where the residual fill does not run for it - and it
stops repairing by itself the day A's applier honours the class
- MGPipeVertexAttribDefaultRepairCount() makes that repair observable to a test without
reading storage the fill table forbids that verb to read
- the emission gate now goes through MGPipeSubsystemForDirty, the one bit-to-subsystem map,
instead of a second copy of it written out by hand at the validate point; five
static_asserts tie that map to the field-emitter map it has to agree with
- the staging mirror is advanced only by the branch that sent dynamic bytes, with the
invariant it used to rely on (BumpVersions moves both counters, RenderState.h) asserted
here rather than assumed of another package's file
- TrackerShippedEmitter drives MGPipeValidateForVerb itself and reads the real singletons
back, so the blend-toggle and viewport shapes are pinned on the shipped emitter and not
only on the unit tests' local re-implementation; the fixtures reset the applier, the cache
and the tracker together, which is the only consistent state of the three
- comments: the derivation probe is a one-field sample, the residual block's trip wire is
half a tautology until package A's c1 lands, and the widened counter cannot see a change of
exactly 65536 - all three recorded where the code is, not only in a review
- set_pixel_pack_state on NEW_PIXEL_PACK, set_patch_state on NEW_PATCH_STATE,
set_vertex_attrib_defaults on NEW_VERTEX_ATTRIB_DEFAULTS, each gated on its own runtime
subsystem bit so the bitmask stays a per-subsystem A/B.
- MG_Impl/Pipe/SetHashSuppressor.h: seven slots, one per kVarTail set_*, with
SetVertexAttribDefaults the one P2 wires. 0 is reserved for "never emitted" and a computed 0
is remapped to 1, so the first emission always goes out. The other six are the carrier for
the ~175 lines of backend debounce that move in P3b/P4b; landing the mechanism now means the
shape is pinned by a test rather than by a plan.
- The var-tail carries only the attributes that differ from the tracker's mirror, underneath
the set-hash suppression of the whole resolved set - the two suppressors answer different
questions and both are cheap.
Two rows of Coverage.def's emitted list CANNOT yet retire their pull, and each says why in the
code rather than being silently absent:
- GetPixelStoreParameters is BOTH halves of the pixel store and set_pixel_pack_state
deliberately carries only PACK, so the unpack half has no carrier at all. The field keeps
being pulled and the verify comparator keeps proving it.
- GetCurrentVertexAttribute's three views are not bit-identical - GLContext CONVERTS between
them - while MGPipeApplySetVertexAttribDefaults memcpys one Data[4] into all three and
ignores MGPAttribValue::ValueClass, which the wire type carries precisely so it does not
have to. Until that applier reads ValueClass the carrier cannot reproduce the frontend
value. The call is still emitted, so the wire shape, the payload bytes and the suppressor
are all real; the residual fill runs after emission, so the mirror ends up correct either
way.
Both are contract-side defects in files this package does not own; they are reported to the
integrator with the exact fix rather than worked around here.
- MG_Impl/Pipe/CsoCache.h: 64 entries, LRU, hash -> probe -> MEMCMP -> handle. The memcmp is
not optional: a bare 64-bit hash equality would let a collision alias two different render
states onto one CSO, which is silent wrong pixels with no gate that can see it, and Mesa's
cso_cache memcmps for exactly that reason. It runs only when the pipeline version moved, so
never in the steady state. Eviction emits delete_render_state and frees the client slot.
- kMGPipeBehaviourNoCsoContentAddressing (bit 63) turns off the PROBE and the handle reuse,
not the records: every pipeline-version change then mints, binds and evicts, which is the
whole-block content addressing the design is measured against.
- The validate point's step 3: bind_render_state when the pipeline version moved (12 bytes, no
hashing, no blob when the cache hits), set_dynamic_state when m_version moved, carrying only
the dynamic chunks that differ from the tracker's staging mirror. An EMPTY chunk mask still
sends the 32-byte header, because the version is what Magma's dynamic tail gates on and it
moved.
- The residual fill now skips a field a P2 call supplies, driven by the generated
kMGPipeFieldEmittedBy[] and gated per subsystem on the runtime MOBILEGL_PIPE_PUSH bitmask, so
the bitmask is a true per-subsystem A/B. THE STAMP IS UNCHANGED: a stamp says "this verb
published this field", which is as true of an emitted field as of a copied one, and
withholding it would abort every backend read of the fields the migration just took over.
- PipeStats::RecordDrawPayloadBytes has been implemented, unit-tested and called by nothing
since P0. This is its first emitter.
- A field that reaches PipeInputs only through MGPipeDeriveRenderStateFields is skipped only
when that derivation is really there. It is package A's and is a declared stub on the
p2/contract tag this branch starts from, so rather than hard-code which branch this is, the
filler probes once: a sentinel in a scratch block, the mirror cleared, the derivation run,
the answer latched. It stays useful after A lands - if the derivation is ever deleted the
filler degrades to PULLING those fields rather than rendering a default.
- integration-verify, 818 entries, green: the comparator re-reads every field from the live
context at every backend read, so "the assembled block equals the live context" is now
proven rather than asserted, and the entry compare has stopped being a tautology.
- MGPipeFillForVerb becomes MGPipeValidateForVerb and MGP_FILL expands to the new name. The
macro spelling, the 83 call sites and the verb enum do not change: the dispatch is
kMGPipeVerbClass's nine classes, which is the same code as nine named ValidateFor* entry
points with one call site per verb instead of nine (P2 brief D1, against ARCHITECTURE.md's
eight - FillPoints.def argues in its own comment for splitting kProgramOp out, and the landed
table is what runs).
- MG_Impl/Pipe/Tracker.h: MGPipeDirty's 18 bits, the widened Uint16 shutters, the per-verb walk
and the per-bit-per-verb-class fire tallies. The widening happens in the TRACKER and MG_State
is not changed for it; a wrap costs one extra re-push and never a missed one.
- NOTHING IS EMITTED YET. The mask is computed, latched and counted, and the full P1 residual
fill runs after it unchanged. That is the point of this step: it says the walk is
semantically free before any field stops being pulled, so a regression in the next commit
cannot be blamed on the walk.
- Every shutter over-fires on purpose. Bits 2 and 3 are BYTE compares, not value compares,
because a NaN patch level is a legal glPatchParameterfv value and has to equal itself; bits
5..17 are composed with a mixing hash, which can in principle collide, and that is stated in
the file and is acceptable only because nothing consumes those bits in P2.
- The shutter for bits 6..8 reads the current program's version counters WITHOUT
GetProgramForDraw, so the walk never joins a pending link to answer "did the shader move".
- Header-only rather than Tracker.{h,cpp}: the root CMakeLists.txt that would have to name a
new .cpp belongs to package A and is frozen behind the p2/contract tag. One translation unit
in the library includes it, so inline costs nothing, and splitting it out is one list(APPEND)
line whenever the ownership allows.
- MG_Test/ScopedPipeVerb.h and MG_Test/Pipe/PipeInputsTest.cpp follow the rename. Five comment
references to the old name live in package A's files (MGPipe.h, the two generated .inc, and
gen_pipe.py) and are deliberately left for their owner.