mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-13 06:38:31 +09:00
[Feat] (Pipe): map every frontend mutator onto the aggregate generation that publishes it, and make the dirty-surface scanner a gate
- MG_Pipe/DirtySurface.def: 73 rows, one per distinct mutator the scanner finds, each answering
"what publishes this". The answer vocabulary is a MGPipeDirty bit name or one of five
non-bit answers, and each of the five is documented in the file's header rather than left to
be inferred: kImmediate, kReverseChannel, kNoBackendRead, kExplicitDestroy and
kPulledEveryVerb. Where a mutator has more than one true answer the row carries the COARSER
one - the one that cannot under-fire.
- gen_pipe_dirty_surface.py --check is the gate and it fails in BOTH directions: an unmapped
mutator renders stale, and a row naming a mutator the scan no longer finds keeps a real hole
looking covered. It also rejects an answer that is neither a documented non-bit answer nor a
bit name read out of Tracker.h's own kMGPipeDirtyNames, so a renamed bit cannot leave a row
silently pointing at nothing.
- --self-test runs three canned negative controls - a withheld mutator, a stale row, a bad
answer - and each must trip; trips == 0 is itself an error, the shape
check_include_closure.py and gen_pipe.py --self-test already use. ROADMAP.md's rule is that
every gate must be able to go red for the reason it exists.
- --summary keeps working unchanged, because the CI file that still calls it belongs to
another package until it lands.
- The human report prints the mapped answer where it printed UNMAPPED.
- FillPoints.def: the verdict on the eight statically over-approximated rows, recorded per
group in the def's own comment. All eight are KEPT and the reason is the same in all three
groups - each row names a concrete backend path (the depth/stencil read emulation's paused
capture, VkClearManager::PreCompensateSrgbClearColor's GL_FRAMEBUFFER_SRGB read, the shader
blit's viewport / provoking vertex / binding-point reads), and the only evidence that could
retire one is dynamic. A corpus that never reaches a path proves nothing about it, and a row
dropped on that basis turns a rare path into Fatal{UnmigratedPipeInput} in a shipped build.
The contract's new FramebufferSrgb storage in fact makes one of the eight MORE load-bearing
than it was, not less: it used to read a compile-time constant.
This commit is contained in:
@@ -26,6 +26,44 @@
|
||||
// Fatal{UnmigratedPipeInput, "Field@Verb"} found there is fixed by adding the (class, field)
|
||||
// row, never by marking the field sticky.
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// THE VERDICT ON THE EIGHT STATICALLY OVER-APPROXIMATED ROWS (P2 brief C.1, MEASUREMENTS.md
|
||||
// section 4). Every one of them is KEPT, and the reason is the same in all three groups: the
|
||||
// row is not a guess, it names a concrete backend path, and the only evidence that could
|
||||
// retire it is DYNAMIC - a corpus that never reaches the path proves nothing, because a row
|
||||
// removed on that basis turns a rare path into Fatal{UnmigratedPipeInput} in a shipped build.
|
||||
//
|
||||
// kReadback + IsTransformFeedbackActive / IsTransformFeedbackPaused
|
||||
// KEPT. The depth/stencil read emulation draws (ScopedEmulationDrawState, DirectGLES.cpp)
|
||||
// and pauses an active capture around its own draw, so a glReadPixels of a depth or
|
||||
// stencil attachment reads the transform-feedback state exactly as a draw does. Reached
|
||||
// only when the emulation is armed, which is a driver-shaped decision, so no desktop
|
||||
// corpus can decide it.
|
||||
//
|
||||
// kTextureOp + IsCapabilityEnabled, kDispatch + IsCapabilityEnabled
|
||||
// KEPT. Magma's GenerateMipmap materialises a texture's queued clear before it blits and
|
||||
// PrepareStorageImageTextures does the same for every storage image a dispatch writes;
|
||||
// both go through VkClearManager::PreCompensateSrgbClearColor, which reads
|
||||
// GL_FRAMEBUFFER_SRGB. The P2 contract gave that capability real storage for the first
|
||||
// time, so this row went from reading a compile-time constant to reading real state -
|
||||
// which is the opposite of a row that could be dropped.
|
||||
//
|
||||
// kBlitOrCopy / kTextureOp + the shader blit's viewport and vertex/buffer bindings
|
||||
// (GetViewportIndexed, GetDepthRangeIndexed, GetProvokingVertexMode, GetBufferBindingPoint)
|
||||
// KEPT. TryBlitToDefaultFramebufferWithShader is a real draw of a backend-owned helper
|
||||
// program: ApplyGLViewportState -> ComputeGLViewport reads viewport 0 and its depth range,
|
||||
// GetOrCreateBlitPipeline -> SelectProvokingVertexMode reads the provoking vertex, and
|
||||
// BindProgramUniformBuffers' block resolvers read the frontend binding points. It is taken
|
||||
// when a blit's destination is the default framebuffer and the driver cannot do it
|
||||
// natively - again a driver-shaped decision.
|
||||
//
|
||||
// What WOULD retire a row: the poison build already answers "was this field read at this
|
||||
// verb" exactly (MOBILEGL_PIPE_POISON_OMIT withholds one field's stamp for one verb and a
|
||||
// read of it aborts naming the pair). Turning that into a retirement gate means running the
|
||||
// omission across the full CTS caselist on both devices, not the desktop corpus, and that is
|
||||
// recorded as P3a work rather than done here on evidence that cannot support it.
|
||||
// ---------------------------------------------------------------------------------------
|
||||
//
|
||||
// gen_pipe.py's block regexes end at a blank line: keep the empty line after each macro.
|
||||
//
|
||||
// clang-format off
|
||||
|
||||
Reference in New Issue
Block a user