From 4610b573f405379084e27448b5fee9c71d82885f Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sun, 20 Sep 2026 12:18:08 -0400 Subject: [PATCH] [MG_Remote] (Disaggregated): gate timer caps before renderer creation and advertise native primitive queries --- MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp | 5 +++++ MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp | 9 +++++++++ MobileGL/MG_Remote/Client/SlotCaps.h | 12 +++++------- MobileGL/MG_Test/Pipe/PipeCatalogueTest.cpp | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 5da0ca22..6f131962 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -1327,6 +1327,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { } // namespace Bool IsTimerQuerySupported() { +#if MOBILEGL_BUILD_DISAGGREGATED + // The first caps snapshot is sent during the transport handshake, + // before eglMakeCurrent creates the server's Vulkan renderer. + if (MG_Config::Transport != MG_Config::TransportMode::Monolith && !pVulkanRenderer) return false; +#endif MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::IsTimerQuerySupported called with null VulkanRenderer"); return pVulkanRenderer->IsTimerQuerySupported(); } diff --git a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp index 64c990fc..68a6fbed 100644 --- a/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp +++ b/MobileGL/MG_Impl/GLImpl/Query/GL_Query.cpp @@ -778,6 +778,15 @@ namespace MobileGL::MG_Impl::GLImpl { return; } case GL_QUERY_COUNTER_BITS: { +#if MOBILEGL_BUILD_DISAGGREGATED + if (MG_Config::Transport != MG_Config::TransportMode::Monolith && + (target == GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN || target == GL_PRIMITIVES_GENERATED)) { + // Both wire query paths now return native GPU counters. GLES' + // core counter has 32 bits, so advertise that shared lower bound. + *params = MGL_BACKEND_SLOT_CAP(BeginXfbPrimitivesQuery, MG_Pipe::kCapXfbPrimitivesQuery) ? 32 : 0; + return; + } +#endif // 64 bits are advertised only while the live backend can actually // time: IsTimerQuerySupported is the dynamic truth (extension / // entry points / timestamp valid bits at call time, not at table diff --git a/MobileGL/MG_Remote/Client/SlotCaps.h b/MobileGL/MG_Remote/Client/SlotCaps.h index 517a3d16..4a0894b7 100644 --- a/MobileGL/MG_Remote/Client/SlotCaps.h +++ b/MobileGL/MG_Remote/Client/SlotCaps.h @@ -56,10 +56,9 @@ // now calls the emitter and the server preserves the optional/native-null fallback. // GL_Texture.cpp:6537 GetTextureImage -> the frontend's own CPU readback, which is exact // GL_Texture.cpp:6799 GetTexImage -> the same -// GL_Getter.cpp x2 GetGpuTimestampNs -> 0, which BackendObject.h:192 already names as -// the unsupported answer -// GL_Query.cpp the four query probes -> CPU primitive accounting / target rejection / -// COUNTER_BITS 0, all of them spec answers +// GL_Getter.cpp x2 GetGpuTimestampNs and GL_Query.cpp's query probes now use their +// timer/occlusion/primitive capability bits. An advertised path emits real query +// records; only an unavailable native capability reports COUNTER_BITS 0. // // NOT converted, deliberately, because "absent" would be wrong rather than quiet: // GL_Drawing.cpp:1274/:1371/:1420/:1435/:1641/:1673 the transform-feedback span family. The @@ -86,9 +85,8 @@ // as it does under monolith. GL_Drawing.cpp:844's PatchParameteri stays a plain guard for the // same reason as the six: the slot is class B now, so "absent" never arises. // -// The one XFB slot still class C is DeleteTransformFeedback, which CONTRACT-P5B.md gives no row -// (unmeasured); :1641's guard therefore still reaches Fatal{UnmigratedVerb} by name, which is -// the outcome R-4 asks for. +// DeleteTransformFeedback now emits DeleteStreamOutput with the object's lifetime +// identity; its ordinary slot guard reaches that emitter under a transport. // // WHAT THIS HEADER DELIBERATELY DOES NOT DO. It does not touch the 28 unguarded slots: those // have no probe to convert, and calling one reaches Fatal{UnmigratedVerb, ""} by name, diff --git a/MobileGL/MG_Test/Pipe/PipeCatalogueTest.cpp b/MobileGL/MG_Test/Pipe/PipeCatalogueTest.cpp index 48d5869c..cef7c382 100644 --- a/MobileGL/MG_Test/Pipe/PipeCatalogueTest.cpp +++ b/MobileGL/MG_Test/Pipe/PipeCatalogueTest.cpp @@ -638,7 +638,8 @@ TEST(PipeCatalogue, LateArrivalsAreAppendedWithoutRenumbering) { // host span in the third; it lands with a null route and a sink that refuses it by name, // exactly as set_shader_buffers has sat catalogued-and-dead since P4a. EXPECT_EQ(static_cast(MGPWireOp::SetProgramBindings), 80); - EXPECT_EQ(static_cast(MGPWireOp::kOpCount), 81); + EXPECT_EQ(static_cast(MGPWireOp::DeleteStreamOutput), 81); + EXPECT_EQ(static_cast(MGPWireOp::kOpCount), 82); EXPECT_EQ(MGPipeCallFlagsFor(MGPWireOp::SetProgramBindings), static_cast(kVarTail | kHostSpan)); EXPECT_EQ(MGPipeCallFlagsFor(MGPWireOp::ApplierReset), static_cast(kNone));