[Docs] (MG_Backend/DirectGLES, MG_Backend/MGPipe, MG_Backend/Record, MG_Impl/Pipe, MG_IntegrationTest, MG_IntegrationTest/Harness, MG_IntegrationTest/Scenarios, MG_Pipe, MG_Pipe/generated, MG_Remote, MG_Remote/Client, MG_Remote/Server, MG_Remote/Transport, MG_Remote/Wire, MG_State/GLState, MG_Test/Pipe, MG_Test/Wire, MG_Util/Metrics, MobileGL, scripts, scripts/ci): cite symbols, not line numbers, in the shortened files

This commit is contained in:
2026-10-15 22:27:15 -04:00
parent 23ee8bdb49
commit 265966a15d
58 changed files with 146 additions and 150 deletions
+1 -1
View File
@@ -163,7 +163,7 @@ namespace MobileGL {
// lavapipe and on an Adreno 830, because the two Init calls are two statements in one
// thread. And "the legacy pull path runs for it" is false under split - the client has
// no pull path to fall back to - so the records are simply lost, and only a later
// respecify's self-healing create (TextureEmit.h:872) ever brings one back.
// respecify's self-healing create (EmitResourceRespecify in TextureEmit.h) ever brings one back.
//
// A BOUNDED WAIT INSIDE ServerConsumes CANNOT FIX THIS AND WOULD DEADLOCK: during
// MG_State::Init() no handshake is in flight, and the one that will land is started
@@ -3078,7 +3078,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
static_cast<Uint>(std::max(g_GLESCapabilities.MaxImageUnits, 0)));
// P4a e3 (D-G2, D-J2), CORRECTED BY THE REVIEW'S MAJOR-1.
//
// THE RECORD'S WINDOW IS NOT THIS SWEEP'S MEMBERSHIP. D-J2 and PipeApply.h:461-464
// THE RECORD'S WINDOW IS NOT THIS SWEEP'S MEMBERSHIP. D-J2 and PipeApply.h's MGPipeWorkingState
// are a rule about RECORD RETENTION - entries outside the var-tail window are not
// cleared in the applier - and say nothing about which DRIVER units a re-issue
// sweep has to visit. The membership this loop needs is "every unit the driver
@@ -3100,7 +3100,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Start is as undescribed as one above Start + Count).
//
// A8, which the review adds to this package's assumption list: NOTHING IN THE
// CONTRACT PINS THE WINDOW'S MEMBERSHIP. PipeApply.h:461-464 says only that the
// CONTRACT PINS THE WINDOW'S MEMBERSHIP. PipeApply.h's MGPipeWorkingState says only that the
// record is the last set as received, and that Start + Count above the bound is
// Fatal{ProtocolCorruption}. Until package C documents in ImageEmit.h that the
// window covers every unit the driver holds, this union is load-bearing; the
+7 -7
View File
@@ -4555,7 +4555,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return PipeRecordAt(MG_Pipe::MGPipeApplier().ShaderCsos, cso);
}
// N-7: D KEYS ON THE UPLOAD HALF; WIRE (AccumulatePendingUpload, PipeApply.cpp:814) KEYS ON
// N-7: D KEYS ON THE UPLOAD HALF; WIRE (AccumulatePendingUpload, PipeApply.cpp) KEYS ON
// THE WHOLE PACKED FIELD. That asymmetry is resolved HERE, in D's favour and with the
// reason, rather than by widening the two comparisons: D's question is per (uploadTarget,
// level) because that is the granularity its upload loop iterates - it is handed a
@@ -4567,10 +4567,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
//
// So the low byte is CROSS-CHECKED instead of ignored. The comparand is the resource's own
// descriptor Target, which B fills from exactly the expression the sub-data's low byte
// comes from (TextureEmit.h:223 / :517 against :1037), so the two are carried and equal by
// construction and any disagreement is a seam defect, not a shape to learn. This is also
// MGPResourceDesc::Target's first reader in this package (esprytobj-v2.md §2(6) recorded it
// as having none).
// comes from (TextureEmit.h's MGPipeBuildTextureResourceDesc and EmitResourceCreate against
// EmitOneLevel), so the two are carried and equal by construction and any disagreement is a
// seam defect, not a shape to learn. This is also MGPResourceDesc::Target's first reader in
// this package (esprytobj-v2.md §2(6) recorded it as having none).
static void NotePipeSubDataTargetLowByte(const MG_Pipe::MGPipeResourceRecord& record, Uint16 packedTarget,
Uint16 level) {
const Uint8 carried = MG_Pipe::MGPipeSubDataResourceTargetOf(packedTarget);
@@ -4932,8 +4932,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
// THE KEY IS THE ATTRIBUTE INDEX, NOT MGPVertexAttribWire::BindingIndex, and the two
// live in different spaces. Espryt consumes RESOLVED attributes, so the client emits
// set_vertex_buffers as one entry per attribute slot with
// MGPVertexBuffer::BindingIndex == the attribute index (VertexInputEmit.h:190-193,
// :229 - "Espryt consumes RESOLVED attributes, so the set is one entry per attribute
// MGPVertexBuffer::BindingIndex == the attribute index (EmitVertexBuffers in VertexInputEmit.h -
// "Espryt consumes RESOLVED attributes, so the set is one entry per attribute
// slot with BindingIndex == the attribute index"), each carrying that attribute's
// already-folded buffer, stride and divisor. MGPVertexAttribWire::BindingIndex is the
// OTHER thing: the GL binding POINT the attribute was attached to by
+2 -2
View File
@@ -3239,9 +3239,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// BoundSamplerStates[unit])` (the record arm of BindCurrentUnitSamplers, E's S4) could
// never find a twin, the record arm bound nothing on every draw, and every glBindSampler
// reached the driver only through the pre-handle program pass - S-1's confusion one
// loop over, and exactly what SamplerEmit.h:201-205 forbids ("a backend must NOT key a
// loop over, and exactly what ARCHITECTURE.md §2.3.1 forbids (a backend must NOT key a
// sampler twin on a SamplerObject's lifetime id; the twin's life is
// create_sampler_state -> delete_sampler_state").
// create_sampler_state -> delete_sampler_state).
//
// This is the twin keyed the way the record is: resolved-or-created AT THE CSO HANDLE
// (GetOrCreateByHandle, the same slot table, a slot the identity family can never hold)
+1 -1
View File
@@ -540,7 +540,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// GetOrCreate from a twin destructor cannot resurrect it.
//
// The slot itself is NOT freed here: it belongs to the kind, and for a handle-keyed
// kind the CLIENT frees it after the destroy call returns (SlotAllocator.h:60 - the
// kind the CLIENT frees it after the destroy call returns (MGPipeSlotAllocator::Free - the
// Gen bump rides the next handout, so a double free cannot skip a generation). An
// entry whose Gen no longer matches is a twin of the slot's previous owner and is
// left alone: the successor's own GetOrCreate resets it.
+2 -2
View File
@@ -387,9 +387,9 @@ namespace MobileGL::MG_Pipe {
}
// THE ONE FIELD TABLE 2 NARROWS BY ARGUMENT. m_pixelStore[2] is one array indexed by
// this accessor's own argument, exactly as m_bufferBindingSlot[15] is indexed by a
// BufferTarget, and Coverage.def:62-69 already rules that such a field stays ONE row.
// BufferTarget, and Coverage.def's GetBufferBindingSlot row already rules that such a field stays ONE row.
// Only [0] (pack) has a carrier - set_pixel_pack_state, which the applier writes
// (PipeApply.cpp:1373) - so the field is APPLIER-DERIVED and the UNPACK half is FATAL:
// (MGPipeApplySetPixelPackState) - so the field is APPLIER-DERIVED and the UNPACK half is FATAL:
// every gPipeInputs->GetPixelStoreParameters site in the tree passes false
// (DirectGLES.cpp's PackStateFromContext, StoreReadbackRowsToClient and ReadPixels, Utils.cpp's
// ReadbackImpl::StoreClientRows, RecordVerbSink::ReadBoundFramebufferTight and
@@ -10,7 +10,7 @@
// StagedShadow.h (R-11), held to its four rulings (CONTRACT-P5C.md §2.1).
//
// THE DEFECT THIS ENDS (T1/T5). resource_subdata's texture half stages the level bytes into
// SEG_STAGE and ApplyTextureUpload (PipeApply.cpp:989-1036) drops the pointer after the gate,
// SEG_STAGE and ApplyTextureUpload (PipeApply.cpp) drops the pointer after the gate,
// the accumulation and the serial. Espryt then re-reads the client's MipmapStorage at sync
// time (Managers.cpp:6940, :7129, :7198, :7315), reads per-level shape off the client object
// (:6928, :6936, :7314, :7332, DirectGLES.cpp:8502-8507, :8528-8529), and Magma WRITES the
+7 -7
View File
@@ -819,7 +819,7 @@ namespace MobileGL::MG_Pipe {
// R-8 (c1). THE SECOND CONJUNCT MOVES UNDER SPLIT, AND ONLY UNDER SPLIT.
//
// `MGPipeGetResourceOps() != nullptr` asks "has a backend registered the consumer". That
// table is the SERVER's registration and it is a PROCESS-WIDE global (PipeApply.cpp:402):
// table is the SERVER's registration and it is a PROCESS-WIDE global (g_resourceOps in PipeApply.cpp):
// under inproc a client reading it answers correctly BY ACCIDENT, and under spawn the
// client process has no backend at all, so the read answers null and five record families
// stop emitting - silently, while the emitters go on clearing their per-level dirty flags
@@ -956,8 +956,8 @@ namespace MobileGL::MG_Pipe {
// - and DeviceLost() is false.
if (MG_Remote::Client::ClientWireRecordsEmitted() == before &&
!MG_Remote::Client::ClientSession::DeviceLost()) {
// UncarriedInitialBytes, not a second word for the same family: WireTables.cpp:418
// already dies of exactly this - a respecify that crossed with no initial bytes -
// UncarriedInitialBytes, not a second word for the same family: Wire_Escape_ResourceRespecify
// (WireTables.cpp) already dies of exactly this - a respecify that crossed with no initial bytes -
// under that name, and two words for one family is the vocabulary drift a6
// censused and 5.2's .def exists to bound (P7 wave 0).
MGLOG_F("MGPipe: Fatal{UncarriedInitialBytes, \"resource_respecify\"} - the "
@@ -976,7 +976,7 @@ namespace MobileGL::MG_Pipe {
// THE CAP THE TWO CONTENT WALKS BELOW CUT A RANGE AT. The record's own bound (2^32-1) is not
// the one a real upload meets first: one piece's bytes are staged WHOLE in SEG_STAGE, a
// linear arena, and a blob larger than that arena is Fatal{RingOverrun, "SEG_STAGE"} at the
// encoder rather than a split (PipeWireCodec.cpp:856-864). Measured on the CI traces: a
// encoder rather than a split (PipeWireEncoder::StageAllocate). Measured on the CI traces: a
// 128 MiB arena's whole-buffer follow-up against a 32 MiB segment aborted there, which is
// the RingOverrun this walk exists to prevent.
//
@@ -2008,7 +2008,7 @@ namespace MobileGL::MG_Pipe {
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
// DELETED with an active transport (CONTRACT-P5C §4.2): R-12's caps
// re-publication already invalidates the CLIENT's compile environment when the
// second snapshot arrives (CapsMirror.cpp:78-80), and this forward is a write
// second snapshot arrives (CapsMirror::Adopt), and this forward is a write
// into the frontend with no wire shape. A caller that still needs it under a
// transport is a defect to fix, not a pull to serve.
return;
@@ -3338,8 +3338,8 @@ namespace MobileGL::MG_Pipe {
// P3a's vertex segment, in the order the design fixes: vertex elements, then the
// vertex buffers that fill them, then the index binding. All three are LIVE now (m1):
// bits 5 / 9 / 10 map onto kMGPipeSubsystemVertexInput in Tracker.h:145-148 and all
// three emitters have bodies, so `wants()` answers true whenever bit 8 is in the push
// bits 5 / 9 / 10 map onto kMGPipeSubsystemVertexInput in Tracker.h's MGPipeSubsystemForDirty and
// all three emitters have bodies, so `wants()` answers true whenever bit 8 is in the push
// mask - which the phase default 0x1ff sets, on every backend. The sentence that used
// to stand here ("all three still resolve to false today - their dirty bits map to no
// subsystem") was the contract commit's and stopped being true when the client landed.
+1 -1
View File
@@ -560,7 +560,7 @@ namespace MobileGL::MG_Record {
info.RestartIndex = 0;
info.DrawIdOffset = 0;
info.IndexResource = MG_Pipe::kMGPipeNullHandle;
info.MinIndex = ~0u; // "unknown", MGPipeTypes.h:1330
info.MinIndex = ~0u; // "unknown", MGPDrawInfo::MinIndex in MGPipeTypes.h
info.MaxIndex = ~0u;
info.XfbCpuCapturedVertices = 0;
info.NumDraws = 1;
+1 -1
View File
@@ -534,7 +534,7 @@ function(mgl_itest_probe_for_two_symbols outVar directory symbolRegexA symbolReg
endfunction()
# DirectGLES' Track H arm, probed by the subsystem bit it is gated on rather than by
# SlotTables.h existing: the bit is declared in the contract (MG_Pipe/MGPipe.h:77) and the
# SlotTables.h existing: the bit is declared in the contract (kMGPipeSubsystemEsprytSlots, MG_Pipe/MGPipe.h) and the
# backend has to name it to honour MOBILEGL_PIPE_PUSH's default mask, whatever files package C
# spreads the slot tables across.
mgl_itest_probe_for_symbol(MGL_ITEST_ESPRYT_SLOTS
@@ -33,7 +33,7 @@
// MOBILEGL_TRANSPORT=inproc` (review finding M-5).
// 2. `ClientSession::Active() != nullptr`. c0 made this one deliberately return null rather
// than Fatal, because "does a session exist" has a legitimate "no" - it is the monolith
// answer (ClientSession.cpp:31). So it is exactly "a client session exists in this process",
// answer (ClientSession::Active's definition). So it is exactly "a client session exists in this process",
// and no amount of editing stub MESSAGES makes a null pointer non-null.
// 3. `ImplementedVerbCount() > 0`. c0's stub returns 0; the contract gives this function the
// job of making "a table that silently lost an emitter" distinguishable from "a table that
@@ -819,12 +819,11 @@ void main() { oColor = texture(uTex, vUv); }
EXPECT_EQ(liveAfter, liveBefore)
<< kChurn << " " << kindName << SpaceSuffix(space)
<< " objects were created, drawn with and destroyed and "
<< (liveAfter - liveBefore)
<< " objects were created, drawn with and destroyed and " << (liveAfter - liveBefore)
<< " slots never came back. Each one holds a SlotState, a lifetime-id map node "
"and the applier's record for the life of the process, and past the kind's "
"slot bound every create trips Fatal{ProtocolCorruption} for good "
"(PipeApply.h:97-113). This is P3a's C-1 defect, which is why every P4a kind "
"(PipeApply.h's slot bounds). This is P3a's C-1 defect, which is why every P4a kind "
"frees its slot from the frontend destructor through one client-side helper "
"(D-I1) rather than from a backend death table. Backend "
<< Gl().BackendName();
@@ -290,7 +290,7 @@ void main() { oColor = vec4(vColor, 1.0); }
// undefined and this function returned at the line above before asserting anything;
// the split build's monolith lane, where the tracker IS compiled, adopts
// (MGPipeApplyMapPersistent's R-6 decline is ANDed with `Transport != Monolith`,
// PipeApply.cpp:2005), and seven entries went red the first time the assertion ran at
// PipeApply.cpp), and seven entries went red the first time the assertion ran at
// all.
//
// So the expectation is `live == (arm == emulated)`, taken from the SAME peek
@@ -11,8 +11,8 @@
// P3a migrates two subsystems: kMGPipeSubsystemResources (bit 7, the resource_* family) and
// kMGPipeSubsystemVertexInput (bit 8, vertex elements / buffers / index). The push build's default
// mask becomes kMGPipeSubsystemsMigratedAtP3a = 0x1ff, and P2's 0x7f survives as the control that
// clears exactly those two bits - MGPipe.h:79's rule that every phase's constant keeps meaning what
// it meant, so an operator's recorded mask is still readable a phase later.
// clears exactly those two bits - the rule in MGPipe.h's MOBILEGL_PIPE_PUSH bitmask section that every
// phase's constant keeps meaning what it meant, so an operator's recorded mask is still readable a phase later.
//
// That A/B is what every "push vs pull" number in MEASUREMENTS.md is taken against, and it has one
// characteristic failure mode: the bits stop steering anything, both arms run the same code, and
+2 -2
View File
@@ -122,12 +122,12 @@
// reviewer's head and so that the generator's completeness check has something to accept.
#define MGP_VERB_OP_EXEMPT_LIST(X) \
X(Present, \
"FillPoints.def:21 - Present and SetSwapInterval go through BackendObject virtuals and " \
"Present and SetSwapInterval go through BackendObject virtuals and " \
"read no frontend state, so they are not verbs here. There is no MGPipeVerb::Present, " \
"MGPipeValidateForVerb is never called for it, and stamping would retire the previous " \
"verb's answers with nothing to put in their place. It is class B all the same.") \
X(SetSwapInterval, \
"the same sentence of FillPoints.def:21, and it is class C besides") \
"not a verb for the same reason as Present, and it is class C besides") \
X(Flush, \
"not a verb at all: the verb census (BRIEF §12 C-3) found Flush is not a GLFunctionsTable " \
"slot and glFlush/glFinish are empty function bodies (Definitions.cpp:111-112), so there " \
+3 -3
View File
@@ -360,9 +360,9 @@ namespace MobileGL::MG_Pipe {
// of a content hash (section 4.2.1). Widened from the plan's two bytes, which
// cannot hold one.
Uint32 GlNameForDiag;
// The pair HasRespecifiedLevel above gates. Byte for byte the two members of
// MGPRespecifiedLevel (PipeApply.h:792-795), in that order, so the applier's existing
// struct and this carrier are one layout - but spelled as two Uint16s rather than as
// The pair HasRespecifiedLevel above gates. Byte for byte the first two members of
// MGPRespecifiedLevel (PipeApply.h), in that order, so the applier's existing
// struct and this carrier share that pair's layout - but spelled as two Uint16s rather than as
// that type, because PipeApply.h includes THIS header and not the other way round.
Uint16 RespecifiedUploadTarget;
Uint16 RespecifiedLevel;
+1 -1
View File
@@ -39,7 +39,7 @@
/* as resource_subdata records IMMEDIATELY AFTER this one. Reuses a path that is */ \
/* already chunked (MGPipeForEachSubDataRecordRange) and already acceptance-gated; the */ \
/* cost is one extra record. NOTE the SECOND uncarried companion on this call, the */ \
/* MGPRespecifiedLevel* scope (PipeApply.h:792) - it is NOT bytes and NOT covered by */ \
/* MGPRespecifiedLevel* scope (PipeApply.h) - it is NOT bytes and NOT covered by */ \
/* this ruling; table 1 row 19 gives it the two pad fields of MGPResourceDesc. */ \
X(ResourceRespecify, MGPResourceDesc, kScreen, kNeedsAck|kReplySlot, kWaitReply) \
X(ResourceDestroy, MGPHandleOnly, kScreen, kNone, kWaitNone) \
@@ -206,10 +206,9 @@ inline constexpr SizeT kMGPipeFieldOwnershipRowCount =
static_assert(kMGPipeFieldOwnershipRowCount == 70, "table 2's row count moved");
// An ARGUMENT-KEYED narrowing of one field. The field keeps its single row above; this
// says that one argument value of it belongs to a different class. Coverage.def:62-69 already
// rules the shape for GetBufferBindingSlot - "THE ROW STAYS ONE ROW ... the field is ONE array
// that a second row of the same name could only duplicate" - and m_pixelStore[2] is the same
// shape indexed by its own isUnpack argument.
// says that one argument value of it belongs to a different class. Coverage.def's comment on the
// GetBufferBindingSlot row already rules the shape - "The field is one array, so it stays one
// row" - and m_pixelStore[2] is the same shape indexed by its own isUnpack argument.
struct MGPipeFieldArgumentOwnership {
MGPipeInputField Field;
Uint32 Arg0;
@@ -265,8 +264,8 @@ static_assert(MGPipeEveryFieldIsClassified(),
// mask and name, so a field inside that mask would read FRESH while holding the previous
// verb's value - the one silent failure this table has. The exemptions:
// Flush not a verb at all: the verb census (BRIEF §12 C-3) found Flush is not a GLFunctionsTable
// Present FillPoints.def:21 - Present and SetSwapInterval go through BackendObject virtuals and
// SetSwapInterval the same sentence of FillPoints.def:21, and it is class C besides
// Present Present and SetSwapInterval go through BackendObject virtuals and
// SetSwapInterval not a verb for the same reason as Present, and it is class C besides
constexpr MGPipeVerb MGPipeVerbForWireOp(MGPWireOp op) {
switch (op) {
case MGPWireOp::Clear: return MGPipeVerb::Clear;
+2 -2
View File
@@ -9,9 +9,9 @@
// The MGPCaps snapshot's serializers, and the CallMask encoding. Owner: package w1 (the two
// blob codecs) and s1 (the handshake asserts). Signatures by c0.
//
// MGPCaps (MG_Pipe/MGPipeTypes.h:126-139) has four members. Two are flat and cross by memcpy
// MGPCaps (MG_Pipe/MGPipeTypes.h) has four members. Two are flat and cross by memcpy
// (DynamicBackendParameters Dynamic, Uint64 CallMask); two are MGPBlobRefs over containers
// and HAVE NO SERIALIZER IN THE TREE - the header says so itself at MGPipeTypes.h:134-136,
// and HAVE NO SERIALIZER IN THE TREE - the header says so itself above MGPCaps::FormatCapabilities,
// "Their serializers land with the transport (P5)". They are:
//
// FormatCapabilities -> FormatCapabilityCache (MG_Backend/BackendObject.h:93-98):
+7 -7
View File
@@ -504,8 +504,8 @@ namespace MobileGL::MG_Remote::Client {
static_cast<unsigned>(head->RangeCount),
static_cast<unsigned long long>(tail));
}
// EventRange and MGPRange are the same two Uint64s (EventRing.h:61-66
// asserts it), so the tail is handed over as-is rather than copied into
// EventRange and MGPRange are the same two Uint64s (EventRing.h asserts it next
// to EventRange), so the tail is handed over as-is rather than copied into
// a second array a later reader could get out of step with.
const auto* ranges = reinterpret_cast<const MG_Pipe::MGPRange*>(
static_cast<const Uint8*>(view.payload) + sizeof(*head));
@@ -1989,8 +1989,8 @@ namespace MobileGL::MG_Remote::Client {
// 1. publish and let the server drain. Bounded: a lost record must be a red lane, not
// a hung exit.
if (m_link->Attached()) {
// The PRODUCER's own last-published seq, not RingControl::submittedSeq. Ring.h:72-77
// permits submittedSeq to be published lazily and Ring.h:243 encourages batching
// The PRODUCER's own last-published seq, not RingControl::submittedSeq. Ring.h's header comment
// permits submittedSeq to be published lazily and RingProducer::Publish encourages batching
// the publish, so the shared watermark is allowed to lag the emitter - and a drain
// that waited for `appliedSeq >= submittedSeq` would then under-wait and free an
// emitter-owned var-tail while a record still names it. With the verb barrier armed
@@ -2677,9 +2677,9 @@ namespace MobileGL::MG_Remote::Client {
// (P5d round 3, package D). Every line below is a pure predicate whose only effect is
// "no violation, go home"; the Fatal fires on the AND of all of them, so reordering
// cannot change which touches abort. It changes only what a touch that does NOT abort
// pays, and this guard sits on the per-verb fill path (PipeFill.cpp:542, :1951, :2789
// - MGPipeValidateForVerb is 4.11% self / 10.9% inclusive of the client thread), so
// "what it costs to answer no" is the whole of its cost in a healthy process.
// pays, and this guard sits on the per-verb fill path (PipeFill.cpp's MGPipeNoteFrontendMutation,
// MGPipeLeaveVerb and MGPipeValidateForVerb - the last is 4.11% self / 10.9% inclusive of the
// client thread), so "what it costs to answer no" is the whole of its cost in a healthy process.
//
// The two config reads come first because they are the two answers that are constant
// for the life of the process and true for nearly every process that runs this code:
+4 -4
View File
@@ -218,7 +218,7 @@ namespace MobileGL::MG_Remote::Client {
// catalogue's reply rule, and it exists for exactly one row - resource_subdata's
// BUFFER half, whose Bool the only caller discards (PipeFill.cpp's
// MGPipeEmitResourceSubData). The row keeps kReplySlot on the wire (the server still
// posts; an unread slot is harmless, ReplySlot.h:16, 105), so nothing about the
// posts; an unread slot is harmless, ReplySlotPool's seq-stamped slots), so nothing about the
// protocol moves - what moves is that under run-ahead this client neither waits for
// the answer nor reads it, which is what makes the 64 KB persistent-map push
// fire-and-forget instead of a hidden round trip per block. It is NOT a licence to
@@ -302,7 +302,7 @@ namespace MobileGL::MG_Remote::Client {
// direction - it only adds waits - so it is allowed.
Bool RunAheadArmed() const;
// §2.3: the four O-class SharedPtr rows of gPipeInputs (PipeInputs.h:801-809 - the
// §2.3: the four O-class SharedPtr rows of gPipeInputs (PipeInputs' SharedPtr members - the
// bound VAO and the three programs), dropped on the GL thread once a barriered apply
// has returned. Under lockstep the next fill overwrites them within a verb; under
// run-ahead the next fill may be a frame away, and a pinned VAO whose last owner ends
@@ -508,13 +508,13 @@ namespace MobileGL::MG_Remote::Client {
// SEG_EVENT's ring capacity, exposed so the readback path can slice a writeback
// request into records that always fit (RingProducer::MaxRecordBytes ==
// capacity/2, Ring.h:288).
// capacity/2, Ring.h).
Uint64 EventRingCapacityBytes() const;
// SEG_STAGE's capacity, exposed so a content emitter can cut a range into records that
// always stage whole: the staging area is a linear arena of exactly these bytes (w1),
// and one blob larger than it is Fatal{RingOverrun, "SEG_STAGE"} at the encoder rather
// than a split (PipeWireCodec.cpp:856-864).
// than a split (PipeWireEncoder::StageAllocate in PipeWireCodec.cpp).
Uint64 StageCapacityBytes() const;
// The CLIENT's own segment table (P5c ev, CONTRACT-P5C §4.3): the writeback
@@ -52,7 +52,7 @@ namespace MobileGL::MG_Remote::Client {
// avoided.
const Uint64 quarter = stageCapacityBytes / 4;
// A floor so a pathologically small operator-supplied segment cannot make the piece
// width zero, which the walk reads as "refuse" (ResourceTracker.h:254); such a segment
// width zero, which the walk reads as "refuse" (MGPipeForEachSubDataRecordRange); such a segment
// is broken anyway, and the producer's Fatal{RingOverrun} names it on the first stage.
const Uint64 chunk = quarter < 4096 ? 4096 : quarter;
return static_cast<SizeT>(chunk > stageCapacityBytes ? stageCapacityBytes : chunk);
+3 -4
View File
@@ -39,11 +39,10 @@ namespace MobileGL::MG_Remote::Client {
// 0 with no session, where every writeback is synchronous and needs no ordering.
Uint64 GpuWriteOrderSeq();
// The slice a whole-buffer readback is cut into so one writeback event always fits
// SEG_EVENT. The writeback's bytes travel INLINE in the event record (P5c ev, CONTRACT-P5C
// §4.2), one record must fit the ring (RingProducer::MaxRecordBytes == capacity/2,
// Ring.h:288), and a 24 MiB arena's single shot cannot (measured: Fatal{EventRingOverflow}
// Ring.h), and a 24 MiB arena's single shot cannot (measured: Fatal{EventRingOverflow}
// on LargeArenaAdoptionScenario.GpuWriteIntoTheArenaIsReadBack). 0 when no session is
// active - the synchronous arm never slices.
SizeT BufferWritebackSliceBytes();
@@ -52,7 +51,7 @@ namespace MobileGL::MG_Remote::Client {
// before the range has to be cut. SEG_STAGE is a linear arena, one record's blob is
// allocated from it whole, and a blob larger than the arena is
// Fatal{RingOverrun, "SEG_STAGE"} at the encoder rather than a split
// (PipeWireCodec.cpp:856-864) - measured on the CI traces, where a 128 MiB arena's
// (PipeWireCodec.cpp's PipeWireEncoder::StageAllocate) - measured on the CI traces, where a 128 MiB arena's
// whole-buffer follow-up against a 32 MiB segment aborted. 0 means "do not cut", i.e. the
// record's own bound (MGPipeForEachSubDataRecordRange's default), which is the answer for
// monolith, for the server role's own uploads (they run the monolith adapter) and for a
@@ -61,7 +60,7 @@ namespace MobileGL::MG_Remote::Client {
// The clamp itself, a pure function of the segment's size so that a unit gate can drive the
// splitter at exactly the value a live session produces. A quarter of the segment, never
// below 4096 (a zero-width piece is a refusal, ResourceTracker.h:254) and never above the
// below 4096 (a zero-width piece is a refusal, MGPipeForEachSubDataRecordRange) and never above the
// segment (a larger cap would stage the very blob the arena refuses).
SizeT MGPipeStageChunkBytesFor(Uint64 stageCapacityBytes);
+7 -7
View File
@@ -227,14 +227,14 @@ namespace MobileGL::MG_Remote::Client {
// -- the rows that fit none of the three shapes --------------------------------
// set_dynamic_state. AN OPTIONAL BLOB, NOT A MANDATORY ONE (round-2 regression, the
// census's Fatal{BlobMissing, "SetDynamicState"}). EmitRenderState (PipeFill.cpp:2405-
// 2421) sends a set_dynamic_state whenever the RenderState VERSION moved, and when the
// census's Fatal{BlobMissing, "SetDynamicState"}). EmitRenderState (PipeFill.cpp) sends a
// set_dynamic_state whenever the RenderState VERSION moved, and when the
// chunk-level suppressor finds NO dynamic chunk changed it sends the 32-byte header with
// ChunkMask == 0 and blobByteCount == 0 - a version-only update, which the comment there
// calls out as deliberate. The generic MGP_WIRE_BLOB wrapper stages through StageRequired,
// which Fatals on a zero count, so a legal header-only update aborted the process with a
// blob-shape complaint that had nothing to do with the actual state of the pipe. The
// DECODER already handles it: PipeWireCodec.cpp:1571-1587 takes the `ChunkMask == 0` arm
// DECODER already handles it: PipeWireDecoder::ApplyChecked takes the `ChunkMask == 0` arm
// (CheckBlobIsHonest, no blob resolved) and applies the header alone. So the emitter is
// the only side that was wrong; it stages OPTIONALLY, exactly like the two sub-data rows.
// A non-empty mask still stages (blobByteCount > 0), so the reduced-path scenarios, whose
@@ -504,9 +504,9 @@ namespace MobileGL::MG_Remote::Client {
// not - the shared pool, whose slot is seq % slotCount and is reused - the answer the
// drain comes back for may already be gone, and there is NO recovery: retrying wedges
// the row for the rest of the process, and re-latching the object by sending another
// create wipes the server's record along with its PendingUploads (PipeApply.cpp:2033,
// PipeApply.h:332) while the client cleared its dirty flags at emission
// (PipeApply.h:298-304), so nobody re-sends those texels. So it takes the blocking
// create wipes the server's record along with its PendingUploads (MGPipeApplyResourceCreate,
// MGPipeResourceRecord::PendingUploads) while the client cleared its dirty flags at emission
// (PipeApply.h's PendingUpload comment), so nobody re-sends those texels. So it takes the blocking
// path instead, which is the pre-window shape exactly.
const Uint32 window = session.LinkRetainsReplies() ? CreateWindowEffective() : 1u;
// P15: UNDER RUN-AHEAD A CREATE IS FIRE-AND-FORGET. The handle is the client's own
@@ -651,7 +651,7 @@ namespace MobileGL::MG_Remote::Client {
// the only caller discards it (PipeFill.cpp's MGPipeEmitResourceSubData), so
// "accepted" is not a re-derivation of a server decision - it is the absence of a
// question. The server still posts the real answer into the slot; nothing reads
// it, which ReplySlot.h:16, 105 makes legal. A row whose acceptance a caller USES
// it, which ReplySlotPool's seq-stamped slots make legal. A row whose acceptance a caller USES
// may never take this path - R-5 has not moved.
const Bool wantReply = MG_Pipe::MGPipeSubDataWantsItsReply(record);
Int32 status = 0;
+1 -1
View File
@@ -53,7 +53,7 @@ namespace MobileGL::MG_Remote::Client {
// moves for the class-B verbs too. So an armed Clear-only lane is green on EmitSeq while this
// counter stays 0. Making the harness read THIS instead is t1's file (SplitRuntimePeek), so
// the honest statement is the one here: c1 counts the routed ordinal at the only place that
// can, PipeFill's InitialBytesNotCarried self-check reads it (PipeFill.cpp:755), and the
// can, PipeFill's InitialBytesNotCarried self-check reads it (MGPipeEmitResourceRespecify), and the
// lane's own arming remains EmitSeq until t1 re-points it. c1-v3.md M7 has the full note.
Uint64 ClientWireRecordsEmitted();
+5 -5
View File
@@ -344,7 +344,7 @@ namespace MobileGL::MG_Remote::Server {
}
++m_applierResetSerial;
// THE WHOLE POINT OF THE RECORD: the reset runs HERE, on the apply thread, against
// the g_applier this role owns (PipeApply.cpp:409). The layer-2 guard inside
// the applier this role owns (MGPipeApplier() in PipeApply.h). The layer-2 guard inside
// MGPipeApplierReset passes because this IS the apply thread; the GL-thread direct
// call it replaced is the Fatal arm.
MG_Pipe::MGPipeApplierReset();
@@ -754,10 +754,10 @@ namespace MobileGL::MG_Remote::Server {
// calling it unconditionally on every record is both correct and cheap. Four ops stamp:
// Clear -> Clear, DrawVbo -> DrawArrays, ReadPixels -> ReadPixels, Blit -> BlitFramebuffer.
//
// PRESENT IS DELIBERATELY NOT ONE, although contract 7 puts it in class B: FillPoints.def:21
// says Present and SetSwapInterval "go through BackendObject virtuals and read no frontend
// state, so they are not verbs here". There is no MGPipeVerb::Present, and stamping there
// would retire the previous verb's answers with nothing to put in their place.
// PRESENT IS DELIBERATELY NOT ONE, although contract 7 puts it in class B: Present and
// SetSwapInterval sit outside GLFunctionsTable (BackendObject.h) and read no frontend state,
// so FillPoints.def's MGP_FILL_VERB_LIST has no row for them. There is no MGPipeVerb::Present,
// and stamping there would retire the previous verb's answers with nothing to put in their place.
void PipeApplier::StampVerbBoundary(MG_Pipe::MGPWireOp op) {
const MG_Pipe::MGPipeVerb verb = MG_Pipe::MGPipeVerbForWireOp(op);
if (verb == MG_Pipe::MGPipeVerb::kVerbCount) return; // not a verb boundary: stamp nothing
+2 -2
View File
@@ -420,7 +420,7 @@ int RunSession(std::unique_ptr<SocketTransport> control, std::vector<std::uint8_
}
DelaySessionHandshakeForTest();
// THE FIRST FRAME, CLASSIFIED BY THE SAME FUNCTION THE TCP SUPERVISOR USES (plan §1.1, fuzz
// arm 1 row: "ServerMain.cpp:193 CtrlEnvelopeBufferHasIdentifier"). The identifier is asked
// arm 1 row: add CtrlEnvelopeBufferHasIdentifier to this first-frame read). The identifier is asked
// first, and every malformed shape is refused BY NAME - this read used to `_exit(67)` on all
// of them, so a peer that sent garbage got a bare close and the supervisor counted a fault.
const auto shape = Server::ClassifyFirstFrame(helloFrame.data(), helloFrame.size());
@@ -840,7 +840,7 @@ bool ReapActiveSession(pid_t& active, unsigned long& sessionsFaulted) {
if (::waitpid(active, &status, WNOHANG) != active) return false;
const int reaped = static_cast<int>(active);
active = -1;
// WIFEXITED / WIFSIGNALED / WTERMSIG, the same three questions ServerSpawn.cpp:289 asks of
// WIFEXITED / WIFSIGNALED / WTERMSIG, the same three questions ReapServer (ServerSpawn.cpp) asks of
// the same kind of child - but logged rather than folded into one signed integer, because
// this side has nobody to return the answer to.
if (WIFEXITED(status)) {
+4 -4
View File
@@ -82,7 +82,7 @@ namespace MobileGL::MG_Remote::Server {
// THE THREE FLAG-SPACE COLLISIONS, AS TRIPWIRES RATHER THAN AS A COMMENT.
//
// MGPipeCallFlags (MG_Pipe/MGPipe.h:42-54) and RingRecordFlags (Ring.h) are separate spaces
// MGPipeCallFlags (MG_Pipe/MGPipe.h) and RingRecordFlags (Ring.h) are separate spaces
// that overlap, and three bits mean DIFFERENT things in each. Ring.h's enum carries the
// table; these are the assertions that break the build if either enum is renumbered, so the
// collision can never become news again. They live here because this is the nearest .cpp
@@ -105,7 +105,7 @@ namespace MobileGL::MG_Remote::Server {
namespace {
// A control-plane frame is small by construction (ITransport.h:56-58: bulk bytes
// A control-plane frame is small by construction (ITransport::SendFrame: bulk bytes
// belong in shm, never here), so one stack-free vector sized from PeekFrameSize is
// the whole reader. The BUFFER_TOO_SMALL half of ReceiveFrame's contract is what
// makes the two-step safe: a short buffer leaves the message queued.
@@ -452,8 +452,8 @@ namespace MobileGL::MG_Remote::Server {
head.RangeCount = static_cast<std::uint32_t>(rangeCount);
std::memcpy(slot, &head, sizeof(head));
if (tailBytes != 0) {
// EventRange and MGPRange are the same two Uint64s (EventRing.h:61-66 asserts
// it), so the tail is a plain copy rather than a per-element conversion.
// EventRange and MGPRange are the same two Uint64s (EventRing.h asserts it at
// EventRange's declaration), so the tail is a plain copy rather than a per-element conversion.
std::memcpy(static_cast<Uint8*>(slot) + sizeof(head), ranges,
static_cast<SizeT>(tailBytes));
}
+1 -1
View File
@@ -79,7 +79,7 @@ namespace MobileGL::MG_Remote::Server {
// which is how DirectGLES - which has no OnCapsInvalidated producer - tells the client
// its InitCapabilities re-ran, without any dev-shaped backend edit. It is also the
// re-open signal for "the server's ES context died and its rings were dropped", the
// event MGPipeCallbacks has no eleventh slot for (MGPipeCallbacks.h:56-58).
// event MGPipeCallbacks has no slot for (the count is pinned by kMGPipeCallbackCount).
MobileGLResult PublishCapsSnapshot();
Transport::RingConsumer& CommandRing();
+4 -4
View File
@@ -36,14 +36,14 @@ namespace MobileGL::MG_Remote::Transport {
kEventFenceSignaled = 5, // P10: a client fence the server saw signaled (CONTRACT-P10 §1)
};
// The 8-byte {slot, gen} pair, mirrored (MGPipeHandles.h:54-65).
// The 8-byte {slot, gen} pair, mirrored (MGPipeHandle in MGPipeHandles.h).
struct EventHandle {
std::uint32_t Slot;
std::uint32_t Gen;
};
static_assert(sizeof(EventHandle) == 8, "the handle is the 8-byte {slot, gen} pair");
// MGPRange, mirrored (MGPipeTypes.h:63-67).
// MGPRange, mirrored (MGPipeTypes.h).
struct EventRange {
std::uint64_t Offset;
std::uint64_t Size;
@@ -79,7 +79,7 @@ namespace MobileGL::MG_Remote::Transport {
};
static_assert(sizeof(EventGpuWrittenHead) == 16, "wire shape");
// OnSurfaceChanged(const MGPSurfaceInfo*), mirrored (MGPipeTypes.h:1394-1401).
// OnSurfaceChanged(const MGPSurfaceInfo*), mirrored (MGPipeTypes.h).
struct EventSurfaceChangedHead {
std::uint32_t Width;
std::uint32_t Height;
@@ -135,7 +135,7 @@ namespace MobileGL::MG_Remote::Transport {
void* Reserve(EventKind kind, std::uint64_t payloadBytes) {
void* slot = m_producer.Reserve(static_cast<std::uint16_t>(kind), kRecNone, payloadBytes);
if (slot == nullptr && m_cmdControl != nullptr) {
// "SEG_EVENT full, server stopped applying" - Ring.h:123. Latched
// "SEG_EVENT full, server stopped applying" - RingControl::eventRingFull in Ring.h. Latched
// here, cleared by the consumer once it has drained.
m_cmdControl->eventRingFull.store(1, std::memory_order_release);
}
+1 -1
View File
@@ -241,7 +241,7 @@ namespace MobileGL::MG_Remote::Transport {
// THESE TWO RETIRE CONTRACT-P5 §3.9. That ruling kept the doorbell
// accessors on the session "so that this stays one switch in one file
// rather than two virtuals every transport has to invent a home for"
// (ServerSession.cpp:709-724) - and the switch it produced aborts for
// (ServerSession::ConsumerDoorbell) - and the switch it produced aborts for
// every role but InProcess, so a spawn apply thread dies in
// ConsumerDoorbell before it pops its first record. The seam is the
// home the ruling said did not exist. lk deletes both accessors rather
+3 -3
View File
@@ -358,7 +358,7 @@ namespace MobileGL::MG_Remote::Transport {
// makes every later advance a no-op and every WaitForApplied on
// kWaitForever - the verb barrier and every reply wait - block for
// ever. A hang with one ERROR line in the log is strictly worse than
// an abort at the instruction that caused it, and Ring.h:181-185
// an abort at the instruction that caused it, and RingCursorsValid (Ring.h)
// already rules the same way for the cursor invariants on this page.
// "Early" can only be caught at the call site, which is why every
// advance below has exactly one caller and a named unit case.
@@ -449,7 +449,7 @@ namespace MobileGL::MG_Remote::Transport {
// RingCursorSet::Stage is driven by nobody (Ring.h's stage triple).
m_cmd->Publish();
// Kept locally as well as on the shared page: the shared watermark is
// allowed to lag (Ring.h:72-77), and teardown's drain must not.
// allowed to lag (Ring.h's header comment: late, never early), and teardown's drain must not.
//
// Clamped UP, not passed through. A caller that republishes an older
// bound - teardown does exactly that, and so does any batched publisher
@@ -638,7 +638,7 @@ namespace MobileGL::MG_Remote::Transport {
// into BOTH tails, i.e. it hands back every byte the consumer has popped
// whether or not a record among them was borrowed into the GPU timeline.
// That would defeat the whole reason the ring carries two tails
// (Ring.h:24-27) and would let the producer overwrite a slot the GPU is
// (Ring.h's header comment) and would let the producer overwrite a slot the GPU is
// still reading. m_retirableCursor stops at the first borrowed record.
m_cmd->PublishApplied();
m_cmd->PublishRetiredUpTo(m_retirableCursor);
+4 -4
View File
@@ -262,8 +262,8 @@ namespace MobileGL::MG_Remote::Transport {
void PublishAndNotify(std::uint64_t submittedSeq);
// The last seq THIS producer published, kept locally rather than read back
// out of RingControl::submittedSeq. Teardown's drain needs it: Ring.h:72-77
// explicitly permits submittedSeq to be published LAZILY and Ring.h:243
// out of RingControl::submittedSeq. Teardown's drain needs it: ARCHITECTURE.md §11.2.1
// explicitly permits submittedSeq to be published LAZILY and Ring.h's RingProducer::Publish
// encourages batching the publish, so the shared watermark may lag the
// emitter - and a drain that waits for `appliedSeq >= submittedSeq` would
// then under-wait and free an emitter's var-tail while a record still
@@ -295,7 +295,7 @@ namespace MobileGL::MG_Remote::Transport {
// True when the peer latched "SEG_EVENT is full and I stopped producing".
bool EventRingIsFull() const;
// Back-pressure when Reserve returned nullptr. NEVER call this when
// FreeBytes() is already >= the record: Ring.h:226-233 - a nullptr with
// FreeBytes() is already >= the record: RingProducer::Reserve (Ring.h) - a nullptr with
// enough free bytes can only mean "too big, chunk", and waiting on it
// stalls forever.
SessionWait WaitForCmdSpace(std::uint64_t bytes, std::uint32_t timeoutMs);
@@ -401,7 +401,7 @@ namespace MobileGL::MG_Remote::Transport {
// THE BYTE CURSOR RetireThrough MAY RECLAIM TO, which is NOT simply
// "everything popped". A record carrying kRecBorrowSlot has been lent
// into the GPU timeline and its slot can only be recycled after
// completedFrameSerial (Ring.h:24-27), so the reclaimable cursor stops
// completedFrameSerial (Ring.h's header comment), so the reclaimable cursor stops
// AT the first borrowed record and does not move again until
// RetireBorrowedUpTo releases it. Nothing sets kRecBorrowSlot yet;
// this is here so that the day something does, the producer does not
+1 -1
View File
@@ -239,7 +239,7 @@ namespace MobileGL::MG_Remote::Transport {
// closes what has already been created: Close only walks m_owned when
// m_owns is true, and setting it afterwards left a failure at segment 3
// holding segments 0-2's descriptors and mappings open with Valid()
// false, against ShmSegment.h:66's "unmaps and releases the descriptor".
// false, against ShmSegment::Close's "unmaps and releases the descriptor".
m_owns = true;
struct Spec {
@@ -663,7 +663,7 @@ namespace MobileGL::MG_Remote::Transport {
outServer.reset();
int stream[2] = {-1, -1};
// SOCK_STREAM, not SOCK_SEQPACKET: Doorbell.h:390-398 already chose a
// SOCK_STREAM, not SOCK_SEQPACKET: SocketDoorbell (Doorbell.h) already chose a
// stream socket for the bell so that a closed peer surfaces as
// POLLIN|POLLHUP with recv()==0 rather than as a hang, and the control
// plane must not disagree with the bell about what death looks like.
+9 -9
View File
@@ -702,7 +702,7 @@ namespace MobileGL::MG_Remote::Wire {
}
case MGPWireOp::SetShaderBuffers: {
// TWO TAILS. HostSpanCount is 0 or Count and NEVER anything else
// (MGPipeTypes.h:820-823), because the two arrays stay index-aligned; a third
// (MGPShaderBuffers in MGPipeTypes.h), because the two arrays stay index-aligned; a third
// value would let a record describe spans for ranges it does not have.
const auto& p = *static_cast<const MGPShaderBuffers*>(payload);
// P5e (sb, CONTRACT-P5E.md §1): the class and the window, bounded HERE as well as
@@ -1750,7 +1750,7 @@ namespace MobileGL::MG_Remote::Wire {
const auto& desc = *static_cast<const MGPResourceDesc*>(payload);
// R-13.3: `initialBytes` IS ALWAYS NULL UNDER SPLIT. Initial content arrives as
// resource_subdata records immediately after this one, which is what the texture
// path already does (TextureEmit.h:1137).
// path already does (ApplyRespecify in TextureEmit.h).
//
// The scope and exact mutable-level extent are one carrier value. Read each part
// through the helpers; forgetting the presence byte would turn a whole-resource
@@ -1886,7 +1886,7 @@ namespace MobileGL::MG_Remote::Wire {
case MGPWireOp::CreateVertexElements: {
const auto& desc = *static_cast<const MGPVertexElements*>(payload);
// The blob's length cross-check against the two counts is the applier's already
// (PipeApply.cpp:1990-1999) and is the model every other row copies; the decoder
// (MGPipeApplyCreateVertexElements in PipeApply.cpp) and is the model every other row copies; the decoder
// adds only what the applier cannot see, which is that the bytes exist at all.
const void* blob = ResolveOrFatal(op, desc.Blob);
if (blob == nullptr) return false;
@@ -1907,7 +1907,7 @@ namespace MobileGL::MG_Remote::Wire {
// R-13.1 gave this call its kHasBlob. The serialization IS the memcpy - a POD -
// and borderColorForm must survive BYTE FOR BYTE, because all three colour
// representations are always numerically populated and it is the only thing that
// says which one the backend must use (MGPipeTypes.h:425-428).
// says which one the backend must use (MGPSamplerDesc in MGPipeTypes.h).
if (!RequireDeclaredBlob(op, desc.Parameters, *m_segments)) return false;
if (desc.Parameters.Size != sizeof(MobileGL::SamplerParameters)) {
return WireProtocolLatchAt("CreateSamplerState.Parameters", desc.Parameters.Size,
@@ -2146,7 +2146,7 @@ namespace MobileGL::MG_Remote::Wire {
case MGPWireOp::SetGlobalConstants: {
const auto& rec = *static_cast<const MGPGlobalConstants*>(payload);
// The length cross-check is the applier's (PipeApply.cpp:2784, against the
// The length cross-check is the applier's (PipeApply.cpp's MGPipeApplySetGlobalConstants, against the
// program's GlobalUboSize, which this record does not carry). Under rule A it
// stops being inert for the first time, which is the whole point of arming Size.
const void* bytes = ResolveOrFatal(op, rec.Blob);
@@ -2201,8 +2201,8 @@ namespace MobileGL::MG_Remote::Wire {
Uint64(rec.UnionBox.Z) + rec.UnionBox.D > rec.LevelDepth))
return WireProtocolLatch("ResourceSubData.LevelExtent", "invalid full image extent or dirty box");
// Rule A arms both halves. The buffer half already declared a real size in
// monolith and is cross-checked at PipeApply.cpp:702; THE TEXTURE HALF DECLARED 0
// (TextureEmit.h:1265-1267, on the grounds that the byte count was "the server's
// monolith and is cross-checked by PipeApply.cpp's SubDataBoxFault; THE TEXTURE HALF DECLARED 0
// (TextureEmit.h's EmitOneLevel, on the grounds that the byte count was "the server's
// to compute") and under split it must declare too - a length the reader computes
// from the record it is checking is not a bounds check.
const Bool namesABuffer = rec.Target == kMGPipeResourceTargetBuffer;
@@ -2263,7 +2263,7 @@ namespace MobileGL::MG_Remote::Wire {
// drives rewrites its range from the AUTHORITATIVE SHADOW, which rule C makes
// server-owned, so resource_subdata is already the only way bytes reach it and a
// second way would be a forgeable one. AccessFlags cross verbatim, never
// normalised (PipeApply.h:902-903).
// normalised (MGPipeApplyResourceFlushRange in PipeApply.h).
MGPipeApplyResourceFlushRange(*static_cast<const MGPFlushRange*>(payload), nullptr);
return true;
@@ -2485,7 +2485,7 @@ namespace MobileGL::MG_Remote::Wire {
return true;
case MGPWireOp::SetSwapInterval:
// Class C, wave 3 (census-classC.md "static cross"); not a verb (FillPoints.def:21).
// Class C, wave 3 (census-classC.md "static cross"); not a verb (no MGP_FILL_VERB_LIST row).
return false;
case MGPWireOp::Flush:
@@ -590,7 +590,7 @@ namespace MobileGL::MG_State::GLState {
// here; under R-1's verb barrier the block is nearly free, since the client is already
// waiting for appliedSeq to reach the record it just emitted.
//
// NO NARROWING (ResourceTracker.h:587-592's rangeCount == 1 assertion stays): this
// NO NARROWING (MGPipeClientOnGpuWritten's rangeCount == 1 assertion stays): this
// phase only gives the client a conservative set, and a zero-range announcement stays
// illegal until P8/P9 make it mean "fully narrowed - nothing is dirty".
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
@@ -7,7 +7,7 @@
// End of Source File Header
#pragma once
#include <Includes.h> // String/Vector/Array/UnorderedMap/SharedPtr + GL enums. DEBT NOTE (MGPipeTypes.h:24-31 style):
#include <Includes.h> // String/Vector/Array/UnorderedMap/SharedPtr + GL enums. DEBT NOTE (MGPipeTypes.h header style):
// Includes.h:80-84 still pulls glslang and :59 spirv_cross_c.h; this header is glslang-free BY
// SYMBOL (what P7's `nm -D | grep glslang` measures), not by preprocessed text. A textually
// glslang-free closure needs MG_Util/Types.h split off Includes.h (Types.h:11 includes it
@@ -51,7 +51,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
#include "Init.h"
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
+2 -2
View File
@@ -333,8 +333,8 @@ TEST_F(FieldOwnershipTest, VerbBoundaryOpsCoverEveryVerbShapedCall) {
EXPECT_EQ(kMGPipeVerbBoundaryExemptCount, SizeT{3});
// Present is class B (it is emitted in P5) and is STILL not a verb boundary:
// FillPoints.def:21 - "Present and SetSwapInterval go through BackendObject virtuals and
// read no frontend state, so they are not verbs here". Stamping there would retire the
// Present and SetSwapInterval go through BackendObject virtuals and read no frontend state,
// so FillPoints.def's MGP_FILL_VERB_LIST has no row for them. Stamping there would retire the
// previous verb's answers with nothing to put in their place.
EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::Present), MGPipeVerb::kVerbCount);
EXPECT_EQ(MGPipeVerbForWireOp(MGPWireOp::SetSwapInterval), MGPipeVerb::kVerbCount);
@@ -57,7 +57,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
+1 -1
View File
@@ -45,7 +45,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
#include "Init.h"
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
+2 -2
View File
@@ -1333,8 +1333,8 @@ TEST(PipeCatalogue, ResourceRespecifyAcksOnlyImmutableStorage) {
// And the four by name, because a count alone would let a row lose the flag while another
// gained one. These are exactly the MGPipeApply* entry points that return Bool
// (PipeApply.h:820, :868, :897, :1023); map_persistent's void* is the fifth answer and was
// already declared.
// (ResourceCreate, ResourceRespecify, ResourceSubData, SetTextureParams in PipeApply.h);
// map_persistent's void* is the fifth answer and was already declared.
Uint32 acceptanceWithSlot = 0;
#define MGP_COUNT_ACCEPTANCE_ROWS(Name, Payload, Class, Flags, Wait) \
if ((std::strcmp(#Name, "ResourceCreate") == 0 || std::strcmp(#Name, "ResourceRespecify") == 0 || \
+1 -1
View File
@@ -50,7 +50,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
#include "Init.h"
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (its #define in PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
+4 -4
View File
@@ -56,7 +56,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
#include <Config.h>
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
@@ -2122,7 +2122,7 @@ namespace {
// is what PipeFill.cpp's two content walks pass - because the record's own 2^32-1 bound is
// not the one a real upload meets first. One piece's bytes are staged WHOLE in SEG_STAGE, a
// linear arena, and a blob larger than that arena is Fatal{RingOverrun, "SEG_STAGE"} at the
// encoder rather than a split (PipeWireCodec.cpp:856-864); measured on the CI traces, where
// encoder rather than a split (PipeWireEncoder::StageAllocate); measured on the CI traces, where
// a 128 MiB arena's whole-buffer follow-up against a 32 MiB segment aborted there.
//
// A UNIT PROCESS HAS NO SESSION, so the live answer is 0 - "nothing to fit, keep the
@@ -2139,7 +2139,7 @@ namespace {
"bound rather than invent a cap";
EXPECT_EQ(MG_Remote::Client::MGPipeStageChunkBytesFor(0), 0u);
// SessionRings.h:89's default segment, and the three shapes the clamp has to get right:
// SessionSegmentSizes::StageBytes' default segment, and the three shapes the clamp has to get right:
// an ordinary arena, a segment below the floor, and a segment equal to it.
constexpr Uint64 kStage = 32ull * 1024ull * 1024ull;
constexpr Uint64 kChunk = kStage / 4;
@@ -2212,7 +2212,7 @@ namespace {
// are bytes to carry: MappedData() answers a NON-NULL pointer for a zero-byte store
// (PipeResource.h:140-143 reserves one byte whatever the size). Reading it alone is what
// sent this call down the split arm's respecify(nullptr)-plus-follow-up shape, whose walk
// emits NOTHING for a zero-length range (ResourceTracker.h:253), so the self-check that
// emits NOTHING for a zero-length range (MGPipeForEachSubDataRecordRange), so the self-check that
// exists to prove the content followed aborted by name:
// Fatal{InitialBytesNotCarried, "resource_respecify"} ... 0 bytes
// measured on the first glBufferData(target, 0, NULL, ...) of the bsl-esc-menu trace.
+1 -1
View File
@@ -56,7 +56,7 @@
#include <cstring>
#include "Init.h"
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
@@ -51,7 +51,7 @@
#include <MG_Pipe/MGPipe.h>
#include "Init.h"
#include <Config.h>
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere else,
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere else,
// so a TU that tests it without this include silently reads it as 0 - and then
// ExpectRefusedNaming takes the in-process arm while the applier's trip wire really does
// abort, which takes the whole binary down with it. ImageEmitTest carries the same include for
+2 -2
View File
@@ -57,7 +57,7 @@
#include "Includes.h"
#include <MG_Pipe/MGPipe.h>
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h:20-26) and nowhere
// MOBILEGL_PIPE_POISON is DERIVED in the header below (PipeInputs.h) and nowhere
// else, so a TU that tests it without this include silently reads it as 0. That is
// invisible in a push build (where it really is 0) and in a verify build (where
// -DMOBILEGL_PIPE_VERIFY=1 is on the command line); MOBILEGL_BUILD_DISAGGREGATED is the
@@ -639,7 +639,7 @@ TEST(TextureEmit, ALevelTooLargeForTheStageChunkIsCutIntoSlabs) {
#else
EXPECT_EQ(MGPipeTextureStageChunkBytes(), 0u)
<< "a unit process has no ClientSession, so the drain must keep the whole-level record";
// SessionRings.h:89's default segment, and the cap is a quarter of it - the number the
// SessionRings.h's default SessionSegmentSizes::StageBytes, and the cap is a quarter of it - the number the
// emitter really passes to the walk.
const SizeT cap = MG_Remote::Client::MGPipeStageChunkBytesFor(32ull * 1024ull * 1024ull);
ASSERT_EQ(cap, static_cast<SizeT>(8ull * 1024ull * 1024ull));
+1 -1
View File
@@ -2684,7 +2684,7 @@ TEST_F(PipeWireCodecTest, ADeclaredPerStageSpirvRunIsFatal) {
}
TEST_F(PipeWireCodecTest, AHostSpanCountThatIsNeitherZeroNorCountIsFatal) {
// MGPipeTypes.h:820-823: HostSpanCount is 0 OR Count, never anything else, so the two
// MGPShaderBuffers (MGPipeTypes.h): HostSpanCount is 0 OR Count, never anything else, so the two
// arrays stay index-aligned. A third value lets a record describe spans for ranges it does
// not have - and the arrays would then be read off by one for the rest of the tail.
const ChildResult r = RunInChild([] {
+12 -12
View File
@@ -306,7 +306,7 @@ TEST(RemoteClientControls, LongFenceWaitBudgetStillWakesOnShutdown) {
TEST(RemoteClientControls, ResourceRespecifyErrorIsNotADecline) {
// THE TEXTURE HALF, WHICH IS THE HALF THAT STILL READS ITS ANSWER (P12). This case used a
// zeroed descriptor, which is a BUFFER target - and the buffer half is now fire-and-forget
// because both of its call sites discard the Bool (PipeFill.cpp:1105, :1142). A row that reads
// because both of its call sites in MGPipeEmitResourceRespecify (PipeFill.cpp) discard the Bool. A row that reads
// no answer cannot fold ERROR into a decision, so the rule this case exists for moved to the
// half that does read one: the transport fault is caught here, at the next row that waits,
// instead of at a record whose verdict nobody ever looked at.
@@ -761,19 +761,19 @@ TEST(RemoteClientControls, ADrawOnASessionWithoutTheRunAheadBitStaysStampedBarri
// =====================================================================================
//
// ReplySink's status space is three-valued and its own header says what the values mean:
// 0 OK, 1 DECLINED IS A REAL ANSWER, 2 ERROR (PipeWireCodec.h:457-460). The escape rows are
// 0 OK, 1 DECLINED IS A REAL ANSWER, 2 ERROR (MGPipeReplySink in PipeVerbSink.h). The escape rows are
// held to the other half of the same rule - "ERROR IS NOT A DECLINE", an escape may not fold
// 2 into `false` (WireTables.cpp:446-450). The fence and query consumers folded BOTH 1 and 2
// 2 into `false` (Wire_Escape_ResourceRespecify, WireTables.cpp). The fence and query consumers folded BOTH 1 and 2
// into a single abort (EmitTables.cpp ReadFenceReply, QueryEmit.inc ReadQueryReply), so a
// client that had latched device-lost - where every verb is DECLINED by design,
// ClientSession.cpp:1837 - died of Fatal{ProtocolCorruption, "Fence.reply"} on its next
// ClientSession::EmitAndWaitTails - died of Fatal{ProtocolCorruption, "Fence.reply"} on its next
// glClientWaitSync instead of going quiet the way the design promises ("GL calls become
// no-ops", design/08-runtime-and-platform.md:33).
//
// THE PEER BELOW IS THE SERVER'S OWN DECLINE, not a substitution of the status byte: these
// verbs answer false when the server cannot answer them, and the codec posts exactly that as
// DECLINED with a zero-length payload (PipeWireCodec.cpp:1820-1830 for the two fence rows,
// :1841-1861 for the three query rows). The CLIENT's own decline is pinned separately, by
// DECLINED with a zero-length payload (PipeWireDecoder::ApplyChecked in PipeWireCodec.cpp, for the
// two fence rows and the three query rows). The CLIENT's own decline is pinned separately, by
// LongFenceWaitBudgetStillWakesOnShutdown above.
//
// THE RED, RUN ONCE: take the `if (status == Wire::ReplySink::kStatusDeclined)` arm out of
@@ -810,7 +810,7 @@ TEST(RemoteClientControls, DeclinedFenceReplyAnswersSignaledInsteadOfAborting) {
auto* sync = RemoteEmitTable().GL.FenceSync();
if (sync == nullptr) ::_exit(131);
// glClientWaitSync on a fence nobody can wait on: signaled now, as every fallback in
// this tree already answers (GL_Sync.cpp:103-106, PipeApplier.cpp:175-177).
// this tree already answers (ClientWaitSync in GL_Sync.cpp, ServerVerbSink::OnFenceWait).
if (RemoteEmitTable().GL.ClientWaitSync(sync, 0, 0) != GL_ALREADY_SIGNALED) ::_exit(132);
// GL_SYNC_STATUS: the same answer, in the boolean the row carries.
if (!RemoteEmitTable().GL.GetSyncStatus(sync)) ::_exit(133);
@@ -919,8 +919,8 @@ TEST(RemoteClientControls, DeviceLostRespecifyDoesNotDieOfTheUncarriedBytesCheck
// P12 exit gate (a): killing the server must give a CLEAN device-lost latch. With the
// latch set every verb is DECLINED, so the resource_subdata that R-13.3 owes emits
// nothing - which is the latch working, not bytes the client forgot to carry. The check
// at PipeFill.cpp:1115 compared client record ordinals only, so the next glBufferData
// with data aborted the client by name instead.
// in MGPipeEmitResourceRespecify (PipeFill.cpp) compared client record ordinals only, so
// the next glBufferData with data aborted the client by name instead.
const auto child = RunInChild([] {
StartControlSession();
// Taken through the production entry point, the way the barrier and the encoder take
@@ -1260,12 +1260,12 @@ TEST(RemoteClientControls, AParameterChangeForAConfirmedObjectTakesNoReply) {
// =====================================================================================
//
// The two halves of resource_respecify are not the same row. The buffer half's Bool is discarded
// at BOTH call sites (PipeFill.cpp:1105, :1142), so its wait bought a value that was thrown away -
// at BOTH call sites in MGPipeEmitResourceRespecify (PipeFill.cpp), so its wait bought a value that was thrown away -
// fire-and-forget costs nothing and saves a round trip per glBufferData, which is the shape a
// chunk uploader produces thousands of times per frame. The texture half's Bool is load-bearing:
// it triggers the self-heal AND gates the acceptance mirror, and advancing that mirror on a
// provisional accept is ID-18 M3 (TextureEmit.h:885-888). So this case asserts BOTH directions -
// the asymmetry is the design, not an oversight.
// provisional accept is ID-18 M3 (EmitResourceRespecify in TextureEmit.h). So this case asserts
// BOTH directions - the asymmetry is the design, not an oversight.
//
// THE RED, RUN ONCE: take the bufferHalf branch out of Wire_Escape_ResourceRespecify and exit 155
// fires (the buffer respecify starts waiting again).
+3 -3
View File
@@ -392,7 +392,7 @@ TEST(SessionTest, TwoThreadsMoveTwentyThousandRecordsAndAgreeOnEveryOne) {
void* payload = nullptr;
while ((payload = session.cmdProducer.Reserve(1, kRecNone, sizeof(std::uint32_t))) ==
nullptr) {
// Never "wait" on a nullptr with enough free bytes - Ring.h:226-233 says that can
// Never "wait" on a nullptr with enough free bytes - RingProducer::Reserve (Ring.h) says that can
// only mean "too big, chunk", and a producer that waited there would stall for ever.
ASSERT_LT(session.cmdProducer.FreeBytes(), 16u);
if (session.producer.WaitForCmdSpace(16, 5000) != SessionWait::Reached) {
@@ -1219,7 +1219,7 @@ TEST(SessionTest, TheInprocPeerGetsItsOwnMappingOfTheSameSharedMemory) {
// M-5. RetireThrough must NOT hand back a slot borrowed into the GPU timeline. The first
// version called RingConsumer::PublishRetired(), which stores the local tail into BOTH tails
// and therefore frees every popped byte regardless of kRecBorrowSlot - defeating the reason the
// ring carries two tails at all (Ring.h:24-27) and letting the producer overwrite a slot the
// ring carries two tails at all (Ring.h's header comment) and letting the producer overwrite a slot the
// GPU is still reading. Nothing sets kRecBorrowSlot yet; this is the case that has to be true
// on the day something does.
TEST(SessionTest, ABorrowedSlotIsNotHandedBackUntilItIsReleased) {
@@ -1269,7 +1269,7 @@ TEST(SessionTest, ABorrowedSlotIsNotHandedBackUntilItIsReleased) {
}
// q-1. Teardown's drain keys on the PRODUCER's own last-published seq, not on
// RingControl::submittedSeq: Ring.h:72-77 permits that watermark to be published lazily, so a
// RingControl::submittedSeq: Ring.h's header comment permits that watermark to be published lazily, so a
// drain that trusted it would under-wait and free an emitter-owned var-tail while a record
// still names it. With the verb barrier armed the two are equal; under
// MOBILEGL_IPC_VERB_BARRIER=0 - R-1's negative control, which the phase must run once - they
@@ -440,7 +440,7 @@ TEST(SocketTransportTest, BlockedReceiverWakesOnSendAndOnShutdown) {
std::uint64_t size = 0;
MobileGLMutableByteSpan span{buffer.data(), buffer.size()};
// The wake is a real POLLHUP here, not a condvar notify: this is the
// mechanism Doorbell.h:390-398 chose a stream socket for, and the reason
// mechanism SocketDoorbell (Doorbell.h) chose a stream socket for, and the reason
// death is an event rather than a hang.
EXPECT_EQ(pair.server->ReceiveFrame(span, &size, kWaitForever), MOBILEGL_ERR_TRANSPORT_CLOSED);
closer.join();
@@ -1004,7 +1004,7 @@ TEST(StagedTextureProductionTest, TextureSubDataThroughTheRealOpsTableCopiesAndS
rec.UnionBox = {0, 0, 0, 4, 4, 1};
rec.RegionCount = 0;
// Under split the codec declares the run's length: "the bytes this record declares ARE
// the level shadow" (TextureEmit.h:1285). The adoption reads exactly this field.
// the level shadow" (TextureEmit.h's EmitOneLevel). The adoption reads exactly this field.
rec.Blob.Size = src.size();
// THE PRODUCTION CALL. Not StagedTextureStore::Adopt directly - the whole point of the
@@ -230,7 +230,7 @@ namespace {
std::atomic<std::uint64_t> answered{0};
void SetUp() override {
StreamClientPublication::SetUp();
// `Start()` does this on the real path (ClientSession.cpp:1615); this harness enters
// `Start()` does this on the real path; this harness enters
// through FinishStartup, so the routed rows have to be installed by hand or
// MGPipeRouteResourceCreate would reach the monolith screen.
Client::InstallClientWireTables();
+1 -1
View File
@@ -99,7 +99,7 @@ namespace MobileGL::MG_Util::PipeStats {
//
// COUNTED AT THE ALLOCATOR, WHICH IS THE ONE CHOKE POINT. Every writer that puts bytes
// into SEG_STAGE reaches them through PipeWireEncoder::StageBytes and that function's
// only allocation call is StageAllocate (PipeWireCodec.h:376), so a single site here
// only allocation call is PipeWireEncoder::StageAllocate (PipeWireCodec.h), so a single site here
// covers the buffer content walks, the texture slabs, the CSO archives and the
// storage-block names alike. Summing at the CALLERS instead would be a hand-kept list of
// the paths that happen to exist today, and the next producer added would be missing
+1 -1
View File
@@ -140,7 +140,7 @@ PROBES = [
"Forbidden": ["MobileGL/Includes.h"],
"Allow": [],
"TextLimits": {},
"Why": "WireLog.h:9-24 states the rule: nothing about a byte pipe needs the GL "
"Why": "ITransport.h's file comment states the rule: nothing about a byte pipe needs the GL "
"frontend's umbrella header. Green today - it is the gate's own canary.",
},
{
+2 -2
View File
@@ -210,10 +210,10 @@ ENUM_VALUE = re.compile(r"^\s*([A-Za-z][A-Za-z0-9]*)\s*=", re.MULTILINE)
# change and not a wave-0 instrument's to make. Recorded for the integrator.
LOCAL_REFUSAL_WORDS = {
"ProtocolMismatch":
"ClientSession.cpp:700/:718 - the CLIENT refusing a control/data transport pair locally, "
"ClientSession.cpp's StartSpawned - the CLIENT refusing a control/data transport pair locally, "
"before any Hello is sent; there is no peer to send a Refuse frame to",
"InitialCapsSnapshot":
"ClientSession.cpp:1292/:1302 - the CLIENT refusing a Welcome that carried no initial "
"ClientSession.cpp's FinishStartup - the CLIENT refusing a Welcome that carried no initial "
"capabilities; the handshake has already been answered, so the decline is local",
"AdoptTierOnStream":
"Transport/AdoptTier.cpp (P11 A1) - either side refusing its OWN MOBILEGL_IPC_ADOPT_TIER=0/1 "
+3 -4
View File
@@ -576,10 +576,9 @@ inline constexpr const char* kMGPipeFieldOwnershipNames[] = {
add("static_assert(kMGPipeFieldOwnershipRowCount == 70, \"table 2's row count moved\");\n")
add("""// An ARGUMENT-KEYED narrowing of one field. The field keeps its single row above; this
// says that one argument value of it belongs to a different class. Coverage.def:62-69 already
// rules the shape for GetBufferBindingSlot - "THE ROW STAYS ONE ROW ... the field is ONE array
// that a second row of the same name could only duplicate" - and m_pixelStore[2] is the same
// shape indexed by its own isUnpack argument.
// says that one argument value of it belongs to a different class. Coverage.def's comment on the
// GetBufferBindingSlot row already rules the shape - "The field is one array, so it stays one
// row" - and m_pixelStore[2] is the same shape indexed by its own isUnpack argument.
struct MGPipeFieldArgumentOwnership {
MGPipeInputField Field;
Uint32 Arg0;