[Feat] (MG_Pipe, MG_Remote/Client, MG_Impl/Pipe): R-17 - install the two generated MGPipe tables over the 37 apply entry points, 40 call sites onto the thunks, 37 wire emitters, the reply mailbox, and ID-47/ID-49 readback

This commit is contained in:
2026-09-16 07:10:51 -04:00
parent aa7ad670c4
commit 02f15bb675
25 changed files with 2336 additions and 273 deletions
+3 -2
View File
@@ -44,6 +44,7 @@
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/MGPipeRenderStateSpans.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Util/Metrics/PipeStats.h>
#include <cstring>
@@ -154,7 +155,7 @@ namespace MobileGL::MG_Pipe {
// minted from a neighbour rather than from nothing.
desc.ChunkMask = kAllPipelineChunks;
desc.Blob.Size = kMGPipePipelineChunkBytes;
MGPipeApplyCreateRenderState(desc, bytes.data());
MGPipeRouteCreateRenderState(desc, bytes.data());
payloadBytes += sizeof(MGPRenderStateDesc) + kMGPipePipelineChunkBytes;
Entry entry;
@@ -175,7 +176,7 @@ namespace MobileGL::MG_Pipe {
MGPHandleOnly handle{};
handle.Handle = m_entries[index].Cso;
handle.Kind = static_cast<Uint32>(MGPipeKind::RenderStateCso);
MGPipeApplyDeleteRenderState(handle);
MGPipeRouteDeleteRenderState(handle);
MGPipeSlots().Free(MGPipeKind::RenderStateCso, m_entries[index].Cso);
m_entries[index] = m_entries.back();
m_entries.pop_back();
+2 -1
View File
@@ -32,6 +32,7 @@
#include <MG_Impl/Pipe/Tracker.h>
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/PipeStats.h>
@@ -456,7 +457,7 @@ namespace MobileGL::MG_Pipe {
m_lastDraw = state;
if (state.Target == static_cast<Uint8>(MGPipeFramebufferTarget::Both)) m_lastRead = state;
}
MGPipeApplySetFramebufferState(state);
MGPipeRouteSetFramebufferState(state);
++m_emissions;
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::FramebufferEmissions, 1);
+2 -1
View File
@@ -38,6 +38,7 @@
#include <MG_Impl/Pipe/SlotAllocator.h>
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/TextureState/TextureState.h>
@@ -126,7 +127,7 @@ namespace MobileGL::MG_Pipe {
m_lastImages.Start = 0;
m_lastImages.Count = count;
m_lastImages.ContentHash = hash;
MGPipeApplySetShaderImages(m_lastImages, m_entries.data());
MGPipeRouteSetShaderImages(m_lastImages, m_entries.data());
++m_imageSets;
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::ShaderImageEmissions, 1);
+83 -16
View File
@@ -36,6 +36,7 @@
#include <MG_Impl/Pipe/VertexInputEmit.h>
#include <MG_Pipe/MGPipeRenderStateSpans.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <Config.h>
@@ -46,6 +47,7 @@
// build-split runs MOBILEGL_TRANSPORT=monolith in every unit and integration-gpu lane and those
// lanes must keep answering exactly what they answered before.
#include <MG_Remote/Client/CapsMirror.h>
#include <MG_Remote/Client/WireTables.h>
#endif
#include <atomic>
@@ -677,7 +679,7 @@ namespace MobileGL::MG_Pipe {
// LATCHED, so the destroy is gated on whether this create actually went out rather
// than on whether a table is still registered when the object dies (D-L, m12).
tracker.NotePublished(handle);
MGPipeApplyResourceCreate(desc);
MGPipeRouteResourceCreate(desc);
}
void MGPipeEmitResourceRespecify(BufferObject& buffer) {
@@ -710,7 +712,7 @@ namespace MobileGL::MG_Pipe {
MGPipeBuildResourceDesc(buffer, handle, bindMask, /*storageDefined=*/false);
tracker.NoteDesc(createDesc, true);
tracker.NotePublished(handle);
MGPipeApplyResourceCreate(createDesc);
MGPipeRouteResourceCreate(createDesc);
}
const MGPResourceDesc desc = MGPipeBuildResourceDesc(buffer, handle, bindMask, true);
tracker.NoteDesc(desc, false);
@@ -723,7 +725,47 @@ namespace MobileGL::MG_Pipe {
// allocation and only it is allowed one. In monolith the acknowledgement is
// ((void)0), because the applier is one function call away and has already run by
// the time this returns; the transport wires the doorbell to that same predicate.
MGPipeApplyResourceRespecify(desc, initialBytes);
#if MOBILEGL_BUILD_DISAGGREGATED
// R-13.3's MISSING PRODUCER, and it is the reason the first joint inproc run died.
// CONTRACT-P5 §2 row 19 rules that `initialBytes` is ALWAYS nullptr under split and
// that "initial content arrives as ResourceSubData records immediately after this
// one" - but nothing emitted those records, so the split arm's refusal
// (Fatal{UncarriedInitialBytes}) fired on the first glBufferData with data, which is
// the first thing every scenario does.
//
// IT IS THE CONTRACT'S OWN PRESCRIBED ROUTE, not a new one: "the chosen route reuses a
// path that is already chunked (MGPipeForEachSubDataRecordRange) and already
// acceptance-gated; it costs one extra record". So the respecify defines the storage
// and the walk below ships the bytes, through the same emitter every later
// glBufferSubData uses - which also means the HasLiveHostWrites bit and the
// acceptance latch are computed in exactly one place instead of two.
//
// SPLIT-ONLY, and that is load-bearing for G2: under monolith the applier reads
// `initialBytes` directly and a second upload would be a real behaviour change in the
// arm the split arm is measured against.
if (MG_Config::Transport != MG_Config::TransportMode::Monolith && initialBytes != nullptr) {
MGPipeRouteResourceRespecify(desc, nullptr);
// COUNTED, NOT ASSUMED, and this is the only thing that can gate the follow-up at
// all. Dropping the walk below leaves a respecify that went out with nullptr and
// bytes that nothing carried - and no P5 scenario's PICTURE changes, because every
// one of them re-uploads its vertices through the ordinary dirty path afterwards.
// So the statement "the content followed" is made HERE, against the client's own
// record ordinal, rather than left to a lane that cannot see it. Remove the call
// below and this aborts by name on the first glBufferData that carries data.
const Uint64 before = MG_Remote::Client::ClientWireRecordsEmitted();
MGPipeEmitResourceSubData(buffer, 0, static_cast<SizeT>(buffer.GetSize()));
if (MG_Remote::Client::ClientWireRecordsEmitted() == before) {
MGLOG_F("MGPipe: Fatal{InitialBytesNotCarried, \"resource_respecify\"} - the "
"respecify crossed with initialBytes = nullptr (R-13.3) and the "
"resource_subdata records that were supposed to follow it emitted "
"NOTHING, so %llu bytes of initial content exist on no side of the wire",
static_cast<unsigned long long>(buffer.GetSize()));
std::abort();
}
return;
}
#endif
MGPipeRouteResourceRespecify(desc, initialBytes);
}
void MGPipeEmitResourceSubData(BufferObject& buffer, SizeT offset, SizeT size) {
@@ -746,7 +788,11 @@ namespace MobileGL::MG_Pipe {
// take the object, which is why it is set here and not in the builder.
record.HasLiveHostWrites = buffer.HasLiveHostWritesForWire() ? 1 : 0;
#endif
MGPipeApplyResourceSubData(record, base + at);
// `length` is this chunk's byte count, which the record also declares
// (MGPipeBuildSubDataRecord writes it into the destination range) - passed
// rather than re-read so the staged run and the record's own claim come from
// one number.
MGPipeRouteResourceSubData(record, base + at, length);
});
if (!encodable) {
MGLOG_E_ONCE("MGPipe: resource_subdata range [%llu, +%llu) on buffer %u cannot be encoded - "
@@ -777,7 +823,7 @@ namespace MobileGL::MG_Pipe {
record.HasLiveHostWrites = buffer.HasLiveHostWritesForWire() ? 1 : 0;
#endif
// The application's STAGING store, valid for the duration of the call only.
MGPipeApplyBufferSubDataResident(record, base + (at - offset));
MGPipeRouteBufferSubDataResident(record, base + (at - offset), length);
});
if (!encodable) {
MGLOG_E_ONCE("MGPipe: buffer_subdata_resident range [%llu, +%llu) on buffer %u cannot be encoded",
@@ -797,7 +843,28 @@ namespace MobileGL::MG_Pipe {
// arm reads INVALIDATE_RANGE / INVALIDATE_BUFFER / UNSYNCHRONIZED per call to choose
// between a map+memcpy+unmap and an upload, so merging them here would change which.
record.AccessFlags = accessFlags;
MGPipeApplyResourceFlushRange(record, buffer.MappedData() + offset);
#if MOBILEGL_BUILD_DISAGGREGATED
// R-13.2's MISSING PRODUCER, the twin of the respecify one above, and the cause of the
// seven PersistentCoherentMapScenario aborts on the first joint inproc run:
// Fatal{ProtocolCorruption} resource_flush_range {slot=1, gen=0, glName=1}:
// a non-empty flush carries no bytes (offset=0, size=120, storage=120 bytes)
//
// CONTRACT-P5 §2 row 20 rules that this record carries NO bytes under split - it is a
// {range, AccessFlags} control record, and a blobref here "would be a second,
// forgeable way to say the same thing" - and that "the bytes of [Offset, Offset+Size)
// arrive AHEAD of it as ResourceSubData records covering exactly that range". Nothing
// emitted those records, so v1's StagedShadowStore had nothing staged for the range
// the flush names, which is precisely the refusal ID-37 asked it to make rather than
// silently reading the bytes again.
//
// EXACTLY THAT RANGE, not the whole buffer: the flush's own [offset, size) is what
// the ladder rewrites, and staging more would be the coverage WIDENING ID-37 forbids.
// Split-only, for the respecify's G2 reason.
if (MG_Config::Transport != MG_Config::TransportMode::Monolith && size != 0) {
MGPipeEmitResourceSubData(buffer, offset, size);
}
#endif
MGPipeRouteResourceFlushRange(record, buffer.MappedData() + offset);
}
void MGPipeEmitResourceReadback(BufferObject& buffer) {
@@ -811,7 +878,7 @@ namespace MobileGL::MG_Pipe {
record.Size = buffer.GetSize();
// The answer travels back through MGPipeClientOnBufferWriteback, and the server's
// epoch bump happens AFTER that writeback, never before.
MGPipeApplyResourceReadback(record);
MGPipeRouteResourceReadback(record);
}
// NO UnmapPersistent PRODUCER IN P3a, AND THAT IS DELIBERATE. The catalogue has the call
@@ -834,7 +901,7 @@ namespace MobileGL::MG_Pipe {
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::MapPersistentRoundtrips, 1);
}
return MGPipeApplyMapPersistent(BufferHandleOnly(handle), buffer.GetSize(), buffer.MappedData());
return MGPipeRouteMapPersistent(BufferHandleOnly(handle), buffer.GetSize(), buffer.MappedData());
}
Bool MGPipeEmitResourceDestroyAndFree(BufferObject& buffer) {
@@ -849,7 +916,7 @@ namespace MobileGL::MG_Pipe {
const Bool published = tracker.WasPublished(handle);
if (published) {
tracker.NoteDestroy();
MGPipeApplyResourceDestroy(BufferHandleOnly(handle));
MGPipeRouteResourceDestroy(BufferHandleOnly(handle));
}
// THE ORDER IS FIXED (D-L): the applier clears the record and the backend drops its
// twin while the handle still resolves, and only then does the slot go back. Free
@@ -889,7 +956,7 @@ namespace MobileGL::MG_Pipe {
MGPHandleOnly only{};
only.Handle = handle;
only.Kind = static_cast<Uint32>(MGPipeKind::VertexElementsCso);
MGPipeApplyDeleteVertexElements(only);
MGPipeRouteDeleteVertexElements(only);
emitter.NoteRecordDestroyed(handle);
}
@@ -2103,7 +2170,7 @@ namespace MobileGL::MG_Pipe {
Uint64 EmitPixelPackState(GLContext& ctx) {
MGPPixelPackState pack{};
pack.Pack = ctx.GetPixelStoreParameters(false);
MGPipeApplySetPixelPackState(pack);
MGPipeRouteSetPixelPackState(pack);
return sizeof(MGPPixelPackState);
}
@@ -2116,7 +2183,7 @@ namespace MobileGL::MG_Pipe {
patch.Vertices = live.PatchVertices;
for (SizeT i = 0; i < 4; ++i) patch.Outer[i] = live.PatchDefaultOuterLevel[i];
for (SizeT i = 0; i < 2; ++i) patch.Inner[i] = live.PatchDefaultInnerLevel[i];
MGPipeApplySetPatchState(patch);
MGPipeRouteSetPatchState(patch);
return sizeof(MGPPatchState);
}
@@ -2205,7 +2272,7 @@ namespace MobileGL::MG_Pipe {
}
if (header.Count == 0) return 0;
g_attribDefaultLastHeader = header;
MGPipeApplySetVertexAttribDefaults(header, tail.data());
MGPipeRouteSetVertexAttribDefaults(header, tail.data());
// Did the applier reproduce it? Byte for byte, over the attributes this call
// named - anything less would be a mirror that disagrees with the frontend in a
@@ -2274,7 +2341,7 @@ namespace MobileGL::MG_Pipe {
block.CapabilityBits |= Uint64{1} << i;
}
}
MGPipeApplySetResidualValueState(block);
MGPipeRouteSetResidualValueState(block);
if (MG_Util::PipeStats::Enabled()) {
// ByteClass::ResidualValueBlock has been a placeholder that "stays at 0
// until P2" since P0. This is what makes it non-zero.
@@ -2328,7 +2395,7 @@ namespace MobileGL::MG_Pipe {
bind.Cso = cso;
bind.Version = version;
bind.PipelineVersion = pipelineVersion;
MGPipeApplyBindRenderState(bind);
MGPipeRouteBindRenderState(bind);
payloadBytes += sizeof(MGPBindRenderState);
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::RenderStateCsoBinds, 1);
@@ -2350,7 +2417,7 @@ namespace MobileGL::MG_Pipe {
dyn.ChunkMask = chunkMask;
dyn.Version = version;
dyn.Blob.Size = blobBytes;
MGPipeApplySetDynamicState(dyn, blob.data());
MGPipeRouteSetDynamicState(dyn, blob.data());
payloadBytes += sizeof(MGPDynamicState) + blobBytes;
}
+11 -5
View File
@@ -41,6 +41,7 @@
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/MGPipeHostSpan.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ProgramState/ProgramObject.h>
@@ -137,19 +138,19 @@ namespace MobileGL::MG_Pipe {
// exactly "nothing bound".
const MGPipeHandle boundCso = !MGPipeHandleIsNull(drawCso) ? drawCso : dispatchCso;
if (boundCso != m_boundCso) {
MGPipeApplyBindShaderState(HandleOnly(boundCso));
MGPipeRouteBindShaderState(HandleOnly(boundCso));
m_boundCso = boundCso;
++m_binds;
bytes += sizeof(MGPHandleOnly);
}
if (drawCso != m_drawCso) {
MGPipeApplySetDrawProgram(HandleOnly(drawCso));
MGPipeRouteSetDrawProgram(HandleOnly(drawCso));
m_drawCso = drawCso;
++m_drawSets;
bytes += sizeof(MGPHandleOnly);
}
if (dispatchCso != m_dispatchCso) {
MGPipeApplySetDispatchProgram(HandleOnly(dispatchCso));
MGPipeRouteSetDispatchProgram(HandleOnly(dispatchCso));
m_dispatchCso = dispatchCso;
++m_dispatchSets;
bytes += sizeof(MGPHandleOnly);
@@ -192,7 +193,12 @@ namespace MobileGL::MG_Pipe {
m_lastConstants.Blob.Seg = kMGHostSpanSegNone;
m_lastConstants.Blob.Offset = reinterpret_cast<Uint64>(program->GetUBOData());
m_lastConstants.Blob.Size = 0;
MGPipeApplySetGlobalConstants(m_lastConstants, program->GetUBOData());
// `size` is GetUBOSize(), and it is passed because the record declares 0 - the
// monolith convention (the bytes ride beside the record) that CONTRACT-P5 table 1
// rule A cannot keep under split. It is the row's largest and least bounded blob,
// per program per frame, so it is also the one R-10's max-record counter watches.
MGPipeRouteSetGlobalConstants(m_lastConstants, program->GetUBOData(),
static_cast<Uint64>(size));
m_constantsCso = cso;
m_constantsVersion = version;
++m_constantSets;
@@ -254,7 +260,7 @@ namespace MobileGL::MG_Pipe {
m_lastDesc.Reflection.Offset = reinterpret_cast<Uint64>(&link);
m_lastDesc.Reflection.Size = 0;
MGPipeApplyCreateShaderState(m_lastDesc, &link, &spirv);
MGPipeRouteCreateShaderState(m_lastDesc, &link, &spirv);
// THE CREATE WENT OUT, so the publication latch is taken here and nowhere else
// (contract-v2 §3.1). MGPipeEmitShaderCsoDestroyAndFree reads it, and without it
// delete_shader_state can never go out - for an ordinary program or for a
+6 -5
View File
@@ -44,6 +44,7 @@
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/MGPipeHostSpan.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/ProgramState/ProgramObject.h>
@@ -455,7 +456,7 @@ namespace MobileGL::MG_Pipe {
// The applier is handed the CACHE's copy, so the pointer stays valid for the whole
// call and the bytes it stores are provably the bytes the memcmp will confirm
// against later.
MGPipeApplyCreateSamplerState(desc, &m_entries.back().Params);
MGPipeRouteCreateSamplerState(desc, &m_entries.back().Params);
// THE CREATE ACTUALLY WENT OUT, so the publication latch is taken here and nowhere
// else (contract-v2 §3.1). It is what the six death helpers read, and without it a
// delete_sampler_state can never go out for this kind.
@@ -490,7 +491,7 @@ namespace MobileGL::MG_Pipe {
// only then does the slot go back. There is no NotifyStateObjectDestroyed step
// here - a content-addressed CSO has no frontend object whose death is being
// announced, which is precisely why this eviction is the only death path it has.
MGPipeApplyDeleteSamplerState(handle);
MGPipeRouteDeleteSamplerState(handle);
// AND THE LATCH GOES WITH THE DELETE. This is the "an emitter that drops a record
// for its own reasons calls MGPipeNoteHandleUnpublished" half of the publication
// protocol (contract-v2 §3.1): the record is gone, so a death helper reaching this
@@ -783,7 +784,7 @@ namespace MobileGL::MG_Pipe {
m_lastViews.Start = 0;
m_lastViews.Count = count;
m_lastViews.ContentHash = hash;
MGPipeApplySetSamplerViews(m_lastViews, m_views.data());
MGPipeRouteSetSamplerViews(m_lastViews, m_views.data());
++m_viewSets;
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::SamplerViewEmissions, 1);
@@ -857,7 +858,7 @@ namespace MobileGL::MG_Pipe {
m_lastStates.Start = 0;
m_lastStates.Count = count;
m_lastStates.ContentHash = hash;
MGPipeApplyBindSamplerStates(m_lastStates, m_states.data());
MGPipeRouteBindSamplerStates(m_lastStates, m_states.data());
++m_stateSets;
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::SamplerStateEmissions, 1);
@@ -914,7 +915,7 @@ namespace MobileGL::MG_Pipe {
m_lastView.NumLayers = static_cast<Uint16>(texture.GetViewNumLayers());
m_lastView.Samples = static_cast<Uint16>(texture.GetSamples() < 0 ? 0 : texture.GetSamples());
m_lastView.FixedSampleLocations = texture.HasFixedSampleLocations() ? 1 : 0;
MGPipeApplyCreateSamplerView(m_lastView);
MGPipeRouteCreateSamplerView(m_lastView);
// THE CREATE WENT OUT, so the publication latch is taken (contract-v2 §3.1). The
// texture's death helper reads it, and without it delete_sampler_view can never go
// out - the C-1 leak, one kind later. Re-taking it on a re-issue is right and
+13 -5
View File
@@ -57,6 +57,7 @@
#include <MG_Impl/Pipe/SlotAllocator.h>
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_Pipe/PipeMutation.h>
#include <MG_State/GLState/Core.h>
#include <MG_State/GLState/RenderbufferState/RenderbufferObject.h>
@@ -802,7 +803,7 @@ namespace MobileGL::MG_Pipe {
++m_paramSets;
// Not behind MGPipeTextureRecordsReachTheApplier() (see its comment): the call is
// dispatched whenever this emitter runs, so the answer is always a real one.
Bool accepted = MGPipeApplySetTextureParams(params);
Bool accepted = MGPipeRouteSetTextureParams(params);
if (!accepted) {
// THE SELF-HEAL, the respecify path's shape, and the parameters are the one
// publication that may be a texture's FIRST: the context's default textures are
@@ -828,7 +829,7 @@ namespace MobileGL::MG_Pipe {
// across it - `entry` is re-fetched below.
EmitResourceRespecify(texture, MGPipeTextureRespecifyScope::WholeResource, 0, 0);
}
accepted = MGPipeApplySetTextureParams(params);
accepted = MGPipeRouteSetTextureParams(params);
}
Entry& latched = EntryFor(m_textures, handle);
if (!accepted) {
@@ -1121,7 +1122,7 @@ namespace MobileGL::MG_Pipe {
Bool dispatched = false;
if constexpr (MGPipeTextureRecordsReachTheApplier()) {
dispatched = true;
accepted = MGPipeApplyResourceCreate(desc);
accepted = MGPipeRouteResourceCreate(desc);
}
if (dispatched && !accepted) return;
MGPipeNoteHandlePublished(kind, handle);
@@ -1134,7 +1135,7 @@ namespace MobileGL::MG_Pipe {
// replaces no storage at all.
static Bool ApplyRespecify(const MGPResourceDesc& desc, const MGPRespecifiedLevel* level) {
if constexpr (MGPipeTextureRecordsReachTheApplier()) {
return MGPipeApplyResourceRespecify(desc, nullptr, level);
return MGPipeRouteResourceRespecify(desc, nullptr, level);
}
(void)level;
return false;
@@ -1275,7 +1276,14 @@ namespace MobileGL::MG_Pipe {
Bool dispatched = false;
if constexpr (MGPipeTextureRecordsReachTheApplier()) {
dispatched = true;
accepted = MGPipeApplyResourceSubData(m_lastSubData, shadow,
// `levelBytes` closes CONTRACT-P5 table 1 row 7's open half. The record still
// declares Blob.Size 0 on the monolith arm - where the applier reads the
// companion pointer and the destination box bounds the write - but under split
// the staged run needs a length, and the comment above already says what it
// is: "the bytes this record declares ARE the level shadow". The regions' own
// SrcOffsets index into exactly that run.
accepted = MGPipeRouteResourceSubData(m_lastSubData, shadow,
static_cast<Uint64>(levelBytes),
m_regions.empty() ? nullptr : m_regions.data());
}
++m_subDatas;
+6 -5
View File
@@ -43,6 +43,7 @@
#include <MG_Impl/Pipe/Tracker.h>
#include <MG_Pipe/MGPipe.h>
#include <MG_Pipe/PipeApply.h>
#include <MG_Pipe/PipeRoute.h>
#include <MG_State/GLState/Core.h>
#include <MG_Util/Metrics/PipeStats.h>
@@ -158,7 +159,7 @@ namespace MobileGL::MG_Pipe {
const auto& vao = ctx.GetBoundVertexArray();
if (!vao) {
if (!MGPipeHandleIsNull(m_boundHandle)) {
MGPipeApplyBindVertexElements(HandleOnly(kMGPipeNullHandle));
MGPipeRouteBindVertexElements(HandleOnly(kMGPipeNullHandle));
++m_binds;
m_boundHandle = kMGPipeNullHandle;
m_boundLifetimeId = 0;
@@ -178,7 +179,7 @@ namespace MobileGL::MG_Pipe {
latch.Gen != handle.Gen;
if (configMoved) bytes += EmitCreate(*vao, handle, latch, configVersion);
if (lifetimeId != m_boundLifetimeId || m_boundHandle != handle) {
MGPipeApplyBindVertexElements(HandleOnly(handle));
MGPipeRouteBindVertexElements(HandleOnly(handle));
++m_binds;
bytes += sizeof(MGPHandleOnly);
m_boundHandle = handle;
@@ -242,7 +243,7 @@ namespace MobileGL::MG_Pipe {
// emulation is server-owned.
m_lastBuffers.BaseInstance = baseInstance;
m_lastBuffers.ContentHash = hash;
MGPipeApplySetVertexBuffers(m_lastBuffers, m_entries.data());
MGPipeRouteSetVertexBuffers(m_lastBuffers, m_entries.data());
++m_bufferSets;
return sizeof(MGPVertexBuffers) + static_cast<Uint64>(count) * sizeof(MGPVertexBuffer);
}
@@ -267,7 +268,7 @@ namespace MobileGL::MG_Pipe {
MGPipeResourceTrackerInstance().NoteBoundAs(m_lastIndex.Res, BufferTarget::Index);
}
}
MGPipeApplySetIndexBuffer(m_lastIndex);
MGPipeRouteSetIndexBuffer(m_lastIndex);
++m_indexSets;
return sizeof(MGPIndexBuffer);
}
@@ -396,7 +397,7 @@ namespace MobileGL::MG_Pipe {
m_lastElements.Blob.Seg = kMGHostSpanSegNone;
m_lastElements.Blob.Offset = 0;
m_lastElements.Blob.Size = kAttribBytes + kBindingBytes;
MGPipeApplyCreateVertexElements(m_lastElements, m_blob.data());
MGPipeRouteCreateVertexElements(m_lastElements, m_blob.data());
++m_creates;
latch.Published = true;
latch.Gen = handle.Gen;