[Refactor] (Espryt): allocate renderbuffer storage from the pushed descriptor and keep the deferred out-of-memory report where it is

This commit is contained in:
2026-09-08 16:57:36 -04:00
committed by rereview
parent 2bd19d5ee2
commit 5e5dc36e57
2 changed files with 95 additions and 4 deletions
+81 -4
View File
@@ -11423,6 +11423,31 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBindRenderbuffer(GL_RENDERBUFFER, m_backendRBOId);
}
// P4a (D-D2): the four values BackendRenderbufferObject::SyncToBackend allocates from,
// spelled once per arm. Macros for the reason the texture-parameter block gives: in the
// PULL build each expands to the pre-P4a expression at its original site, so that
// build's tokens and its symbol sizes are unchanged (D-P).
//
// ARCHITECTURE.md:130 keeps the renderbuffer an INDEPENDENT frontend class while giving
// it the same discriminated MGPResourceDesc a texture gets, and this is where that pays:
// the same four fields, read out of the same record type, with Desc.Target telling the
// applier which of the three per-kind tables the record lives in.
#if MOBILEGL_PIPE_PUSH
#define MGB_RBO_FORMAT \
(pushedRecord != nullptr ? static_cast<TextureInternalFormat>(pushedRecord->Desc.InternalFormat) \
: stateRBOObject->GetInternalFormat())
#define MGB_RBO_WIDTH (pushedRecord != nullptr ? static_cast<Int>(pushedRecord->Desc.Width) : static_cast<Int>(stateRBOObject->GetWidth()))
#define MGB_RBO_HEIGHT \
(pushedRecord != nullptr ? static_cast<Int>(pushedRecord->Desc.Height) : static_cast<Int>(stateRBOObject->GetHeight()))
#define MGB_RBO_SAMPLES \
(pushedRecord != nullptr ? static_cast<Int>(pushedRecord->Desc.Samples) : static_cast<Int>(stateRBOObject->GetSamples()))
#else
#define MGB_RBO_FORMAT stateRBOObject->GetInternalFormat()
#define MGB_RBO_WIDTH static_cast<Int>(stateRBOObject->GetWidth())
#define MGB_RBO_HEIGHT static_cast<Int>(stateRBOObject->GetHeight())
#define MGB_RBO_SAMPLES static_cast<Int>(stateRBOObject->GetSamples())
#endif
void BackendRenderbufferObject::SyncToBackend(
const SharedPtr<MG_State::GLState::RenderbufferObject>& stateRBOObject) {
#ifdef TRACY_ENABLE
@@ -11436,6 +11461,45 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("Syncing RBO with backend ID %u to backend for state ID %u", m_backendRBOId,
stateRBOObject->GetExternalIndex());
#if MOBILEGL_PIPE_PUSH
const MG_Pipe::MGPipeResourceRecord* pushedRecord = nullptr;
if (TextureResourceSubsystemEnabled()) {
// MONOLITH GLUE, named as such: the Renderbuffer handle of an object this
// backend still arrives holding. Under a real split it rides in the payload.
const MG_Pipe::MGPipeHandle res = g_backendRenderbufferObjects.HandleOf(stateRBOObject.get());
pushedRecord = PipeRenderbufferRecordForHandle(res);
if (pushedRecord == nullptr) {
MGLOG_E_ONCE("MGPipe: renderbuffer %u has no applier record on the handle arm, so "
"its storage cannot be allocated from the pushed descriptor "
"(handle {%u, %u})",
stateRBOObject->GetExternalIndex(), res.Slot, res.Gen);
return;
}
if (m_isInitialized && m_syncedResourceSerial != 0 &&
m_syncedResourceSerial == pushedRecord->Serial) {
MGLOG_D("RBO %u already initialized with matching parameters, skipping re-allocation.",
stateRBOObject->GetExternalIndex());
return;
}
} else {
#if !MOBILEGL_PIPE_LEGACY_MEMOS
// UNREACHABLE: ResolveTextureResourceSubsystemArm stops at its first call when
// the bit is clear and the pre-handle arm is not compiled. Kept, and kept loud.
MGLOG_E_ONCE("MGPipe: the texture-resource subsystem bit is clear and "
"MOBILEGL_PIPE_LEGACY_MEMOS=0 removed the pre-handle renderbuffer "
"four-field cache, so this configuration has no arm at all");
return;
#else
if (m_isInitialized && m_cacheInternalFormat == stateRBOObject->GetInternalFormat() &&
m_cacheWidth == stateRBOObject->GetWidth() && m_cacheHeight == stateRBOObject->GetHeight() &&
m_cacheSamples == stateRBOObject->GetSamples()) {
MGLOG_D("RBO %u already initialized with matching parameters, skipping re-allocation.",
stateRBOObject->GetExternalIndex());
return;
}
#endif
}
#else
if (m_isInitialized && m_cacheInternalFormat == stateRBOObject->GetInternalFormat() &&
m_cacheWidth == stateRBOObject->GetWidth() && m_cacheHeight == stateRBOObject->GetHeight() &&
m_cacheSamples == stateRBOObject->GetSamples()) {
@@ -11443,14 +11507,15 @@ namespace MobileGL::MG_Backend::DirectGLES {
stateRBOObject->GetExternalIndex());
return;
}
#endif
Bind();
// Allocate storage
TextureInternalFormat internalFormat = stateRBOObject->GetInternalFormat();
Int width = static_cast<Int>(stateRBOObject->GetWidth());
Int height = static_cast<Int>(stateRBOObject->GetHeight());
Int samples = static_cast<Int>(stateRBOObject->GetSamples());
TextureInternalFormat internalFormat = MGB_RBO_FORMAT;
Int width = MGB_RBO_WIDTH;
Int height = MGB_RBO_HEIGHT;
Int samples = MGB_RBO_SAMPLES;
GLenum glInternalFormat, glType, glFormat;
TextureImpl::GenerateRenderbufferFormatInfo(internalFormat, &glInternalFormat, &glFormat, &glType);
@@ -11492,10 +11557,22 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_cacheWidth = width;
m_cacheHeight = height;
m_cacheSamples = samples;
#if MOBILEGL_PIPE_PUSH
// Stamped in the same breath as the four cache members and AFTER the allocation, so
// an allocation the driver refused with GL_OUT_OF_MEMORY above leaves the twin
// describing what it actually holds. The deferred OOM report and its RecordError are
// untouched: the error still lands on whatever entry point triggered the sync, which
// is where the deferred model puts it.
if (pushedRecord != nullptr) m_syncedResourceSerial = pushedRecord->Serial;
#endif
m_isInitialized = true;
MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId);
}
#undef MGB_RBO_FORMAT
#undef MGB_RBO_WIDTH
#undef MGB_RBO_HEIGHT
#undef MGB_RBO_SAMPLES
TwinRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject, MG_Pipe::MGPipeKind::Renderbuffer>
g_backendRenderbufferObjects;
+14
View File
@@ -2525,6 +2525,20 @@ namespace MobileGL::MG_Backend::DirectGLES {
Int m_cacheWidth = 0;
Int m_cacheHeight = 0;
Int m_cacheSamples = 0;
#if MOBILEGL_PIPE_PUSH
// P4a (D-D2/D-B3): the resource record's Serial at the last completed allocation.
// It replaces the four-field cache above AS A GATE - the four members stay, because
// they are also what the legacy arm compares and what the twin reports about the
// storage it actually holds - and it closes the publication hole D-D2 names:
// RenderbufferObject::{SetInternalFormat, AllocateStorage, SetSamples} bump no
// version and raise no notice, so `glBindRenderbuffer; glRenderbufferStorage(new)`
// on an ALREADY-ATTACHED renderbuffer moved nothing the framebuffer bit could see.
// The client now emits resource_respecify straight from those three mutators, the
// applier bumps this serial, and one compare here sees it.
//
// Push-only, so the pull build's object is byte-for-byte the pre-P4a one (D-P).
Uint64 m_syncedResourceSerial = 0;
#endif
};
extern TwinRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject, MG_Pipe::MGPipeKind::Renderbuffer>