diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 52e3c4f1..f9764f17 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -394,6 +394,22 @@ namespace MobileGL::MG_Backend::DirectGLES { auto locAtBackend = MG_External::GLES::glGetUniformLocation( backendProgramIt->second->GetBackendProgramId(), name.c_str()); MG_External::GLES::glUniform1i(locAtBackend, unit); + + auto samplerObject = MG_State::pGLContext->GetTextureUnitObject(unit).GetSamplerObject(); + + if (samplerObject) { + const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); + SharedPtr backendSamplerObject; + if (backendSamplerIt == SamplerImpl::g_backendSamplerObjects.end()) { + backendSamplerObject = MakeShared(); + SamplerImpl::g_backendSamplerObjects[samplerObject] = backendSamplerObject; + } else { + backendSamplerObject = backendSamplerIt->second; + } + backendSamplerObject->SyncToBackend(samplerObject); + } else { + MG_External::GLES::glBindSampler(unit, 0); + } } } else { MG_External::GLES::glUseProgram(0); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 234309ba..58548188 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -295,6 +295,7 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(mipmap.size.x()), static_cast(mipmap.size.y()), 0, glFormat, glType, mipmap.hasData ? mipmap.data.data() : nullptr); + // TODO: handle more texture types MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId); stateTextureObject->UnmarkMipmapDirty(level); @@ -303,33 +304,39 @@ namespace MobileGL::MG_Backend::DirectGLES { m_isInitialized = true; } - { // Update sampler parameters; TODO: always use sampler objects in backend - const auto& samplerObject = stateTextureObject->GetSamplerObject(); - if (samplerObject) { - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_MIN_FILTER, - MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObject->GetMinFilter())); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_MAG_FILTER, - MG_Util::ConvertSamplerFilterModeToGLEnum(samplerObject->GetMagFilter())); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_WRAP_S, MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObject->GetWrapS())); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_WRAP_T, MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObject->GetWrapT())); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_WRAP_R, MG_Util::ConvertSamplerWrapModeToGLEnum(samplerObject->GetWrapR())); - MG_External::GLES::glTexParameteri(target, GL_TEXTURE_MIN_LOD, samplerObject->GetMinLod()); - MG_External::GLES::glTexParameteri(target, GL_TEXTURE_MAX_LOD, samplerObject->GetMaxLod()); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_COMPARE_FUNC, - MG_Util::ConvertSamplerCompareFuncToGLEnum(samplerObject->GetSamplerCompareFunc())); - MG_External::GLES::glTexParameteri( - target, GL_TEXTURE_COMPARE_MODE, - MG_Util::ConvertSamplerCompareModeToGLEnum(samplerObject->GetCompareMode())); + { // Update built-in sampler parameters + MGLOG_D("Updating sampler parameters for texture with ID: %u", m_backendTextureId); + const auto& samplerParams = stateTextureObject->GetSamplerObject()->GetAllSamplerParameters(); + +#define SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \ + if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \ + MG_External::GLES::glTexParameteri(target, glName, \ + MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \ + m_cacheSamplerParameters.internalName = samplerParams.internalName; \ + } + + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(minFilter, GL_TEXTURE_MIN_FILTER, FilterMode) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(magFilter, GL_TEXTURE_MAG_FILTER, FilterMode) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(wrapS, GL_TEXTURE_WRAP_S, WrapMode) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(wrapT, GL_TEXTURE_WRAP_T, WrapMode) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(wrapR, GL_TEXTURE_WRAP_R, WrapMode) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(compareFunc, GL_TEXTURE_COMPARE_FUNC, CompareFunc) + SYNC_TEX_SAMPLER_PARAM_IF_CHANGED(compareMode, GL_TEXTURE_COMPARE_MODE, CompareMode) + if (m_cacheSamplerParameters.minLod != samplerParams.minLod) { + MG_External::GLES::glTexParameterf(target, GL_TEXTURE_MIN_LOD, samplerParams.minLod); + m_cacheSamplerParameters.minLod = samplerParams.minLod; } + if (m_cacheSamplerParameters.maxLod != samplerParams.maxLod) { + MG_External::GLES::glTexParameterf(target, GL_TEXTURE_MAX_LOD, samplerParams.maxLod); + m_cacheSamplerParameters.maxLod = samplerParams.maxLod; + } + +#undef SYNC_TEX_SAMPLER_PARAM_IF_CHANGED } { // Update texture parameters + MGLOG_D("Updating texture parameters for texture with ID: %u", m_backendTextureId); + const auto& levelRange = stateTextureObject->GetLevelRange(); MG_External::GLES::glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, static_cast(levelRange.x())); MG_External::GLES::glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, static_cast(levelRange.y())); @@ -675,5 +682,65 @@ namespace MobileGL::MG_Backend::DirectGLES { } } // namespace PrgramImpl + namespace SamplerImpl { + BackendSamplerObject::BackendSamplerObject() { + MG_External::GLES::glGenSamplers(1, &m_backendSamplerId); + if (m_backendSamplerId == 0) { + MGLOG_E("Failed to generate sampler object."); + MGLOG_E("ES glGetError(): %s", MG_Util::ConvertGLEnumToString(MG_External::GLES::glGetError()).c_str()); + } else { + MGLOG_D("Generated sampler object with ID: %u.", m_backendSamplerId); + } + } + + void BackendSamplerObject::SyncToBackend(SharedPtr& stateSamplerObject) { + if (!stateSamplerObject) { + MGLOG_E("State sampler object is null, cannot sync to backend."); + return; + } + + MGLOG_D("Syncing sampler with backend ID %u to backend for state ID %u", m_backendSamplerId, + stateSamplerObject->GetExternalIndex()); + + const auto& samplerParams = stateSamplerObject->GetAllSamplerParameters(); + +#define SYNC_SAMPLER_PARAM_IF_CHANGED(internalName, glName, type) \ + if (m_cacheSamplerParameters.internalName != samplerParams.internalName) { \ + MG_External::GLES::glSamplerParameteri(m_backendSamplerId, glName, \ + MG_Util::ConvertSampler##type##ToGLEnum(samplerParams.internalName)); \ + m_cacheSamplerParameters.internalName = samplerParams.internalName; \ + } + + SYNC_SAMPLER_PARAM_IF_CHANGED(minFilter, GL_TEXTURE_MIN_FILTER, FilterMode) + SYNC_SAMPLER_PARAM_IF_CHANGED(magFilter, GL_TEXTURE_MAG_FILTER, FilterMode) + SYNC_SAMPLER_PARAM_IF_CHANGED(wrapS, GL_TEXTURE_WRAP_S, WrapMode) + SYNC_SAMPLER_PARAM_IF_CHANGED(wrapT, GL_TEXTURE_WRAP_T, WrapMode) + SYNC_SAMPLER_PARAM_IF_CHANGED(wrapR, GL_TEXTURE_WRAP_R, WrapMode) + SYNC_SAMPLER_PARAM_IF_CHANGED(compareFunc, GL_TEXTURE_COMPARE_FUNC, CompareFunc) + SYNC_SAMPLER_PARAM_IF_CHANGED(compareMode, GL_TEXTURE_COMPARE_MODE, CompareMode) + if (m_cacheSamplerParameters.minLod != samplerParams.minLod) { + MG_External::GLES::glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MIN_LOD, samplerParams.minLod); + m_cacheSamplerParameters.minLod = samplerParams.minLod; + } + if (m_cacheSamplerParameters.maxLod != samplerParams.maxLod) { + MG_External::GLES::glSamplerParameterf(m_backendSamplerId, GL_TEXTURE_MAX_LOD, samplerParams.maxLod); + m_cacheSamplerParameters.maxLod = samplerParams.maxLod; + } +#undef SYNC_SAMPLER_PARAM_IF_CHANGED + m_isInitialized = true; + } + + void BackendSamplerObject::Bind(Uint unit) { + MG_External::GLES::glBindSampler(static_cast(unit), m_backendSamplerId); + } + + Uint BackendSamplerObject::GetBackendSamplerId() { + return m_backendSamplerId; + } + + UnorderedMap, SharedPtr> + g_backendSamplerObjects; + } // namespace SamplerImpl + namespace Utils {} // namespace Utils } // namespace MobileGL::MG_Backend::DirectGLES diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index fbde7cb6..7330603e 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -1,6 +1,7 @@ #pragma once #include #include "DirectGLES.h" +#include "MG_State/GLState/SamplerState/SamplerObject.h" #include #include @@ -73,6 +74,7 @@ namespace MobileGL::MG_Backend::DirectGLES { Uint m_backendTextureId = 0; Bool m_isInitialized = false; StateTextureBasicInfo m_prevTextureInfo; + SamplerParameters m_cacheSamplerParameters; }; extern UnorderedMap, SharedPtr> @@ -135,4 +137,22 @@ namespace MobileGL::MG_Backend::DirectGLES { extern UnorderedMap, SharedPtr> g_backendProgramObjects; } // namespace PrgramImpl + + namespace SamplerImpl { + class BackendSamplerObject { + public: + BackendSamplerObject(); + void SyncToBackend(SharedPtr& stateSamplerObject); + void Bind(Uint unit); + Uint GetBackendSamplerId(); + + private: + Uint m_backendSamplerId = 0; + Bool m_isInitialized = false; + SamplerParameters m_cacheSamplerParameters; + }; + + extern UnorderedMap, SharedPtr> + g_backendSamplerObjects; + } // namespace SamplerImpl } // namespace MobileGL::MG_Backend::DirectGLES