diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index a2eb6732..5607126e 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -1888,6 +1888,9 @@ namespace MobileGL::MG_Backend::DirectGLES { break; case TextureTarget::Texture3D: case TextureTarget::Texture2DArray: + // ES 3.2 has GL_TEXTURE_CUBE_MAP_ARRAY natively and it stores exactly + // like a 2D array whose depth is 6 * the cube count. + case TextureTarget::TextureCubeMapArray: g_GLESFuncs.glTexImage3D( glUploadTarget, static_cast(level), (GLint)glInternalFormat, static_cast(uploadSize.x()), static_cast(uploadSize.y()), @@ -1965,6 +1968,7 @@ namespace MobileGL::MG_Backend::DirectGLES { break; case TextureTarget::Texture3D: case TextureTarget::Texture2DArray: + case TextureTarget::TextureCubeMapArray: g_GLESFuncs.glTexStorage3D(target, static_cast(mipmapCount), glInternalFormat, static_cast(storageSize.x()), static_cast(storageSize.y()), @@ -2017,6 +2021,7 @@ namespace MobileGL::MG_Backend::DirectGLES { break; case TextureTarget::Texture3D: case TextureTarget::Texture2DArray: + case TextureTarget::TextureCubeMapArray: g_GLESFuncs.glTexSubImage3D( glUploadTarget, static_cast(level), 0, 0, 0, static_cast(uploadSize.x()), @@ -2080,7 +2085,8 @@ namespace MobileGL::MG_Backend::DirectGLES { break; } case TextureTarget::Texture3D: - case TextureTarget::Texture2DArray: { + case TextureTarget::Texture2DArray: + case TextureTarget::TextureCubeMapArray: { g_GLESFuncs.glTexImage3D( glUploadTarget, static_cast(level), (GLint)glInternalFormat, static_cast(uploadSize.x()), @@ -2180,6 +2186,9 @@ namespace MobileGL::MG_Backend::DirectGLES { break; case TextureTarget::Texture3D: case TextureTarget::Texture2DArray: + // ES 3.2 has GL_TEXTURE_CUBE_MAP_ARRAY natively and it stores exactly + // like a 2D array whose depth is 6 * the cube count. + case TextureTarget::TextureCubeMapArray: g_GLESFuncs.glTexSubImage3D(glUploadTarget, static_cast(level), 0, 0, 0, static_cast(uploadSize.x()), static_cast(uploadSize.y()), @@ -2630,6 +2639,8 @@ namespace MobileGL::MG_Backend::DirectGLES { } else if (const auto uploadTarget = attachmentObject.GetTextureUploadTarget(); uploadTarget == TextureUploadTarget::Texture3D || uploadTarget == TextureUploadTarget::Texture2DArray || + uploadTarget == TextureUploadTarget::Texture1DArray || + uploadTarget == TextureUploadTarget::CubeMapArray || uploadTarget == TextureUploadTarget::Texture2DMultisampleArray) { // Single slice/layer of a 3D or array texture: ES has no // glFramebufferTexture3D, layers attach via glFramebufferTextureLayer. diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp index 6da11c3e..4251fbe5 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.cpp @@ -837,6 +837,10 @@ namespace MobileGL::MG_Util::BackendLoader { std::strcmp(extension, "GL_OES_texture_border_clamp") == 0) { caps.SupportsTextureBorderClamp = true; } + if (std::strcmp(extension, "GL_EXT_texture_cube_map_array") == 0 || + std::strcmp(extension, "GL_OES_texture_cube_map_array") == 0) { + caps.SupportsTextureCubeMapArray = true; + } if (std::strcmp(extension, "GL_EXT_base_instance") == 0) { caps.SupportsBaseInstance = true; } @@ -1021,6 +1025,7 @@ namespace MobileGL::MG_Util::BackendLoader { // Core from ES 3.2 on, whatever the extension string says. if (caps.GLESVersion.Major > 3 || (caps.GLESVersion.Major == 3 && caps.GLESVersion.Minor >= 2)) { caps.SupportsTextureBorderClamp = true; + caps.SupportsTextureCubeMapArray = true; } if (caps.SupportsTextureFilterAnisotropy) { GLfloat maxTextureMaxAnisotropy = 1.0f; diff --git a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h index 35f2d650..abbf9757 100644 --- a/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h +++ b/MobileGL/MG_Util/BackendLoaders/OpenGL/Loader.h @@ -1045,6 +1045,8 @@ namespace MobileGL { // EXT/OES_texture_border_clamp before that. Without it every border-colour parameter // raises INVALID_ENUM on the driver, so the syncs have to be gated on it. Bool SupportsTextureBorderClamp = false; + // GL_TEXTURE_CUBE_MAP_ARRAY: ES 3.2 core, or EXT/OES_texture_cube_map_array before it. + Bool SupportsTextureCubeMapArray = false; // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT of the host driver; only queried when the // extension above is present, and left at 1.0 (no anisotropy) otherwise. Float MaxTextureMaxAnisotropy = 1.0f; diff --git a/MobileGL/MG_Util/SelfTest/DriverPost.cpp b/MobileGL/MG_Util/SelfTest/DriverPost.cpp index 2872bdd5..c52077d7 100644 --- a/MobileGL/MG_Util/SelfTest/DriverPost.cpp +++ b/MobileGL/MG_Util/SelfTest/DriverPost.cpp @@ -309,6 +309,16 @@ namespace MobileGL::MG_Util::SelfTest { "sampling outside a GL_CLAMP_TO_BORDER texture reads the driver's default " "border instead of the requested colour"); } + if (caps.SupportsTextureCubeMapArray) { + builder.Pass("Texture cube map array", + "supported (GL_TEXTURE_CUBE_MAP_ARRAY textures get real storage and can be " + "attached to a framebuffer)"); + } else { + builder.Warn("Texture cube map array", + "not supported (pre-ES 3.2 without GL_EXT/OES_texture_cube_map_array); a cube " + "map array texture gets no driver storage at all, so sampling one reads nothing " + "and rendering to one does not reach the screen"); + } if (glesFuncs.glPatchParameteri != nullptr) { builder.Pass("Tessellation patch parameters", "glPatchParameteri present (GL_PATCH_VERTICES reaches the driver)");