mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[MG_Backend, MG_Pipe, MG_Impl, Docs] (Disaggregated): P5e ra2 ID-136 - retire the indirect-binding pull instead of escalating for it, and withdraw escalation (iii)
- TOUCHING mv's FILE UNDER ID-136, deliberately and by ruling: MG_Backend/DirectGLES/
MultiDraw.cpp is mv's per ID-113, and the integrator overrode that boundary for this one
change because the two halves must not exist apart on any head. The boundary has not drifted.
- BoundDrawIndirectBufferId (MultiDraw.cpp) gets the handle arm its neighbour
ResolveBoundIndexBuffer already had, in mv's own idiom rather than a second one beside it:
the arm is `MG_Config::Transport != Monolith`, STATED (ID-81) and never inferred from a null
handle (ID-110); a null handle is "this verb bound no indirect buffer", the same 0 the
monolith arm returns for an empty slot; a missing backend resource is the named refusal
Fatal{RoleViolation, "multidraw-indirect-buffer-arm"}, a sibling of mv's
RefuseMissingIndexBufferRecord, never a quiet fall-back to the frontend. The monolith body
below it is unchanged token for token. The function moved down beside BoundIndexBufferId,
which is the same question about the other target.
- WHY A HANDLE ARM AND NOT A MIGRATION: the tier never reads a byte of the client's indirect
buffer. It binds its OWN scratch command buffer and wants to put back the name that was
there - a save/restore. With a transport the only other writer of this process's
GL_DRAW_INDIRECT_BUFFER is DirectGLES.cpp's DrawSyncBit::IndirectBuffer arm, which binds from
MGPipeApplier().VerbIndirectBuffer and nothing else, so "what was bound" IS "what the verb's
record named".
- Escalation (iii) withdrawn in the same commit - MGPipeBarriered's clause, the client's
verb-keyed half in ClientVerbIsBarriered, and the contract row. It was never wrong, it was
the wrong instrument: there is one draw opcode and the tier is chosen server-side per batch,
so the narrowest key both roles could compute charged EVERY plain glMultiDraw* on the
auto -> ext default - a per-batch rendezvous on the arm the phone ships, added to make a lane
green. THE CHECK ON AN ESCALATION IS "WHICH ARM PAYS FOR IT", NOT "WHICH LANE GOES GREEN";
the rule is recorded in PipeApply.h beside the three that remain and in CONTRACT-P5E §2.1.
- Red-once D: `if (false && ...)` on the new arm and the entry dies 3/3, deterministically, on
`Fatal{UnmigratedPipeInput, "GetBufferBindingSlot@DrawArrays"} [BARRIER-PULLED, UNBARRIERED,
the client did not fill it, retires in P8 (indirect), P9 (readback), P13 (transfer)]`.
Its counterpart is this head itself: the escalation is GONE and the lane is green, so nothing
needed it - and the strict census's admitted set drops from nine rows back to ID-128's eight,
because the pull no longer happens at all rather than being legalised.
- Gate on the flipped head: unit 2256/2256, isplit 179/179, gens rc=0, lane counts unchanged
(179 / 1357 / 2 / 2).
This commit is contained in:
@@ -84,13 +84,8 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
constexpr SizeT kMaxComputeWorkGroups = 65535;
|
||||
constexpr SizeT kMaxComputeFlattenedIndices = kMaxComputeWorkGroups * kComputeWorkGroupSize;
|
||||
|
||||
Uint BoundDrawIndirectBufferId() {
|
||||
const auto& indirect =
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!indirect) return 0;
|
||||
const auto* resource = BufferImpl::EnsureBufferResource(indirect);
|
||||
return resource ? resource->id : 0;
|
||||
}
|
||||
// BoundDrawIndirectBufferId MOVED (P5e ra2, ID-136) to sit beside BoundIndexBufferId,
|
||||
// which is the same question about the other target and now has the same two arms.
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// The bound index buffer, and WHICH SIDE ANSWERS FOR IT
|
||||
@@ -150,6 +145,24 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// ---- P5e (ra2), ID-136: THE SAME REFUSAL FOR THE INDIRECT TARGET -------------------
|
||||
//
|
||||
// A sibling of mv's rather than a second idiom, because it is the same sentence about
|
||||
// the other buffer target: a missing record on the handle arm aborts by name and never
|
||||
// falls back to the frontend binding slot, which answers for whatever the CLIENT has
|
||||
// bound NOW - a later verb than the one being applied.
|
||||
[[noreturn]] void RefuseMissingIndirectBufferRecord(const char* entry,
|
||||
MG_Pipe::MGPipeHandle res) {
|
||||
MGLOG_F("MGPipe: Fatal{RoleViolation, \"multidraw-indirect-buffer-arm\"} - %s found no "
|
||||
"backend resource for the indirect buffer {%u, %u} this verb's record named. "
|
||||
"The indirect buffer of this family is MGPipeApplier().VerbIndirectBuffer "
|
||||
"(CONTRACT-P5E §2.1) and the arm is selected by Transport != Monolith "
|
||||
"(ID-81); falling back to the frontend GL_DRAW_INDIRECT_BUFFER slot here "
|
||||
"would restore whatever the CLIENT has bound now",
|
||||
entry, res.Slot, res.Gen);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// Does the applier's record say the application SUPPLIED this store's content? The M-3
|
||||
// rule ScopedRestartIndexSubstitution spells: for a supplied store a coverage gap in the
|
||||
// server shadow is a missing record and Fatal by name; for one the application ORPHANED
|
||||
@@ -247,6 +260,57 @@ namespace MobileGL::MG_Backend::DirectGLES::MultiDrawImpl {
|
||||
return ResolveBoundIndexBuffer(IndexBufferQuestion::DriverName, "BoundIndexBufferId").Id;
|
||||
}
|
||||
|
||||
// The GL name on GL_DRAW_INDIRECT_BUFFER, i.e. what a tier that swaps in its own scratch
|
||||
// COMMAND buffer has to put back - the exact twin of BoundIndexBufferId above, and now
|
||||
// with the same two arms.
|
||||
//
|
||||
// ---- P5e (ra2), ID-136: THE SEAT THIS FILE'S OWN RULE HAD MISSED -------------------
|
||||
//
|
||||
// This was the LAST unguarded frontend read on the multi-draw apply path, and it sat
|
||||
// twenty lines above the function that retired its neighbour. It asked
|
||||
// `MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect)` and then
|
||||
// `EnsureBufferResource(<frontend object>)` - a registry lookup keyed by the client's
|
||||
// identity, which is §4.4's rule and not only the allocator's. Under run-ahead that is
|
||||
// `Fatal{UnmigratedPipeInput, "GetBufferBindingSlot@DrawArrays"}` on every batch the
|
||||
// indirect tiers execute: 18 lane entries, and the only thing standing between the flip
|
||||
// and a green lane once the fill race was fixed.
|
||||
//
|
||||
// WHAT IT IS NOT: a data dependency. The tier does not want the client's indirect
|
||||
// buffer - it never reads a byte of it. It binds its OWN scratch command buffer
|
||||
// (g_indirectCommands) and wants to put back the name that was there. So the answer is
|
||||
// not "migrate the value" (which is what P8 owes for the ordinary indirect draw path);
|
||||
// it is "ask the side that did the binding". ID-133's escalation (iii) legalised the
|
||||
// pull instead, at the price of a rendezvous on every plain glMultiDraw* on the DEFAULT
|
||||
// tier - a real cost on the shipping arm, paid to make a lane green. ID-136 withdraws
|
||||
// that escalation and retires the read, in the commit that adds this arm.
|
||||
//
|
||||
// WHY MGPipeApplier().VerbIndirectBuffer IS THE WHOLE ANSWER ON THIS ARM: with a
|
||||
// transport, the ONLY writer of this process's GL_DRAW_INDIRECT_BUFFER outside this
|
||||
// function is DirectGLES.cpp's DrawSyncBit::IndirectBuffer arm, which binds from exactly
|
||||
// that handle and nothing else. So "what was bound" IS "what the verb's record named",
|
||||
// and a null handle is "this verb bound none" - the same 0 the monolith arm returns for
|
||||
// an empty slot, and not the arm test (ID-110: the arm was decided by the transport
|
||||
// above, never inferred from a null).
|
||||
Uint BoundDrawIndirectBufferId() {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
if (MG_Config::Transport != MG_Config::TransportMode::Monolith) {
|
||||
const MG_Pipe::MGPipeHandle res = MG_Pipe::MGPipeApplier().VerbIndirectBuffer;
|
||||
if (MG_Pipe::MGPipeHandleIsNull(res)) return 0;
|
||||
auto* resource = BufferImpl::EnsureBufferResourceForHandle(nullptr, res);
|
||||
if (resource == nullptr) {
|
||||
RefuseMissingIndirectBufferRecord("BoundDrawIndirectBufferId", res);
|
||||
}
|
||||
return resource->id;
|
||||
}
|
||||
#endif
|
||||
// MONOLITH GLUE from here down, token for token what this function did before.
|
||||
const auto& indirect =
|
||||
MGB_CTX->GetBufferBindingSlot(BufferTarget::DrawIndirect).GetBoundObject();
|
||||
if (!indirect) return 0;
|
||||
const auto* resource = BufferImpl::EnsureBufferResource(indirect);
|
||||
return resource ? resource->id : 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scratch GL objects
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user