From 25323bfb8ecd8a51a65a647bd6f1d3cdea69d31e Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Thu, 16 Jul 2026 19:44:20 -0400 Subject: [PATCH] [Fix] (MG_Backend/DirectGLES, MG_Impl/GLImpl): sync GL_TEXTURE_2D_ARRAY textures to the ES backend - the target was skipped as unsupported so array textures never uploaded or bound (every KHR-GL33.pixelstoragemodes.teximage3d case failed); also keep array layer counts constant across mip levels in TexStorage3D and generated-mip storage allocation (only true 3D textures halve depth) --- MobileGL/MG_Backend/DirectGLES/Managers.cpp | 7 +++++- MobileGL/MG_Backend/DirectGLES/Managers.h | 2 +- .../MG_Impl/GLImpl/Texture/GL_Texture.cpp | 25 +++++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index bf3aaa7d..b02257ea 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -1715,6 +1715,7 @@ namespace MobileGL::MG_Backend::DirectGLES { 0, glFormat, glType, uploadData); break; case TextureTarget::Texture3D: + case TextureTarget::Texture2DArray: g_GLESFuncs.glTexImage3D( glUploadTarget, static_cast(level), (GLint)glInternalFormat, static_cast(levelTexelSize.x()), static_cast(levelTexelSize.y()), @@ -1790,6 +1791,7 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(baseSize.y())); break; case TextureTarget::Texture3D: + case TextureTarget::Texture2DArray: g_GLESFuncs.glTexStorage3D(target, static_cast(mipmapCount), glInternalFormat, static_cast(baseSize.x()), static_cast(baseSize.y()), @@ -1835,6 +1837,7 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(levelTexelSize.y()), glFormat, glType, uploadData); break; case TextureTarget::Texture3D: + case TextureTarget::Texture2DArray: g_GLESFuncs.glTexSubImage3D( glUploadTarget, static_cast(level), 0, 0, 0, static_cast(levelTexelSize.x()), @@ -1893,7 +1896,8 @@ namespace MobileGL::MG_Backend::DirectGLES { static_cast(levelTexelSize.y()), 0, glFormat, glType, uploadData); break; } - case TextureTarget::Texture3D: { + case TextureTarget::Texture3D: + case TextureTarget::Texture2DArray: { g_GLESFuncs.glTexImage3D( glUploadTarget, static_cast(level), (GLint)glInternalFormat, static_cast(levelTexelSize.x()), @@ -1987,6 +1991,7 @@ namespace MobileGL::MG_Backend::DirectGLES { uploadData); break; case TextureTarget::Texture3D: + case TextureTarget::Texture2DArray: g_GLESFuncs.glTexSubImage3D(glUploadTarget, static_cast(level), 0, 0, 0, static_cast(texelSize.x()), static_cast(texelSize.y()), diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index c1a82b6e..c90fdbaf 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -255,7 +255,7 @@ namespace MobileGL::MG_Backend::DirectGLES { namespace TextureImpl { inline Bool IsSupportedTextureTarget(TextureTarget target) { if (target == TextureTarget::Texture1D || target == TextureTarget::TextureRectangle || - target == TextureTarget::Texture1DArray || target == TextureTarget::Texture2DArray) + target == TextureTarget::Texture1DArray) return false; return true; } diff --git a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp index d0e958ea..77f9a9e3 100644 --- a/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp +++ b/MobileGL/MG_Impl/GLImpl/Texture/GL_Texture.cpp @@ -284,10 +284,16 @@ namespace MobileGL::MG_Impl::GLImpl { MG_State::GLState::TextureState::MAX_TEXTURE_IMAGE_UNITS)); } - Uint ComputeFullMipmapLevelCount(const IntVec3& baseTexelSize) { + // Array targets store their layer count in z; layers never participate in mip + // reduction (GL 3.3 §3.8.14), only true 3D textures halve their depth per level. + Bool DepthParticipatesInMipmapping(TextureTarget target) { + return target == TextureTarget::Texture3D; + } + + Uint ComputeFullMipmapLevelCount(const IntVec3& baseTexelSize, Bool depthMips) { Int maxDimension = std::max( baseTexelSize.x(), - std::max(baseTexelSize.y(), std::max(baseTexelSize.z(), 1))); + std::max(baseTexelSize.y(), depthMips ? std::max(baseTexelSize.z(), 1) : 1)); Uint mipLevelCount = 1; while (maxDimension > 1) { maxDimension = std::max(maxDimension / 2, 1); @@ -296,11 +302,12 @@ namespace MobileGL::MG_Impl::GLImpl { return mipLevelCount; } - IntVec3 ComputeMipmapTexelSize(const IntVec3& baseTexelSize, Uint relativeLevel) { + IntVec3 ComputeMipmapTexelSize(const IntVec3& baseTexelSize, Uint relativeLevel, Bool depthMips) { return { std::max(baseTexelSize.x() >> static_cast(relativeLevel), 1), std::max(baseTexelSize.y() >> static_cast(relativeLevel), 1), - std::max(baseTexelSize.z() >> static_cast(relativeLevel), 1), + depthMips ? std::max(baseTexelSize.z() >> static_cast(relativeLevel), 1) + : std::max(baseTexelSize.z(), 1), }; } @@ -323,9 +330,10 @@ namespace MobileGL::MG_Impl::GLImpl { } const SizeT bytesPerTexel = baseByteSize / baseTexelCount; - const Uint requiredLevelCount = ComputeFullMipmapLevelCount(baseTexelSize); + const Bool depthMips = DepthParticipatesInMipmapping(texture.GetTarget()); + const Uint requiredLevelCount = ComputeFullMipmapLevelCount(baseTexelSize, depthMips); for (Uint level = 1; level < requiredLevelCount; ++level) { - const IntVec3 levelTexelSize = ComputeMipmapTexelSize(baseTexelSize, level); + const IntVec3 levelTexelSize = ComputeMipmapTexelSize(baseTexelSize, level, depthMips); const SizeT levelByteSize = bytesPerTexel * static_cast(levelTexelSize.x()) * static_cast(levelTexelSize.y()) * static_cast(levelTexelSize.z()); @@ -2939,10 +2947,13 @@ namespace MobileGL::MG_Impl::GLImpl { auto* textureMipmapObject = static_cast(textureObject.get()); textureObject->SetInternalFormat(textureInternalFormat); + // Array targets keep their layer count constant across levels; only true 3D + // textures halve depth per level (GL 3.3 §3.9 glTexStorage3D). + const Bool depthMips = DepthParticipatesInMipmapping(textureObject->GetTarget()); for (GLsizei level = 0; level < levels; ++level) { const GLsizei levelWidth = std::max(1, width >> level); const GLsizei levelHeight = std::max(1, height >> level); - const GLsizei levelDepth = std::max(1, depth >> level); + const GLsizei levelDepth = depthMips ? std::max(1, depth >> level) : depth; const SizeT byteSize = ComputeTextureStorageByteSize(textureInternalFormat, levelWidth, levelHeight, levelDepth); textureMipmapObject->AllocateStorage(textureUploadTarget, level,