From e7e6faa571e4687e3d99e0e8c9b2ab6a71786fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 9 Apr 2023 16:00:15 +0200 Subject: [PATCH] GL: rework Texture, TextureArray and MultisampleTexture symbol export. This fixes a "visibility attribute ignored" warning in MultisampleTexture.cpp on newer GCC and makes the three behave consistently without having to perform crazy ordering between function definitions and explicit template instantiation. It's horrible, yes, but I had to resort to the same approach in StringView.cpp because in general every other variant was failing in some way in some compilers. I hate everything about this. --- src/Magnum/GL/MultisampleTexture.cpp | 38 +++++---- src/Magnum/GL/MultisampleTexture.h | 10 ++- src/Magnum/GL/Texture.cpp | 123 ++++++++++++++------------- src/Magnum/GL/Texture.h | 9 +- src/Magnum/GL/TextureArray.cpp | 69 ++++++++------- src/Magnum/GL/TextureArray.h | 10 ++- 6 files changed, 152 insertions(+), 107 deletions(-) diff --git a/src/Magnum/GL/MultisampleTexture.cpp b/src/Magnum/GL/MultisampleTexture.cpp index d91305b17..beb78906b 100644 --- a/src/Magnum/GL/MultisampleTexture.cpp +++ b/src/Magnum/GL/MultisampleTexture.cpp @@ -75,21 +75,8 @@ template MultisampleTexture MultisampleTextu return out; } -/* Other view() overloads at the end */ - -template MultisampleTexture& MultisampleTexture::setLabel(Containers::StringView label) { - AbstractTexture::setLabel(label); - return *this; -} - -template class MAGNUM_GL_EXPORT MultisampleTexture<2>; -template class MAGNUM_GL_EXPORT MultisampleTexture<3>; - -/* Because these refer to concrete types different than the class itself, they - have to be after the explicit type instantiations. Additionally, on Windows (MSVC, clang-cl and MinGw) these need an explicit export otherwise the - symbol doesn't get exported. - - Other view() overloads above. */ +/* On Windows (MSVC, clang-cl and MinGw) these need an explicit export + otherwise the symbol doesn't get exported. */ template<> template<> MAGNUM_GL_EXPORT MultisampleTexture2D MultisampleTexture2D::view(MultisampleTexture2DArray& original, const TextureFormat internalFormat, const Int layer) { /* glTextureView() doesn't work with glCreateTextures() as it needs an object without a name bound, so have to construct manually. The object @@ -112,5 +99,26 @@ template<> template<> MAGNUM_GL_EXPORT MultisampleTexture2DArray MultisampleText return out; } +template MultisampleTexture& MultisampleTexture::setLabel(Containers::StringView label) { + AbstractTexture::setLabel(label); + return *this; +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +template class + /* GCC needs the export macro on the class definition (and here it warns + that the type is already defined so the export is ignored), while Clang + and MSVC need it here (and ignore it on the declaration) */ + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + MultisampleTexture<2>; +template class + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + MultisampleTexture<3>; +#endif + }} #endif diff --git a/src/Magnum/GL/MultisampleTexture.h b/src/Magnum/GL/MultisampleTexture.h index c95e212b6..8bfac461a 100644 --- a/src/Magnum/GL/MultisampleTexture.h +++ b/src/Magnum/GL/MultisampleTexture.h @@ -101,7 +101,15 @@ Note that multisample textures don't support compressed formats. array textures. @requires_gles Multisample textures are not available in WebGL. */ -template class MAGNUM_GL_EXPORT MultisampleTexture: public AbstractTexture { +template class +#ifndef CORRADE_TARGET_MSVC +/* If it's here, MSVC complains that out-of-class inline functions have a + definition while being dllimport'd. If I remove it, GCC then complains that + the export in MultisampleTexture.cpp is ignored as the type is already + defined. */ +MAGNUM_GL_EXPORT +#endif +MultisampleTexture: public AbstractTexture { public: enum: UnsignedInt { Dimensions = dimensions /**< Texture dimension count */ diff --git a/src/Magnum/GL/Texture.cpp b/src/Magnum/GL/Texture.cpp index 3a1166bda..aa800716f 100644 --- a/src/Magnum/GL/Texture.cpp +++ b/src/Magnum/GL/Texture.cpp @@ -83,7 +83,53 @@ template Texture Texture::view(T return out; } -/* Other view() overloads at the end */ +/* On Windows (MSVC, clang-cl and MinGw) these need an explicit export + otherwise the symbol doesn't get exported. */ +#ifndef MAGNUM_TARGET_GLES +template<> template<> MAGNUM_GL_EXPORT Texture1D Texture1D::view(Texture1DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture1D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} +#endif + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(Texture2DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); + return out; +} #endif #ifndef MAGNUM_TARGET_GLES @@ -135,66 +181,29 @@ template Texture& Texture::setLa } #endif +#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_TARGET_GLES -template class MAGNUM_GL_EXPORT Texture<1>; +template class + /* GCC needs the export macro on the class definition (and here it warns + that the type is already defined so the export is ignored), while Clang + and MSVC need it here (and ignore it on the declaration) */ + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + Texture<1>; #endif #if !defined(MAGNUM_TARGET_GLES) || !defined(MAGNUM_TARGET_WEBGL) -template class MAGNUM_GL_EXPORT Texture<2>; -template class MAGNUM_GL_EXPORT Texture<3>; -#endif - -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -/* Because these refer to concrete types different than the class itself, they - have to be after the explicit type instantiations. Additionally, on Windows - (MSVC, clang-cl and MinGw) these need an explicit export otherwise the - symbol doesn't get exported. - - Other view() overloads at the top. */ -#ifndef MAGNUM_TARGET_GLES -template<> template<> MAGNUM_GL_EXPORT Texture1D Texture1D::view(Texture1DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture1D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); - return out; -} +template class + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + Texture<2>; +template class + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + Texture<3>; #endif - -template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(Texture2DArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); - return out; -} - -template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); - return out; -} - -template<> template<> MAGNUM_GL_EXPORT Texture2D Texture2D::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layer) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture2D out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layer, 1); - return out; -} #endif }} diff --git a/src/Magnum/GL/Texture.h b/src/Magnum/GL/Texture.h index 267e173ff..49daeb314 100644 --- a/src/Magnum/GL/Texture.h +++ b/src/Magnum/GL/Texture.h @@ -98,7 +98,14 @@ shaders. @requires_webgl20 3D textures are not available in WebGL 1.0. @requires_gl 1D textures are not available in OpenGL ES or WebGL. */ -template class Texture: public AbstractTexture { +template class +#ifndef CORRADE_TARGET_MSVC +/* If it's here, MSVC complains that out-of-class inline functions have a + definition while being dllimport'd. If I remove it, GCC then may complain + that the export in Texture.cpp is ignored as the type is already defined. */ +MAGNUM_GL_EXPORT +#endif +Texture: public AbstractTexture { public: enum: UnsignedInt { Dimensions = dimensions /**< Texture dimension count */ diff --git a/src/Magnum/GL/TextureArray.cpp b/src/Magnum/GL/TextureArray.cpp index 990a7d864..2896426ce 100644 --- a/src/Magnum/GL/TextureArray.cpp +++ b/src/Magnum/GL/TextureArray.cpp @@ -86,7 +86,29 @@ template TextureArray TextureArray template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} + +template<> template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { + /* glTextureView() doesn't work with glCreateTextures() as it needs an + object without a name bound, so have to construct manually. The object + is marked as Created as glTextureView() binds the name. */ + GLuint id; + glGenTextures(1, &id); + Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; + out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); + return out; +} #endif #ifndef MAGNUM_TARGET_GLES @@ -138,39 +160,22 @@ template TextureArray& TextureArray; +template class + /* GCC needs the export macro on the class definition (and here it warns + that the type is already defined so the export is ignored), while Clang + and MSVC need it here (and ignore it on the declaration) */ + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + TextureArray<1>; #endif -template class MAGNUM_GL_EXPORT TextureArray<2>; - -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -/* Because these refer to concrete types different than the class itself, they - have to be after the explicit type instantiations. Additionally, on Windows - (MSVC, clang-cl and MinGw) these need an explicit export otherwise the - symbol doesn't get exported. - - Other view() overloads at the top. */ -template<> template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTexture& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); - return out; -} - -template<> template<> MAGNUM_GL_EXPORT Texture2DArray Texture2DArray::view(CubeMapTextureArray& original, const TextureFormat internalFormat, const Int levelOffset, const Int levelCount, const Int layerOffset, const Int layerCount) { - /* glTextureView() doesn't work with glCreateTextures() as it needs an - object without a name bound, so have to construct manually. The object - is marked as Created as glTextureView() binds the name. */ - GLuint id; - glGenTextures(1, &id); - Texture2DArray out{id, ObjectFlag::Created|ObjectFlag::DeleteOnDestruction}; - out.viewInternal(original, internalFormat, levelOffset, levelCount, layerOffset, layerCount); - return out; -} +template class + #if defined(CORRADE_TARGET_CLANG) || defined(CORRADE_TARGET_MSVC) + MAGNUM_GL_EXPORT + #endif + TextureArray<2>; #endif }} diff --git a/src/Magnum/GL/TextureArray.h b/src/Magnum/GL/TextureArray.h index 4b633132f..334fd7d3c 100644 --- a/src/Magnum/GL/TextureArray.h +++ b/src/Magnum/GL/TextureArray.h @@ -91,7 +91,15 @@ in shaders. 2D ones. @todo Fix this when @gl_extension{NV,texture_array} is in ES2 extension headers */ -template class TextureArray: public AbstractTexture { +template class +#ifndef CORRADE_TARGET_MSVC +/* If it's here, MSVC complains that out-of-class inline functions have a + definition while being dllimport'd. If I remove it, GCC then may complain + that the export in TextureArray.cpp is ignored as the type is already + defined. */ +MAGNUM_GL_EXPORT +#endif +TextureArray: public AbstractTexture { public: enum: UnsignedInt { Dimensions = dimensions /**< Texture dimension count */