From 7c25130d5a546512ab35467f3d0085bc98763bc1 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 11 Sep 2026 14:13:20 -0400 Subject: [PATCH] [Feat] (MG_Remote, Protocol): delete CapsSnapshot's four redundant trailing fields and give CallMask, the server's backend type and the ABI fingerprint the carriers they never had - tableSlotMask could not address the 69-slot table its comment named and the two compute limits already ride inside dynamicParameters --- .../Protocol/generated/protocol_generated.h | 138 +++++++++++------- MobileGL/MG_Remote/Protocol/protocol.fbs | 48 +++++- 2 files changed, 128 insertions(+), 58 deletions(-) diff --git a/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h b/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h index eb91a6a5..8324e1be 100644 --- a/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h +++ b/MobileGL/MG_Remote/Protocol/generated/protocol_generated.h @@ -532,7 +532,8 @@ struct Hello FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VT_BUILDFINGERPRINT = 8, VT_BACKENDTYPE = 10, VT_PID = 12, - VT_CONFIGBLOB = 14 + VT_CONFIGBLOB = 14, + VT_ABIFINGERPRINT = 16 }; uint32_t abiMajor() const { return GetField(VT_ABIMAJOR, 0); @@ -552,6 +553,9 @@ struct Hello FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const ::flatbuffers::Vector *configBlob() const { return GetPointer *>(VT_CONFIGBLOB); } + uint64_t abiFingerprint() const { + return GetField(VT_ABIFINGERPRINT, 0); + } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && @@ -563,6 +567,7 @@ struct Hello FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VerifyField(verifier, VT_PID, 4) && VerifyOffset(verifier, VT_CONFIGBLOB) && verifier.VerifyVector(configBlob()) && + VerifyField(verifier, VT_ABIFINGERPRINT, 8) && verifier.EndTable(); } }; @@ -589,6 +594,9 @@ struct HelloBuilder { void add_configBlob(::flatbuffers::Offset<::flatbuffers::Vector> configBlob) { fbb_.AddOffset(Hello::VT_CONFIGBLOB, configBlob); } + void add_abiFingerprint(uint64_t abiFingerprint) { + fbb_.AddElement(Hello::VT_ABIFINGERPRINT, abiFingerprint, 0); + } explicit HelloBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -607,8 +615,10 @@ inline ::flatbuffers::Offset CreateHello( ::flatbuffers::Offset<::flatbuffers::String> buildFingerprint = 0, uint32_t backendType = 0, uint32_t pid = 0, - ::flatbuffers::Offset<::flatbuffers::Vector> configBlob = 0) { + ::flatbuffers::Offset<::flatbuffers::Vector> configBlob = 0, + uint64_t abiFingerprint = 0) { HelloBuilder builder_(_fbb); + builder_.add_abiFingerprint(abiFingerprint); builder_.add_configBlob(configBlob); builder_.add_pid(pid); builder_.add_backendType(backendType); @@ -630,7 +640,8 @@ inline ::flatbuffers::Offset CreateHelloDirect( const char *buildFingerprint = nullptr, uint32_t backendType = 0, uint32_t pid = 0, - const std::vector *configBlob = nullptr) { + const std::vector *configBlob = nullptr, + uint64_t abiFingerprint = 0) { auto buildFingerprint__ = buildFingerprint ? _fbb.CreateString(buildFingerprint) : 0; auto configBlob__ = configBlob ? _fbb.CreateVector(*configBlob) : 0; return MobileGL::Wire::CreateHello( @@ -640,7 +651,8 @@ inline ::flatbuffers::Offset CreateHelloDirect( buildFingerprint__, backendType, pid, - configBlob__); + configBlob__, + abiFingerprint); } struct Welcome FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { @@ -653,7 +665,9 @@ struct Welcome FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VT_CMDRING = 10, VT_STAGERING = 12, VT_REPLYPOOL = 14, - VT_EVENTRING = 16 + VT_EVENTRING = 16, + VT_BUILDFINGERPRINT = 18, + VT_ABIFINGERPRINT = 20 }; uint32_t abiMajor() const { return GetField(VT_ABIMAJOR, 0); @@ -676,6 +690,12 @@ struct Welcome FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const MobileGL::Wire::SegmentRef *eventRing() const { return GetPointer(VT_EVENTRING); } + const ::flatbuffers::String *buildFingerprint() const { + return GetPointer(VT_BUILDFINGERPRINT); + } + uint64_t abiFingerprint() const { + return GetField(VT_ABIFINGERPRINT, 0); + } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && @@ -690,6 +710,9 @@ struct Welcome FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { verifier.VerifyTable(replyPool()) && VerifyOffset(verifier, VT_EVENTRING) && verifier.VerifyTable(eventRing()) && + VerifyOffset(verifier, VT_BUILDFINGERPRINT) && + verifier.VerifyString(buildFingerprint()) && + VerifyField(verifier, VT_ABIFINGERPRINT, 8) && verifier.EndTable(); } }; @@ -719,6 +742,12 @@ struct WelcomeBuilder { void add_eventRing(::flatbuffers::Offset eventRing) { fbb_.AddOffset(Welcome::VT_EVENTRING, eventRing); } + void add_buildFingerprint(::flatbuffers::Offset<::flatbuffers::String> buildFingerprint) { + fbb_.AddOffset(Welcome::VT_BUILDFINGERPRINT, buildFingerprint); + } + void add_abiFingerprint(uint64_t abiFingerprint) { + fbb_.AddElement(Welcome::VT_ABIFINGERPRINT, abiFingerprint, 0); + } explicit WelcomeBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -738,8 +767,12 @@ inline ::flatbuffers::Offset CreateWelcome( ::flatbuffers::Offset cmdRing = 0, ::flatbuffers::Offset stageRing = 0, ::flatbuffers::Offset replyPool = 0, - ::flatbuffers::Offset eventRing = 0) { + ::flatbuffers::Offset eventRing = 0, + ::flatbuffers::Offset<::flatbuffers::String> buildFingerprint = 0, + uint64_t abiFingerprint = 0) { WelcomeBuilder builder_(_fbb); + builder_.add_abiFingerprint(abiFingerprint); + builder_.add_buildFingerprint(buildFingerprint); builder_.add_eventRing(eventRing); builder_.add_replyPool(replyPool); builder_.add_stageRing(stageRing); @@ -755,6 +788,31 @@ struct Welcome::Traits { static auto constexpr Create = CreateWelcome; }; +inline ::flatbuffers::Offset CreateWelcomeDirect( + ::flatbuffers::FlatBufferBuilder &_fbb, + uint32_t abiMajor = 0, + uint32_t abiMinor = 0, + uint32_t serverPid = 0, + ::flatbuffers::Offset cmdRing = 0, + ::flatbuffers::Offset stageRing = 0, + ::flatbuffers::Offset replyPool = 0, + ::flatbuffers::Offset eventRing = 0, + const char *buildFingerprint = nullptr, + uint64_t abiFingerprint = 0) { + auto buildFingerprint__ = buildFingerprint ? _fbb.CreateString(buildFingerprint) : 0; + return MobileGL::Wire::CreateWelcome( + _fbb, + abiMajor, + abiMinor, + serverPid, + cmdRing, + stageRing, + replyPool, + eventRing, + buildFingerprint__, + abiFingerprint); +} + struct CapsSnapshot FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef CapsSnapshotBuilder Builder; struct Traits; @@ -764,10 +822,8 @@ struct CapsSnapshot FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VT_FORMATCAPS = 8, VT_EXTENSIONS = 10, VT_APIVERSION = 12, - VT_MAXCOMPUTEWORKGROUPCOUNT = 14, - VT_MAXCOMPUTEWORKGROUPSIZE = 16, - VT_TABLESLOTMASK = 18, - VT_PREFERSCPUXFBPRIMITIVEACCOUNTING = 20 + VT_CALLMASK = 14, + VT_BACKENDTYPE = 16 }; const ::flatbuffers::Vector *dynamicParameters() const { return GetPointer *>(VT_DYNAMICPARAMETERS); @@ -784,17 +840,11 @@ struct CapsSnapshot FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { const ::flatbuffers::String *apiVersion() const { return GetPointer(VT_APIVERSION); } - const ::flatbuffers::Vector *maxComputeWorkGroupCount() const { - return GetPointer *>(VT_MAXCOMPUTEWORKGROUPCOUNT); + uint64_t callMask() const { + return GetField(VT_CALLMASK, 0); } - const ::flatbuffers::Vector *maxComputeWorkGroupSize() const { - return GetPointer *>(VT_MAXCOMPUTEWORKGROUPSIZE); - } - uint64_t tableSlotMask() const { - return GetField(VT_TABLESLOTMASK, 0); - } - bool prefersCpuXfbPrimitiveAccounting() const { - return GetField(VT_PREFERSCPUXFBPRIMITIVEACCOUNTING, 0) != 0; + uint32_t backendType() const { + return GetField(VT_BACKENDTYPE, 0); } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { @@ -810,12 +860,8 @@ struct CapsSnapshot FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { verifier.VerifyVectorOfStrings(extensions()) && VerifyOffset(verifier, VT_APIVERSION) && verifier.VerifyString(apiVersion()) && - VerifyOffset(verifier, VT_MAXCOMPUTEWORKGROUPCOUNT) && - verifier.VerifyVector(maxComputeWorkGroupCount()) && - VerifyOffset(verifier, VT_MAXCOMPUTEWORKGROUPSIZE) && - verifier.VerifyVector(maxComputeWorkGroupSize()) && - VerifyField(verifier, VT_TABLESLOTMASK, 8) && - VerifyField(verifier, VT_PREFERSCPUXFBPRIMITIVEACCOUNTING, 1) && + VerifyField(verifier, VT_CALLMASK, 8) && + VerifyField(verifier, VT_BACKENDTYPE, 4) && verifier.EndTable(); } }; @@ -839,17 +885,11 @@ struct CapsSnapshotBuilder { void add_apiVersion(::flatbuffers::Offset<::flatbuffers::String> apiVersion) { fbb_.AddOffset(CapsSnapshot::VT_APIVERSION, apiVersion); } - void add_maxComputeWorkGroupCount(::flatbuffers::Offset<::flatbuffers::Vector> maxComputeWorkGroupCount) { - fbb_.AddOffset(CapsSnapshot::VT_MAXCOMPUTEWORKGROUPCOUNT, maxComputeWorkGroupCount); + void add_callMask(uint64_t callMask) { + fbb_.AddElement(CapsSnapshot::VT_CALLMASK, callMask, 0); } - void add_maxComputeWorkGroupSize(::flatbuffers::Offset<::flatbuffers::Vector> maxComputeWorkGroupSize) { - fbb_.AddOffset(CapsSnapshot::VT_MAXCOMPUTEWORKGROUPSIZE, maxComputeWorkGroupSize); - } - void add_tableSlotMask(uint64_t tableSlotMask) { - fbb_.AddElement(CapsSnapshot::VT_TABLESLOTMASK, tableSlotMask, 0); - } - void add_prefersCpuXfbPrimitiveAccounting(bool prefersCpuXfbPrimitiveAccounting) { - fbb_.AddElement(CapsSnapshot::VT_PREFERSCPUXFBPRIMITIVEACCOUNTING, static_cast(prefersCpuXfbPrimitiveAccounting), 0); + void add_backendType(uint32_t backendType) { + fbb_.AddElement(CapsSnapshot::VT_BACKENDTYPE, backendType, 0); } explicit CapsSnapshotBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { @@ -869,20 +909,16 @@ inline ::flatbuffers::Offset CreateCapsSnapshot( ::flatbuffers::Offset<::flatbuffers::Vector> formatCaps = 0, ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> extensions = 0, ::flatbuffers::Offset<::flatbuffers::String> apiVersion = 0, - ::flatbuffers::Offset<::flatbuffers::Vector> maxComputeWorkGroupCount = 0, - ::flatbuffers::Offset<::flatbuffers::Vector> maxComputeWorkGroupSize = 0, - uint64_t tableSlotMask = 0, - bool prefersCpuXfbPrimitiveAccounting = false) { + uint64_t callMask = 0, + uint32_t backendType = 0) { CapsSnapshotBuilder builder_(_fbb); - builder_.add_tableSlotMask(tableSlotMask); - builder_.add_maxComputeWorkGroupSize(maxComputeWorkGroupSize); - builder_.add_maxComputeWorkGroupCount(maxComputeWorkGroupCount); + builder_.add_callMask(callMask); + builder_.add_backendType(backendType); builder_.add_apiVersion(apiVersion); builder_.add_extensions(extensions); builder_.add_formatCaps(formatCaps); builder_.add_rendererInfo(rendererInfo); builder_.add_dynamicParameters(dynamicParameters); - builder_.add_prefersCpuXfbPrimitiveAccounting(prefersCpuXfbPrimitiveAccounting); return builder_.Finish(); } @@ -898,17 +934,13 @@ inline ::flatbuffers::Offset CreateCapsSnapshotDirect( const std::vector *formatCaps = nullptr, const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *extensions = nullptr, const char *apiVersion = nullptr, - const std::vector *maxComputeWorkGroupCount = nullptr, - const std::vector *maxComputeWorkGroupSize = nullptr, - uint64_t tableSlotMask = 0, - bool prefersCpuXfbPrimitiveAccounting = false) { + uint64_t callMask = 0, + uint32_t backendType = 0) { auto dynamicParameters__ = dynamicParameters ? _fbb.CreateVector(*dynamicParameters) : 0; auto rendererInfo__ = rendererInfo ? _fbb.CreateVector(*rendererInfo) : 0; auto formatCaps__ = formatCaps ? _fbb.CreateVector(*formatCaps) : 0; auto extensions__ = extensions ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*extensions) : 0; auto apiVersion__ = apiVersion ? _fbb.CreateString(apiVersion) : 0; - auto maxComputeWorkGroupCount__ = maxComputeWorkGroupCount ? _fbb.CreateVector(*maxComputeWorkGroupCount) : 0; - auto maxComputeWorkGroupSize__ = maxComputeWorkGroupSize ? _fbb.CreateVector(*maxComputeWorkGroupSize) : 0; return MobileGL::Wire::CreateCapsSnapshot( _fbb, dynamicParameters__, @@ -916,10 +948,8 @@ inline ::flatbuffers::Offset CreateCapsSnapshotDirect( formatCaps__, extensions__, apiVersion__, - maxComputeWorkGroupCount__, - maxComputeWorkGroupSize__, - tableSlotMask, - prefersCpuXfbPrimitiveAccounting); + callMask, + backendType); } struct DefaultFramebufferInfo FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { diff --git a/MobileGL/MG_Remote/Protocol/protocol.fbs b/MobileGL/MG_Remote/Protocol/protocol.fbs index 968f235b..0e9d52c3 100644 --- a/MobileGL/MG_Remote/Protocol/protocol.fbs +++ b/MobileGL/MG_Remote/Protocol/protocol.fbs @@ -63,6 +63,15 @@ table Hello { backendType: uint; pid: uint; configBlob: [ubyte]; + // CONTRACT-P5 table 0, "ABI agreement": MGPCaps has only a COMPOSITIONAL size + // assertion, because DynamicBackendParameters still carries SizeT and GLenum. + // So the two peers assert they were built from the same struct shapes instead + // of rewriting them fixed-width (that is P7's account). This is + // MG_Remote::CapsAbiFingerprint(): sizeof(DynamicBackendParameters), + // sizeof(MGPCaps), sizeof(GLFunctionsTable), the protocol ABI version and the + // build's git stamp, mixed. A mismatch is Fatal{AbiMismatch} and NEVER a + // downgrade - every alternative silently reads one struct as another. + abiFingerprint: ulong; } table Welcome { @@ -73,6 +82,12 @@ table Welcome { stageRing: SegmentRef; replyPool: SegmentRef; eventRing: SegmentRef; + // The server's half of the assertion above. The string is carried beside the + // mixed value only so a mismatch can name both builds in the Fatal line; the + // COMPARISON is on abiFingerprint, which also covers the three sizeofs the + // string cannot. + buildFingerprint: string; + abiFingerprint: ulong; } // --------------------------------------------------------------------------- @@ -83,16 +98,41 @@ table Welcome { // (plan B appendix A, `get_caps`). The three blobs are byte-for-byte images of // the corresponding POD structs; they are versioned by structSize-first // discipline, not by this schema. +// The four fields this table used to end with are DELETED (CONTRACT-P5 table 0, +// "CapsSnapshot redundancy"), not renamed and not deprecated: +// +// maxComputeWorkGroupCount / maxComputeWorkGroupSize - they ride inside +// `dynamicParameters` already (BackendObject.h:392-393), and two spellings of +// one number is how the two sides come to disagree about it. +// tableSlotMask - GLFunctionsTable has SIXTY-NINE function-pointer slots +// (BackendObject.h:117-292) and a ulong is 64 bits, so the field could never +// address the table its own comment named; and ARCHITECTURE.md:114 already +// retired "is this table slot null" as the capability probe in favour of +// CallMask, so keeping it would re-introduce exactly what replaced it. +// prefersCpuXfbPrimitiveAccounting - answered by kCapCpuXfbPrimitiveAccounting +// in `callMask` below. +// +// They were the LAST four fields, so nothing before them moved a vtable slot. table CapsSnapshot { dynamicParameters: [ubyte]; rendererInfo: [ubyte]; formatCaps: [ubyte]; extensions: [string]; apiVersion: string; - maxComputeWorkGroupCount: [int]; // 3 entries - maxComputeWorkGroupSize: [int]; // 3 entries - tableSlotMask: ulong; // which GLFunctionsTable slots the peer registered - prefersCpuXfbPrimitiveAccounting: bool; + // MGPCaps::CallMask (MGPipeTypes.h:127). Bits 0..8 are MGPCapBit; bits 32..47 + // are the CONSUMER MASK - bit (32+n) means "the server has a consumer for + // MGPipe subsystem bit n" - and MG_Remote/CapsCodec.h holds the four constexprs + // that are the only legal way to fold and test them. It needs a carrier of its + // own because `dynamicParameters` is the image of DynamicBackendParameters, + // which CallMask is not a member of; and without a carrier R-8's rule that the + // client's liveness gates read the caps mirror has nothing to read. + callMask: ulong; + // The SERVER's backend type, for CapsMirror::Backend(). Hello.backendType is + // the CLIENT's request; this is the answer, and the frontend branches that + // switch on it (GL_Framebuffer.cpp:47, GL_Texture.cpp:6536, CompileEnv.cpp:122) + // take a wrong arm rather than fail on a value they do not know, so it may not + // be guessed from the renderer string. + backendType: uint; } table DefaultFramebufferInfo {