[Fix] (DirectGLES): the seven backend format-capability reads use the server-private cache via ActiveBackendFormatCaps under split, not pActiveBackendObject (C6); guarded so the pull build is byte-identical

This commit is contained in:
2026-09-16 07:45:29 -04:00
parent 0fde95357c
commit 7a925b3259
3 changed files with 72 additions and 0 deletions
@@ -812,6 +812,19 @@ namespace MobileGL::MG_Backend::DirectGLES {
Int maxSamples = 0;
const SizeT formatIndex = static_cast<SizeT>(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<Int>& 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);
}
+45
View File
@@ -10,6 +10,9 @@
#include "Utils.h"
#include "Managers.h"
#include "MG_Backend/BackendObjects.h"
#if MOBILEGL_BUILD_DISAGGREGATED
#include <MG_Remote/Server/ServerLoop.h>
#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 <regex>
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<PixelFormatNormalizeOptionBit> GetForcedPixelFormatNormalizeOptions() {
Flags<PixelFormatNormalizeOptionBit> 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<SizeT>(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<PixelFormatNormalizeOptionBit> 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<PixelFormatNormalizeOptionBit> options = GetRuntimeFallbackNormalizeOptions(
requestedInternalFormat, GetRenderTargetNormalizeOptions(g_GLESCapabilities, targetIndex));
+13
View File
@@ -13,6 +13,19 @@
#include <MG_Util/Texture/TextureFormatProcessor.h>
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: