[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());
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) {
backendObj = MakeShared<BackendBufferObject>();
}
@@ -109,6 +109,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
g_backendBufferObjects.CollectGarbageIfNeeded();
// All buffers we need are:
// 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
@@ -162,6 +164,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
g_backendVertexArrayObjects.CollectGarbageIfNeeded();
auto& currentVAOObject = MG_State::pGLContext->GetBoundVertexArray();
if (!currentVAOObject) {
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());
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) {
backendObj = MakeShared<VertexArrayImpl::BackendVertexArrayObject>();
}
@@ -186,7 +190,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
#endif
const auto& backendTextureIt = g_backendTextureObjects.find(textureObject.get());
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) {
backendObj = MakeShared<BackendTextureObject>();
}
@@ -201,6 +205,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
g_backendTextureObjects.CollectGarbageIfNeeded();
// All textures we need are:
// 1. textures bound to texture units (TODO: only sync ones that are used in current program)
// 2. textures used in current FBO
@@ -235,6 +241,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
g_backendFramebufferObjects.CollectGarbageIfNeeded();
TextureImpl::g_backendTextureObjects.CollectGarbageIfNeeded();
RenderbufferImpl::g_backendRenderbufferObjects.CollectGarbageIfNeeded();
const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read};
MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr;
@@ -263,7 +273,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendFBOIt = g_backendFramebufferObjects.find(currentFBO.get());
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) {
backendObj = MakeShared<BackendFramebufferObject>();
}
@@ -457,6 +467,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif
g_backendProgramObjects.CollectGarbageIfNeeded();
SamplerImpl::g_backendSamplerObjects.CollectGarbageIfNeeded();
auto& currentProgram = MG_State::pGLContext->GetCurrentProgram();
if (!currentProgram || !currentProgram->GetLinkStatus()) {
g_GLESFuncs.glUseProgram(0);
@@ -464,7 +477,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
const auto& backendProgramIt = g_backendProgramObjects.find(currentProgram.get());
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) {
backendObj = MakeShared<BackendProgramObjectImpl>();
backendObj->SyncToBackend(currentProgram);
@@ -657,7 +670,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
SamplerImpl::g_backendSamplerObjects.find(samplerObject.get());
Bool exist = (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end());
auto& backendObj = exist ? backendSamplerIt->second
: SamplerImpl::g_backendSamplerObjects[samplerObject.get()];
: SamplerImpl::g_backendSamplerObjects.GetOrCreate(samplerObject);
if (!exist) {
backendObj = MakeShared<SamplerImpl::BackendSamplerObject>();
}
@@ -887,7 +900,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject.get());
Bool exist = (backendTextureIt != TextureImpl::g_backendTextureObjects.end());
auto& backendObj =
exist ? backendTextureIt->second : TextureImpl::g_backendTextureObjects[textureObject.get()];
exist ? backendTextureIt->second : TextureImpl::g_backendTextureObjects.GetOrCreate(textureObject);
if (!exist) {
backendObj = MakeShared<TextureImpl::BackendTextureObject>();
}
+18 -12
View File
@@ -189,7 +189,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
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;
} // namespace BufferImpl
@@ -301,7 +301,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions = allAttributeVersions;
}
UnorderedMap<MG_State::GLState::VertexArrayObject*, SharedPtr<BackendVertexArrayObject>>
StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects;
} // namespace VertexArrayImpl
@@ -531,8 +531,11 @@ namespace MobileGL::MG_Backend::DirectGLES {
SharedPtr<BufferImpl::BackendBufferObject> backendBufferObject;
const auto& backendBufferIt = backendBuffers.find(buffer.get());
if (backendBufferIt == backendBuffers.end()) {
backendBufferObject = MakeShared<BufferImpl::BackendBufferObject>();
backendBuffers[buffer.get()] = backendBufferObject;
auto& backendBufferSlot = backendBuffers.GetOrCreate(buffer);
if (!backendBufferSlot) {
backendBufferSlot = MakeShared<BufferImpl::BackendBufferObject>();
}
backendBufferObject = backendBufferSlot;
} else {
backendBufferObject = backendBufferIt->second;
}
@@ -760,7 +763,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache;
UnorderedMap<MG_State::GLState::ITextureObject*, SharedPtr<BackendTextureObject>> g_backendTextureObjects;
StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject> g_backendTextureObjects;
} // namespace TextureImpl
namespace FramebufferImpl {
@@ -809,9 +812,12 @@ namespace MobileGL::MG_Backend::DirectGLES {
RenderbufferImpl::g_backendRenderbufferObjects.find(renderbufferObject.get());
SharedPtr<RenderbufferImpl::BackendRenderbufferObject> backendRenderbufferObject;
if (backendRenderbufferIt == RenderbufferImpl::g_backendRenderbufferObjects.end()) {
backendRenderbufferObject = MakeShared<RenderbufferImpl::BackendRenderbufferObject>();
RenderbufferImpl::g_backendRenderbufferObjects[renderbufferObject.get()] =
backendRenderbufferObject;
auto& backendRenderbufferSlot =
RenderbufferImpl::g_backendRenderbufferObjects.GetOrCreate(renderbufferObject);
if (!backendRenderbufferSlot) {
backendRenderbufferSlot = MakeShared<RenderbufferImpl::BackendRenderbufferObject>();
}
backendRenderbufferObject = backendRenderbufferSlot;
} else {
backendRenderbufferObject = backendRenderbufferIt->second;
}
@@ -976,13 +982,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
return glBackendReadBuffer;
}
UnorderedMap<MG_State::GLState::FramebufferObject*, SharedPtr<BackendFramebufferObject>>
StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects;
Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions = {0};
} // namespace FramebufferImpl
namespace PrgramImpl {
UnorderedMap<MG_State::GLState::ProgramObject*, SharedPtr<BackendProgramObjectImpl>> g_backendProgramObjects;
StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl> g_backendProgramObjects;
BackendProgramObjectImpl::BackendProgramObjectImpl() {
#ifdef TRACY_ENABLE
@@ -1273,7 +1279,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
}
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 RenderbufferImpl {
@@ -1335,7 +1341,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
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;
} // namespace RenderbufferImpl
} // namespace MobileGL::MG_Backend::DirectGLES
+89 -7
View File
@@ -15,6 +15,87 @@
#include <MG_State/GLState/Core.h>
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 {
const GLenum TempBufferTarget = GL_ARRAY_BUFFER;
class BackendBufferObject {
@@ -36,7 +117,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
};
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 VertexArrayImpl {
@@ -55,7 +136,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
m_syncedAttributeVersions;
};
extern UnorderedMap<MG_State::GLState::VertexArrayObject*, SharedPtr<BackendVertexArrayObject>>
extern StateBackendObjectRegistry<MG_State::GLState::VertexArrayObject, BackendVertexArrayObject>
g_backendVertexArrayObjects;
} // namespace VertexArrayImpl
@@ -110,7 +191,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<MG_State::GLState::ITextureObject*, SharedPtr<BackendTextureObject>>
extern StateBackendObjectRegistry<MG_State::GLState::ITextureObject, BackendTextureObject>
g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
@@ -153,7 +234,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
FramebufferObject::FramebufferAttachmentVersionArray m_syncedFrontendAttachmentVersions = {0};
};
extern UnorderedMap<MG_State::GLState::FramebufferObject*, SharedPtr<BackendFramebufferObject>>
extern StateBackendObjectRegistry<MG_State::GLState::FramebufferObject, BackendFramebufferObject>
g_backendFramebufferObjects;
extern Array<Uint16, SizeT(FramebufferTarget::FramebufferTargetCount)> g_fboBindVersions;
} // namespace FramebufferImpl
@@ -174,7 +255,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Bool m_isInitialized = false;
};
extern UnorderedMap<MG_State::GLState::ProgramObject*, SharedPtr<BackendProgramObjectImpl>>
extern StateBackendObjectRegistry<MG_State::GLState::ProgramObject, BackendProgramObjectImpl>
g_backendProgramObjects;
} // namespace PrgramImpl
@@ -197,7 +278,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache;
extern UnorderedMap<MG_State::GLState::SamplerObject*, SharedPtr<BackendSamplerObject>> g_backendSamplerObjects;
extern StateBackendObjectRegistry<MG_State::GLState::SamplerObject, BackendSamplerObject>
g_backendSamplerObjects;
} // namespace SamplerImpl
namespace RenderbufferImpl {
@@ -216,7 +298,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
Int m_cacheHeight = 0;
};
extern UnorderedMap<MG_State::GLState::RenderbufferObject*, SharedPtr<BackendRenderbufferObject>>
extern StateBackendObjectRegistry<MG_State::GLState::RenderbufferObject, BackendRenderbufferObject>
g_backendRenderbufferObjects;
} // namespace RenderbufferImpl
} // namespace MobileGL::MG_Backend::DirectGLES