From 0a89ad4f301cccd78b9df4380f6d80133a6f1bdf Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 9 Dec 2025 10:57:10 +0800 Subject: [PATCH 01/18] [Feat] (MG_State/Texture): separate mipmap from TextureObjectBase --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 5 +- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 162 +++++++++--------- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 85 +++++++-- .../FramebufferState/FramebufferObject.cpp | 4 +- .../GLState/TextureState/TextureEnum.h | 5 + .../GLState/TextureState/TextureObject.h | 40 ++--- .../TextureState/TextureObject2DCube.cpp | 2 +- .../TextureState/TextureObject2DCube.h | 2 +- 8 files changed, 189 insertions(+), 116 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index e36da553..dfedf9be 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -750,7 +750,10 @@ namespace MobileGL::MG_Backend::DirectGLES { auto textureObject = bindingSlot.GetBoundObject(); textureObject->SetInternalFormat(mglInternalFormat); - textureObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0}); + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0}); } void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index dc75d9c3..cf0168e3 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -289,58 +289,103 @@ namespace MobileGL::MG_Backend::DirectGLES { errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - - const auto mipmapCount = stateTextureObject->GetMipmapLevelCount(); const auto baseSize = stateTextureObject->GetBaseSize(); StateTextureBasicInfo currentTextureInfo = { stateTextureObject->GetFormat(), static_cast(baseSize.x()), static_cast(baseSize.y()), - static_cast(baseSize.z()), mipmapCount}; + static_cast(baseSize.z()), 0}; + switch (stateTextureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + auto* textureMipmapObject = static_cast(stateTextureObject.get()); + const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); + currentTextureInfo.mipmapLevels = mipmapCount; - Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo); + Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo); - MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(), - baseSize.z(), mipmapCount, - MG_Util::ConvertTextureInternalFormatToString(stateTextureObject->GetFormat()).c_str()); + MGLOG_D("%s: Got texture info: %dx%dx%d, mips %d, format %s", __func__, baseSize.x(), baseSize.y(), + baseSize.z(), mipmapCount, + MG_Util::ConvertTextureInternalFormatToString(textureMipmapObject->GetFormat()).c_str()); - if (needsRegeneration) { - MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u", - m_backendTextureId); + if (needsRegeneration) { + MGLOG_D("Texture state changed significantly or not initialized, regenerating texture with ID: %u", + m_backendTextureId); - // Regenerate all mipmap levels - GLenum glInternalFormat, glType, glFormat; - TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType, - &glFormat); + // Regenerate all mipmap levels + GLenum glInternalFormat, glType, glFormat; + TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType, + &glFormat); - const auto& uploadTargets = stateTextureObject->GetUploadTargets(); - for (auto uploadTarget : uploadTargets) { - for (SizeT level = 0; level < mipmapCount; ++level) { - auto levelTexelSize = stateTextureObject->GetMipmapTexelSize(uploadTarget, level); - auto levelByteSize = stateTextureObject->GetMipmapByteSize(uploadTarget, level); - bool levelDirty = stateTextureObject->IsStorageDirty(uploadTarget, 0); - auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); - auto* pData = (levelDirty && levelByteSize != 0) - ? stateTextureObject->MapMipmapData(uploadTarget, level) - : nullptr; - MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, - MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, - levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData); - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); - errorLopper.Clear(); - MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - MG_External::GLES::glTexImage2D(glUploadTarget, static_cast(level), glInternalFormat, - static_cast(levelTexelSize.x()), - static_cast(levelTexelSize.y()), 0, glFormat, glType, - pData); + const auto& uploadTargets = textureMipmapObject->GetUploadTargets(); + for (auto uploadTarget : uploadTargets) { + for (SizeT level = 0; level < mipmapCount; ++level) { + auto levelTexelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); + auto levelByteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level); + bool levelDirty = textureMipmapObject->IsStorageDirty(uploadTarget, 0); + auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); + auto* pData = (levelDirty && levelByteSize != 0) + ? textureMipmapObject->MapMipmapData(uploadTarget, level) + : nullptr; + MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, + MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, + levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData); + BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = + BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + errorLopper.Clear(); + MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + MG_External::GLES::glTexImage2D(glUploadTarget, static_cast(level), glInternalFormat, + static_cast(levelTexelSize.x()), + static_cast(levelTexelSize.y()), 0, glFormat, glType, + pData); - // TODO: handle more texture types + // TODO: handle more texture types - MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId); - stateTextureObject->MarkStorageDirty(uploadTarget, level, false); + MGLOG_D("Regenerated mipmap level %d for texture with ID: %u", level, m_backendTextureId); + textureMipmapObject->MarkStorageDirty(uploadTarget, level, false); + } + } + + m_isInitialized = true; } - } - m_isInitialized = true; + { // Update all dirty mipmap levels + const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); + GLenum glInternalFormat, glType, glFormat; + TextureImpl::GenerateTextureFormatInfo(textureMipmapObject->GetFormat(), &glInternalFormat, &glType, + &glFormat); + const auto& uploadTargets = textureMipmapObject->GetUploadTargets(); + for (auto uploadTarget : uploadTargets) { + for (SizeT level = 0; level < mipmapCount; ++level) { + if (!textureMipmapObject->IsStorageDirty(uploadTarget, level)) { + continue; + } + + auto byteSize = textureMipmapObject->GetMipmapByteSize(uploadTarget, level); + if (byteSize == 0) { + MGLOG_W("Mipmap level %d has no data, skipping update.", level); + continue; + } + + auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); + + BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = + BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { + MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, + MG_Util::ConvertGLEnumToString(err).c_str()); + }); + auto texelSize = textureMipmapObject->GetMipmapTexelSize(uploadTarget, level); + MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast(level), 0, 0, + static_cast(texelSize.x()), + static_cast(texelSize.y()), glFormat, glType, + textureMipmapObject->MapMipmapData(uploadTarget, level)); + + textureMipmapObject->MarkStorageDirty(uploadTarget, level, false); + } + } + } + break; + } + default: THROW_UNIMPL_EXCEPTION; } { // Update built-in sampler parameters @@ -448,43 +493,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } } - { // Update all dirty mipmap levels - const auto mipmapCount = stateTextureObject->GetMipmapLevelCount(); - GLenum glInternalFormat, glType, glFormat; - TextureImpl::GenerateTextureFormatInfo(stateTextureObject->GetFormat(), &glInternalFormat, &glType, - &glFormat); - const auto& uploadTargets = stateTextureObject->GetUploadTargets(); - for (auto uploadTarget : uploadTargets) { - for (SizeT level = 0; level < mipmapCount; ++level) { - if (!stateTextureObject->IsStorageDirty(uploadTarget, level)) { - continue; - } - - auto byteSize = stateTextureObject->GetMipmapByteSize(uploadTarget, level); - if (byteSize == 0) { - MGLOG_W("Mipmap level %d has no data, skipping update.", level); - continue; - } - - auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); - - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); - MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { - MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, - MG_Util::ConvertGLEnumToString(err).c_str()); - }); - auto texelSize = stateTextureObject->GetMipmapTexelSize(uploadTarget, level); - MG_External::GLES::glTexSubImage2D(glUploadTarget, static_cast(level), 0, 0, - static_cast(texelSize.x()), - static_cast(texelSize.y()), glFormat, glType, - stateTextureObject->MapMipmapData(uploadTarget, level)); - - stateTextureObject->MarkStorageDirty(uploadTarget, level, false); - } - } - } errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 811c4fc5..baea89f0 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -64,9 +64,14 @@ namespace MobileGL { if (!TextureImpl::ValidateTextureSubImageOffsets(textureObject, xoffset, width, yoffset, height)) return; // ======================= Processing ================================ - // auto& mipmap = textureObject->GetMipmap(level); - // Vector& data = mipmap.data; - auto texelSize = textureObject->GetMipmapTexelSize(textureUploadingTarget, level); + // Texture object here should always be an object with mipmap + // Assert this for extra safety. + // This should automatically compiled out in release, + // so that we don't take the perf hit of dyn-cast. + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level); SizeT imageSize = 0; const SizeT bytesPerPixel = MG_Util::GetInputBytesPerPixel(textureInternalFormat, texturePixelDataType); @@ -107,7 +112,7 @@ namespace MobileGL { } const auto* srcData = static_cast(processedPixels); - Uint8* destData = (Uint8*)textureObject->MapMipmapData(textureUploadingTarget, level); + Uint8* destData = (Uint8*)textureMipmapObject->MapMipmapData(textureUploadingTarget, level); // No allocation should be done here // if (data.empty()) { // SizeT totalSize = texelSize.x() * texelSize.y() * bytesPerPixel; @@ -122,7 +127,7 @@ namespace MobileGL { free(processedPixels); - textureObject->MarkStorageDirty(textureUploadingTarget, level, true); + textureMipmapObject->MarkStorageDirty(textureUploadingTarget, level, true); // mipmap.dirty = true; // mipmap.hasData = true; } @@ -398,8 +403,13 @@ namespace MobileGL { reinterpret_cast(pixels); } + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(textureObject.get()); + + // Allocate in TextureObject - textureObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, totalBytes}); + textureMipmapObject->AllocateStorage(textureUploadingTarget, level, {{width, height, 1}, totalBytes}); if (!originalPixels) { MGLOG_D("TexImage2D_State: No input pixel and no PBO bound, no pixel transfer"); @@ -420,7 +430,7 @@ namespace MobileGL { const SizeT copySize = std::min(imageSize, totalBytes); DataPtr texelInput{processedPixels, copySize}; - textureObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput); + textureMipmapObject->UpdateMipmapSubData(textureUploadingTarget, level, texelInput); } free(processedPixels); @@ -648,17 +658,41 @@ namespace MobileGL { switch (pname) { case GL_TEXTURE_WIDTH: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_HEIGHT: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_DEPTH: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_INTERNAL_FORMAT: @@ -714,18 +748,41 @@ namespace MobileGL { switch (pname) { case GL_TEXTURE_WIDTH: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_HEIGHT: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_DEPTH: if (params) { - *params = textureObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); - } + switch (textureObject->GetStorageType()) { + case TextureStorageType::Mipmap: { + const auto textureMipmapObject = static_cast(textureObject.get()); + *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); + break; + } + default: + THROW_UNIMPL_EXCEPTION; + } } break; case GL_TEXTURE_INTERNAL_FORMAT: if (params) { diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp index b5c91dcf..68482117 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -52,7 +52,9 @@ namespace MobileGL { IntVec3 FramebufferAttachment::GetSize() const { if (IsTexture()) { // TODO: get correct upload target - return m_texture->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); + MOBILEGL_ASSERT(nullptr != dynamic_cast(m_texture.get()), "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(m_texture.get()); + return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); } else if (IsRenderbuffer()) { // TODO } diff --git a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h index c71517ee..25d75b13 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h @@ -49,6 +49,11 @@ namespace MobileGL { Unknown = -1 }; + enum class TextureStorageType { + Mipmap, + Buffer + }; + enum class TextureInputFormat { Red, RG, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index e7c5854b..eecfefe8 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -14,14 +14,7 @@ namespace MobileGL { using TargetEnum = TextureTarget; virtual ~ITextureObject() = default; - virtual Uint GetMipmapLevelCount() const = 0; - virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; - virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; - virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0; - virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0; - virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0; - virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0; - virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; + virtual TextureStorageType GetStorageType() const = 0; virtual TextureInternalFormat GetFormat() const = 0; virtual TextureTarget GetTarget() const = 0; @@ -49,17 +42,6 @@ namespace MobileGL { TextureObjectBase(TextureTarget target, Uint externalIndex); virtual ~TextureObjectBase() = default; - // Mipmap ops - // Uint GetMipmapLevelCount() const = 0; - // const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = - // 0; const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = - // 0; void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, - // MipmapInput input) = 0; void UpdateMipmapSubData(TextureUploadTarget uploadTarget, - // Uint mipmapLevel, DataPtr input) = 0; void* MapMipmapData(TextureUploadTarget - // uploadTarget, Uint mipmapLevel) = 0; void MarkStorageDirty(TextureUploadTarget - // uploadTarget, Uint mipmapLevel, bool dirty) = 0; bool - // IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; - TextureInternalFormat GetFormat() const override; TextureTarget GetTarget() const override; IntVec3 GetBaseSize() const override; @@ -87,10 +69,26 @@ namespace MobileGL { UintVec2 m_levelRange = {0, 1000}; }; - class TextureObjectWithOneMipmap : public TextureObjectBase { + class TextureMipmapObject : public TextureObjectBase { + public: + TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} + + TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } + + virtual Uint GetMipmapLevelCount() const = 0; + virtual const IntVec3 GetMipmapTexelSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; + virtual const SizeT GetMipmapByteSize(TextureUploadTarget target, Uint mipmapLevel) const = 0; + virtual void AllocateStorage(TextureUploadTarget uploadTarget, Uint mipmapLevel, MipmapInput input) = 0; + virtual void UpdateMipmapSubData(TextureUploadTarget uploadTarget, Uint mipmapLevel, DataPtr input) = 0; + virtual void* MapMipmapData(TextureUploadTarget uploadTarget, Uint mipmapLevel) = 0; + virtual void MarkStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel, bool dirty) = 0; + virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; + }; + + class TextureObjectWithOneMipmap : public TextureMipmapObject { public: TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) - : TextureObjectBase(target, externalIndex) {} + : TextureMipmapObject(target, externalIndex) {} virtual ~TextureObjectWithOneMipmap() = default; Uint GetMipmapLevelCount() const override; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp index 1d10506c..6521138e 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { TextureObject2DCube::TextureObject2DCube(Uint externalIndex) - : TextureObjectBase(TextureTarget::TextureCubeMap, externalIndex) {} + : TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {} Uint TextureObject2DCube::GetMipmapLevelCount() const { return m_textureStorage.GetLevelCount(); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h index a5c6207e..3c31b125 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { - class TextureObject2DCube : public TextureObjectBase { + class TextureObject2DCube : public TextureMipmapObject { public: explicit TextureObject2DCube(Uint externalIndex); From 3f36248638fc8eb1d148d8b191ed9ce2e17e51f2 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 9 Dec 2025 13:48:18 +0800 Subject: [PATCH 02/18] [Fix] (MG_Test/Program): does this fix ci failure? --- MobileGL/MG_Test/Program/ProgramTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Test/Program/ProgramTest.cpp b/MobileGL/MG_Test/Program/ProgramTest.cpp index 2b53a570..7ad62693 100644 --- a/MobileGL/MG_Test/Program/ProgramTest.cpp +++ b/MobileGL/MG_Test/Program/ProgramTest.cpp @@ -1204,9 +1204,9 @@ TEST_F(ProgramTest, CompileShaderWithSamplerAsVarName) { spvc_compiler_options options; spvcSession.CreateOptions(&options); - spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 460); + spvc_compiler_options_set_uint(options, SPVC_COMPILER_OPTION_GLSL_VERSION, 320); spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_ES, SPVC_TRUE); - // spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, SPVC_FALSE); + spvc_compiler_options_set_bool(options, SPVC_COMPILER_OPTION_GLSL_VULKAN_SEMANTICS, SPVC_FALSE); spvcSession.SetOptions(options); From cb4e6b5f19a4c6b281ac00951e38ee99b8c485e8 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 9 Dec 2025 21:20:39 +0800 Subject: [PATCH 03/18] [Feat] (MG_State/Texture, MG_Impl/Texture): `glTexBuffer` (and implement `TextureObjectBuffer` accordingly) --- CMakeLists.txt | 1 + MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 4 +- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 2 +- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 71 +++++++++++++++---- .../FramebufferState/FramebufferObject.cpp | 4 +- .../GLState/TextureState/TextureEnum.h | 1 + .../GLState/TextureState/TextureObject.h | 8 +-- .../TextureState/TextureObject2DCube.cpp | 2 +- .../TextureState/TextureObject2DCube.h | 2 +- .../TextureState/TextureObjectBuffer.cpp | 20 ++++++ .../TextureState/TextureObjectBuffer.h | 23 ++++++ .../GLState/TextureState/TextureObjectStubs.h | 4 +- .../GLState/TextureState/TextureState.cpp | 7 +- 13 files changed, 118 insertions(+), 31 deletions(-) create mode 100644 MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp create mode 100644 MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2528ad2e..922ac20f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,6 +165,7 @@ set(SOURCE_FILES MobileGL/MG_State/GLState/TextureState/TextureObject2D.cpp MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp MobileGL/MG_State/GLState/TextureState/TextureObject3D.cpp + MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp MobileGL/MG_State/GLState/TextureState/TextureUnit.cpp MobileGL/MG_State/GLState/TextureState/TextureState.cpp MobileGL/MG_State/GLState/ProgramState/ProgramObject.cpp diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index dfedf9be..96ffcb2f 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -750,9 +750,9 @@ namespace MobileGL::MG_Backend::DirectGLES { auto textureObject = bindingSlot.GetBoundObject(); textureObject->SetInternalFormat(mglInternalFormat); - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); textureMipmapObject->AllocateStorage(TextureUploadTarget::Texture2D, level, {{width, height, 1}, 0}); } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index cf0168e3..594e7ad3 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -295,7 +295,7 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(baseSize.z()), 0}; switch (stateTextureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - auto* textureMipmapObject = static_cast(stateTextureObject.get()); + auto* textureMipmapObject = static_cast(stateTextureObject.get()); const auto mipmapCount = textureMipmapObject->GetMipmapLevelCount(); currentTextureInfo.mipmapLevels = mipmapCount; diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index baea89f0..87b9e199 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -7,6 +7,8 @@ #include "MG_Util/Types.h" #include "Validators.h" #include "ProxyTexture.h" +#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" + #include #include #include @@ -68,9 +70,9 @@ namespace MobileGL { // Assert this for extra safety. // This should automatically compiled out in release, // so that we don't take the perf hit of dyn-cast. - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); auto texelSize = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level); SizeT imageSize = 0; @@ -403,9 +405,9 @@ namespace MobileGL { reinterpret_cast(pixels); } - MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), + MOBILEGL_ASSERT(nullptr != dynamic_cast(textureObject.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(textureObject.get()); + auto textureMipmapObject = static_cast(textureObject.get()); // Allocate in TextureObject @@ -442,9 +444,48 @@ namespace MobileGL { THROW_UNIMPL_EXCEPTION; } - void TexBuffer_State(GLenum target, GLenum internalformat, GLuint texture) { - // TODO: implement - THROW_UNIMPL_EXCEPTION; + void TexBuffer_State(GLenum target, GLenum internalformat, GLuint buffer) { + // ======================= Converting ================================ + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureInternalFormat textureInternalFormat = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTextureUploadTarget(textureUploadingTarget)) return; + if (!TextureImpl::ValidateTextureInternalFormat(textureInternalFormat)) return; + // TODO: make sure `internalformat` is in one of supported format for TexBuffer + auto bufferObject = MG_State::pGLContext->GetBufferObject(buffer); + if (!bufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", __func__, + "`buffer` is not zero and is not the name of an existing buffer object.")); + return; + } + + // ======================= Processing ================================ + auto activeUnit = + MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + auto textureObject = bindingSlot.GetBoundObject(); + + // ===================== Error Checking ============================== + if (!TextureImpl::ValidateTextureObject(textureObject)) return; + if (textureObject->GetStorageType() != TextureStorageType::Buffer) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared("MG_Impl/GLImpl", __func__, + "The effective target of `texture` is not `GL_TEXTURE_BUFFER`.")); + return; + } + + // ======================= Processing ================================ + // Now we can rest assured, and down-cast texture object to texture buffer + auto* texBufferObject = static_cast(textureObject.get()); + auto& bufferSlot = texBufferObject->GetBufferBindingSlot(); + bufferSlot.Bind(bufferObject); + + texBufferObject->SetInternalFormat(textureInternalFormat); } GLboolean IsTexture_State(GLuint texture) { @@ -660,7 +701,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); break; } @@ -673,7 +714,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); break; } @@ -686,7 +727,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); break; } @@ -750,7 +791,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).x(); break; } @@ -763,7 +804,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).y(); break; } @@ -776,7 +817,7 @@ namespace MobileGL { if (params) { switch (textureObject->GetStorageType()) { case TextureStorageType::Mipmap: { - const auto textureMipmapObject = static_cast(textureObject.get()); + const auto textureMipmapObject = static_cast(textureObject.get()); *params = textureMipmapObject->GetMipmapTexelSize(textureUploadingTarget, level).z(); break; } @@ -1017,8 +1058,8 @@ namespace MobileGL { TexImage1D_State(target, level, internalFormat, width, border, format, type, pixels); } - void TexBuffer(GLenum target, GLenum internalformat, GLuint texture) { - TexBuffer_State(target, internalformat, texture); + void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer) { + TexBuffer_State(target, internalformat, buffer); } GLboolean IsTexture(GLuint texture) { diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp index 68482117..4c88c2cf 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -52,8 +52,8 @@ namespace MobileGL { IntVec3 FramebufferAttachment::GetSize() const { if (IsTexture()) { // TODO: get correct upload target - MOBILEGL_ASSERT(nullptr != dynamic_cast(m_texture.get()), "Texture object here should always be an object with mipmap"); - auto textureMipmapObject = static_cast(m_texture.get()); + MOBILEGL_ASSERT(nullptr != dynamic_cast(m_texture.get()), "Texture object here should always be an object with mipmap"); + auto textureMipmapObject = static_cast(m_texture.get()); return textureMipmapObject->GetMipmapTexelSize(TextureUploadTarget::Texture2D, m_textureLevel); } else if (IsRenderbuffer()) { // TODO diff --git a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h index 25d75b13..e5a3dcfe 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h @@ -38,6 +38,7 @@ namespace MobileGL { CubeMapNegativeY, CubeMapPositiveZ, CubeMapNegativeZ, + TextureBuffer, ProxyCubeMap, CubeMapArray, ProxyCubeMapArray, diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index eecfefe8..236114a9 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -69,9 +69,9 @@ namespace MobileGL { UintVec2 m_levelRange = {0, 1000}; }; - class TextureMipmapObject : public TextureObjectBase { + class TextureObjectMipmap : public TextureObjectBase { public: - TextureMipmapObject(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} + TextureObjectMipmap(TextureTarget target, Uint externalIndex): TextureObjectBase(target, externalIndex) {} TextureStorageType GetStorageType() const override { return TextureStorageType::Mipmap; } @@ -85,10 +85,10 @@ namespace MobileGL { virtual bool IsStorageDirty(TextureUploadTarget uploadTarget, Uint mipmapLevel) const = 0; }; - class TextureObjectWithOneMipmap : public TextureMipmapObject { + class TextureObjectWithOneMipmap : public TextureObjectMipmap { public: TextureObjectWithOneMipmap(TextureTarget target, Uint externalIndex) - : TextureMipmapObject(target, externalIndex) {} + : TextureObjectMipmap(target, externalIndex) {} virtual ~TextureObjectWithOneMipmap() = default; Uint GetMipmapLevelCount() const override; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp index 6521138e..f643f539 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.cpp @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { TextureObject2DCube::TextureObject2DCube(Uint externalIndex) - : TextureMipmapObject(TextureTarget::TextureCubeMap, externalIndex) {} + : TextureObjectMipmap(TextureTarget::TextureCubeMap, externalIndex) {} Uint TextureObject2DCube::GetMipmapLevelCount() const { return m_textureStorage.GetLevelCount(); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h index 3c31b125..46c42a4a 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject2DCube.h @@ -4,7 +4,7 @@ namespace MobileGL { namespace MG_State { namespace GLState { - class TextureObject2DCube : public TextureMipmapObject { + class TextureObject2DCube : public TextureObjectMipmap { public: explicit TextureObject2DCube(Uint externalIndex); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp new file mode 100644 index 00000000..e96301fa --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.cpp @@ -0,0 +1,20 @@ +#include "TextureObjectBuffer.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + TextureObjectBuffer::TextureObjectBuffer(Uint externalIndex) + : TextureObjectBase(TextureTarget::TextureBuffer, externalIndex) {} + + Uint TextureObjectBuffer::GetIndexOfTextureUploadTarget(TextureUploadTarget target) const { + MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!"); + return 0; + } + + BindingSlot& TextureObjectBuffer::GetBufferBindingSlot(TextureUploadTarget target) { + MOBILEGL_ASSERT(target == TextureUploadTarget::TextureBuffer, "Invalid TextureUploadTarget!"); + return m_bufferBindingSlot; + } + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL \ No newline at end of file diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h new file mode 100644 index 00000000..29fcc21a --- /dev/null +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectBuffer.h @@ -0,0 +1,23 @@ +#pragma once +#include "TextureObject.h" +#include "MG_State/GLState/BufferState/BufferObject.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class TextureObjectBuffer : public TextureObjectBase { + public: + TextureStorageType GetStorageType() const override { return TextureStorageType::Buffer; } + explicit TextureObjectBuffer(Uint externalIndex); + const Vector& GetUploadTargets() const override { return m_uploadTargets; } + BindingSlot& GetBufferBindingSlot(TextureUploadTarget target = TextureUploadTarget::TextureBuffer); + + protected: + Uint GetIndexOfTextureUploadTarget(TextureUploadTarget target) const override; + + BindingSlot m_bufferBindingSlot = BindingSlot(BufferTarget::Texture); + const Vector m_uploadTargets{TextureUploadTarget::TextureBuffer}; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h index 541b5be6..fad347df 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObjectStubs.h @@ -31,8 +31,8 @@ namespace MobileGL { STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject2DMultisample, TextureTarget::Texture2DMultisample, {TextureUploadTarget::Texture2DMultisample}); - STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer, - {TextureUploadTarget::Unknown}); + // STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObjectBuffer, TextureTarget::TextureBuffer, + // {TextureUploadTarget::Unknown}); STUB_TEXTURE_OBJECT_CLASS_DEFINITION(TextureObject1DArray, TextureTarget::Texture1DArray, {TextureUploadTarget::Texture1DArray}); diff --git a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp index c479c7a9..aab12d87 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureState.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureState.cpp @@ -6,6 +6,7 @@ #include "TextureObject2D.h" #include "TextureObject3D.h" #include "TextureObject2DCube.h" +#include "TextureObjectBuffer.h" #include "TextureObjectStubs.h" namespace MobileGL { @@ -46,6 +47,9 @@ namespace MobileGL { case TextureTarget::Texture3D: textureObject = MakeShared(index); break; + case TextureTarget::TextureBuffer: + textureObject = MakeShared(index); + break; // These texture types are stubbed: case TextureTarget::TextureRectangle: @@ -54,9 +58,6 @@ namespace MobileGL { case TextureTarget::Texture2DMultisample: textureObject = MakeShared(index); break; - case TextureTarget::TextureBuffer: - textureObject = MakeShared(index); - break; case TextureTarget::Texture1DArray: textureObject = MakeShared(index); break; From b79424a78c0ffb3d23a25436e31fe7d4a18c0c8f Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 10 Dec 2025 09:17:30 +0800 Subject: [PATCH 04/18] [Feat] (MG_Backend/DirectGLES): sync tex buffer to backend --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 2 +- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 39 ++++++++++++++++++- MobileGL/MG_Backend/DirectGLES/Managers.h | 3 +- .../GLToMG/TextureEnumConverter.cpp | 2 + 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 96ffcb2f..9e2c72d0 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -386,7 +386,7 @@ namespace MobileGL::MG_Backend::DirectGLES { // Bind texture object auto target = textureObject->GetTarget(); - if (target == TextureTarget::TextureBuffer || target == TextureTarget::Texture1D || + if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle || target == TextureTarget::Texture2DMultisampleArray || target == TextureTarget::Texture1DArray || target == TextureTarget::Texture3D || target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) { diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 594e7ad3..bdced48e 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -2,6 +2,8 @@ #include "MG_Backend/Backends.h" #include "Utils.h" #include "DirectGLES.h" +#include "MG_State/GLState/TextureState/TextureObjectBuffer.h" + #include #include #include @@ -262,7 +264,7 @@ namespace MobileGL::MG_Backend::DirectGLES { auto targetInternal = stateTextureObject->GetTarget(); MGLOG_D(" Texture target for syncing is %s", MG_Util::ConvertTextureTargetToString(targetInternal).c_str()); - if (targetInternal == TextureTarget::TextureBuffer || targetInternal == TextureTarget::Texture1D || + if (targetInternal == TextureTarget::Texture1D || targetInternal == TextureTarget::TextureRectangle || targetInternal == TextureTarget::Texture2DMultisampleArray || targetInternal == TextureTarget::Texture1DArray || targetInternal == TextureTarget::Texture3D || @@ -292,7 +294,7 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto baseSize = stateTextureObject->GetBaseSize(); StateTextureBasicInfo currentTextureInfo = { stateTextureObject->GetFormat(), static_cast(baseSize.x()), static_cast(baseSize.y()), - static_cast(baseSize.z()), 0}; + static_cast(baseSize.z()), 0, 0}; switch (stateTextureObject->GetStorageType()) { case TextureStorageType::Mipmap: { auto* textureMipmapObject = static_cast(stateTextureObject.get()); @@ -385,6 +387,39 @@ namespace MobileGL::MG_Backend::DirectGLES { } break; } + case TextureStorageType::Buffer: { + auto* textureBufferObject = static_cast(stateTextureObject.get()); + auto& slot = textureBufferObject->GetBufferBindingSlot(); + auto buffer = slot.GetBoundObject(); + auto bufferIndex = buffer->GetExternalIndex(); + currentTextureInfo.bufferExternalIndex = bufferIndex; + + Bool needsRegeneration = !m_isInitialized || (currentTextureInfo != m_prevTextureInfo); + MGLOG_D("Texture state changed significantly or not initialized, regenerating texture (tex buffer) with ID: %u", + m_backendTextureId); + + // Need to sync texture buffer if not synced yet + auto& backendBuffers = BufferImpl::g_backendBufferObjects; + SharedPtr backendBufferObject; + const auto& backendBufferIt = backendBuffers.find(buffer); + if (backendBufferIt == backendBuffers.end()) { + backendBufferObject = MakeShared(); + backendBuffers[buffer] = backendBufferObject; + } else { + backendBufferObject = backendBufferIt->second; + } + backendBufferObject->SyncToBackend(buffer); + + // Bind buffer to texture + auto backendId = backendBufferObject->GetBackendBufferId(); + + GLenum glInternalFormat, glType, glFormat; + TextureImpl::GenerateTextureFormatInfo(textureBufferObject->GetFormat(), &glInternalFormat, &glType, + &glFormat); + + MG_External::GLES::glTexBuffer(GL_TEXTURE_BUFFER, glInternalFormat, backendId); + break; + } default: THROW_UNIMPL_EXCEPTION; } diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index 86209aa8..3c193a8b 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -54,10 +54,11 @@ namespace MobileGL::MG_Backend::DirectGLES { SizeT height = 0; SizeT depth = 0; SizeT mipmapLevels = 0; + Uint bufferExternalIndex = 0; bool operator==(const StateTextureBasicInfo& other) const { return internalFormat == other.internalFormat && width == other.width && height == other.height && - depth == other.depth && mipmapLevels == other.mipmapLevels; + depth == other.depth && mipmapLevels == other.mipmapLevels && bufferExternalIndex == other.bufferExternalIndex; } bool operator!=(const StateTextureBasicInfo& other) const { return !(*this == other); } diff --git a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp index c4f41ad6..60c3aaa4 100644 --- a/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp +++ b/MobileGL/MG_Util/Converters/GLToMG/TextureEnumConverter.cpp @@ -317,6 +317,8 @@ namespace MobileGL { return TextureUploadTarget::CubeMapPositiveZ; case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return TextureUploadTarget::CubeMapNegativeZ; + case GL_TEXTURE_BUFFER: + return TextureUploadTarget::TextureBuffer; case GL_PROXY_TEXTURE_CUBE_MAP: return TextureUploadTarget::ProxyCubeMap; case GL_TEXTURE_2D_MULTISAMPLE: From a1a9b1645772ef904b67d9eed6b07c96d105580b Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 10 Dec 2025 15:25:20 +0800 Subject: [PATCH 05/18] [Chore] (MG_Backend/DirectGLES): rearrange DebugImpl --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 9e2c72d0..c1fd053b 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -30,24 +30,21 @@ namespace MobileGL::MG_Backend::DirectGLES { } namespace DebugImpl { - void ErrorLopper::Loop(std::function func) { #if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG + void ErrorLopper::Loop(std::function func) { GLenum err = MG_External::GLES::glGetError(); while (err != GL_NO_ERROR) { func(err); err = MG_External::GLES::glGetError(); } -#endif } void ErrorLopper::Clear() { -#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG GLenum err = MG_External::GLES::glGetError(); while (err != GL_NO_ERROR) { MGLOG_D("Stray GL Error cleared: %s", MG_Util::ConvertGLEnumToString(err).c_str()); err = MG_External::GLES::glGetError(); } -#endif } ErrorLopper::ErrorLopper() { @@ -56,6 +53,12 @@ namespace MobileGL::MG_Backend::DirectGLES { ErrorLopper::~ErrorLopper() { Clear(); } +#else + void ErrorLopper::Loop(std::function func) {} + void ErrorLopper::Clear() {} + ErrorLopper::ErrorLopper() {} + ErrorLopper::~ErrorLopper() {} +#endif } // namespace DebugImpl // TODO: deletion for deleted objects From eb705c53bf5eed356ca0c7c41d127792dc7abe76 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 10 Dec 2025 15:29:59 +0800 Subject: [PATCH 06/18] [Chore] (MG_State/Texture): explicitly specify value for enums --- MobileGL/MG_State/GLState/TextureState/TextureEnum.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h index e5a3dcfe..99e14728 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureEnum.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureEnum.h @@ -2,7 +2,7 @@ namespace MobileGL { enum class TextureTarget { - Texture1D, + Texture1D = 0, Texture2D, Texture3D, TextureCubeMap, @@ -20,7 +20,7 @@ namespace MobileGL { // Don't tinker with order in this enum (especially CubeMap faces), // it is used in MipmapUploadTargetArray enum class TextureUploadTarget { - Texture1D, + Texture1D = 0, Texture2D, Texture3D, ProxyTexture1D, From 6b4c911f0676b293becf964c6d15dd6e549fd0cc Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Wed, 10 Dec 2025 17:53:33 +0800 Subject: [PATCH 07/18] [Fix] (CMake): lower tests to O2 optimization --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 922ac20f..5b64c747 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT) elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") add_compile_options(/O2 /GL) else () - add_compile_options(-O3) + add_compile_options(-O2) endif() endif() From f94861926a2af04de42fb184238cf9a5b74c23c7 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 15:12:19 +0800 Subject: [PATCH 08/18] [Feat] (3rdparty/tracy): initial integration of Tracy Profiler --- .gitmodules | 3 +++ 3rdparty/tracy | 1 + CMakeLists.txt | 15 ++++++++++++++- MobileGL/Includes.h | 4 ++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 160000 3rdparty/tracy diff --git a/.gitmodules b/.gitmodules index cbaec99b..bd45300f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "include/FastSTL"] path = include/FastSTL url = https://github.com/MobileGL-Dev/FastSTL.git +[submodule "3rdparty/tracy"] + path = 3rdparty/tracy + url = https://github.com/wolfpld/tracy.git diff --git a/3rdparty/tracy b/3rdparty/tracy new file mode 160000 index 00000000..e6b9ea46 --- /dev/null +++ b/3rdparty/tracy @@ -0,0 +1 @@ +Subproject commit e6b9ea460993a6f093283055ef3c98025b19f909 diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b64c747..72f32bf7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR MOBILEGL_FORCE_RELEASE_OPT) add_compile_options(-O3 -ffunction-sections -fdata-sections) add_link_options(-Wl,--gc-sections) elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - add_compile_options(/O2 /GL) +# add_compile_options(/O2) else () add_compile_options(-O2) endif() @@ -77,6 +77,12 @@ set(SPIRV_CROSS_STATIC ON CACHE BOOL "Prefer static libs" FORCE) add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/SPIRV-Cross) +option(TRACY_ENABLE "Enable Tracy" OFF) +option(TRACY_ON_DEMAND "Enable profiling only connected" ON) +option(TRACY_NO_EXIT "Don't exit Tracy until connected" OFF) + +add_subdirectory(3rdparty/tracy) + set(SOURCE_FILES MobileGL/Init.cpp @@ -250,6 +256,13 @@ target_link_libraries(${CMAKE_PROJECT_NAME}_s spirv-cross-c ) +if (TRACY_ENABLE) + target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC Tracy::TracyClient) + target_link_libraries(${CMAKE_PROJECT_NAME}_s PUBLIC Tracy::TracyClient) + target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC -DTRACY_ENABLE) + target_compile_definitions(${CMAKE_PROJECT_NAME}_s PUBLIC -DTRACY_ENABLE) +endif () + if (ANDROID) target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC android diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index cc36fd53..a9088e3e 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -76,6 +76,10 @@ #include #endif +#ifdef TRACY_ENABLE +#include +#endif + // Post-includes for significant project headers #include "MG_Util/Debug/Log.h" #include "MG_Util/Types.h" From 1e64a85bcd56883669804349e19c4fc392cda373 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 15:14:07 +0800 Subject: [PATCH 09/18] [Fix] (Defines.h): include mingw as Windows platform --- MobileGL/Defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MobileGL/Defines.h b/MobileGL/Defines.h index b80f8552..b8047ac1 100644 --- a/MobileGL/Defines.h +++ b/MobileGL/Defines.h @@ -43,7 +43,7 @@ #define MOBILEGL_LOG_FILE_PATH "" #endif -#if _MSC_VER +#if defined _MSC_VER or defined __MINGW32__ or defined __MINGW64__ #define TRAP assert(false) #elif __clang__ #define TRAP __builtin_debugtrap() From 0e9bca40f36a47afbdcf9b605cd95215b3a5d876 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 16:28:07 +0800 Subject: [PATCH 10/18] [Chore] (CMake): use set() instead of option() --- CMakeLists.txt | 6 +++--- MobileGL/Defines.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72f32bf7..657d309e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,9 +77,9 @@ set(SPIRV_CROSS_STATIC ON CACHE BOOL "Prefer static libs" FORCE) add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/SPIRV-Cross) -option(TRACY_ENABLE "Enable Tracy" OFF) -option(TRACY_ON_DEMAND "Enable profiling only connected" ON) -option(TRACY_NO_EXIT "Don't exit Tracy until connected" OFF) +set(TRACY_ENABLE OFF CACHE BOOL "Enable Tracy") +set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected") +set(TRACY_NO_EXIT OFF CACHE BOOL "Don't exit Tracy until connected" FORCE) add_subdirectory(3rdparty/tracy) diff --git a/MobileGL/Defines.h b/MobileGL/Defines.h index b8047ac1..8a0131a0 100644 --- a/MobileGL/Defines.h +++ b/MobileGL/Defines.h @@ -31,7 +31,7 @@ #define MOBILEGL_BACKEND_TYPE_DIRECT_GLES 3 // ====================== MobileGL configurations ======================= // -#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_DEBUG +#define MOBILEGL_LOG_ACTIVE_LEVEL MOBILEGL_LOG_LEVEL_FATAL #define MOBILEGL_LOG_ENABLE_CONSOLE 0 #define MOBILEGL_LOG_ENABLE_FILE 1 From ffd4ec340800a95bca02b16ab1f69afed34dbd71 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 17:18:26 +0800 Subject: [PATCH 11/18] [Feat] (tracy): initial tracy integration --- CMakeLists.txt | 6 ++-- MobileGL/Includes.h | 3 ++ .../MG_Impl/EGLImpl/Exporting/Definitions.cpp | 9 ++++++ .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 30 ++++++++++++++----- 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 657d309e..9f90c259 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,9 +77,11 @@ set(SPIRV_CROSS_STATIC ON CACHE BOOL "Prefer static libs" FORCE) add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/SPIRV-Cross) -set(TRACY_ENABLE OFF CACHE BOOL "Enable Tracy") -set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected") +set(TRACY_ENABLE ON CACHE BOOL "Enable Tracy" FORCE) +set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected" FORCE) set(TRACY_NO_EXIT OFF CACHE BOOL "Don't exit Tracy until connected" FORCE) +set(TRACY_DELAYED_INIT ON CACHE BOOL "Don't init Tracy on library load" FORCE) +set(TRACY_MANUAL_LIFETIME ON CACHE BOOL "Manually control Tracy lifetime" FORCE) add_subdirectory(3rdparty/tracy) diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index a9088e3e..2400bcbb 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -78,6 +78,9 @@ #ifdef TRACY_ENABLE #include +#define TRACY_ZONECOLOR_ENTRY 0xFF0000 +#define TRACY_ZONECOLOR_FRONTEND 0x00FF00 +#define TRACY_ZONECOLOR_BACKEND 0x00FF00 #endif // Post-includes for significant project headers diff --git a/MobileGL/MG_Impl/EGLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/EGLImpl/Exporting/Definitions.cpp index 303dc5c4..aefa0ec4 100644 --- a/MobileGL/MG_Impl/EGLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/EGLImpl/Exporting/Definitions.cpp @@ -13,6 +13,9 @@ MOBILEGL_EGL_API EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint* attrib MOBILEGL_EGL_API EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext shareCtx, const EGLint* attrib_list) { +#ifdef TRACY_ENABLE + tracy::StartupProfiler(); +#endif return MobileGL::MG_Impl::EGLImpl::CreateContext(dpy, config, shareCtx, attrib_list); } @@ -33,6 +36,9 @@ MOBILEGL_EGL_API EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLS } MOBILEGL_EGL_API EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { +#ifdef TRACY_ENABLE + tracy::ShutdownProfiler(); +#endif return MobileGL::MG_Impl::EGLImpl::DestroyContext(dpy, ctx); } @@ -73,6 +79,9 @@ MOBILEGL_EGL_API EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { } MOBILEGL_EGL_API EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) { +#ifdef TRACY_ENABLE + FrameMark; +#endif return MobileGL::MG_Impl::EGLImpl::SwapBuffers(dpy, draw); } diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 8cd2b48d..65b5bcdc 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -24,15 +24,29 @@ MOBILEGL_GL_API type gl##name(__VA_ARGS__) { #define DECLARE_GL_FUNCTION_HEAD(type,name,...) \ MOBILEGL_GL_API type gl##name(__VA_ARGS__) { -#define DECLARE_GL_FUNCTION_END(type,name,...) \ - MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ - return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ -} +#ifdef TRACY_ENABLE + #define DECLARE_GL_FUNCTION_END(type,name,...) \ + ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \ + MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ + return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ + } -#define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \ - MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ - MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ -} + #define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \ + ZoneScopedC(TRACY_ZONECOLOR_ENTRY); \ + MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ + MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ + } +#else + #define DECLARE_GL_FUNCTION_END(type,name,...) \ + MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ + return MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ + } + + #define DECLARE_GL_FUNCTION_END_NO_RETURN(type,name,...) \ + MGLOG_D("Implementing function: %s(...)", __FUNCTION__); \ + MobileGL::MG_Impl::GLImpl::name(__VA_ARGS__); \ + } +#endif DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetStringi, GLenum name, GLuint index) DECLARE_GL_FUNCTION_END(const GLubyte*, GetStringi, name, index) DECLARE_GL_FUNCTION_HEAD(const GLubyte*, GetString, GLenum name) DECLARE_GL_FUNCTION_END(const GLubyte*, GetString, name) From 91b04f6995fb711f20a931d3f3e39c77646e5bd5 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 20:37:20 +0800 Subject: [PATCH 12/18] [Feat] (MG_Backend/DirectGLES): tracy integration for DirectGLES backend --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 27 +++++++ MobileGL/MG_Backend/DirectGLES/Managers.cpp | 81 +++++++++++++++++-- MobileGL/MG_Backend/DirectGLES/Utils.cpp | 51 ++++++++++++ .../MG_Impl/GLImpl/Drawing/GL_Drawing.cpp | 54 +++++++++++++ 4 files changed, 208 insertions(+), 5 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index c1fd053b..b7042714 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -65,6 +65,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace BufferImpl { void SyncNeccessaryBuffers(Bool includeIBO = false, Bool includeIndirectBuffer = false) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif // 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 @@ -141,6 +144,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace VertexArrayImpl { void SyncCurrentVAO(Bool needDivisor) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif auto currentVAOObject = MG_State::pGLContext->GetBoundVertexArray(); if (!currentVAOObject) { MGLOG_E("No VAO is currently bound, cannot sync current VAO."); @@ -162,6 +168,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace TextureImpl { SharedPtr SyncTextureObjectToBackend( SharedPtr& textureObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif const auto& backendTextureIt = g_backendTextureObjects.find(textureObject); SharedPtr backendTextureObject; if (backendTextureIt == g_backendTextureObjects.end()) { @@ -175,6 +184,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void SyncNeccessaryTextures() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif // 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 @@ -219,6 +231,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace FramebufferImpl { void SyncCurrentFBO() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif const FramebufferTarget fboTargets[] = {FramebufferTarget::Draw, FramebufferTarget::Read}; MG_State::GLState::FramebufferObject* lastUpdatedFBO = nullptr; @@ -260,6 +275,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace RenderStateImpl { void SyncRenderState() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glViewport( MG_State::pGLContext->GetViewport().x(), MG_State::pGLContext->GetViewport().y(), MG_State::pGLContext->GetViewport().z(), MG_State::pGLContext->GetViewport().w()); @@ -320,6 +338,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace PrgramImpl { void SyncCurrentProgram() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif auto currentProgram = MG_State::pGLContext->GetCurrentProgram(); if (!currentProgram || !currentProgram->GetLinkStatus()) { MG_External::GLES::glUseProgram(0); @@ -341,6 +362,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } // namespace PrgramImpl void BindCurrentFBO(FramebufferTarget target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif const auto& currentFBO = MG_State::pGLContext->GetFramebufferBindingSlot(target).GetBoundObject(); if (currentFBO && currentFBO != MG_Impl::GLImpl::FramebufferImpl::pDefaultFramebufferInfo->defaultFBO) { const auto& backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find(currentFBO); @@ -358,6 +382,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void PrepareForDraw(DrawSyncBit syncBit) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif BufferImpl::SyncNeccessaryBuffers(syncBit & DrawSyncBit::IndexBuffer, syncBit & DrawSyncBit::IndirectBuffer); VertexArrayImpl::SyncCurrentVAO(syncBit & DrawSyncBit::Instancing); TextureImpl::SyncNeccessaryTextures(); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index bdced48e..92c8071f 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -18,6 +18,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace BufferImpl { BackendBufferObject::BackendBufferObject() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGenBuffers(1, &m_backendBufferId); if (m_backendBufferId == 0) { MGLOG_E("Failed to generate buffer object."); @@ -29,6 +32,9 @@ namespace MobileGL::MG_Backend::DirectGLES { const GLenum TempBufferTarget = GL_ARRAY_BUFFER; void BackendBufferObject::SyncToBackend(SharedPtr& stateBufferObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (!stateBufferObject) { MGLOG_E("State buffer object is null, cannot sync to backend."); return; @@ -74,6 +80,9 @@ namespace MobileGL::MG_Backend::DirectGLES { void BackendBufferObject::SyncToBackend_glBufferData( SharedPtr& stateBufferObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif BackendBufferBindingProtector backendBufferBindingProtector(TempBufferTarget); MGLOG_D("Syncing buffer data (glBufferData) for object with ID : %u", m_backendBufferId); @@ -90,6 +99,9 @@ namespace MobileGL::MG_Backend::DirectGLES { void BackendBufferObject::SyncToBackend_glBufferSubData( SharedPtr& stateBufferObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif BackendBufferBindingProtector backendBufferBindingProtector(TempBufferTarget); MGLOG_D("Syncing buffer sub-data (glBufferSubData) for object with ID : %u", m_backendBufferId); @@ -109,6 +121,9 @@ namespace MobileGL::MG_Backend::DirectGLES { void BackendBufferObject::SyncToBackend_glMapBufferRange( SharedPtr& stateBufferObject, Bool invalidate) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif BackendBufferBindingProtector backendBufferBindingProtector(TempBufferTarget); MGLOG_D("Syncing buffer map (glMapBuffer) for object with ID : %u", m_backendBufferId); @@ -133,10 +148,16 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendBufferObject::Bind() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindBuffer(TempBufferTarget, m_backendBufferId); } void BackendBufferObject::Bind(GLenum target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindBuffer(target, m_backendBufferId); } @@ -145,6 +166,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace VertexArrayImpl { BackendVertexArrayObject::BackendVertexArrayObject() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGenVertexArrays(1, &m_backendVAOId); if (m_backendVAOId == 0) { MGLOG_E("Failed to generate vertex array object."); @@ -155,11 +179,17 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendVertexArrayObject::Bind() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindVertexArray(m_backendVAOId); } void BackendVertexArrayObject::SyncToBackend(SharedPtr& stateVAOObject, Bool needDivisor) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (!stateVAOObject) { MGLOG_E("State VAO object is null, cannot sync to backend."); return; @@ -233,6 +263,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace TextureImpl { BackendTextureObject::BackendTextureObject() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGenTextures(1, &m_backendTextureId); if (m_backendTextureId == 0) { MGLOG_E("Failed to generate texture object."); @@ -243,14 +276,23 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendTextureObject::Bind(GLenum target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindTexture(target, m_backendTextureId); } Uint BackendTextureObject::GetBackendTextureId() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif return m_backendTextureId; } void BackendTextureObject::SyncToBackend(SharedPtr& stateTextureObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif DebugImpl::ErrorLopper errorLopper; if (!stateTextureObject) { MGLOG_E("State texture object is null, cannot sync to backend."); @@ -329,8 +371,7 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("%s: target: %s: syncing mip %d: %dx%dx%d, byteSize = %d, pData = %p", __func__, MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str(), level, levelTexelSize.x(), levelTexelSize.y(), levelTexelSize.z(), levelByteSize, pData); - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + errorLopper.Clear(); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); MG_External::GLES::glTexImage2D(glUploadTarget, static_cast(level), glInternalFormat, @@ -367,9 +408,6 @@ namespace MobileGL::MG_Backend::DirectGLES { } auto glUploadTarget = MG_Util::ConvertTextureUploadTargetToGLEnum(uploadTarget); - - BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = - BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); MG_External::GLES::glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, @@ -541,6 +579,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace FramebufferImpl { BackendFramebufferObject::BackendFramebufferObject() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGenFramebuffers(1, &m_backendFBOId); if (m_backendFBOId == 0) { MGLOG_E("Failed to generate framebuffer object."); @@ -551,6 +592,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendFramebufferObject::Bind(FramebufferTarget target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (target == FramebufferTarget::Read) MG_External::GLES::glBindFramebuffer(GL_READ_FRAMEBUFFER, m_backendFBOId); else @@ -559,6 +603,9 @@ namespace MobileGL::MG_Backend::DirectGLES { void BackendFramebufferObject::SyncToBackend(SharedPtr& stateFBOObject, FramebufferTarget asTarget) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (!stateFBOObject) { MGLOG_E("State FBO object is null, cannot sync to backend."); return; @@ -664,6 +711,9 @@ namespace MobileGL::MG_Backend::DirectGLES { g_backendProgramObjects; BackendProgramObjectImpl::BackendProgramObjectImpl() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif m_backendProgramId = MG_External::GLES::glCreateProgram(); if (m_backendProgramId == 0) { MGLOG_E("Failed to create program object in backend."); @@ -675,6 +725,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } BackendProgramObjectImpl::~BackendProgramObjectImpl() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (m_backendProgramId != 0) { MGLOG_D("Deleting backend program object with ID: %u", m_backendProgramId); MG_External::GLES::glDeleteProgram(m_backendProgramId); @@ -682,6 +735,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendProgramObjectImpl::SyncToBackend(SharedPtr& stateProgramObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (!stateProgramObject) { MGLOG_E("State program object is null, skipping backend sync."); return; @@ -822,6 +878,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendProgramObjectImpl::Use() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MGLOG_D("Using program %u", m_backendProgramId); MG_External::GLES::glUseProgram(m_backendProgramId); } @@ -829,6 +888,9 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace SamplerImpl { BackendSamplerObject::BackendSamplerObject() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGenSamplers(1, &m_backendSamplerId); if (m_backendSamplerId == 0) { MGLOG_E("Failed to generate sampler object."); @@ -839,6 +901,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendSamplerObject::SyncToBackend(SharedPtr& stateSamplerObject) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif if (!stateSamplerObject) { MGLOG_E("State sampler object is null, cannot sync to backend."); return; @@ -889,10 +954,16 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendSamplerObject::Bind(Uint unit) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindSampler(static_cast(unit), m_backendSamplerId); } Uint BackendSamplerObject::GetBackendSamplerId() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif return m_backendSamplerId; } diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index 5d048156..579d3b3e 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -11,37 +11,58 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace BufferImpl { BackendBufferBindingProtector::BackendBufferBindingProtector(GLenum target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif m_target = target; MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding); } BackendBufferBindingProtector::~BackendBufferBindingProtector() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindBuffer(m_target, m_previousBinding); } } // namespace BufferImpl namespace VertexArrayImpl { BackendVertexArrayBindingProtector::BackendVertexArrayBindingProtector() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &m_previousBinding); } BackendVertexArrayBindingProtector::~BackendVertexArrayBindingProtector() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindVertexArray(m_previousBinding); } } // namespace VertexArrayImpl namespace TextureImpl { BackendTextureBindingProtector::BackendTextureBindingProtector(GLenum target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif m_target = target; MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, true), &m_previousBinding); } BackendTextureBindingProtector::~BackendTextureBindingProtector() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindTexture(m_target, m_previousBinding); } void NormalizePixelFormat(GLenum internalFormat, GLenum* outInternalFormat, GLenum* outType, GLenum* outFormat) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif switch (internalFormat) { case GL_DEPTH_COMPONENT16: if (outInternalFormat) *outInternalFormat = internalFormat; @@ -365,6 +386,9 @@ namespace MobileGL::MG_Backend::DirectGLES { void GenerateTextureFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat, GLenum* outType, GLenum* outFormat) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif NormalizePixelFormat(MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat), outInternalFormat, outType, outFormat); } @@ -372,15 +396,24 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace FramebufferImpl { BackendFramebufferBindingProtector::BackendFramebufferBindingProtector(GLenum target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif m_target = target; MG_External::GLES::glGetIntegerv(Utils::GetBindingQuery(target, false), &m_previousBinding); } BackendFramebufferBindingProtector::~BackendFramebufferBindingProtector() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindFramebuffer(m_target, m_previousBinding); } GLuint BackendFramebufferBindingProtector::GetTempFBO(FramebufferTarget target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target); GLuint& fbo = (glTarget == GL_DRAW_FRAMEBUFFER) ? s_tempDrawFBO : s_tempReadFBO; if (fbo == 0) { @@ -390,6 +423,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } void BackendFramebufferBindingProtector::BindTempFBO(MobileGL::FramebufferTarget target) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif GLuint fbo = GetTempFBO(target); GLenum glTarget = MG_Util::ConvertFramebufferTargetToGLEnum(target); MG_External::GLES::glBindFramebuffer(glTarget, fbo); @@ -398,12 +434,18 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace PrgramImpl { String ProcessOutColorLocations(const String& glslCode) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif const static std::regex pattern(R"(\n(out highp vec4 outColor)(\d+);)"); const String replacement = "\nlayout(location=$2) $1$2;"; return std::regex_replace(glslCode, pattern, replacement); } String ForceSupporterOutput(const String& glslCode) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif Bool hasPrecisionFloat = glslCode.find("precision ") != String::npos && glslCode.find("float;") != String::npos; Bool hasPrecisionInt = glslCode.find("precision ") != String::npos && glslCode.find("int;") != String::npos; @@ -460,6 +502,9 @@ namespace MobileGL::MG_Backend::DirectGLES { } String RemoveLayoutBinding(const String& glslCode) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif static std::regex bindingRegex(R"(layout\s*\(\s*binding\s*=\s*\d+\s*\)\s*)"); String result = std::regex_replace(glslCode, bindingRegex, ""); static std::regex bindingRegex2(R"(layout\s*\(\s*binding\s*=\s*\d+\s*,)"); @@ -470,12 +515,18 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace Utils { void CheckGLESError() { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif while (GLenum err = MG_External::GLES::glGetError() != GL_NO_ERROR) { MGLOG_E("-> GLES Error: %s", MG_Util::ConvertGLEnumToString(err).c_str()); } } GLenum GetBindingQuery(GLenum target, bool isTexture) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif switch (target) { case GL_TEXTURE_BUFFER: return isTexture ? GL_TEXTURE_BINDING_BUFFER : GL_TEXTURE_BUFFER_BINDING; diff --git a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp index 0dcc432d..3d94461c 100644 --- a/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp +++ b/MobileGL/MG_Impl/GLImpl/Drawing/GL_Drawing.cpp @@ -9,12 +9,18 @@ namespace MobileGL { namespace MG_Impl::GLImpl { void Clear_Backend(GLbitfield mask) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::Clear(mask); #endif } void DrawElements_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElements(mode, count, type, indices); #endif @@ -22,6 +28,9 @@ namespace MobileGL { void MultiDrawElements_Backend(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawcount) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::MultiDrawElements(mode, count, type, indices, drawcount); #endif @@ -30,12 +39,18 @@ namespace MobileGL { void MultiDrawElementsBaseVertex_Backend(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawcount, const GLint* basevertex) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::MultiDrawElementsBaseVertex(mode, count, type, indices, drawcount, basevertex); #endif } void DrawArrays_Backend(GLenum mode, GLint first, GLsizei count) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawArrays(mode, first, count); #endif @@ -43,6 +58,9 @@ namespace MobileGL { void DrawElementsBaseVertex_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint basevertex) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsBaseVertex(mode, count, type, indices, basevertex); #endif @@ -50,12 +68,18 @@ namespace MobileGL { void MultiDrawElementsIndirect_Backend(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::MultiDrawElementsIndirect(mode, type, indirect, drawcount, stride); #endif } void MultiDrawArraysIndirect_Backend(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::MultiDrawArraysIndirect(mode, indirect, drawcount, stride); #endif @@ -63,6 +87,9 @@ namespace MobileGL { void DrawRangeElementsBaseVertex_Backend(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices, GLint basevertex) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex); #endif @@ -70,6 +97,9 @@ namespace MobileGL { void DrawRangeElements_Backend(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawRangeElements(mode, start, end, count, type, indices); #endif @@ -78,6 +108,9 @@ namespace MobileGL { void DrawElementsInstancedBaseVertexBaseInstance_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsInstancedBaseVertexBaseInstance( mode, count, type, indices, instancecount, basevertex, baseinstance); @@ -86,6 +119,9 @@ namespace MobileGL { void DrawElementsInstancedBaseVertex_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLint basevertex) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex); @@ -94,6 +130,9 @@ namespace MobileGL { void DrawElementsInstancedBaseInstance_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount, GLuint baseinstance) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsInstancedBaseInstance(mode, count, type, indices, instancecount, baseinstance); @@ -102,30 +141,45 @@ namespace MobileGL { void DrawElementsInstanced_Backend(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instancecount) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsInstanced(mode, count, type, indices, instancecount); #endif } void DrawElementsIndirect_Backend(GLenum mode, GLenum type, const void* indirect) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawElementsIndirect(mode, type, indirect); #endif } void DrawArraysInstancedBaseInstance_Backend(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawArraysInstancedBaseInstance(mode, first, count, instancecount, baseinstance); #endif } void DrawArraysInstanced_Backend(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawArraysInstanced(mode, first, count, instancecount); #endif } void DrawArraysIndirect_Backend(GLenum mode, const void* indirect) { +#ifdef TRACY_ENABLE + ZoneScopedC(TRACY_ZONECOLOR_BACKEND); +#endif #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES MG_Backend::DirectGLES::DrawArraysIndirect(mode, indirect); #endif From 6a9738a7c5aafc765e2d52fccd22fff04328c8ed Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 11 Dec 2025 20:38:09 +0800 Subject: [PATCH 13/18] [Optimization] (MG_Backend/DirectGLES): optimize `BackendTextureBindingProtector` usage --- MobileGL/Includes.h | 1 + MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 15 +++++++++++++++ MobileGL/MG_Backend/DirectGLES/Managers.cpp | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/MobileGL/Includes.h b/MobileGL/Includes.h index 2400bcbb..e6f303ed 100644 --- a/MobileGL/Includes.h +++ b/MobileGL/Includes.h @@ -33,6 +33,7 @@ #include #include #include +#include // Include FastSTL #include diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index b7042714..508bfa89 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -191,6 +191,8 @@ namespace MobileGL::MG_Backend::DirectGLES { // 1. textures bound to texture units (TODO: only sync ones that are used in current program) // 2. textures used in current FBO // 3. textures bound to image units (TODO) + constexpr SizeT TextureTargetCount = static_cast(TextureTarget::TextureTargetCount); + std::bitset dirtyTextureTargetBits; Vector> texturesToSync; @@ -202,6 +204,7 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& end = texturesToSync.end(); if (std::find(texturesToSync.begin(), end, textureObject) == end) { texturesToSync.push_back(textureObject); + dirtyTextureTargetBits.set(static_cast(textureObject->GetTarget())); } } } @@ -217,11 +220,23 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& end = texturesToSync.end(); if (std::find(texturesToSync.begin(), end, textureObject) == end) { texturesToSync.push_back(textureObject); + dirtyTextureTargetBits.set(static_cast(textureObject->GetTarget())); } } } } + BufferImpl::BackendBufferBindingProtector pixelUnpackProtector = + BufferImpl::BackendBufferBindingProtector(GL_PIXEL_UNPACK_BUFFER); + + Vector textureBindingProtectors; + for (SizeT target = 0; target < TextureTargetCount; ++target) { + if (dirtyTextureTargetBits[target]) { + textureBindingProtectors.emplace_back( + MG_Util::ConvertTextureTargetToGLEnum(static_cast(target))); + } + } + // Do real sync for (auto& textureObject : texturesToSync) { SyncTextureObjectToBackend(textureObject); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 92c8071f..2e0e5770 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -328,7 +328,7 @@ namespace MobileGL::MG_Backend::DirectGLES { return; } - BackendTextureBindingProtector backendTextureBindingProtector(target); + // BackendTextureBindingProtector backendTextureBindingProtector(target); Bind(target); errorLopper.Loop([file = __FILE__, line = __LINE__, func = __func__](GLenum err) { MGLOG_D("%s(%s:%d) ES error: %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); From f08859d1c5db2607eed868bfc203295735a547f1 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 12 Dec 2025 09:30:34 +0800 Subject: [PATCH 14/18] [Fix] (3rdparty/tracy): enable `TRACY_NO_CRASH_HANDLER` to prevent unwanted crash detection --- CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f90c259..9ce42d4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,12 +78,16 @@ add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/SPIRV-Cross) set(TRACY_ENABLE ON CACHE BOOL "Enable Tracy" FORCE) -set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected" FORCE) -set(TRACY_NO_EXIT OFF CACHE BOOL "Don't exit Tracy until connected" FORCE) -set(TRACY_DELAYED_INIT ON CACHE BOOL "Don't init Tracy on library load" FORCE) -set(TRACY_MANUAL_LIFETIME ON CACHE BOOL "Manually control Tracy lifetime" FORCE) -add_subdirectory(3rdparty/tracy) +if (TRACY_ENABLE) + set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected" FORCE) + set(TRACY_NO_EXIT OFF CACHE BOOL "Don't exit Tracy until connected" FORCE) + set(TRACY_DELAYED_INIT ON CACHE BOOL "Don't init Tracy on library load" FORCE) + set(TRACY_MANUAL_LIFETIME ON CACHE BOOL "Manually control Tracy lifetime" FORCE) + set(TRACY_NO_CRASH_HANDLER ON CACHE BOOL "Disable crash handling" FORCE) + + add_subdirectory(3rdparty/tracy) +endif () set(SOURCE_FILES MobileGL/Init.cpp From 0519cdeb9ca91a7404711a4e724f1207513dc7f1 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 12 Dec 2025 10:25:39 +0800 Subject: [PATCH 15/18] [Optimization] (MG_Backend/DirectGLES): add more tracy zones --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 211 ++++++++++-------- 1 file changed, 119 insertions(+), 92 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 508bfa89..59b468cd 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -409,63 +409,79 @@ namespace MobileGL::MG_Backend::DirectGLES { BindCurrentFBO(FramebufferTarget::Draw); - const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray(); - if (currentVAO) { - const auto& backendVAOIt = VertexArrayImpl::g_backendVertexArrayObjects.find(currentVAO); - if (backendVAOIt != VertexArrayImpl::g_backendVertexArrayObjects.end()) { - backendVAOIt->second->Bind(); - } - } else { - MG_External::GLES::glBindVertexArray(0); - } - - Int maxTextureUnits = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; - for (Int unit = 0; unit < maxTextureUnits; ++unit) { - auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit); - - MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit); - - for (const auto& bindingSlot : textureUnit.GetAllBindingSlots()) { - const auto& textureObject = bindingSlot.GetBoundObject(); - if (!textureObject) continue; - - // Bind texture object - auto target = textureObject->GetTarget(); - if (target == TextureTarget::Texture1D || - target == TextureTarget::TextureRectangle || target == TextureTarget::Texture2DMultisampleArray || - target == TextureTarget::Texture1DArray || target == TextureTarget::Texture3D || - target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) { - MGLOG_D(" Texture target %s is not supported, skipping.", - MG_Util::ConvertTextureTargetToString(target).c_str()); - continue; - } - const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); - if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue; - - GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target); - backendTextureIt->second->Bind(targetGL); - } - - // Bind sampler object - const auto& samplerObject = textureUnit.GetSamplerObject(); - if (samplerObject) { - const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); - if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) { - backendSamplerIt->second->Bind(unit); + { +#ifdef TRACY_ENABLE + ZoneScopedNC("BindCurrentVAO", TRACY_ZONECOLOR_BACKEND); +#endif + const auto& currentVAO = MG_State::pGLContext->GetBoundVertexArray(); + if (currentVAO) { + const auto& backendVAOIt = VertexArrayImpl::g_backendVertexArrayObjects.find(currentVAO); + if (backendVAOIt != VertexArrayImpl::g_backendVertexArrayObjects.end()) { + backendVAOIt->second->Bind(); } } else { - MG_External::GLES::glBindSampler(unit, 0); + MG_External::GLES::glBindVertexArray(0); + } + } + + { +#ifdef TRACY_ENABLE + ZoneScopedNC("BindCurrentTextures", TRACY_ZONECOLOR_BACKEND); +#endif + Int maxTextureUnits = MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS; + for (Int unit = 0; unit < maxTextureUnits; ++unit) { + auto& textureUnit = MG_State::pGLContext->GetTextureUnitObject(unit); + + MG_External::GLES::glActiveTexture(GL_TEXTURE0 + unit); + + for (const auto& bindingSlot : textureUnit.GetAllBindingSlots()) { + const auto& textureObject = bindingSlot.GetBoundObject(); + if (!textureObject) continue; + + // Bind texture object + auto target = textureObject->GetTarget(); + if (target == TextureTarget::Texture1D || + target == TextureTarget::TextureRectangle || target == TextureTarget::Texture2DMultisampleArray || + target == TextureTarget::Texture1DArray || target == TextureTarget::Texture3D || + target == TextureTarget::Texture2DMultisample || target == TextureTarget::Texture2DArray) { + MGLOG_D(" Texture target %s is not supported, skipping.", + MG_Util::ConvertTextureTargetToString(target).c_str()); + continue; + } + const auto& backendTextureIt = TextureImpl::g_backendTextureObjects.find(textureObject); + if (backendTextureIt == TextureImpl::g_backendTextureObjects.end()) continue; + + GLenum targetGL = MG_Util::ConvertTextureTargetToGLEnum(target); + backendTextureIt->second->Bind(targetGL); + } + + // Bind sampler object + const auto& samplerObject = textureUnit.GetSamplerObject(); + if (samplerObject) { + const auto& backendSamplerIt = SamplerImpl::g_backendSamplerObjects.find(samplerObject); + if (backendSamplerIt != SamplerImpl::g_backendSamplerObjects.end()) { + backendSamplerIt->second->Bind(unit); + } + } else { + MG_External::GLES::glBindSampler(unit, 0); + } } } const auto& currentProgram = MG_State::pGLContext->GetCurrentProgram(); if (currentProgram && currentProgram->GetLinkStatus()) { +#ifdef TRACY_ENABLE + ZoneScopedNC("BindCurrentProgram", TRACY_ZONECOLOR_BACKEND); +#endif const auto& backendProgramIt = PrgramImpl::g_backendProgramObjects.find(currentProgram); if (backendProgramIt != PrgramImpl::g_backendProgramObjects.end()) { backendProgramIt->second->Use(); auto backendProgramId = backendProgramIt->second->GetBackendProgramId(); // Global UBO if (currentProgram->GetUBOSize() > 0) { +#ifdef TRACY_ENABLE + ZoneScopedNC("UpdateGlobalUBO", TRACY_ZONECOLOR_BACKEND); +#endif MG_External::GLES::glBindBuffer(GL_UNIFORM_BUFFER, backendProgramIt->second->GetBackendGlobalUBOId()); MG_External::GLES::glBufferSubData(GL_UNIFORM_BUFFER, 0, currentProgram->GetUBOSize(), @@ -480,67 +496,78 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, 0, backendProgramIt->second->GetBackendGlobalUBOId()); } - // Normal UBO - auto uboCount = currentProgram->GetActiveUniformBlocksCount(); - Uint lastUBOBinding = 0; // to prevent overlapping bindings between global UBO and normal UBOs - for (Int i = 0; i < uboCount; ++i) { - ++lastUBOBinding; - // program state binding index == backend binding index - // Connect program ubo index to backend binding point - auto binding = currentProgram->GetUniformBlockBinding(i); - auto& name = currentProgram->GetUniformBlockName(i); - GLuint backendBlkIdx = MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str()); - MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding); + { +#ifdef TRACY_ENABLE + ZoneScopedNC("UpdateUBO", TRACY_ZONECOLOR_BACKEND); +#endif + // Normal UBO + auto uboCount = currentProgram->GetActiveUniformBlocksCount(); + Uint lastUBOBinding = 0; // to prevent overlapping bindings between global UBO and normal UBOs + for (Int i = 0; i < uboCount; ++i) { + ++lastUBOBinding; + // program state binding index == backend binding index - // Connect buffer to backend binding point - auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding); - auto bufferObj = point.GetBoundObject(); - auto range = point.GetRange(); + // Connect program ubo index to backend binding point + auto binding = currentProgram->GetUniformBlockBinding(i); + auto& name = currentProgram->GetUniformBlockName(i); + GLuint backendBlkIdx = MG_External::GLES::glGetUniformBlockIndex(backendProgramId, name.c_str()); + MG_External::GLES::glUniformBlockBinding(backendProgramId, backendBlkIdx, lastUBOBinding); - if (bufferObj) { - const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObj); - if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) { - const auto& backendBufferObject = backendBufferIt->second; - backendBufferObject->Bind(GL_UNIFORM_BUFFER); - if (range.end == 0) { - MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding, - backendBufferObject->GetBackendBufferId()); + // Connect buffer to backend binding point + auto& point = MG_State::pGLContext->GetBufferBindingPoint(BufferTarget::Uniform, binding); + auto bufferObj = point.GetBoundObject(); + auto range = point.GetRange(); + + if (bufferObj) { + const auto& backendBufferIt = BufferImpl::g_backendBufferObjects.find(bufferObj); + if (backendBufferIt != BufferImpl::g_backendBufferObjects.end()) { + const auto& backendBufferObject = backendBufferIt->second; + backendBufferObject->Bind(GL_UNIFORM_BUFFER); + if (range.end == 0) { + MG_External::GLES::glBindBufferBase(GL_UNIFORM_BUFFER, lastUBOBinding, + backendBufferObject->GetBackendBufferId()); + } else { + MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding, + backendBufferObject->GetBackendBufferId(), + range.start, range.end - range.start); + } } else { - MG_External::GLES::glBindBufferRange(GL_UNIFORM_BUFFER, lastUBOBinding, - backendBufferObject->GetBackendBufferId(), - range.start, range.end - range.start); + MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO."); } - } else { - MGLOG_E("No backend buffer found for UBO binding, cannot bind UBO."); } } } - // Sampler unit binding - auto maxUniformLoc = currentProgram->GetMaxUniformLocation(); - for (int loc = 0; loc < maxUniformLoc; ++loc) { - auto unit = currentProgram->GetUniformSamplerOrImageUnitIndex(loc); - if (unit == -1) continue; - auto& name = currentProgram->GetUniformName(loc); - auto locAtBackend = MG_External::GLES::glGetUniformLocation( - backendProgramIt->second->GetBackendProgramId(), name.c_str()); - MG_External::GLES::glUniform1i(locAtBackend, unit); + { +#ifdef TRACY_ENABLE + ZoneScopedNC("BindSamplerUnit", TRACY_ZONECOLOR_BACKEND); +#endif + // Sampler unit binding + auto maxUniformLoc = currentProgram->GetMaxUniformLocation(); + for (int loc = 0; loc < maxUniformLoc; ++loc) { + auto unit = currentProgram->GetUniformSamplerOrImageUnitIndex(loc); + if (unit == -1) continue; + auto& name = currentProgram->GetUniformName(loc); + 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(); + 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; + 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 { - backendSamplerObject = backendSamplerIt->second; + MG_External::GLES::glBindSampler(unit, 0); } - backendSamplerObject->SyncToBackend(samplerObject); - } else { - MG_External::GLES::glBindSampler(unit, 0); } } } else { From 17bbe3e6bab6e98d1ae78aa5d15c3a89e3ba6fc8 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Fri, 12 Dec 2025 23:38:24 +0800 Subject: [PATCH 16/18] [Feat] (CMake): make `TRACY_ENABLE` as an option --- CMakeLists.txt | 2 +- build.gradle | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ce42d4d..78162e35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ set(SPIRV_CROSS_STATIC ON CACHE BOOL "Prefer static libs" FORCE) add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/SPIRV-Cross) -set(TRACY_ENABLE ON CACHE BOOL "Enable Tracy" FORCE) +option(TRACY_ENABLE "Enable Tracy" OFF) if (TRACY_ENABLE) set(TRACY_ON_DEMAND ON CACHE BOOL "Enable profiling only connected" FORCE) diff --git a/build.gradle b/build.gradle index 3cdee6a5..4b1148d4 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,12 @@ android { minSdk 26 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + +// externalNativeBuild { +// cmake { +// arguments "-DTRACY_ENABLE=ON" +// } +// } } buildTypes { From 81a717ada78800e630f8ac9a7c9f6f705f71db39 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 13 Dec 2025 20:48:59 +0800 Subject: [PATCH 17/18] [Feat] (MG_Impl/Texture): partially implement `glTexParameter*v` - Fixing NeoForge loading screen --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 8 +- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 82 +++++++++++++++++++ MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h | 5 ++ .../GLState/SamplerState/SamplerObject.h | 2 +- 4 files changed, 92 insertions(+), 5 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 65b5bcdc..16c09670 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -158,9 +158,9 @@ DECLARE_GL_FUNCTION_HEAD(void, StencilOp, GLenum fail, GLenum zfail, GLenum zpas DECLARE_GL_FUNCTION_HEAD(void, StencilOpSeparate, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) DECLARE_GL_FUNCTION_END_NO_RETURN(void, StencilOpSeparate, face, sfail, dpfail, dppass) DECLARE_GL_FUNCTION_HEAD(void, TexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage2D, target, level, internalformat, width, height, border, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, TexParameterf, GLenum target, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameterf, target, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterfv, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameterfv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TexParameterfv, GLenum target, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameterfv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TexParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameteri, target, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameteriv, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameteriv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TexParameteriv, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameteriv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, TexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels) DECLARE_GL_FUNCTION_HEAD(void, Uniform1f, GLint location, GLfloat v0) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1f, location, v0) DECLARE_GL_FUNCTION_HEAD(void, Uniform1fv, GLint location, GLsizei count, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Uniform1fv, location, count, value) @@ -401,8 +401,8 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnUniformiv, GLuint program, GLint locatio DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnUniformuiv, GLuint program, GLint location, GLsizei bufSize, GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetnUniformuiv, program, location, bufSize, params) DECLARE_GL_FUNCTION_STUB_HEAD(void, MinSampleShading, GLfloat value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, MinSampleShading, value) DECLARE_GL_FUNCTION_STUB_HEAD(void, PatchParameteri, GLenum pname, GLint value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PatchParameteri, pname, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterIiv, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameterIiv, target, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, TexParameterIuiv, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexParameterIuiv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TexParameterIiv, GLenum target, GLenum pname, const GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameterIiv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, TexParameterIuiv, GLenum target, GLenum pname, const GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexParameterIuiv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTexParameterIiv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexParameterIiv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetTexParameterIuiv, GLenum target, GLenum pname, GLuint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetTexParameterIuiv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, SamplerParameterIiv, GLuint sampler, GLenum pname, const GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, SamplerParameterIiv, sampler, pname, param) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 87b9e199..031a447a 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -305,6 +305,72 @@ namespace MobileGL { } } + // Quick and dirty TexParameter*v implementation to make NeoForge happy. + // TODO: implement the missing part + void TexParameterfv_State(GLenum target, GLenum pname, const GLfloat * params) { + switch (pname) { + case GL_TEXTURE_BORDER_COLOR: { + THROW_UNIMPL_EXCEPTION; + break; + } + case GL_TEXTURE_SWIZZLE_RGBA: { + THROW_UNIMPL_EXCEPTION; + break; + } + default: + TexParameterf_State(target, pname, *params); + break; + } + } + + void TexParameteriv_State(GLenum target, GLenum pname, const GLint * params) { + switch (pname) { + case GL_TEXTURE_BORDER_COLOR: { + THROW_UNIMPL_EXCEPTION; + break; + } + case GL_TEXTURE_SWIZZLE_RGBA: { + THROW_UNIMPL_EXCEPTION; + break; + } + default: + TexParameteri_State(target, pname, *params); + break; + } + } + + void TexParameterIiv_State(GLenum target, GLenum pname, const GLint * params) { + switch (pname) { + case GL_TEXTURE_BORDER_COLOR: { + THROW_UNIMPL_EXCEPTION; + break; + } + case GL_TEXTURE_SWIZZLE_RGBA: { + THROW_UNIMPL_EXCEPTION; + break; + } + default: + TexParameteri_State(target, pname, *params); + break; + } + } + + void TexParameterIuiv_State(GLenum target, GLenum pname, const GLuint * params) { + switch (pname) { + case GL_TEXTURE_BORDER_COLOR: { + THROW_UNIMPL_EXCEPTION; + break; + } + case GL_TEXTURE_SWIZZLE_RGBA: { + THROW_UNIMPL_EXCEPTION; + break; + } + default: + TexParameteri_State(target, pname, static_cast(*params)); + break; + } + } + void TexImage3DMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { // TODO: implement @@ -1033,6 +1099,22 @@ namespace MobileGL { TexParameteri_State(target, pname, param); } + void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params) { + TexParameterfv_State(target, pname, params); + } + + void TexParameteriv(GLenum target, GLenum pname, const GLint * params) { + TexParameteriv_State(target, pname, params); + } + + void TexParameterIiv(GLenum target, GLenum pname, const GLint * params) { + TexParameterIiv_State(target, pname, params); + } + + void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params) { + TexParameterIuiv_State(target, pname, params); + } + void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) { TexImage3DMultisample_State(target, samples, internalformat, width, height, depth, fixedsamplelocations); diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h index 0aa49015..0b05e7a7 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.h @@ -12,6 +12,11 @@ namespace MobileGL { const GLvoid* pixels); void TexParameterf(GLenum target, GLenum pname, GLfloat param); void TexParameteri(GLenum target, GLenum pname, GLint param); + void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params); + void TexParameteriv(GLenum target, GLenum pname, const GLint * params); + void TexParameterIiv(GLenum target, GLenum pname, const GLint * params); + void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params); + void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); void TexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, diff --git a/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h b/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h index 96fe0c6b..b8d84e69 100644 --- a/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h +++ b/MobileGL/MG_State/GLState/SamplerState/SamplerObject.h @@ -51,7 +51,7 @@ namespace MobileGL { SamplerWrapMode wrapS = SamplerWrapMode::Repeat; SamplerWrapMode wrapT = SamplerWrapMode::Repeat; SamplerWrapMode wrapR = SamplerWrapMode::Repeat; - SamplerFilterMode minFilter = SamplerFilterMode::Linear; + SamplerFilterMode minFilter = SamplerFilterMode::Nearest; SamplerFilterMode magFilter = SamplerFilterMode::Linear; SamplerMipmapMode mipmapMode = SamplerMipmapMode::Linear; Float minLod = -1000.0f; From c3755d77ef356790a1f3194bf17698108e6c11b6 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 13 Dec 2025 21:28:04 +0800 Subject: [PATCH 18/18] [Feat] (MG_Impl/Texture): implement `GL_TEXTURE_SWIZZLE_RGBA` --- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 177 ++++++++++++++---- .../GLState/TextureState/TextureObject.cpp | 3 + .../GLState/TextureState/TextureObject.h | 2 + 3 files changed, 142 insertions(+), 40 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index 031a447a..b81b013e 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -20,6 +20,24 @@ namespace MobileGL { namespace MG_Impl::GLImpl { + SharedPtr GetTextureObjectByTarget(TextureUploadTarget textureUploadingTarget, TextureTarget textureTarget) { + SharedPtr textureObject = nullptr; + if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) { + textureObject = + TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget); + } else { + auto activeUnit = + MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); + auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); + textureObject = bindingSlot.GetBoundObject(); + } + + if (!TextureImpl::ValidateTextureObject(textureObject)) + return nullptr; + + return textureObject; + } + void TexSubImage3D_State(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* pixels) { // TODO: implement @@ -147,18 +165,10 @@ namespace MobileGL { TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); // ======================= Processing ================================ - SharedPtr textureObject = nullptr; - if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) { - textureObject = - TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget); - } else { - auto activeUnit = - MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); - auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); - textureObject = bindingSlot.GetBoundObject(); - } - - if (!TextureImpl::ValidateTextureObject(textureObject)) return; + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; switch (pname) { case GL_TEXTURE_MAG_FILTER: @@ -193,12 +203,6 @@ namespace MobileGL { textureObject->SetSwizzleParam(swizzleParam, swizzleValue); break; } - case GL_TEXTURE_SWIZZLE_RGBA: - // Not supported in this function - break; - case GL_TEXTURE_BORDER_COLOR: - // Not supported in this function - break; case GL_TEXTURE_WRAP_S: textureObject->GetSamplerObject()->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(param)); break; @@ -215,6 +219,10 @@ namespace MobileGL { textureObject->GetSamplerObject()->SetSamplerCompareFunc( MG_Util::ConvertGLEnumToSamplerCompareFunc(param)); break; + case GL_TEXTURE_SWIZZLE_RGBA: + // Not supported in this function + case GL_TEXTURE_BORDER_COLOR: + // Not supported in this function default: MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", "TexParameteri_State", @@ -229,18 +237,10 @@ namespace MobileGL { TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); // ======================= Processing ================================ - SharedPtr textureObject = nullptr; - if (TextureImpl::IsProxyTextureTarget(textureUploadingTarget)) { - textureObject = - TextureImpl::pProxyTextureManager->CreateOrReplaceProxyTextureObject(textureUploadingTarget); - } else { - auto activeUnit = - MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit()); - auto& bindingSlot = activeUnit.GetBindingSlot(textureTarget); - textureObject = bindingSlot.GetBoundObject(); - } - - if (!TextureImpl::ValidateTextureObject(textureObject)) return; + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; switch (pname) { case GL_TEXTURE_MAG_FILTER: @@ -275,12 +275,6 @@ namespace MobileGL { textureObject->SetSwizzleParam(swizzleParam, swizzleValue); break; } - case GL_TEXTURE_SWIZZLE_RGBA: - // Not supported in this function - break; - case GL_TEXTURE_BORDER_COLOR: - // Not supported in this function - break; case GL_TEXTURE_WRAP_S: textureObject->GetSamplerObject()->SetWrapS(MG_Util::ConvertGLEnumToSamplerWrapMode(param)); break; @@ -297,6 +291,10 @@ namespace MobileGL { textureObject->GetSamplerObject()->SetSamplerCompareFunc( MG_Util::ConvertGLEnumToSamplerCompareFunc(param)); break; + case GL_TEXTURE_SWIZZLE_RGBA: + // Not supported in this function + case GL_TEXTURE_BORDER_COLOR: + // Not supported in this function default: MG_State::pGLContext->RecordError( ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", "TexParameteri_State", @@ -310,11 +308,40 @@ namespace MobileGL { void TexParameterfv_State(GLenum target, GLenum pname, const GLfloat * params) { switch (pname) { case GL_TEXTURE_BORDER_COLOR: { + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; THROW_UNIMPL_EXCEPTION; break; } case GL_TEXTURE_SWIZZLE_RGBA: { - THROW_UNIMPL_EXCEPTION; + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; + + Vec4 swizzleParams; + for (int i = 0; i < 4; i++) { + swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); + if (TextureSwizzleParam::Unknown == swizzleParams[i]) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + "`params` is not valid.")); + return; + } + } + textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -326,11 +353,41 @@ namespace MobileGL { void TexParameteriv_State(GLenum target, GLenum pname, const GLint * params) { switch (pname) { case GL_TEXTURE_BORDER_COLOR: { + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; + THROW_UNIMPL_EXCEPTION; break; } case GL_TEXTURE_SWIZZLE_RGBA: { - THROW_UNIMPL_EXCEPTION; + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; + + Vec4 swizzleParams; + for (int i = 0; i < 4; i++) { + swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); + if (TextureSwizzleParam::Unknown == swizzleParams[i]) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + "`params` is not valid.")); + return; + } + } + textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -346,7 +403,27 @@ namespace MobileGL { break; } case GL_TEXTURE_SWIZZLE_RGBA: { - THROW_UNIMPL_EXCEPTION; + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; + + Vec4 swizzleParams; + for (int i = 0; i < 4; i++) { + swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); + if (TextureSwizzleParam::Unknown == swizzleParams[i]) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + "`params` is not valid.")); + return; + } + } + textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: @@ -362,7 +439,27 @@ namespace MobileGL { break; } case GL_TEXTURE_SWIZZLE_RGBA: { - THROW_UNIMPL_EXCEPTION; + // ======================= Converting ================================ + TextureUploadTarget textureUploadingTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(target); + TextureTarget textureTarget = MG_Util::ConvertGLEnumToTextureTarget(target); + + // ======================= Processing ================================ + SharedPtr textureObject = + GetTextureObjectByTarget(textureUploadingTarget, textureTarget); + if (!textureObject) + return; + + Vec4 swizzleParams; + for (int i = 0; i < 4; i++) { + swizzleParams[i] = MG_Util::ConvertGLEnumToTextureSwizzleParam(static_cast(params[i])); + if (TextureSwizzleParam::Unknown == swizzleParams[i]) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + "`params` is not valid.")); + return; + } + } + textureObject->SetSwizzleParamRGBA(swizzleParams); break; } default: diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp index dd5cdb88..98219968 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.cpp @@ -91,6 +91,9 @@ namespace MobileGL { break; } } + void TextureObjectBase::SetSwizzleParamRGBA(const Vec4& values) { + m_swizzleParams = values; + } const UintVec2& TextureObjectBase::GetLevelRange() const { return m_levelRange; diff --git a/MobileGL/MG_State/GLState/TextureState/TextureObject.h b/MobileGL/MG_State/GLState/TextureState/TextureObject.h index 236114a9..0d83409e 100644 --- a/MobileGL/MG_State/GLState/TextureState/TextureObject.h +++ b/MobileGL/MG_State/GLState/TextureState/TextureObject.h @@ -28,6 +28,7 @@ namespace MobileGL { virtual void SetBorderColor(const FloatVec4& color) = 0; virtual TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const = 0; virtual void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) = 0; + virtual void SetSwizzleParamRGBA(const Vec4& values) = 0; virtual const Vec4& GetAllSwizzleParams() const = 0; virtual const UintVec2& GetLevelRange() const = 0; virtual void SetBaseLevel(Uint baseLevel) = 0; @@ -54,6 +55,7 @@ namespace MobileGL { TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const override; const Vec4& GetAllSwizzleParams() const override; void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) override; + void SetSwizzleParamRGBA(const Vec4& values) override; const UintVec2& GetLevelRange() const override; void SetBaseLevel(Uint baseLevel) override; void SetMaxLevel(Uint maxLevel) override;