[MG_Remote] (Disaggregated): gate timer caps before renderer creation and advertise native primitive queries

This commit is contained in:
2026-09-20 12:18:08 -04:00
parent 03c6b8c979
commit 4610b573f4
4 changed files with 21 additions and 8 deletions
@@ -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();
}
@@ -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
+5 -7
View File
@@ -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, "<slot>"} by name,
+2 -1
View File
@@ -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<Uint16>(MGPWireOp::SetProgramBindings), 80);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::kOpCount), 81);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::DeleteStreamOutput), 81);
EXPECT_EQ(static_cast<Uint16>(MGPWireOp::kOpCount), 82);
EXPECT_EQ(MGPipeCallFlagsFor(MGPWireOp::SetProgramBindings),
static_cast<Uint32>(kVarTail | kHostSpan));
EXPECT_EQ(MGPipeCallFlagsFor(MGPWireOp::ApplierReset), static_cast<Uint32>(kNone));