mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-17 08:38:30 +09:00
[Fix, Test] (DirectGLES/Managers, MG_Test/Wire): M-3's two whole-store refusals key on the DESCRIPTOR's HasDefinedContent - content the application supplied (glBufferData(size, data)) must be fully staged by the draw, a gap is a missing record and Fatal{StageSnapshotTooNarrow} by name; a store the application orphaned (glBufferData(size, NULL)) has undefined bytes by its own declaration, so the streaming idiom (orphan, partial glBufferSubData, draw) uploads the staged bytes plus zero-fill exactly as the monolith arm uploads MappedData(); round 2 refused both shapes and aborted six LargeArenaAdoption / ResourceSubsystemControl joint entries by name (hidden under c1 round 2's BlobMissing abort until c1 round 3); two positive gates run the idiom end to end in a forked child through each reader and red on their own string when the refusal is made unconditional again
This commit is contained in:
@@ -2003,6 +2003,23 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
const auto* record = ResourceRecordOf(res);
|
||||
return record != nullptr ? static_cast<SizeT>(record->Desc.Width) : 0;
|
||||
}
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
// M-3's rule for the two WHOLE-STORE readers (v1 round 3). The descriptor is the
|
||||
// application's own statement about the store: HasDefinedContent set means it SUPPLIED
|
||||
// the content (glBufferData(size, data)), which under split arrives as resource_subdata
|
||||
// records behind the respecify (table 1 row 19) - so a coverage gap at the draw is a
|
||||
// MISSING RECORD and the zero-fill past the coverage is not the application's bytes.
|
||||
// Clear means it ORPHANED the store (glBufferData(size, NULL), glBufferStorage(NULL)):
|
||||
// every byte it has not staged since is UNDEFINED by its own declaration, the streaming
|
||||
// idiom (orphan, partial glBufferSubData, draw) is the ordinary case, and uploading the
|
||||
// shadow's zero-fill for the rest is exactly what the monolith arm uploads from
|
||||
// MappedData(). Round 2 refused both shapes and aborted six LargeArenaAdoption /
|
||||
// ResourceSubsystemControl entries on the joint by name (v1-v3.md 6).
|
||||
Bool ResourceContentIsDeclared(MG_Pipe::MGPipeHandle res) {
|
||||
const auto* record = ResourceRecordOf(res);
|
||||
return record != nullptr && record->Desc.HasDefinedContent != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Ops_H_Create(MG_Pipe::MGPipeHandle res, const MG_Pipe::MGPResourceDesc& desc) {
|
||||
(void)res;
|
||||
@@ -3028,13 +3045,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
resource->pendingRespecify = false;
|
||||
BindBufferId(TempBufferTarget, reused);
|
||||
// M-3 / codex 4: this is a WHOLE-STORE upload from the base, and under split
|
||||
// the base is the server shadow (M-2), whose zero-filled bytes past the staged
|
||||
// coverage are not the application's - uploading them is the silent data loss
|
||||
// the M-6 ruling forbids. RequireCoverage is a no-op for the legacy arm's
|
||||
// MappedData() and for a non-copying store; under split it Fatals by name on a
|
||||
// sparse shadow rather than seeding the driver with zeroes.
|
||||
MGL_SERVER_STAGED_REQUIRE(*resource, liveHostBase(), 0, poolSize,
|
||||
"pool_reuse_whole_store");
|
||||
// the base is the server shadow (M-2). For a store whose content the
|
||||
// application SUPPLIED, zero-filled bytes past the staged coverage are not the
|
||||
// application's - uploading them is the silent data loss the M-6 ruling
|
||||
// forbids, and a gap is a missing record: Fatal by name. For a store the
|
||||
// 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_DISAGGREGATED
|
||||
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,
|
||||
@@ -3112,13 +3135,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
||||
// [0, size) upload from the base, so it owes the same coverage the pending-range drain
|
||||
// below owes - the two respecify arms were the readers M-6's "never widened" rule did
|
||||
// not reach. No-op for the legacy arm's MappedData() and for a non-copying store; a
|
||||
// Fatal{StageSnapshotTooNarrow, "respecify_whole_store"} under split when the shadow's
|
||||
// coverage does not span the store, instead of uploading its zero-fill as content.
|
||||
// Fatal{StageSnapshotTooNarrow, "respecify_whole_store"} under split when the
|
||||
// DESCRIPTOR says the application supplied the content and the shadow's coverage does
|
||||
// not span the store (a missing record), instead of uploading its zero-fill as content.
|
||||
// NOT for a store the application orphaned: there `shadowHasContent` is the frontend
|
||||
// object's flag, which the streaming idiom's partial glBufferSubData flips to true, and
|
||||
// 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 (initialData != nullptr) {
|
||||
#if MOBILEGL_BUILD_DISAGGREGATED
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user