diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index b36af187..2598df93 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -812,6 +812,19 @@ namespace MobileGL::MG_Backend::DirectGLES { Int maxSamples = 0; const SizeT formatIndex = static_cast(logicalFormat); +#if MOBILEGL_BUILD_DISAGGREGATED + // C6 / ID-52: read the ROLE's own cache. Under split that is the server's private backend + // (ActiveBackendFormatCaps), not pActiveBackendObject, which holds the client's mirror. + const FormatCapabilityCache* activeCaps = ActiveBackendFormatCaps(); + if (activeCaps != nullptr && targetIndex < kFormatCapabilityTargetCount && + formatIndex < kFormatCapabilityFormatCount) { + // Descending, so the head is the largest count this device actually allocated. + const Vector& probedCounts = activeCaps->SampleCounts[targetIndex][formatIndex]; + if (!probedCounts.empty()) { + maxSamples = probedCounts.front(); + } + } +#else if (pActiveBackendObject && targetIndex < kFormatCapabilityTargetCount && formatIndex < kFormatCapabilityFormatCount) { // Descending, so the head is the largest count this device actually allocated. @@ -821,6 +834,7 @@ namespace MobileGL::MG_Backend::DirectGLES { maxSamples = probedCounts.front(); } } +#endif if (maxSamples <= 0) { maxSamples = GetGLESFormatMaxSamples(g_GLESCapabilities, logicalFormat, imageFormat); } diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index fa645890..7cfe864f 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -10,6 +10,9 @@ #include "Utils.h" #include "Managers.h" #include "MG_Backend/BackendObjects.h" +#if MOBILEGL_BUILD_DISAGGREGATED +#include +#endif #include "MG_Util/Converters/GLToMG/FramebufferEnumConverter.h" #include "MG_Util/SelfTest/DriverBugProbes.h" #include "MG_Util/Texture/TextureFormatProcessor.h" @@ -33,6 +36,21 @@ #include namespace MobileGL::MG_Backend::DirectGLES { +#if MOBILEGL_BUILD_DISAGGREGATED + const FormatCapabilityCache* ActiveBackendFormatCaps() { + // Under a live split session the SERVER's private backend is what owns the context on the + // apply thread (and these reads all run there), so its cache is the authoritative one. + // Before the session lands, or under monolith transport in a disaggregated build, fall + // back to the process global exactly as the monolith path always has. + if (MG_Config::Transport != MG_Config::TransportMode::Monolith) { + if (MG_Backend::BackendObject* server = MG_Remote::Server::ServerLoopInstance().Backend()) { + return &server->GetFormatCapabilities(); + } + } + return pActiveBackendObject ? &pActiveBackendObject->GetFormatCapabilities() : nullptr; + } +#endif + namespace { Flags GetForcedPixelFormatNormalizeOptions() { Flags options; @@ -71,15 +89,26 @@ namespace MobileGL::MG_Backend::DirectGLES { SizeT targetIndex, Bool caveat, FormatCapability capability) { +#if MOBILEGL_BUILD_DISAGGREGATED + const FormatCapabilityCache* activeCaps = ActiveBackendFormatCaps(); + if (activeCaps == nullptr || targetIndex >= kFormatCapabilityTargetCount) { + return false; + } +#else if (!pActiveBackendObject || targetIndex >= kFormatCapabilityTargetCount) { return false; } +#endif const SizeT formatIndex = static_cast(internalFormat); if (formatIndex >= kFormatCapabilityFormatCount) { return false; } +#if MOBILEGL_BUILD_DISAGGREGATED + const FormatCapabilityCache& cache = *activeCaps; +#else const FormatCapabilityCache& cache = pActiveBackendObject->GetFormatCapabilities(); +#endif const FormatCapabilityFlags caps = caveat ? cache.CaveatCaps[targetIndex][formatIndex] : cache.FullCaps[targetIndex][formatIndex]; return HasFormatCapability(caps, capability); @@ -123,7 +152,11 @@ namespace MobileGL::MG_Backend::DirectGLES { using namespace MobileGL::MG_Util::TextureFormatProcessor; const GLenum requestedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); Flags options; +#if MOBILEGL_BUILD_DISAGGREGATED + if (ActiveBackendFormatCaps() == nullptr || ShouldUseCaveatFormat(internalFormat, targetIndex)) { +#else if (!pActiveBackendObject || ShouldUseCaveatFormat(internalFormat, targetIndex)) { +#endif options = GetRuntimeFallbackNormalizeOptions( requestedInternalFormat, TextureImpl::GetRenderTargetNormalizeOptions(g_GLESCapabilities, targetIndex)); @@ -217,9 +250,15 @@ namespace MobileGL::MG_Backend::DirectGLES { // not be resolved yet - a probe run then would latch "cannot tell" as "clean" // forever. Once the backend exists, the first narrow-format image this process // creates runs the probe on a live context. +#if MOBILEGL_BUILD_DISAGGREGATED + if (ActiveBackendFormatCaps() == nullptr) { + return false; + } +#else if (pActiveBackendObject == nullptr) { return false; } +#endif return MG_Util::SelfTest::CopyImageMirrorsPacked16FieldOrder(g_GLESFuncs); } @@ -257,9 +296,15 @@ namespace MobileGL::MG_Backend::DirectGLES { if (!TargetRequiresRenderableFormat(targetIndex)) { return false; } +#if MOBILEGL_BUILD_DISAGGREGATED + if (ActiveBackendFormatCaps() != nullptr && !ShouldUseCaveatFormat(internalFormat, targetIndex)) { + return false; + } +#else if (pActiveBackendObject && !ShouldUseCaveatFormat(internalFormat, targetIndex)) { return false; } +#endif const GLenum requestedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); const Flags options = GetRuntimeFallbackNormalizeOptions( requestedInternalFormat, GetRenderTargetNormalizeOptions(g_GLESCapabilities, targetIndex)); diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index ae7f4af0..ffedd745 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -13,6 +13,19 @@ #include namespace MobileGL::MG_Backend::DirectGLES { +#if MOBILEGL_BUILD_DISAGGREGATED + // C6 / ID-52 / CONTRACT-P5 table 3's pActiveBackendObject row. The format-capability cache of + // THIS ROLE's backend. Under an active transport the server's own private + // BackendObject_DirectGLES owns the context on the apply thread, so a backend-internal format + // lookup must read ITS probed cache - not pActiveBackendObject's, which under split is the + // CLIENT's BackendObject_Remote mirror (a caps snapshot, generation-lagged, and on an + // independent server not usable at all). Monolith build/transport: pActiveBackendObject, so a + // pull build never sees this symbol. Null when no backend is up. The seven table-3 reads + // (five in Utils.cpp, ClampSamplesToBackendSupport in BackendObject_DirectGLES.cpp) go through + // this instead of dereferencing pActiveBackendObject directly. + const FormatCapabilityCache* ActiveBackendFormatCaps(); +#endif + namespace DebugImpl { class ErrorLopper { public: