[Refactor] (P13 W5 S8): MOBILEGL_BUILD_RECORD_ARM is folded away - the record arm is unconditional - and retired_switches keeps it from coming back.

This commit is contained in:
2026-10-06 15:03:11 -04:00
parent a0b9ca0772
commit 7fb18840dc
91 changed files with 46 additions and 2725 deletions
-185
View File
@@ -18,12 +18,10 @@
// needs only the name - the deleter is captured where the archive is constructed - but the
// program build reads through it, so the one translation unit that does needs the whole type.
#include <MG_State/GLState/ProgramState/ProgramArtifactsCodec.h>
#if MOBILEGL_BUILD_RECORD_ARM
// R-11's server-owned staging copy. Header-only and package v1's; see its own header block for
// why GLESBufferResource does not simply gain a member.
#include <MG_Backend/Record/StagedShadow.h>
#include <MG_Backend/Record/StagedTextureStore.h>
#endif
#if MOBILEGL_BUILD_DISAGGREGATED
#include <MG_Remote/Server/ServerLoop.h>
// P5c (ct): object_death's producer (CONTRACT-P5C.md §5.2) - the death notice's split arm
@@ -1256,7 +1254,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return StorageMatchesSize(resource, bufferObject.GetSize());
}
#if MOBILEGL_BUILD_RECORD_ARM
// -------------------------------------------------------------------------------
// R-11 - THE SERVER'S OWN COPY OF THE STAGED BYTES. Package v1.
//
@@ -1304,7 +1301,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
ServerStaged().RequireCoverage(&resource, hostBase, start, end, site);
}
}
#endif // MOBILEGL_BUILD_RECORD_ARM
#if MOBILEGL_BUILD_DISAGGREGATED
// -------------------------------------------------------------------------------
@@ -1385,7 +1381,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// The four hostBytes sites read the same in both builds. The non-split expansion is the
// ORIGINAL EXPRESSION, character for character - `raw - offset` - so a push or verify build
// compiles exactly what it compiled before R-11 and the split arm is the only new behaviour.
#if MOBILEGL_BUILD_RECORD_ARM
#define MGL_SERVER_STAGED_ADOPT(res, width, bytes, offset, size) \
ServerStaged().Adopt(&(res), (width), (bytes), (offset), (size))
#define MGL_SERVER_STAGED_DROP(res) ServerStaged().Drop(&(res))
@@ -1394,14 +1389,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
ServerStaged().RequireCoverage(&(res), (base), (start), (end), (site))
#define MGL_SERVER_STAGED_REQUIRE_PENDING(res, base, frontendSize, site) \
RequireStagedCoverageForPendingRanges((res), (base), (frontendSize), (site))
#else
#define MGL_SERVER_STAGED_ADOPT(res, width, bytes, offset, size) \
(static_cast<const Uint8*>(bytes) - (offset))
#define MGL_SERVER_STAGED_DROP(res) ((void)0)
#define MGL_SERVER_STAGED_DROP_ALL() ((void)0)
#define MGL_SERVER_STAGED_REQUIRE(res, base, start, end, site) ((void)0)
#define MGL_SERVER_STAGED_REQUIRE_PENDING(res, base, frontendSize, site) ((void)0)
#endif
// The host bytes a range upload/flush reads. On the legacy arm the frontend object's
// shadow; on the handle arm the base the last content-carrying call handed over.
@@ -1410,9 +1397,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
if (start >= end || hostBase == nullptr) return;
#if MOBILEGL_BUILD_RECORD_ARM
MGL_SERVER_STAGED_REQUIRE(resource, hostBase, start, end, "upload_range");
#endif
BindBufferId(TempBufferTarget, resource.id);
g_GLESFuncs.glBufferSubData(TempBufferTarget, (GLintptr)start, (GLsizeiptr)(end - start),
hostBase + start);
@@ -1987,9 +1972,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto* glesResource = static_cast<GLESBufferResource*>(resource.get());
if (glesResource->contextGeneration != g_bufferContextGeneration) {
glesResource->id = 0; // id belonged to a destroyed context
#if MOBILEGL_BUILD_RECORD_ARM
RetireT0Import(*glesResource); // P11 B2: its GL store died with that context
#endif
return;
}
if (CanTouchGLNow()) {
@@ -2005,10 +1988,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glDeleteBuffers(1, &glesResource->id);
glesResource->id = 0;
}
#if MOBILEGL_BUILD_RECORD_ARM
// P11 B2: a T0 store's AHardwareBuffer goes only after a fence behind the delete.
RetireT0Import(*glesResource);
#endif
return;
}
const std::lock_guard<std::mutex> lock(g_deferredBufferReleasesMutex);
@@ -2112,7 +2093,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
void Ops_H_Respecify(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPResourceDesc& desc,
const void* initialBytes) {
auto* resource = FindBufferResourceForHandle(res);
#if MOBILEGL_BUILD_RECORD_ARM
// P13 W4a (§1.4): ON MONOLITH'S RECORD ARM THE TWIN IS MINTED HERE, not lazily at
// the first draw. The record arm's readers have no frontend object to re-read a
// base from, so the base this call carries - the client's shadow, for an orphaning
@@ -2122,9 +2102,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (resource == nullptr && aliasesFrontend && initialBytes != nullptr) {
resource = GetOrCreateBufferResourceForHandle(res);
}
#else
constexpr Bool aliasesFrontend = false;
#endif
if (resource != nullptr) {
// A respecify's companion pointer IS the shadow base (offset 0) - and an
// ORPHANING one (glBufferData with NULL) carries HasDefinedContent clear and
@@ -2155,11 +2132,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGL_SERVER_STAGED_DROP(*resource);
resource->hostBytes = nullptr;
}
#if MOBILEGL_BUILD_RECORD_ARM
// P8-C: whatever a shader wrote belonged to the store this call replaces.
resource->serverGpuWritten = false;
resource->contentSinceRespecify = false;
#endif
}
if (!resource) return; // lazy: the ensure path full-uploads on creation
if (resource->immutableStorage) {
@@ -2178,13 +2153,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
resource->id = 0;
resource->immutableStorage = false;
}
#if MOBILEGL_BUILD_RECORD_ARM
// P11 B2: a respecified T0 store ends here on the server's side too. Its
// AHardwareBuffer is released only after a fence behind the delete (or at once
// when the store's context is already gone) - never under a frame in flight,
// however the client's own release (at this respecify) raced it.
RetireT0Import(*resource);
#endif
resource->storageInitialized = false;
resource->storageSize = 0;
resource->pendingRespecify = true;
@@ -2219,7 +2192,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
const SizeT offset = static_cast<SizeT>(MG_Pipe::MGPipeSubDataBufferOffset(record));
const SizeT size = static_cast<SizeT>(MG_Pipe::MGPipeSubDataBufferSize(record));
auto* resource = FindBufferResourceForHandle(res);
#if MOBILEGL_BUILD_RECORD_ARM
// R-11 / ID-52 item 3: under an ACTIVE TRANSPORT this record's bytes are the ONLY
// delivery of the buffer's content - the client sends no companion pointer and the
// server has no MappedData to fall back on. But the twin is created LAZILY at the
@@ -2233,9 +2205,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Config::DataArmIsRecord()) {
resource = GetOrCreateBufferResourceForHandle(res);
}
#endif
if (!resource) return;
#if MOBILEGL_BUILD_RECORD_ARM
// P11 B2: A T0 STORE TAKES A SERVER-ORIGINATED WRITE GPU-ORDERED. Its pages are the
// client's AHardwareBuffer, so there is no staged copy to refresh and the adopted
// early return below ("the coherent map already has the bytes") is false for bytes
@@ -2294,7 +2264,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (resource != nullptr) resource->serverGpuWritten = true;
return;
}
#endif
// M-2: UNDER pendingMutex, because this line runs BEFORE the CanTouchGLNow()
// test below - i.e. on the arm D-A2 deliberately keeps reachable off the render
// thread - while every reader of hostBytes (Ops_H_Readback's drain, the
@@ -2317,9 +2286,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
// ("these bytes, at this base") and the drain takes this mutex to lift them.
resource->hostBytes =
MGL_SERVER_STAGED_ADOPT(*resource, ResourceWidthOf(res), bytes, offset, size);
#if MOBILEGL_BUILD_RECORD_ARM
if (size != 0) resource->contentSinceRespecify = true;
#endif
}
if (resource->pendingRespecify) return; // full re-upload pending anyway
if (!CanTouchGLNow() || resource->id == 0 ||
@@ -2380,9 +2347,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const std::lock_guard<std::mutex> lock(resource->pendingMutex);
resource->hostBytes = MGL_SERVER_STAGED_ADOPT(*resource, ResourceWidthOf(res), bytes,
start, end - start);
#if MOBILEGL_BUILD_RECORD_ARM
if (end > start) resource->contentSinceRespecify = true;
#endif
}
if (resource->pendingRespecify) return;
if (!CanTouchGLNow() || resource->id == 0 ||
@@ -2413,14 +2378,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
#if MOBILEGL_BUILD_RECORD_ARM
// The kill-switch arm's own Memcpy, and the one that passes
// GL_MAP_INVALIDATE_RANGE_BIT - i.e. the one that tells the driver the old
// bytes are dead. Bytes outside the staged coverage are exactly the ones
// that claim is false for.
MGL_SERVER_STAGED_REQUIRE(*resource, resource->hostBytes, start, end,
"flush_range_invalidate_map");
#endif
BindBufferId(TempBufferTarget, resource->id);
void* mappedData = g_GLESFuncs.glMapBufferRange(
TempBufferTarget, (GLintptr)start, (GLsizeiptr)(end - start),
@@ -2440,15 +2403,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
void Ops_H_Readback(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPReadback& record) {
#if MOBILEGL_BUILD_RECORD_ARM
// An empty capture may conservatively request a writeback before
// any draw materialized this buffer. Resolve its staged resource
// exactly as a GPU consumer would, then return the real bytes.
auto* resource = MG_Config::DataArmIsRecord()
? EnsureBufferResourceForHandle(nullptr, res) : FindBufferResourceForHandle(res);
#else
auto* resource = FindBufferResourceForHandle(res);
#endif
if (!resource || resource->id == 0 || !resource->storageInitialized) return;
if (!CanTouchGLNow() || resource->contextGeneration != g_bufferContextGeneration) return;
if (resource->persistentMapped) {
@@ -2517,7 +2476,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// The shadow now matches the backend byte for byte; without this the next draw
// would see a newer serial and re-upload the readback over it.
resource->syncedChangeSerial = ResourceSerialOf(res);
#if MOBILEGL_BUILD_RECORD_ARM
// P13 W4a: on monolith's record arm the base this twin reads IS the shadow the
// writeback just filled, so a whole-store readback is also the refresh
// SplitHostBytesForCpuRead would owe. (A copying store's copy is not the
@@ -2525,7 +2483,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (MG_Config::RecordArmAliasesFrontend() && readOffset == 0 && size >= ResourceWidthOf(res)) {
resource->serverGpuWritten = false;
}
#endif
}
void Ops_H_Destroy(MG_Pipe::MGPipeHandle res) {
@@ -3052,7 +3009,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
#endif // MOBILEGL_BUILD_DISAGGREGATED && __ANDROID__
#if MOBILEGL_BUILD_RECORD_ARM
// ---- P5c (tx): the TEXTURE half of the resource family, staged server-side --------
//
// The buffer half's R-11 pattern (ServerStaged() above), for texture levels: the
@@ -3110,7 +3066,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// disaggregation did not compile. The narrower fix (guarding the macro block too) is wrong:
// that block also carries TextureDiagName and MGB_TEXTURE_RECORD_ARM_SELECTED, which the push
// flavour does need. Caught by the `flavours` gate step; see ID-124.
#endif // MOBILEGL_BUILD_RECORD_ARM
// The inverse of MG_Pipe::MGPipeResourceTargetForTextureTarget, for the sync's
// target reads (ConvertTextureTargetToBackendGLEnum and MapToBackendTextureTarget
// both want the frontend enum).
@@ -3130,7 +3085,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
default: return TextureTarget::Unknown;
}
}
#if MOBILEGL_BUILD_RECORD_ARM
void Ops_H_TextureSubData(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPSubData& record,
const void* bytes, const MG_Pipe::MGPSubRegion* regions) {
@@ -3232,7 +3186,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Record::ServerStagedTexture().Drop(
MG_Record::StagedTextureStore::KeyForHandle(res));
}
#endif // MOBILEGL_BUILD_RECORD_ARM
const MG_Pipe::MGPipeResourceOps g_glesResourceOps = {
.Create = Ops_H_Create,
@@ -3244,7 +3197,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
.Destroy = Ops_H_DestroyTracked,
.MapPersistent = Ops_H_MapPersistentTracked,
.UnmapPersistent = Ops_H_UnmapPersistent,
#if MOBILEGL_BUILD_RECORD_ARM
.TextureSubData = Ops_H_TextureSubData,
.TextureRespecify = Ops_H_TextureRespecify,
.TextureDestroy = Ops_H_TextureDestroy,
@@ -3252,7 +3204,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// P11 B2 (T0). Android only: nowhere else is there an AHardwareBuffer to import.
.ImportExternal = Ops_H_ImportExternalTracked,
.SelfTestExternal = Ops_H_SelfTestExternal,
#endif
#endif
};
@@ -3512,7 +3463,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return twin ? twin->get() : nullptr;
}
#if MOBILEGL_BUILD_RECORD_ARM
void RequireStagedCoverage(GLESBufferResource& resource, const Uint8* hostBase, SizeT start,
SizeT end, const char* site) {
ServerStaged().RequireCoverage(&resource, hostBase, start, end, site);
@@ -3678,7 +3628,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
const std::lock_guard<std::mutex> lock(resource.pendingMutex);
resource.hostBytes = MGL_SERVER_STAGED_ADOPT(resource, ResourceWidthOf(res), bytes, offset, size);
}
#endif
MG_Pipe::MGPipeHandle HandleOfBuffer(const MG_State::GLState::BufferObject* bufferObject) {
if (bufferObject == nullptr) return MG_Pipe::kMGPipeNullHandle;
@@ -3690,7 +3639,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// allocator probe on a miss - and remembers the answer, which the minting overload
// was previously the only writer of. A null answer is deliberately never memoised
// (see the comment at HandleOf).
#if MOBILEGL_BUILD_RECORD_ARM
// P5c merge coordination (CONTRACT-P5C §3.1's named exemption): every caller of
// this function is a site whose handle-carrying records (set_shader_buffers /
// set_stream_output_targets) the client does not emit until sb, so the probe
@@ -3706,7 +3654,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// IsBufferDrawCleanByHandle / MarkBufferGpuWrittenByHandle, which is the last
// caller set this function has.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
return g_backendBufferResources.HandleOf(bufferObject);
}
@@ -3816,7 +3763,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// generation, and a shadow that outlived its twin would be looked up by a RECYCLED
// address on the next allocation - which is the quietest possible wrong answer.
MGL_SERVER_STAGED_DROP_ALL();
#if MOBILEGL_BUILD_RECORD_ARM
// tx's texture shadows die for the same reason, keyed by handle rather than address
// but with the same recycled-identity failure mode: a new context's allocator may
// hand out a {slot, gen} the old one's store still answers for.
@@ -3827,7 +3773,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
#if MOBILEGL_BUILD_DISAGGREGATED
ProcessDeferredT0Retires();
SweepT0Retired(/*contextGone=*/true);
#endif
#endif
}
@@ -3929,11 +3874,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
const auto* record = ResourceRecordOf(res);
if (record == nullptr) return false;
#if MOBILEGL_PIPE_VERIFY && !MOBILEGL_BUILD_RECORD_ARM
MOBILEGL_ASSERT(!record->HasLiveHostWrites,
"MGPipeResourceRecord::HasLiveHostWrites is set, but this build has no producer "
"for it - P5 b1's producer is MGPSubData::HasLiveHostWrites and is split-only");
#endif
if (record->HasLiveHostWrites) return false;
// THE LAST FRONTEND READ IN THIS FUNCTION, AND P5 b1 RETIRES IT - under split
// only, because that is the only build where it is both wrong and replaceable.
@@ -4012,7 +3952,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// fallback for the drains that have NO object (the readback flush), and it is
// nulled at both of those events.
const auto liveHostBase = [&resource, &bufferObject]() -> const Uint8* {
#if MOBILEGL_BUILD_RECORD_ARM
// M-2 / codex 3 / ID-52 item 3: under an ACTIVE TRANSPORT the server's staged
// copy (resource->hostBytes, filled by MGL_SERVER_STAGED_ADOPT in Ops_H_SubData /
// Ops_H_FlushRange) is the ONLY authoritative base. Preferring the frontend
@@ -4024,7 +3963,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (MG_Config::DataArmIsRecord()) {
return resource->hostBytes;
}
#endif
if (bufferObject) return bufferObject->MappedData();
return resource->hostBytes;
};
@@ -4041,7 +3979,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
resource->persistentMapped = false;
resource->persistentPtr = nullptr;
resource->immutableStorage = false;
#if MOBILEGL_BUILD_RECORD_ARM
// m-5 / codex 5: OnBackendContextDestroyed ran MGL_SERVER_STAGED_DROP_ALL(), which
// frees every server shadow but does NOT null the hostBytes that name them - so a
// twin that SURVIVES a context loss still carries a base into the freed allocation.
@@ -4084,7 +4021,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
RetireT0Import(*resource);
}
}
#endif
#endif
}
@@ -4129,12 +4065,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// application ORPHANED the gap is its own undefined content and the upload is
// legal (ResourceContentIsDeclared, above). RequireCoverage is a no-op for the
// legacy arm's MappedData() and for a non-copying store.
#if MOBILEGL_BUILD_RECORD_ARM
if (ResourceContentIsDeclared(res)) {
MGL_SERVER_STAGED_REQUIRE(*resource, liveHostBase(), 0, poolSize,
"pool_reuse_whole_store");
}
#endif
g_GLESFuncs.glBufferSubData(TempBufferTarget, 0, (GLsizeiptr)poolSize, liveHostBase());
if (MG_Util::PipeStats::Enabled()) {
MG_Util::PipeStats::AddBytes(MG_Util::PipeStats::ByteClass::StageBuffer,
@@ -4161,7 +4095,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// D-N keeps this call here for P3a. It can queue ranges and move the record, so
// everything below is read AFTER it.
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (hd, CONTRACT-P5C §3.8): under an active transport the frontend accessor is a
// layer-1 surface ("buffer-legacy-arm") and the client's own pre-verb
// persistent-map push is the only producer; the call is skipped outright. Under
@@ -4169,9 +4102,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (bufferObject && !MG_Config::DataArmIsRecord()) {
bufferObject->SyncPersistentMappedRange();
}
#else
if (bufferObject) bufferObject->SyncPersistentMappedRange();
#endif
const auto* record = ResourceRecordOf(res);
const SizeT size = record != nullptr ? static_cast<SizeT>(record->Desc.Width) : 0;
@@ -4214,13 +4144,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
// the last orphan". With no coverage and a clear bit the store is undefined by the
// application's own declaration and the upload stays a pure NULL reallocation.
const Bool shadowHasContent =
#if MOBILEGL_BUILD_RECORD_ARM
MG_Config::DataArmIsRecord()
? (record->Desc.HasDefinedContent != 0 ||
(ServerStaged().CopiesIntoServerStorage() ? ServerStaged().CoveredRunCount(resource) != 0
: resource->contentSinceRespecify))
:
#endif
(bufferObject ? bufferObject->HasDefinedContent() : (record->Desc.HasDefinedContent != 0));
const void* initialData = shadowHasContent ? hostBase : nullptr;
// M-3 / codex 4: a RespecifyStorageWith(..., initialData != nullptr) is a WHOLE-STORE
@@ -4235,14 +4163,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// the bytes it did not write are undefined by its own glBufferData(NULL) - the rule at
// ResourceContentIsDeclared. Round 2 refused that idiom and aborted six joint entries.
const auto requireWholeStoreCoverage = [&]() {
#if MOBILEGL_BUILD_RECORD_ARM
if (initialData != nullptr && record->Desc.HasDefinedContent != 0) {
MGL_SERVER_STAGED_REQUIRE(*resource, static_cast<const Uint8*>(initialData), 0,
size, "respecify_whole_store");
}
#else
(void)initialData;
#endif
};
if (resource->pendingRespecify || !resource->storageInitialized || resource->storageSize != size) {
@@ -4942,7 +4866,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return true;
}
#if MOBILEGL_BUILD_RECORD_ARM
// THE SAFETY ARGUMENT P4a MADE AND NEVER RAN (P3b/P4b espryt D1 slice 5).
//
// "Running the legacy arm" is a real answer in a monolith and a POSTPONED CRASH under a
@@ -4974,7 +4897,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
bit, detail);
BufferImpl::StopOnArmlessPipeSubsystem(what);
}
#endif
// The release-build VOICE for StateBackendObjectRegistry::GetOrCreateByHandle's two
// silent refusals, shared by the kinds P4a re-keys so the wording cannot drift between
@@ -5096,7 +5018,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemFramebuffer (bit 9) clear (or refuses "
"it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables the pre-handle g_fboSynced* arm");
}
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord() &&
verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) {
StopOnTransportWithoutRecordArm(
@@ -5107,7 +5028,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"to reach it would raise Fatal{UnmigratedPipeInput, "
"\"GetFramebufferBindingSlot@<verb>\"} mid-frame instead");
}
#endif
const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles;
MGLOG_D("MGPipe: Espryt framebuffer family runs the %s arm", enabled ? "handle" : "legacy");
return enabled;
@@ -5141,7 +5061,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"refuses it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables the pre-handle texture "
"cheap-gate trio");
}
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord() &&
verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) {
StopOnTransportWithoutRecordArm(
@@ -5150,7 +5069,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"objects and their binding slots, which under a transport are client memory (rule "
"E) rather than anything this side owns");
}
#endif
const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles;
MGLOG_D("MGPipe: Espryt texture-resource family runs the %s arm", enabled ? "handle" : "legacy");
return enabled;
@@ -5177,7 +5095,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"it) and MOBILEGL_PIPE_LEGACY_MEMOS=0 disables UnitSamplerLookupMemo's WeakPtr "
"arm and SamplerPassMemo's raw-pointer rows");
}
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord() &&
verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) {
StopOnTransportWithoutRecordArm(
@@ -5187,7 +5104,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"this side to key on - a WeakPtr that can never lock is not a slower arm, it is a "
"unit that samples through whatever it last held");
}
#endif
const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles;
MGLOG_D("MGPipe: Espryt sampler family runs the %s arm", enabled ? "handle" : "legacy");
return enabled;
@@ -5206,7 +5122,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"MOBILEGL_PIPE_PUSH leaves kMGPipeSubsystemPrograms (bit 12) clear and "
"MOBILEGL_PIPE_LEGACY_MEMOS=0 disables g_programTwinLookupMemo");
}
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord() &&
verdict != BufferImpl::PipeSubsystemArmVerdict::Handles) {
StopOnTransportWithoutRecordArm(
@@ -5216,7 +5131,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
"ShaderCso handle with its archive beside the record and there is no frontend "
"program here at all");
}
#endif
const Bool enabled = verdict == BufferImpl::PipeSubsystemArmVerdict::Handles;
MGLOG_D("MGPipe: Espryt program family runs the %s arm", enabled ? "handle" : "legacy");
return enabled;
@@ -5487,11 +5401,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// MGPipeSlots().FindByLifetimeId, which is a hash lookup. HandleOf answers
// identically - the same allocator probe on a miss - and remembers the answer; a
// null answer is deliberately never memoised (SlotTables.h, at HandleOf).
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named debt inside
// the scope - P3b/P4b rekeys the sampler-view registry onto handles.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
return g_backendSamplerViews.HandleOf(textureObject);
}
} // namespace SamplerViewImpl
@@ -6366,15 +6278,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
// recorded shadow base for such a resource read freed memory; hostBytes is nulled
// at adoption for the same reason, so the fallback below is a null and a refusal
// rather than a stale read.
#if MOBILEGL_BUILD_RECORD_ARM
const Bool sourceGpuWritten =
MG_Config::DataArmIsRecord() && resource->serverGpuWritten;
if (sourceGpuWritten) {
BufferImpl::SplitHostBytesForCpuRead(*resource, binding.Res, "fp64_vertex_narrowing");
}
#else
constexpr Bool sourceGpuWritten = false;
#endif
const Uint8* const sourceBase =
(resource->persistentMapped && resource->persistentPtr != nullptr)
? static_cast<const Uint8*>(resource->persistentPtr)
@@ -6553,7 +6461,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (m_imageBindableStorageRequired) {
return;
}
#if MOBILEGL_BUILD_RECORD_ARM
// P13 W4b (defect h): monolith's record arm takes the body too; its old arm only
// cleared m_isInitialized and replayed the frontend shadow at the next sync.
if (MG_Config::DataArmIsRecord()) {
@@ -6704,10 +6611,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::PipeStats::AddCalls(MG_Util::PipeStats::CallClass::TextureRemintPulls, 1);
}
}
#else
(void)res;
(void)record;
#endif
// Every defined byte now belongs to the server and every required
// replay is in its pending set. The existing upload path builds and
// fills the immutable/widened carrier from those records.
@@ -6948,11 +6851,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
const MG_Pipe::MGPipeHandle rearmRes =
TextureResourceSubsystemEnabled()
? [&]() {
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed resolution, named
// debt inside the scope - P3b/P4b rekeys the registry.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
return g_backendTextureObjects.HandleOf(stateTextureObject.get());
}()
: MG_Pipe::kMGPipeNullHandle;
@@ -7171,11 +7072,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
static inline GLint s_skipImages = 0;
};
#if MOBILEGL_BUILD_RECORD_ARM
void ExerciseDefaultUnpackScopeForTesting() {
const ScopedDefaultUnpackState scope;
}
#endif
// --- Unpack-ring staging (see BufferImpl::UnpackRingAvailable) ---------------
// One rectangular (or whole-level) region of a level shadow, repacked TIGHTLY
@@ -7859,12 +7758,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
// read). Sites that were previously correct only because every writer of a handle-note happens
// to be transport-gated now say so themselves, so a future by-handle noter cannot quietly
// re-open ID-107's hole somewhere else.
#if MOBILEGL_BUILD_RECORD_ARM
#define MGB_TEXTURE_RECORD_ARM_SELECTED() \
(MG_Config::DataArmIsRecord() && TextureResourceSubsystemEnabled())
#else
#define MGB_TEXTURE_RECORD_ARM_SELECTED() (false)
#endif
// Returns true when the caller must decline (no handle noted: the caller's bug it always
// was, named by the caller's own log line), false when the record arm can serve the call,
@@ -8017,7 +7912,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
StampViewSyncKeys(stateTextureObject);
}
#if MOBILEGL_BUILD_RECORD_ARM
// P5e (tx2): see the declaration for the split between what the record answers and what
// the wire still cannot say about a view.
void BackendTextureObject::SyncTextureViewToBackendByRecord(
@@ -8102,7 +7996,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// The storage's, for the steady arm's reason above (P3b/P4b D3).
m_syncedResourceSerial = storageSerial;
}
#endif
// P4a (D-D5), the dirty-ownership inversion, applied at the two places the upload loops
// below actually ask: "does this (uploadTarget, level) owe an upload" and "it has been
@@ -8126,7 +8019,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// pre-P4a expression exactly when MOBILEGL_PIPE_PUSH is off, so the pull build's
// preprocessed text, and therefore its object code, is unchanged. Both are #undef'd
// immediately after the function.
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (tx): THE READS THE FOUR UPLOAD ARMS MAKE, re-sourced. With an active transport the
// apply thread may not name the client's TextureObjectMipmap at all (rule E), so on the
// handle arm:
@@ -8172,15 +8064,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Record::StagedTextureStore::KeyForHandle(pushedRes), static_cast<Uint16>(tgt), \
static_cast<Uint16>(lvl), site) \
: (obj)->MapMipmapData(tgt, lvl))
#else
#define MGB_TEXTURE_TARGET(obj) ((obj)->GetTarget())
#define MGB_UPLOAD_TARGETS(obj) ((obj)->GetUploadTargets())
#define MGB_LEVEL_TEXEL_SIZE(obj, tgt, lvl) ((obj)->GetMipmapTexelSize(tgt, lvl))
#define MGB_LEVEL_BYTE_SIZE(obj, tgt, lvl) ((obj)->GetMipmapByteSize(tgt, lvl))
#define MGB_LEVEL_TEXELS(obj, tgt, lvl, site) ((obj)->MapMipmapData(tgt, lvl))
#endif
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (tx): the disaggregated pair adds ONE term and ONE clear to the P4a shapes - the
// staged-texture store's GPU-dirty mark (T5: a level the GPU generated dirties the SERVER's
// shadow, and the pending set cannot see it). The mark is never set on Espryt today - its
@@ -8210,23 +8094,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
(obj)->MarkStorageDirty(tgt, lvl, false); \
} \
} while (0)
#else
#define MGB_LEVEL_NEEDS_UPLOAD(obj, tgt, lvl) \
(pushedStorage != nullptr \
? FindPipeTextureUpload(*pushedStorage, static_cast<Uint16>(tgt), static_cast<Uint16>(lvl)) != nullptr \
: (obj)->IsStorageDirty(tgt, lvl))
// Re-resolves the record itself, so it is safe after any amount of driver work - and it
// invalidates any PendingUpload* taken earlier for THIS texture, which is why every such pointer
// is used and dropped inside one level's iteration.
#define MGB_LEVEL_UPLOAD_DONE(obj, tgt, lvl) \
do { \
if (pushedStorage != nullptr) { \
ConsumePipeTextureUpload(pushedRes, static_cast<Uint16>(tgt), static_cast<Uint16>(lvl)); \
} else { \
(obj)->MarkStorageDirty(tgt, lvl, false); \
} \
} while (0)
#endif
// THE STORAGE SHAPE, and on the handle arm it is the DESCRIPTOR's (C.3's d2: "the
// m_prevTextureInfo probe re-keyed onto the resource record's Serial AND Desc"; review
@@ -8480,7 +8347,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return;
}
}
#if MOBILEGL_BUILD_RECORD_ARM
#if MOBILEGL_BUILD_DISAGGREGATED
// SHARED IMAGES: ahead of the view test and of the staged-store and serial gates below,
// none of which knows the texels belong to an image - the staged store holds none of
@@ -8515,7 +8381,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (MG_Config::DataArmIsRecord() && pushedStorage != nullptr) {
// Not a view: fall through to the storage body with the frontend test skipped.
} else
#endif
// A texture created by glTextureView owns no storage: the levels, the format and
// every texel belong to the texture it views, and this name only has to be made to
// ALIAS them. Everything below - storage allocation, respecification, per-level
@@ -8563,14 +8428,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
pushedStorage->Desc.ImageBindableHint != 0 ||
(pushedStorage->Desc.BindMask & MG_Pipe::kMGPipeBindShaderImage) != 0;
if (pushedWantsImageBindableStorage && !m_imageBindableStorageRequired) {
#if MOBILEGL_BUILD_RECORD_ARM
// P5e (tx2), ruling 1's arm: under a transport the re-dirty half is a NAMED
// refusal at its entry (§5.2) instead of a walk of the client's level shadows;
// the push-monolith build keeps the frontend transition exactly as it is.
if (MG_Config::DataArmIsRecord()) {
RequireImageBindableStorageByHandle(pushedRes, *pushedStorage);
} else
#endif
RequireImageBindableStorage(stateTextureObject);
}
@@ -8638,7 +8501,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// left the backend name with no levels whatsoever, so the level that WAS defined could
// never be sampled or read back. Sync whenever some level holds an image; the per-level
// loops below skip the degenerate ones individually.
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (gt, CONTRACT-P5C §6 layer 1): on the staged arm the same question is answered
// out of the SERVER's staged-texture store, never out of the frontend object - the
// store's Defined-ness (fed by the respecify hook and the sub-data adoption) IS "some
@@ -8679,7 +8541,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
return;
}
} else
#endif
if (!stateTextureObject->IsComplete() && !HasAnyDefinedMipmapLevel(stateTextureObject.get())) {
MGLOG_D("Texture object with ID: %u has no defined image level, skipping sync.",
stateTextureObject->GetExternalIndex());
@@ -9263,7 +9124,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
: nullptr;
const auto dirtyRegion = [&]() -> MG_State::GLState::MipmapDirtyRegion {
if (pendingUpload == nullptr) {
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (tx): a level this arm owes with NO pending upload behind it
// was dirtied by the GPU (T5), and the dirty answer is the
// server's own mark on the staged shadow - the whole level,
@@ -9276,7 +9136,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
static_cast<Uint16>(uploadTarget), static_cast<Uint16>(level));
return MG_State::GLState::MipmapDirtyRegion{IntVec3{0, 0, 0}, gpuExtent};
}
#endif
return textureMipmapObject->GetStorageDirtyRegion(uploadTarget, level);
}
// MGPBox is {origin, extent}; MipmapDirtyRegion is {lo, hi}. The
@@ -9469,13 +9328,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
region.Z + static_cast<Int32>(region.D)}};
}
} else
#if MOBILEGL_BUILD_RECORD_ARM
// tx: with an active transport the rect list is the record's (the
// pendingUpload arm above) or nothing - the server's GPU-dirty mark
// is whole-level and has no scatter refinement to hand out, and the
// frontend's rect model is not this side's to read.
if (!MGB_STAGED_TEXTURE_LIVE)
#endif
dirtyRectCount = textureMipmapObject->GetStorageDirtyRects(
uploadTarget, level, dirtyRects,
MG_State::GLState::MipmapStorage::kMaxDirtyRects);
@@ -9512,14 +9369,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
region.Z + static_cast<Int32>(region.D)}});
}
} else
#if MOBILEGL_BUILD_RECORD_ARM
// With an active transport and no record behind the level, the
// server's own whole-level GPU-dirty mark is the whole story (the
// same reason the rect list above is not read here).
if (MGB_STAGED_TEXTURE_LIVE) {
dirtyFootprint.clear();
} else
#endif
textureMipmapObject->GetStorageDirtyFootprint(uploadTarget, level, dirtyFootprint);
// One box is the union box itself, which the branches below already
// upload exactly (as the whole level when it is the whole level).
@@ -10052,9 +9907,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#undef MGB_LEVEL_TEXEL_SIZE
#undef MGB_LEVEL_BYTE_SIZE
#undef MGB_LEVEL_TEXELS
#if MOBILEGL_BUILD_RECORD_ARM
#undef MGB_STAGED_TEXTURE_LIVE
#endif
// P5e (tx2), CONTRACT-P5E §5.2: THIS TWIN'S OWN RECORD. On the by-handle arm the handle
// is already known - the caller resolved the record before it resolved this twin and
@@ -10066,11 +9919,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Pipe::MGPipeHandle res = m_pushedSyncHandle;
if (MG_Pipe::MGPipeHandleIsNull(res)) {
if (!stateTextureObject) return nullptr;
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed resolution, named debt inside the
// scope - the by-handle arm above is what retires it.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
res = g_backendTextureObjects.HandleOf(stateTextureObject.get());
}
return PipeTextureRecordForHandle(res);
@@ -10687,18 +10538,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
storage = record->Desc.ViewOf;
}
if (auto* twin = ResolveTextureTwin(storage)) twin->NoteDriverSideWrite();
#if MOBILEGL_BUILD_RECORD_ARM
// P8-E: the staged store stops standing for this texture's content (a no-op on a
// monolith arm, where the store does not copy).
if (!storeFollowsTheWrite && !MG_Pipe::MGPipeHandleIsNull(storage)) {
MG_Record::ServerStagedTexture().MarkDriverWritten(
MG_Record::StagedTextureStore::KeyForHandle(storage));
}
#else
(void)storeFollowsTheWrite;
#endif
}
#if MOBILEGL_BUILD_RECORD_ARM
Bool FollowCopyImageInStagedStore(MG_Pipe::MGPipeHandle source, Uint32 sourceLevel, const IntVec3& sourceOrigin,
MG_Pipe::MGPipeHandle destination, Uint32 destinationLevel,
const IntVec3& destinationOrigin, const IntVec3& size) {
@@ -10737,7 +10583,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
destinationTarget, static_cast<Uint16>(destinationLevel), destinationOrigin,
size);
}
#endif
} // namespace TextureImpl
namespace FramebufferImpl {
@@ -10900,11 +10745,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (attachmentObject.IsTexture()) {
const auto& textureObject = attachmentObject.GetTexture();
SharedPtr<TextureImpl::BackendTextureObject> backendTextureObject;
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution (and the mint on
// a first attach), named debt inside the scope - P3b/P4b rekeys the registry.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
if (auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get())) {
backendTextureObject = *backendTextureSlot;
} else {
@@ -10957,11 +10800,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
} else if (attachmentObject.IsRenderbuffer()) {
const auto& renderbufferObject = attachmentObject.GetRenderbuffer();
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution (and the mint on
// a first attach), named debt inside the scope - P3b/P4b rekeys the registry.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject;
if (auto* backendRenderbufferSlot =
RenderbufferImpl::g_backendRenderbufferObjects.Find(renderbufferObject.get())) {
@@ -11295,14 +11136,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
// push-monolith arm keeps the frontend sync it had at f6cfcbd3, token for token,
// because tx2's record arm inside SyncMipmapsToBackend is itself selected by
// `Transport != Monolith` and cannot answer here.
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
backendTextureObject->SyncMipmapsToBackendByHandle(surface.Res);
// From here on every draw, clear and blit into this framebuffer can write the
// texture behind the staged shadow's back (the frontend arm's note, by handle).
TextureImpl::NoteDriverSideTextureWriteByHandle(surface.Res);
} else
#endif
{
const SharedPtr<MG_State::GLState::ITextureObject> monolithTexture =
(monolithAttachment != nullptr && monolithAttachment->IsTexture())
@@ -11384,11 +11223,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// GLContext (RecordError) and the by-handle form deliberately does not, because
// under a transport there is no application on this side to report it to. On the
// push-monolith arm there is, so the monolith arm keeps the object form.
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
backendRenderbufferObject->SyncToBackendByHandle(surface.Res);
} else
#endif
{
const SharedPtr<MG_State::GLState::RenderbufferObject> monolithRenderbuffer =
(monolithAttachment != nullptr && monolithAttachment->IsRenderbuffer())
@@ -11436,12 +11273,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// (the three-channel colour-renderable widening). GL answers such a read with 1.0, but
// the storage holds whatever the draw wrote there, so the readback has to overwrite it.
Bool IsAlphaWidenedFallbackReadAttachment() {
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* record = MG_Pipe::MGPipeApplier().ReadFramebuffer();
return record && IsAlphaWidenedColorSurface(record->ReadSurface);
}
#endif
const auto* attachmentObject = GetReadColorAttachment();
if (attachmentObject == nullptr) {
return false;
@@ -11450,13 +11285,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
Bool IsFixedPointFallbackReadAttachment() {
#if MOBILEGL_BUILD_RECORD_ARM
if (MG_Config::DataArmIsRecord()) {
const auto* record = MG_Pipe::MGPipeApplier().ReadFramebuffer();
return record && record->ReadSurface.Kind != MG_Pipe::kMGPipeSurfaceKindNone &&
IsSnormFormat(static_cast<TextureInternalFormat>(record->ReadSurface.InternalFormat));
}
#endif
const auto& readFBO =
MG_Pipe::gPipeInputs.GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
if (!readFBO) {
@@ -11623,11 +11456,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// P5c (hd): with an active transport the handle is the caller's
// (m_pushedSyncHandle), never the client allocator's - see SyncToBackend.
const MG_Pipe::MGPipeHandle fbo =
#if MOBILEGL_BUILD_RECORD_ARM
MG_Config::DataArmIsRecord()
? m_pushedSyncHandle
:
#endif
g_backendFramebufferObjects.HandleOf(stateFBOObject.get());
// ID-19: the OBJECT's record, not "the record of whatever is bound to READ". A
// framebuffer whose read buffer is being pushed need not be the read binding at
@@ -11801,11 +11632,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// is never probed (T2). A null there means a caller reached this arm without a
// record, which the null-record refusal below names.
const MG_Pipe::MGPipeHandle fbo =
#if MOBILEGL_BUILD_RECORD_ARM
MG_Config::DataArmIsRecord()
? m_pushedSyncHandle
:
#endif
g_backendFramebufferObjects.HandleOf(stateFBOObject.get());
pushedRecord = PushedFramebufferRecord(fbo);
if (pushedRecord == nullptr) {
@@ -12083,11 +11912,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
// Verify that the backend object's name and parameters match the frontend attachment state
if (attachmentObject.IsTexture()) {
const auto& textureObject = attachmentObject.GetTexture();
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named
// debt inside the scope - P3b/P4b rekeys the registry.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
auto* backendTextureSlot = TextureImpl::g_backendTextureObjects.Find(textureObject.get());
MOBILEGL_ASSERT(backendTextureSlot != nullptr && *backendTextureSlot != nullptr,
"No backend texture found while framebuffer reports texture attachment.");
@@ -12104,11 +11931,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
"Attachment texture level mismatch between GLES and state object.");
} else if (attachmentObject.IsRenderbuffer()) {
const auto& renderbufferObject = attachmentObject.GetRenderbuffer();
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): frontend-keyed twin resolution, named
// debt inside the scope - P3b/P4b rekeys the registry.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
auto* backendRboSlot =
RenderbufferImpl::g_backendRenderbufferObjects.Find(renderbufferObject.get());
MOBILEGL_ASSERT(
@@ -12253,11 +12078,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
fbo.Slot, fbo.Gen);
return;
}
#if MOBILEGL_BUILD_RECORD_ARM
// Kept in step for the monolith-glue overloads that still resolve their record
// through it (SyncReadBufferToBackend's push arm).
m_pushedSyncHandle = fbo;
#endif
const GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget);
Bind(asTarget);
@@ -13109,7 +12932,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
// outside the frontend's array, which cannot be addressed at all.
Uint BoundImageUnitFormat(Int unit) {
if (unit < 0 || unit >= MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS) return 0;
#if MOBILEGL_BUILD_RECORD_ARM
// P5e (fb, §5.4): the format-less image bake asks what format the APPLICATION
// named at this unit, and under a transport the record is the only statement of
// it - MGPImageView::InternalFormat is that same GLenum, copied by the client
@@ -13120,7 +12942,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (static_cast<SizeT>(unit) >= st.BoundShaderImages.size()) return 0;
return static_cast<Uint>(st.BoundShaderImages[static_cast<SizeT>(unit)].InternalFormat);
}
#endif
return static_cast<Uint>(MG_Pipe::gPipeInputs.GetImageTextureBinding(unit).Format);
}
@@ -15241,14 +15062,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
// nine-clause rebuild condition reads on the handle arm; the clause COUNT does not
// shrink, its inputs move (D-H5).
if (ProgramSubsystemEnabled()) {
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): MONOLITH GLUE ONLY. This is the frontend-keyed
// lookup the phase exists to retire, and it survives here for the reason
// ruling 1 (ID-81) gives: under Transport=monolith the push build keeps its
// frontend arms token for token, and this arm is only ever reached from them.
// The handle half below names no frontend identity at all.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
// The reader hides the composite band, so a program-pipeline composite - which
// the server must never learn is one - resolves through the same call.
const MG_Pipe::MGPipeHandle cso = g_backendProgramObjects.HandleOf(stateProgramObject.get());
@@ -15593,12 +15412,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
// the values are taken from the object, which in monolith are the very
// values the client content-addressed, so the picture stays right while
// the gap is visible rather than silent.
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): the registration probe below resolves the
// sampler's handle by frontend identity - frontend-keyed twin resolution,
// named debt inside the scope - P3b/P4b rekeys the registry onto handles.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
if (!MG_Pipe::MGPipeHandleIsNull(
g_backendSamplerObjects.HandleOf(stateSamplerObject.get()))) {
MGLOG_E_ONCE("MGPipe: sampler %u was synced without its unit's SamplerCso handle, so "
@@ -15849,12 +15666,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
const MG_Pipe::MGPipeResourceRecord* pushedRecord = nullptr;
if (TextureResourceSubsystemEnabled()) {
#if MOBILEGL_BUILD_RECORD_ARM
// P5c (G6, CONTRACT-P5C §5.4): the renderbuffer's handle is resolved by
// frontend identity below - frontend-keyed twin resolution, named debt inside
// the scope - P3b/P4b rekeys the registry onto handles.
const MG_Pipe::MGPipeFrontendKeyedRegistryScope frontendKeyedRegistry;
#endif
// MONOLITH GLUE, named as such: the Renderbuffer handle of an object this
// backend still arrives holding. Under a real split it rides in the payload.
const MG_Pipe::MGPipeHandle res = g_backendRenderbufferObjects.HandleOf(stateRBOObject.get());