diff --git a/MobileGL/MG_Impl/Pipe/PipeFill.cpp b/MobileGL/MG_Impl/Pipe/PipeFill.cpp index 5c88caec..1276cb4c 100644 --- a/MobileGL/MG_Impl/Pipe/PipeFill.cpp +++ b/MobileGL/MG_Impl/Pipe/PipeFill.cpp @@ -552,6 +552,16 @@ namespace MobileGL::MG_Pipe { ctx->RecordError(code, Move(info)); } + void MGPipeLeaveVerb() { + PipeInputs& inputs = gPipeInputs; +#if MOBILEGL_PIPE_POISON + // Same bump the next fill would make, without a verb to fill from: no field is + // stamped, so every stamp this verb made falls behind the serial. + ++MGPipeFillAccess::Filled(inputs).CurrentVerbSerial; +#endif + MGPipeFillAccess::SetVerb(inputs, MGPipeVerb::kVerbCount); + } + // ---- the filler ---- void MGPipeFillForVerb(MGPipeVerb verb) { PipeInputs& inputs = gPipeInputs; diff --git a/MobileGL/MG_Impl/Pipe/PipeFill.h b/MobileGL/MG_Impl/Pipe/PipeFill.h index deda5991..f03a3b82 100644 --- a/MobileGL/MG_Impl/Pipe/PipeFill.h +++ b/MobileGL/MG_Impl/Pipe/PipeFill.h @@ -24,6 +24,15 @@ namespace MobileGL::MG_Pipe { // runs the entry compare against a second snapshot (P1 brief D8). void MGPipeFillForVerb(MGPipeVerb verb); + // Ends the verb in flight without starting another: bumps the serial, so every field the + // verb stamped goes stale, and puts the current verb back to "none", so a read made after + // it aborts as Fatal{UnmigratedPipeInput, "@"} - which is what such a read + // is - instead of naming whichever verb happened to be filled last. Nothing in the GL + // entry points calls this: a real verb is always followed by the next verb's fill. It + // exists for a caller that drives a backend helper directly and wants its declaration to + // stop where it says it stops (MG_Test/ScopedPipeVerb.h). + void MGPipeLeaveVerb(); + // PipeFill.cpp. Negative control B (P1 brief D6): the filler withholds the STAMP - never // the value - of `field` at `verb`, so that verb's read of it is // Fatal{UnmigratedPipeInput, "Field@Verb"} while every other verb is unaffected. The diff --git a/MobileGL/MG_Test/ScopedPipeVerb.h b/MobileGL/MG_Test/ScopedPipeVerb.h index 1172cf90..aa0d90fc 100644 --- a/MobileGL/MG_Test/ScopedPipeVerb.h +++ b/MobileGL/MG_Test/ScopedPipeVerb.h @@ -65,13 +65,14 @@ namespace MobileGL::MG_Test { } #if MOBILEGL_PIPE_PUSH - ~ScopedPipeVerb() { MG_Pipe::MGPipeFillForVerb(kLeaveVerb); } + // Leaving bumps the serial and puts the current verb back to "none": every field + // this scope stamped goes stale, and a later test that forgets its own declaration + // aborts with "@" rather than with the name of a verb it never issued. + // That matters when the suite runs as one process (a developer running the test + // binary directly, rather than one ctest entry per case). + ~ScopedPipeVerb() { MG_Pipe::MGPipeLeaveVerb(); } private: - // Leaving is a fill of the narrowest verb class there is: kQuery names one field, so - // the serial bump lands and every field this scope stamped falls behind it. The one - // field is a transform-feedback counter read - no side effect, and nothing to undo. - static constexpr MG_Pipe::MGPipeVerb kLeaveVerb = MG_Pipe::MGPipeVerb::GetGpuTimestampNs; MG_Pipe::MGPipeVerb m_verb; #endif }; diff --git a/scripts/check_include_closure.py b/scripts/check_include_closure.py index 5465edaf..5fbde4c7 100755 --- a/scripts/check_include_closure.py +++ b/scripts/check_include_closure.py @@ -106,6 +106,25 @@ PROBES = [ "Why": "P7 ships the reflection artifacts over the wire; the archive header must not " "depend on the compiler front end that produced them.", }, + { + "Name": "mutation-header", + "Header": "MobileGL/MG_Pipe/PipeMutation.h", + "Tu": "#include \n", + "Forbidden": [ + "MobileGL/MG_Impl/", + "MobileGL/MG_State/GLState/Core.h", + "MobileGL/MG_Remote/", + ], + "Allow": [], + "TextLimits": {}, + "Why": "P1 finding F2 put MGP_NOTE_MUTATION in frontend mutators, so MG_State now " + "includes this header (TextureState.h, SamplerObject.h). It may only DECLARE " + "the notice: reaching MG_Impl would pull the fill implementation into the " + "state machine that calls it, and reaching GLState/Core.h would close the " + "cycle back onto the context. The MGPipeTypes -> BackendObject -> TextureEnum " + "reach it inherits from MGPipe.h is D1's known exception, which is why gate A " + "asserts MGPipeValueTypes.h rather than MGPipeTypes.h.", + }, { "Name": "wire-header", "Header": "MobileGL/MG_Remote/Transport/ITransport.h",