[Feat|Fix] (MG_Backend/DirectGLES): Unify state-backend registries with weak-ref GC.

This commit is contained in:
BZLZHH
2026-02-24 15:27:28 +08:00
parent 15e24cda78
commit 8320b4f456
3 changed files with 127 additions and 26 deletions
+20 -7
View File
@@ -98,7 +98,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject.get()); const auto& backendBufferIt = g_backendBufferObjects.find(bufferObject.get());
Bool exist = (backendBufferIt != g_backendBufferObjects.end()); Bool exist = (backendBufferIt != g_backendBufferObjects.end());
auto& backendObj = exist ? backendBufferIt->second : g_backendBufferObjects[bufferObject.get()]; auto& backendObj = exist ? backendBufferIt->second : g_backendBufferObjects.GetOrCreate(bufferObject);
if (!exist) { if (!exist) {
backendObj = MakeShared<BackendBufferObject>(); backendObj = MakeShared<BackendBufferObject>();
} }
@@ -109,6 +109,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendBufferObjects.CollectGarbageIfNeeded();
// All buffers we need are: // All buffers we need are:
// 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO) // 1.VBO 2.IBO (if needed) 3.UBO 4.IndirectBuffer (if needed) 5.SSBO (TODO)
// PBO is not needed since it should be handled in frontend // PBO is not needed since it should be handled in frontend
@@ -162,6 +164,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendVertexArrayObjects.CollectGarbageIfNeeded();
auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
if (!currentVAOObject) { if (!currentVAOObject) {
MGLOG_E("No VAO is currently bound, cannot sync current VAO."); MGLOG_E("No VAO is currently bound, cannot sync current VAO.");
@@ -170,7 +174,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendVAOIt = g_backendVertexArrayObjects.find(currentVAOObject.get()); const auto& backendVAOIt = g_backendVertexArrayObjects.find(currentVAOObject.get());
Bool exist = (backendVAOIt != g_backendVertexArrayObjects.end()); Bool exist = (backendVAOIt != g_backendVertexArrayObjects.end());
auto& backendObj = exist ? backendVAOIt->second : g_backendVertexArrayObjects[currentVAOObject.get()]; auto& backendObj = exist ? backendVAOIt->second : g_backendVertexArrayObjects.GetOrCreate(currentVAOObject);
if (!exist) { if (!exist) {
backendObj = MakeShared<VertexArrayImpl::BackendVertexArrayObject>(); backendObj = MakeShared<VertexArrayImpl::BackendVertexArrayObject>();
} }
@@ -186,7 +190,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif #endif
const auto& backendTextureIt = g_backendTextureObjects.find(textureObject.get()); const auto& backendTextureIt = g_backendTextureObjects.find(textureObject.get());
Bool exist = (backendTextureIt != g_backendTextureObjects.end()); Bool exist = (backendTextureIt != g_backendTextureObjects.end());
auto& backendObj = exist ? backendTextureIt->second : g_backendTextureObjects[textureObject.get()]; auto& backendObj = exist ? backendTextureIt->second : g_backendTextureObjects.GetOrCreate(textureObject);
if (!exist) { if (!exist) {
backendObj = MakeShared<BackendTextureObject>(); backendObj = MakeShared<BackendTextureObject>();
} }
@@ -201,6 +205,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendTextureObjects.CollectGarbageIfNeeded();
// All textures we need are: // All textures we need are:
// 1. textures bound to texture units (TODO: only sync ones that are used in current program) // 1. textures bound to texture units (TODO: only sync ones that are used in current program)
// 2. textures used in current FBO // 2. textures used in current FBO
@@ -235,6 +241,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendFramebufferObjects.CollectGarbageIfNeeded();
TextureImpl::g_backendTextureObjects.CollectGarbageIfNeeded();
RenderbufferImpl::g_backendRenderbufferObjects.CollectGarbageIfNeeded();
const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read}; const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read};
MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr;
@@ -263,7 +273,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO.get()); const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO.get());
Bool exist = (backendFBOIt != g_backendFramebufferObjects.end()); Bool exist = (backendFBOIt != g_backendFramebufferObjects.end());
auto& backendObj = exist ? backendFBOIt->second : g_backendFramebufferObjects[currentFBO.get()]; auto& backendObj = exist ? backendFBOIt->second : g_backendFramebufferObjects.GetOrCreate(currentFBO);
if (!exist) { if (!exist) {
backendObj = MakeShared<BackendFramebufferObject>(); backendObj = MakeShared<BackendFramebufferObject>();
} }
@@ -457,6 +467,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
g_backendProgramObjects.CollectGarbageIfNeeded();
SamplerImpl::g_backendSamplerObjects.CollectGarbageIfNeeded();
auto& currentProgram = MG_State::pGLContext->GetCurrentProgram(); auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (!currentProgram || !currentProgram->GetLinkStatus()) { if (!currentProgram || !currentProgram->GetLinkStatus()) {
g_GLESFuncs.glUseProgram(0); g_GLESFuncs.glUseProgram(0);
@@ -464,7 +477,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram.get()); const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram.get());
Bool exist = (backendProgramIt != g_backendProgramObjects.end()); Bool exist = (backendProgramIt != g_backendProgramObjects.end());
auto& backendObj = exist ? backendProgramIt->second : g_backendProgramObjects[currentProgram.get()]; auto& backendObj = exist ? backendProgramIt->second : g_backendProgramObjects.GetOrCreate(currentProgram);
if (!exist) { if (!exist) {
backendObj = MakeShared<BackendProgramObjectImpl>(); backendObj = MakeShared<BackendProgramObjectImpl>();
backendObj->SyncToBackend(currentProgram); backendObj->SyncToBackend(currentProgram);
@@ -657,7 +670,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
SamplerImpl::g_backendSamplerObjects.find(samplerObject.get()); SamplerImpl::g_backendSamplerObjects.find(samplerObject.get());
Bool exist = (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()); Bool exist = (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end());
auto& backendObj = exist ? backendSamplerIt->second auto& backendObj = exist ? backendSamplerIt->second
: SamplerImpl::g_backendSamplerObjects[samplerObject.get()]; : SamplerImpl::g_backendSamplerObjects.GetOrCreate(samplerObject);
if (!exist) { if (!exist) {
backendObj = MakeShared<SamplerImpl::BackendSamplerObject>(); backendObj = MakeShared<SamplerImpl::BackendSamplerObject>();
} }
@@ -887,7 +900,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get()); const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
Bool exist = (backendTextureIt != TextureImpl::g_backendTextureObjects.end()); Bool exist = (backendTextureIt != TextureImpl::g_backendTextureObjects.end());
auto& backendObj = auto& backendObj =
exist ? backendTextureIt->second : TextureImpl::g_backendTextureObjects[textureObject.get()]; exist ? backendTextureIt->second : TextureImpl::g_backendTextureObjects.GetOrCreate(textureObject);
if (!exist) { if (!exist) {
backendObj = MakeShared<TextureImpl::BackendTextureObject>(); backendObj = MakeShared<TextureImpl::BackendTextureObject>();
} }
+18 -12
View File
@@ -189,7 +189,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
g_GLESFuncs.glBindBuffer(target, m_backendBufferId); g_GLESFuncs.glBindBuffer(target, m_backendBufferId);
} }
UnorderedMap<MG_State::GLState::BufferObject*, SharedPtr<BackendBufferObject>> g_backendBufferObjects; StateBackendObjectRegistry<MG_State::GLState::BufferObject, BackendBufferObject> g_backendBufferObjects;
BackendBufferObject* g_boundVertexBufferObject = nullptr; BackendBufferObject* g_boundVertexBufferObject = nullptr;
} // namespace BufferImpl } // namespace BufferImpl
@@ -301,7 +301,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions = allAttributeVersions; m_syncedAttributeVersions = allAttributeVersions;
} }
UnorderedMap<MG_State::GLState::VertexArrayObject*, SharedPtr<BackendVertexArrayObject>> StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects; g_backendVertexArrayObjects;
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
@@ -531,8 +531,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject; SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject;
const auto& backendBufferIt = backendBuffers.find(buffer.get()); const auto& backendBufferIt = backendBuffers.find(buffer.get());
if (backendBufferIt == backendBuffers.end()) { if (backendBufferIt == backendBuffers.end()) {
backendBufferObject = MakeShared<BufferImpl::BackendBufferObject>(); auto& backendBufferSlot = backendBuffers.GetOrCreate(buffer);
backendBuffers[buffer.get()] = backendBufferObject; if (!backendBufferSlot) {
backendBufferSlot = MakeShared<BufferImpl::BackendBufferObject>();
}
backendBufferObject = backendBufferSlot;
} else { } else {
backendBufferObject = backendBufferIt->second; backendBufferObject = backendBufferIt->second;
} }
@@ -760,7 +763,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>, Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache; g_boundTexturesCache;
UnorderedMap<MG_State::GLState::ITextureObject*, SharedPtr<BackendTextureObject>> g_backendTextureObjects; StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject> g_backendTextureObjects;
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {
@@ -809,9 +812,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject.get()); RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject.get());
SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject; SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject;
if (backendRenderbufferIt == RenderbufferImpl::g_backendRenderbufferObjects.end()) { if (backendRenderbufferIt == RenderbufferImpl::g_backendRenderbufferObjects.end()) {
backendRenderbufferObject = MakeShared<RenderbufferImpl::BackendRenderbufferObject>(); auto& backendRenderbufferSlot =
RenderbufferImpl::g_backendRenderbufferObjects[renderbufferObject.get()] = RenderbufferImpl::g_backendRenderbufferObjects.GetOrCreate(renderbufferObject);
backendRenderbufferObject; if (!backendRenderbufferSlot) {
backendRenderbufferSlot = MakeShared<RenderbufferImpl::BackendRenderbufferObject>();
}
backendRenderbufferObject = backendRenderbufferSlot;
} else { } else {
backendRenderbufferObject = backendRenderbufferIt->second; backendRenderbufferObject = backendRenderbufferIt->second;
} }
@@ -976,13 +982,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
return glBackendReadBuffer; return glBackendReadBuffer;
} }
UnorderedMap<MG_State::GLState::FramebufferObject*, SharedPtr<BackendFramebufferObject>> StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects; g_backendFramebufferObjects;
Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions = {0}; Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions = {0};
} // namespace FramebufferImpl } // namespace FramebufferImpl
namespace PrgramImpl { namespace PrgramImpl {
UnorderedMap<MG_State::GLState::ProgramObject*, SharedPtr<BackendProgramObjectImpl>> g_backendProgramObjects; StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl> g_backendProgramObjects;
BackendProgramObjectImpl::BackendProgramObjectImpl() { BackendProgramObjectImpl::BackendProgramObjectImpl() {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
@@ -1273,7 +1279,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> g_boundSamplersCache; Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> g_boundSamplersCache;
UnorderedMap<MG_State::GLState::SamplerObject*, SharedPtr<BackendSamplerObject>> g_backendSamplerObjects; StateBackendObjectRegistry<MG_State::GLState::SamplerObject, BackendSamplerObject> g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
namespace RenderbufferImpl { namespace RenderbufferImpl {
@@ -1335,7 +1341,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId); MGLOG_D("RBO %u sync completed. backend ID %u", stateRBOObject->GetExternalIndex(), m_backendRBOId);
} }
UnorderedMap<MG_State::GLState::RenderbufferObject*, SharedPtr<BackendRenderbufferObject>> StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
g_backendRenderbufferObjects; g_backendRenderbufferObjects;
} // namespace RenderbufferImpl } // namespace RenderbufferImpl
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES
+89 -7
View File
@@ -15,6 +15,87 @@
#include <MG_State/GLState/Core.h> #include <MG_State/GLState/Core.h>
namespace MobileGL::MG_Backend::DirectGLES { namespace MobileGL::MG_Backend::DirectGLES {
template <typename StateObject, typename BackendObject>
class StateBackendObjectRegistry {
public:
using StatePtr = SharedPtr<StateObject>;
using StateWeakPtr = std::weak_ptr<StateObject>;
using BackendPtr = SharedPtr<BackendObject>;
using BackendMap = UnorderedMap<StateObject*, BackendPtr>;
using StateRefMap = UnorderedMap<StateObject*, StateWeakPtr>;
using iterator = typename BackendMap::iterator;
using const_iterator = typename BackendMap::const_iterator;
BackendPtr& GetOrCreate(const StatePtr& stateObj) {
MOBILEGL_ASSERT(stateObj != nullptr, "State object must not be null");
auto* key = stateObj.get();
auto trackedStateIt = m_stateRefs.find(key);
if (trackedStateIt != m_stateRefs.end() && trackedStateIt->second.expired()) {
EraseByKey(key);
}
m_stateRefs[key] = stateObj;
return m_backendObjects[key];
}
iterator find(StateObject* stateObj) {
if (!IsAlive(stateObj)) {
EraseByKey(stateObj);
return m_backendObjects.end();
}
return m_backendObjects.find(stateObj);
}
const_iterator find(StateObject* stateObj) const {
return const_cast<StateBackendObjectRegistry*>(this)->find(stateObj);
}
iterator end() { return m_backendObjects.end(); }
const_iterator end() const { return m_backendObjects.end(); }
void CollectGarbageIfNeeded() {
++m_gcTick;
if (m_gcTick < kGCInterval) {
return;
}
CollectGarbage();
m_gcTick = 0;
}
void CollectGarbageNow() { CollectGarbage(); }
private:
bool IsAlive(StateObject* stateObj) const {
const auto trackedStateIt = m_stateRefs.find(stateObj);
if (trackedStateIt == m_stateRefs.end()) {
return false;
}
return !trackedStateIt->second.expired();
}
void EraseByKey(StateObject* stateObj) {
m_stateRefs.erase(stateObj);
m_backendObjects.erase(stateObj);
}
void CollectGarbage() {
for (auto trackedStateIt = m_stateRefs.begin(); trackedStateIt != m_stateRefs.end();) {
if (trackedStateIt->second.expired()) {
m_backendObjects.erase(trackedStateIt->first);
trackedStateIt = m_stateRefs.erase(trackedStateIt);
} else {
++trackedStateIt;
}
}
}
private:
static constexpr Uint32 kGCInterval = 1024;
StateRefMap m_stateRefs;
BackendMap m_backendObjects;
Uint32 m_gcTick = 0;
};
namespace BufferImpl { namespace BufferImpl {
const GLenum TempBufferTarget = GL_ARRAY_BUFFER; const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
class BackendBufferObject { class BackendBufferObject {
@@ -36,7 +117,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}; };
extern BackendBufferObject* g_boundVertexBufferObject; extern BackendBufferObject* g_boundVertexBufferObject;
extern UnorderedMap<MG_State::GLState::BufferObject*, SharedPtr<BackendBufferObject>> g_backendBufferObjects; extern StateBackendObjectRegistry<MG_State::GLState::BufferObject, BackendBufferObject> g_backendBufferObjects;
} // namespace BufferImpl } // namespace BufferImpl
namespace VertexArrayImpl { namespace VertexArrayImpl {
@@ -55,7 +136,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions; m_syncedAttributeVersions;
}; };
extern UnorderedMap<MG_State::GLState::VertexArrayObject*, SharedPtr<BackendVertexArrayObject>> extern StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects; g_backendVertexArrayObjects;
} // namespace VertexArrayImpl } // namespace VertexArrayImpl
@@ -110,7 +191,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
void ActivateTextureUnit(Uint unit); void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target); void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<MG_State::GLState::ITextureObject*, SharedPtr<BackendTextureObject>> extern StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject>
g_backendTextureObjects; g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>, extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
@@ -153,7 +234,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0}; FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0};
}; };
extern UnorderedMap<MG_State::GLState::FramebufferObject*, SharedPtr<BackendFramebufferObject>> extern StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects; g_backendFramebufferObjects;
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions; extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
} // namespace FramebufferImpl } // namespace FramebufferImpl
@@ -174,7 +255,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Bool m_isInitialized = false; Bool m_isInitialized = false;
}; };
extern UnorderedMap<MG_State::GLState::ProgramObject*, SharedPtr<BackendProgramObjectImpl>> extern StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl>
g_backendProgramObjects; g_backendProgramObjects;
} // namespace PrgramImpl } // namespace PrgramImpl
@@ -197,7 +278,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache; g_boundSamplersCache;
extern UnorderedMap<MG_State::GLState::SamplerObject*, SharedPtr<BackendSamplerObject>> g_backendSamplerObjects; extern StateBackendObjectRegistry<MG_State::GLState::SamplerObject, BackendSamplerObject>
g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
namespace RenderbufferImpl { namespace RenderbufferImpl {
@@ -216,7 +298,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Int m_cacheHeight = 0; Int m_cacheHeight = 0;
}; };
extern UnorderedMap<MG_State::GLState::RenderbufferObject*, SharedPtr<BackendRenderbufferObject>> extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
g_backendRenderbufferObjects; g_backendRenderbufferObjects;
} // namespace RenderbufferImpl } // namespace RenderbufferImpl
} // namespace MobileGL::MG_Backend::DirectGLES } // namespace MobileGL::MG_Backend::DirectGLES