mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-13 14:48:32 +09:00
842af23331819fcddfe59b9d64954faf946f56d7
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bee07c3273 |
[Fix] (Pipe): arm both applier trip wires off the applier's own scatter ledger instead of off a bound handle, and stop leaving a mixed CSO or a malformed attribute tail to a DEBUG-only assertion
- MGPipeApplierState gains ScatteredChunkBits: the global chunk bits this applier has itself
scattered into PipeInputs::m_renderState, set by bind_render_state (the whole pipeline half)
and set_dynamic_state (the chunks it names), cleared by MGPipeApplierReset. set_patch_state's
own write is deliberately NOT in it - that is the other carrier, and a wire comparing against
bytes it had just written would be a tautology.
- The residual trip wire now compares capability i only once every chunk that capability's
answer is read out of is in the ledger. Both of the previous form's contracts were undeclared
and one of them was wrong: with the render-state subsystem off (MOBILEGL_PIPE_PUSH=0x10 is a
legal per-subsystem A/B, D14) the working block is the per-verb fill loop's, published per
verb CLASS, and FillPoints.def does not publish GetRenderStateParameters at kDispatch or
kTextureOp - so at a dispatch after a draw the block held the draw's bytes and a correct
context could abort. With the ledger empty the wire now says nothing there, and with the
subsystem on the applier is the block's only writer and its bytes are current at every class.
- The per-capability grain is not decoration: a bind alone owns the pipeline half, and the
eight ClipDistances are answered from ClipDistanceEnabledMask in dynamic chunk D7, so between
a bind and the first set_dynamic_state exactly those eight are unanswerable. The source
chunks come from the same MGP_PLAIN_CAPABILITY_LIST and the same boundary table
DeriveCapability reads, so the two cannot drift.
- The patch-carrier wire arms the same way, which replaces its "some CSO is bound" condition -
a process-global that stayed set from the first bind onward - and covers the verb-class
contract as well as the ordering one.
- Both wires now run in the shipped push build too, counting and logging where a poison or
verify build aborts (one MGP_TRIP_WIRE_REPORT/TAG pair, so only the fatal arm writes the
"Fatal{...}" marker G4 greps for). A wire compiled out of every build a device runs is not a
wire, and the counters are what let a unit case see it fire in every build.
- create_render_state no longer leaves a dead BaseCso to MOBILEGL_ASSERT, which is inert at
INFO - the level every gate and every shipped build uses. A recycled slot's record still
holds the previous occupant's 396 bytes, so inheriting nothing and scattering the delta on
top handed out a record that was half one CSO and half another. Both arms now start from a
defined base and report. The same for a brand-new CSO that does not name every chunk.
- set_vertex_attrib_defaults walks the mask's 32 bits rather than the slot array, consumes a
tail entry for every named location so a named-but-unstorable attribute cannot desynchronise
the rest, and reports all three consistency faults in every build.
|
||
|
|
a9bb99a46a |
[Fix] (Pipe): scope the derivation to the chunks a scatter moved, and give the patch trio and the residual block trip wires that do not depend on call order
- MGPipeDeriveRenderStateFieldsForChunks: the applier no longer recomputes all 29 fields on every scatter. The four wide walks - the 8-wide blend/colour-mask loop, the 16-wide viewport loop, the 16-wide depth-range loop and the 35-arm capability switch - are guarded by the chunks whose bytes they read, so a per-frame glViewport (the D8 case that sends dynamic chunk D0 alone) pays for one 16-entry copy instead of ~170 stores and 35 switch dispatches. That cost sat on the per-draw path and the gate it threatened is G11's pinned ns/draw. - Every guard is MGPipeRenderStateChunkBitsCovering(offsetof(member), sizeof(member)) over the members the guarded block reads, computed from the boundary table: there is no second, hand-maintained member-to-chunk mapping to go stale when a boundary moves. The scalar copies stay unguarded on purpose - they cannot go stale, which keeps the risk of the scoping confined to four guards. - MGP_PLAIN_CAPABILITY_LIST is written once and used twice, for DeriveCapability's switch arms and for the capability guard's chunk set, so the two cannot drift. - set_patch_state now asserts under poison/verify that the trio agrees with what pipeline chunk P0 delivered, which D6 and D10 both ask for and which was missing: a stale set_patch_state silently clobbered the CSO-delivered levels. Compared bitwise, because a NaN outer level is legal and must equal itself; armed only once a CSO has been bound, which states the ordering contract rather than assuming it. - set_residual_value_state's trip wire compares the carried bits against the WORKING BLOCK instead of PipeInputs::m_capability. Only the derivation writes m_capability, so a residual block emitted before the first bind of a context - what "once per context" means - compared against all-false storage while Dither and Multisample default to true, and aborted under poison. The check is unchanged in strength and now has no ordering contract at all. - PipeApply.h no longer implies the verify comparator is this package's oracle: it arms off MG_Config::Features.PipeVerify, which a unit-test process never sets, so the unit oracle is named for what it is and the comparator is credited to the retrace and integration-verify lanes. |
||
|
|
810850b13a |
[Feat] (Pipe): derive every render-state PipeInputs field from the assembled working block instead of pulling it again from GLContext
- 29 of the 47 kDraw PipeInputs fields are pure functions of RenderStateParameters. Once bind_render_state and set_dynamic_state have assembled the working block - which IS PipeInputs::m_renderState - copying those fields out of GLContext a second time is the per-verb pull P2 exists to remove. The applier now derives them after any scatter. - Each line is a transcription of the RenderState getter of the same name; GLContext's accessors are one-line forwards to those, so the derivation and the pull path answer the same question from the same bytes. Two are not field copies and are transcribed exactly: GetViewport (viewport 0 rounded with std::lround, because glGetIntegerv on float state rounds to nearest and truncating a 63.5-wide viewport would hand the backends a rectangle one pixel short), and IsCapabilityEnabled (the 35-way switch, including Blend -> BlendStates[0].Enabled, ScissorTest -> ScissorTestEnabledMask & 1 and the ClipDistance run). The indexed twin is the same for Blend[8] and ScissorTest[16]. - IsCapabilityEnabled could not have been written before the contract commit: DepthClamp, FramebufferSrgb and TextureCubeMapSeamless fell to `default: return false`, so three of the 35 answers were a compile-time constant rather than state. - This departs from P1 brief D4's "no derivation logic is re-implemented in PipeInputs", deliberately: the alternative is to keep pulling those 29 fields per verb. The guard is the oracle P1 built - MOBILEGL_PIPE_VERIFY's compare-at-read re-reads every one of them from the live context at EVERY backend read and compares field-wise, so a transcription error is caught on the first draw that reads it, across 79 retraces and the integration-verify entries. - The body sits in MGPipeApplyAccess, the struct PipeInputs already names as its friend, so no new friend and no new accessor per field. Pull build untouched: PipeApply.cpp compiles only under MOBILEGL_PIPE_PUSH. |
||
|
|
9c6a8a25d8 |
[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.
|