[Perf] (MG_Backend/DirectGLES): Add cache for Texture and Sampler binding.

This commit is contained in:
BZLZHH
2026-02-03 16:44:00 +08:00
parent b966ef8b5e
commit 5eff8b2e30
4 changed files with 71 additions and 25 deletions
+15 -23
View File
@@ -7,6 +7,7 @@
// End of Source File Header // End of Source File Header
#include "DirectGLES.h" #include "DirectGLES.h"
#include "MG_State/GLState/SamplerState/SamplerObject.h"
#include "Utils.h" #include "Utils.h"
#include "Managers.h" #include "Managers.h"
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h> #include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
@@ -419,8 +420,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
for (Int unit = 0; unit < maxTextureUnits; ++unit) { for (Int unit = 0; unit < maxTextureUnits; ++unit) {
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit); auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
for (const auto& bindingSlot : textureUnit.GetAllBindingSlots()) { for (const auto& bindingSlot : textureUnit.GetAllBindingSlots()) {
const auto& textureObject = bindingSlot.GetBoundObject(); const auto& textureObject = bindingSlot.GetBoundObject();
if (!textureObject) continue; if (!textureObject) continue;
@@ -436,18 +435,18 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue; if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue;
GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target); GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target);
backendTextureIt->second->Bind(targetGL); backendTextureIt->second->Bind(targetGL, unit);
} }
// Bind sampler object // Bind sampler object if necessary
const auto& samplerObject = textureUnit.GetSamplerObject(); const auto& samplerObject = textureUnit.GetSamplerObject();
if (samplerObject) { if (samplerObject) {
const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject);
if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) { if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) {
backendSamplerIt->second->Bind(unit); backendSamplerIt->second->Bind(unit);
} }
} else { } else {
MG_External::GLES::glBindSampler(unit, 0);
} }
} }
} }
@@ -551,7 +550,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
backendSamplerObject->SyncToBackend(samplerObject); backendSamplerObject->SyncToBackend(samplerObject);
} else { } else {
MG_External::GLES::glBindSampler(unit, 0); SamplerImpl::UnbindSampler(unit);
} }
} }
} }
@@ -751,14 +750,13 @@ namespace MobileGL::MG_Backend::DirectGLES {
}); });
} }
bool UpdateTextureBindingAtTarget(GLenum target) { Bool UpdateTextureBindingAtTarget(GLenum target) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND); ZoneScopedNC(__func__, TRACY_ZONECOLOR_BACKEND);
#endif #endif
auto unit = MG_State::pGLContext->GetActiveTextureUnit(); auto unit = MG_State::pGLContext->GetActiveTextureUnit();
auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit); auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit);
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); auto textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target);
if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) { if (!TextureImpl::IsSupportedTextureTarget(textureTarget)) {
MOBILEGL_ASSERT(false, " Texture target %s is not supported, skipping.", MOBILEGL_ASSERT(false, " Texture target %s is not supported, skipping.",
@@ -782,7 +780,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
} else { } else {
backendTextureObject = backendTextureIt->second; backendTextureObject = backendTextureIt->second;
} }
backendTextureObject->Bind(target); backendTextureObject->Bind(target, unit);
} }
return true; return true;
} }
@@ -809,12 +807,6 @@ namespace MobileGL::MG_Backend::DirectGLES {
if (!UpdateTextureBindingAtTarget(target)) return; if (!UpdateTextureBindingAtTarget(target)) return;
// GLint realInternalFormat;
// MG_External::GLES::glGetTexLevelParameteriv(target, level, GL_TEXTURE_INTERNAL_FORMAT,
// &realInternalFormat); errorLopper.Loop([file = __FILE__, line = __LINE__](auto err) {
// MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str());
// });
// internalformat = (GLenum)realInternalFormat;
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
GLenum format = GL_DEPTH_COMPONENT; GLenum format = GL_DEPTH_COMPONENT;
@@ -827,9 +819,9 @@ namespace MobileGL::MG_Backend::DirectGLES {
MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str()); MG_Util::ConvertGLEnumToString(format).c_str(), MG_Util::ConvertGLEnumToString(type).c_str());
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type); TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
bool isDepthFormat = Bool isDepthFormat =
MG_Util::IsDepthFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)); MG_Util::IsDepthFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
bool isStencilFormat = Bool isStencilFormat =
MG_Util::IsStencilFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat)); MG_Util::IsStencilFormatInternalFormat(MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat));
if (!isDepthFormat) { if (!isDepthFormat) {
@@ -902,8 +894,8 @@ namespace MobileGL::MG_Backend::DirectGLES {
}); });
auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat); auto mglInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalFormat);
bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat); Bool isDepthFormat = MG_Util::IsDepthFormatInternalFormat(mglInternalFormat);
bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat); Bool isStencilFormat = MG_Util::IsStencilFormatInternalFormat(mglInternalFormat);
if (!isDepthFormat) { if (!isDepthFormat) {
MG_External::GLES::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); MG_External::GLES::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
@@ -946,7 +938,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
auto texture = slot.GetBoundObject(); auto texture = slot.GetBoundObject();
auto backendTexture = TextureImpl::SyncTextureObjectToBackend(texture); auto backendTexture = TextureImpl::SyncTextureObjectToBackend(texture);
backendTexture->Bind(target); backendTexture->Bind(target, unitIndex);
MG_External::GLES::glGenerateMipmap(target); MG_External::GLES::glGenerateMipmap(target);
} }
@@ -995,7 +987,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
bool found = false; Bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i; realDrawbuffer = i;
@@ -1048,7 +1040,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
bool found = false; Bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i; realDrawbuffer = i;
@@ -1102,7 +1094,7 @@ namespace MobileGL::MG_Backend::DirectGLES {
return; return;
} }
bool found = false; Bool found = false;
for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) {
if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) {
realDrawbuffer = i; realDrawbuffer = i;
@@ -8,6 +8,8 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#include <MG_State/GLState/TextureState/TextureState.h>
#include <MG_State/GLState/SamplerState/SamplerObject.h>
#define CallAndCheck(operation) \ #define CallAndCheck(operation) \
MGLOG_D("Call GLES func: %s", #operation); \ MGLOG_D("Call GLES func: %s", #operation); \
+42 -1
View File
@@ -7,6 +7,10 @@
// End of Source File Header // End of Source File Header
#include "Managers.h" #include "Managers.h"
#include "MG_State/GLState/TextureState/TextureEnum.h"
#include "MG_State/GLState/TextureState/TextureObject.h"
#include "MG_State/GLState/TextureState/TextureState.h"
#include "MG_Util/Converters/GLToMG/TextureEnumConverter.h"
#include "Utils.h" #include "Utils.h"
#include "DirectGLES.h" #include "DirectGLES.h"
@@ -345,11 +349,16 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void BackendTextureObject::Bind(GLenum target) { void BackendTextureObject::Bind(GLenum target, Uint unit) {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
auto targetN = static_cast<SizeT>(MG_Util::ConvertGLEnumToTextureTarget(target));
if (this == g_boundTexturesCache[unit][targetN]) return;
ActivateTextureUnit(unit);
MG_External::GLES::glBindTexture(target, m_backendTextureId); MG_External::GLES::glBindTexture(target, m_backendTextureId);
g_boundTexturesCache[unit][targetN] = this;
} }
Uint BackendTextureObject::GetBackendTextureId() { Uint BackendTextureObject::GetBackendTextureId() {
@@ -759,6 +768,27 @@ namespace MobileGL::MG_Backend::DirectGLES {
} }
} }
void ActivateTextureUnit(Uint unit) {
if (unit == g_activeTextureUnit) {
return;
}
MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit);
g_activeTextureUnit = unit;
}
void UnbindTexture(Uint unit, GLenum target) { // Active unit will be modified
auto targetN = static_cast<SizeT>(MG_Util::ConvertGLEnumToTextureTarget(target));
if (g_boundTexturesCache[unit][targetN] == nullptr) return;
ActivateTextureUnit(unit);
MG_External::GLES::glBindTexture(target, 0);
g_boundTexturesCache[unit][targetN] = nullptr;
}
Uint g_activeTextureUnit = 0;
Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache;
UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>> UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>>
g_backendTextureObjects; g_backendTextureObjects;
} // namespace TextureImpl } // namespace TextureImpl
@@ -1194,7 +1224,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
#ifdef TRACY_ENABLE #ifdef TRACY_ENABLE
ZoneScopedC(TRACY_ZONECOLOR_BACKEND); ZoneScopedC(TRACY_ZONECOLOR_BACKEND);
#endif #endif
if (g_boundSamplersCache[unit] == this) return;
MG_External::GLES::glBindSampler(static_cast<GLenum>(unit), m_backendSamplerId); MG_External::GLES::glBindSampler(static_cast<GLenum>(unit), m_backendSamplerId);
g_boundSamplersCache[unit] = this;
} }
Uint BackendSamplerObject::GetBackendSamplerId() { Uint BackendSamplerObject::GetBackendSamplerId() {
@@ -1204,6 +1237,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
return m_backendSamplerId; return m_backendSamplerId;
} }
void UnbindSampler(Uint unit) {
if (g_boundSamplersCache[unit] == nullptr) return;
MG_External::GLES::glBindSampler(static_cast<GLenum>(unit), 0);
g_boundSamplersCache[unit] = nullptr;
}
Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS> g_boundSamplersCache;
UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>> UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>>
g_backendSamplerObjects; g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl
+12 -1
View File
@@ -90,13 +90,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); } bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); }
}; };
inline const Uint TempTextureUnit = 0;
class BackendTextureObject { class BackendTextureObject {
public: public:
BackendTextureObject(); BackendTextureObject();
void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncMipmapsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncBuiltinSamplerToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncBuiltinSamplerToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void SyncTextureParamsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject); void SyncTextureParamsToBackend(SharedPtr<MG_State::GLState::ITextureObject>& stateTextureObject);
void Bind(GLenum target); void Bind(GLenum target, Uint unit = TempTextureUnit);
Uint GetBackendTextureId(); Uint GetBackendTextureId();
private: private:
@@ -112,8 +113,14 @@ namespace MobileGL::MG_Backend::DirectGLES {
Uint16 m_syncedTextureParamsVersion = 0; Uint16 m_syncedTextureParamsVersion = 0;
}; };
void ActivateTextureUnit(Uint unit);
void UnbindTexture(Uint unit, GLenum target);
extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::ITextureObject>, SharedPtr<BackendTextureObject>>
g_backendTextureObjects; g_backendTextureObjects;
extern Array<Array<BackendTextureObject*, (SizeT)TextureTarget::TextureTargetCount>,
MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundTexturesCache;
extern Uint g_activeTextureUnit;
} // namespace TextureImpl } // namespace TextureImpl
namespace FramebufferImpl { namespace FramebufferImpl {
@@ -193,6 +200,10 @@ namespace MobileGL::MG_Backend::DirectGLES {
Uint16 m_syncedSamplerVersion = 0; Uint16 m_syncedSamplerVersion = 0;
}; };
void UnbindSampler(Uint unit);
extern Array<BackendSamplerObject*, MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS>
g_boundSamplersCache;
extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>> extern UnorderedMap<SharedPtr<MG_State::GLState::SamplerObject>, SharedPtr<BackendSamplerObject>>
g_backendSamplerObjects; g_backendSamplerObjects;
} // namespace SamplerImpl } // namespace SamplerImpl