Browse Source

Shaders: avoid including GL/Shader.h in headers.

The class is rather heavy (strings, STL vector) and it'll stay heavier
than strictly needed even after the planned STL cleanup -- shader users
should not bear the overhead of Array, StringView etc. that it needs in
order to compile the shader sources.

I might eventually come to a different conclusion (maybe separating
GL::Shader population and usage like doing in Vulkan with CreateInfos),
but right now this commit has the best available solution -- converting
the instance to a lightweight class containing just ID and type, and
then converting that back to a GL::Shader upon checking compilation/link
status.

While at it, also removed the not-strictly-needed Optional usage from
the header. It wouldn't work with forward-declared GL::Shader anyway.
pull/589/head
Vladimír Vondruš 4 years ago
parent
commit
eede671755
  1. 5
      src/Magnum/Shaders/CMakeLists.txt
  2. 3
      src/Magnum/Shaders/DistanceFieldVectorGL.cpp
  3. 4
      src/Magnum/Shaders/DistanceFieldVectorGL.h
  4. 3
      src/Magnum/Shaders/FlatGL.cpp
  5. 4
      src/Magnum/Shaders/FlatGL.h
  6. 16
      src/Magnum/Shaders/MeshVisualizerGL.cpp
  7. 21
      src/Magnum/Shaders/MeshVisualizerGL.h
  8. 3
      src/Magnum/Shaders/PhongGL.cpp
  9. 4
      src/Magnum/Shaders/PhongGL.h
  10. 3
      src/Magnum/Shaders/Test/CMakeLists.txt
  11. 171
      src/Magnum/Shaders/Test/GLShaderWrapperGLTest.cpp
  12. 58
      src/Magnum/Shaders/Test/GLShaderWrapperTest.cpp
  13. 2
      src/Magnum/Shaders/VectorGL.cpp
  14. 4
      src/Magnum/Shaders/VectorGL.h
  15. 2
      src/Magnum/Shaders/VertexColorGL.cpp
  16. 4
      src/Magnum/Shaders/VertexColorGL.h
  17. 61
      src/Magnum/Shaders/glShaderWrapper.cpp
  18. 62
      src/Magnum/Shaders/glShaderWrapper.h

5
src/Magnum/Shaders/CMakeLists.txt

@ -42,7 +42,9 @@ set(MagnumShaders_GracefulAssert_SRCS
MeshVisualizerGL.cpp MeshVisualizerGL.cpp
PhongGL.cpp PhongGL.cpp
VectorGL.cpp VectorGL.cpp
VertexColorGL.cpp) VertexColorGL.cpp
glShaderWrapper.cpp)
set(MagnumShaders_HEADERS set(MagnumShaders_HEADERS
DistanceFieldVector.h DistanceFieldVector.h
@ -60,6 +62,7 @@ set(MagnumShaders_HEADERS
VectorGL.h VectorGL.h
VertexColorGL.h VertexColorGL.h
glShaderWrapper.h
visibility.h) visibility.h)
if(MAGNUM_BUILD_DEPRECATED) if(MAGNUM_BUILD_DEPRECATED)

3
src/Magnum/Shaders/DistanceFieldVectorGL.cpp

@ -33,6 +33,7 @@
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
@ -171,7 +172,7 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
if(!id()) return; if(!id()) return;
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

4
src/Magnum/Shaders/DistanceFieldVectorGL.h

@ -33,8 +33,8 @@
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -690,7 +690,7 @@ template<UnsignedInt dimensions> class DistanceFieldVectorGL<dimensions>::Compil
explicit CompileState(DistanceFieldVectorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): DistanceFieldVectorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} explicit CompileState(DistanceFieldVectorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): DistanceFieldVectorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag;
GL::Version _version; GL::Version _version;
}; };

3
src/Magnum/Shaders/FlatGL.cpp

@ -33,6 +33,7 @@
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
@ -246,7 +247,7 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(CompileState&& state
if(!id()) return; if(!id()) return;
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

4
src/Magnum/Shaders/FlatGL.h

@ -33,8 +33,8 @@
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -1101,7 +1101,7 @@ template<UnsignedInt dimensions> class FlatGL<dimensions>::CompileState: public
explicit CompileState(FlatGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): FlatGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} explicit CompileState(FlatGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): FlatGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag;
GL::Version _version; GL::Version _version;
}; };

16
src/Magnum/Shaders/MeshVisualizerGL.cpp

@ -517,7 +517,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
out.submitLink(); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; return CompileState{std::move(out), std::move(vert), std::move(frag), geom ? &*geom : nullptr, flags, version};
} }
MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{compile(flags)} {} MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{compile(flags)} {}
@ -537,10 +537,10 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D
if(!id()) return; if(!id()) return;
#endif #endif
if(state._geom) if(state._geom.id)
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag, *state._geom})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag), GL::Shader(state._geom)}));
else else
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;
@ -906,7 +906,7 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
out.submitLink(); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version}; return CompileState{std::move(out), std::move(vert), std::move(frag), geom ? &*geom : nullptr, flags, version};
} }
MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D{static_cast<MeshVisualizerGL3D&&>(std::move(state))} { MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D{static_cast<MeshVisualizerGL3D&&>(std::move(state))} {
@ -916,10 +916,10 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D
if(!id()) return; if(!id()) return;
#endif #endif
if(state._geom) if(state._geom.id)
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag, *state._geom})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag), GL::Shader(state._geom)}));
else else
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

21
src/Magnum/Shaders/MeshVisualizerGL.h

@ -33,11 +33,10 @@
#include <Corrade/Utility/Utility.h> #include <Corrade/Utility/Utility.h>
#include <Corrade/Containers/Optional.h>
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -928,12 +927,13 @@ class MeshVisualizerGL2D::CompileState: public MeshVisualizerGL2D {
/* Everything deliberately private except for the inheritance */ /* Everything deliberately private except for the inheritance */
friend class MeshVisualizerGL2D; friend class MeshVisualizerGL2D;
explicit CompileState(NoCreateT): MeshVisualizerGL2D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} explicit CompileState(NoCreateT): MeshVisualizerGL2D{NoCreate}, _vert{NoCreate}, _frag{NoCreate}, _geom{NoCreate} {}
explicit CompileState(MeshVisualizerGL2D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional<GL::Shader>&& geom, Flags flags, GL::Version version): MeshVisualizerGL2D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} explicit CompileState(MeshVisualizerGL2D&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Shader* geom, Flags flags, GL::Version version): MeshVisualizerGL2D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{NoCreate}, _flags{flags}, _version{version} {
if(geom) _geom = Implementation::GLShaderWrapper{std::move(*geom)};
}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag, _geom;
Containers::Optional<GL::Shader> _geom;
Flags _flags; Flags _flags;
GL::Version _version; GL::Version _version;
}; };
@ -2465,12 +2465,13 @@ class MeshVisualizerGL3D::CompileState: public MeshVisualizerGL3D {
/* Everything deliberately private except for the inheritance */ /* Everything deliberately private except for the inheritance */
friend class MeshVisualizerGL3D; friend class MeshVisualizerGL3D;
explicit CompileState(NoCreateT): MeshVisualizerGL3D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {} explicit CompileState(NoCreateT): MeshVisualizerGL3D{NoCreate}, _vert{NoCreate}, _frag{NoCreate}, _geom{NoCreate} {}
explicit CompileState(MeshVisualizerGL3D&& shader, GL::Shader&& vert, GL::Shader&& frag, Containers::Optional<GL::Shader>&& geom, Flags flags, GL::Version version): MeshVisualizerGL3D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{std::move(geom)}, _flags{flags}, _version{version} {} explicit CompileState(MeshVisualizerGL3D&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Shader* geom, Flags flags, GL::Version version): MeshVisualizerGL3D{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _geom{NoCreate}, _flags{flags}, _version{version} {
if(geom) _geom = Implementation::GLShaderWrapper{std::move(*geom)};
}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag, _geom;
Containers::Optional<GL::Shader> _geom;
Flags _flags; Flags _flags;
GL::Version _version; GL::Version _version;
}; };

3
src/Magnum/Shaders/PhongGL.cpp

@ -39,6 +39,7 @@
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
@ -356,7 +357,7 @@ PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast<PhongGL&&>(std::move
if(!id()) return; if(!id()) return;
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

4
src/Magnum/Shaders/PhongGL.h

@ -32,8 +32,8 @@
*/ */
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -1847,7 +1847,7 @@ class PhongGL::CompileState: public PhongGL {
explicit CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): PhongGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} explicit CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): PhongGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag;
GL::Version _version; GL::Version _version;
}; };

3
src/Magnum/Shaders/Test/CMakeLists.txt

@ -30,6 +30,7 @@ set(CMAKE_FOLDER "Magnum/Shaders/Test")
corrade_add_test(ShadersDistanceFieldVectorTest DistanceFieldVectorTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersDistanceFieldVectorTest DistanceFieldVectorTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersFlatTest FlatTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersFlatTest FlatTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersGenericTest GenericTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersGenericTest GenericTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersGLShaderWrapperTest GLShaderWrapperTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersMeshVisualizerTest MeshVisualizerTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersMeshVisualizerTest MeshVisualizerTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersPhongTest PhongTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersPhongTest PhongTest.cpp LIBRARIES MagnumShaders)
corrade_add_test(ShadersVectorTest VectorTest.cpp LIBRARIES MagnumShaders) corrade_add_test(ShadersVectorTest VectorTest.cpp LIBRARIES MagnumShaders)
@ -164,6 +165,8 @@ if(MAGNUM_BUILD_GL_TESTS)
endif() endif()
endif() endif()
corrade_add_test(ShadersGLShaderWrapperGLTest GLShaderWrapperGLTest.cpp LIBRARIES MagnumShaders MagnumOpenGLTester)
set(ShadersMeshVisualizerGLTest_SRCS MeshVisualizerGLTest.cpp) set(ShadersMeshVisualizerGLTest_SRCS MeshVisualizerGLTest.cpp)
if(CORRADE_TARGET_IOS) if(CORRADE_TARGET_IOS)
list(APPEND ShadersMeshVisualizerGLTest_SRCS FlatTestFiles MeshVisualizerTestFiles) list(APPEND ShadersMeshVisualizerGLTest_SRCS FlatTestFiles MeshVisualizerTestFiles)

171
src/Magnum/Shaders/Test/GLShaderWrapperGLTest.cpp

@ -0,0 +1,171 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/GL/OpenGLTester.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Version.h"
#include "Magnum/Shaders/glShaderWrapper.h"
namespace Magnum { namespace Shaders { namespace Test { namespace {
struct GLShaderWrapperGLTest: GL::OpenGLTester {
explicit GLShaderWrapperGLTest();
void construct();
void constructMove();
void convert();
void convertRvalue();
};
GLShaderWrapperGLTest::GLShaderWrapperGLTest() {
addTests({&GLShaderWrapperGLTest::construct,
&GLShaderWrapperGLTest::constructMove,
&GLShaderWrapperGLTest::convert,
&GLShaderWrapperGLTest::convertRvalue});
}
void GLShaderWrapperGLTest::construct() {
{
GL::Shader glShader{
#ifndef MAGNUM_TARGET_GLES
GL::Version::GL300,
#else
GL::Version::GLES300,
#endif
GL::Shader::Type::Fragment};
GLuint id = glShader.id();
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(id > 0);
Implementation::GLShaderWrapper shader{std::move(glShader)};
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(shader.id, id);
CORRADE_COMPARE(shader.type, GL_FRAGMENT_SHADER);
CORRADE_VERIFY(!glShader.id());
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
void GLShaderWrapperGLTest::constructMove() {
GL::Shader glShaderA{
#ifndef MAGNUM_TARGET_GLES
GL::Version::GL300,
#else
GL::Version::GLES300,
#endif
GL::Shader::Type::Fragment};
Implementation::GLShaderWrapper a{std::move(glShaderA)};
GLuint id = a.id;
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(id > 0);
Implementation::GLShaderWrapper b{std::move(a)};
CORRADE_VERIFY(!a.id);
CORRADE_COMPARE(b.id, id);
CORRADE_COMPARE(b.type, GL_FRAGMENT_SHADER);
GL::Shader glShaderB{
#ifndef MAGNUM_TARGET_GLES
GL::Version::GL210,
#else
GL::Version::GLES200,
#endif
GL::Shader::Type::Vertex};
Implementation::GLShaderWrapper c{std::move(glShaderB)};
GLuint cId = c.id;
c = std::move(b);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(cId > 0);
CORRADE_COMPARE(b.id, cId);
CORRADE_COMPARE(c.id, id);
CORRADE_COMPARE(c.type, GL_FRAGMENT_SHADER);
CORRADE_VERIFY(std::is_nothrow_move_constructible<Implementation::GLShaderWrapper>::value);
CORRADE_VERIFY(std::is_nothrow_move_assignable<Implementation::GLShaderWrapper>::value);
}
void GLShaderWrapperGLTest::convert() {
{
GL::Shader glShader{
#ifndef MAGNUM_TARGET_GLES
GL::Version::GL300,
#else
GL::Version::GLES300,
#endif
GL::Shader::Type::Fragment};
Implementation::GLShaderWrapper shader{std::move(glShader)};
GLuint id = shader.id;
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(id > 0);
GL::Shader glShader2 = shader;
MAGNUM_VERIFY_NO_GL_ERROR();
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(glShader2.id(), id);
CORRADE_COMPARE(glShader2.type(), GL::Shader::Type::Fragment);
CORRADE_VERIFY(shader.id);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
void GLShaderWrapperGLTest::convertRvalue() {
{
GL::Shader glShader{
#ifndef MAGNUM_TARGET_GLES
GL::Version::GL300,
#else
GL::Version::GLES300,
#endif
GL::Shader::Type::Fragment};
Implementation::GLShaderWrapper shader{std::move(glShader)};
GLuint id = shader.id;
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(id > 0);
GL::Shader glShader2 = std::move(shader);
MAGNUM_VERIFY_NO_GL_ERROR();
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(glShader2.id(), id);
CORRADE_COMPARE(glShader2.type(), GL::Shader::Type::Fragment);
CORRADE_VERIFY(!shader.id);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
}}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::GLShaderWrapperGLTest)

58
src/Magnum/Shaders/Test/GLShaderWrapperTest.cpp

@ -0,0 +1,58 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/Magnum.h"
#include "Magnum/Shaders/glShaderWrapper.h"
namespace Magnum { namespace Shaders { namespace Test { namespace {
struct GLShaderWrapperTest: TestSuite::Tester {
explicit GLShaderWrapperTest();
void constructNoCreate();
void constructCopy();
};
GLShaderWrapperTest::GLShaderWrapperTest() {
addTests({&GLShaderWrapperTest::constructNoCreate,
&GLShaderWrapperTest::constructCopy});
}
void GLShaderWrapperTest::constructNoCreate() {
Implementation::GLShaderWrapper shader{NoCreate};
CORRADE_COMPARE(shader.type, 0);
CORRADE_COMPARE(shader.id, 0);
}
void GLShaderWrapperTest::constructCopy() {
CORRADE_VERIFY(!std::is_copy_constructible<Implementation::GLShaderWrapper>{});
CORRADE_VERIFY(!std::is_copy_assignable<Implementation::GLShaderWrapper>{});
}
}}}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::GLShaderWrapperTest)

2
src/Magnum/Shaders/VectorGL.cpp

@ -173,7 +173,7 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(CompileState&& s
if(!id()) return; if(!id()) return;
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

4
src/Magnum/Shaders/VectorGL.h

@ -33,8 +33,8 @@
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -640,7 +640,7 @@ template<UnsignedInt dimensions> class VectorGL<dimensions>::CompileState: publi
explicit CompileState(VectorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VectorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} explicit CompileState(VectorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VectorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag;
GL::Version _version; GL::Version _version;
}; };

2
src/Magnum/Shaders/VertexColorGL.cpp

@ -151,7 +151,7 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(Compil
if(!id()) return; if(!id()) return;
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({state._vert, state._frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink({GL::Shader(state._vert), GL::Shader(state._frag)}));
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
const GL::Version version = state._version; const GL::Version version = state._version;

4
src/Magnum/Shaders/VertexColorGL.h

@ -33,8 +33,8 @@
#include "Magnum/DimensionTraits.h" #include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/glShaderWrapper.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
@ -489,7 +489,7 @@ template<UnsignedInt dimensions> class VertexColorGL<dimensions>::CompileState:
explicit CompileState(VertexColorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VertexColorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {} explicit CompileState(VertexColorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version): VertexColorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag; Implementation::GLShaderWrapper _vert, _frag;
GL::Version _version; GL::Version _version;
}; };

61
src/Magnum/Shaders/glShaderWrapper.cpp

@ -0,0 +1,61 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "glShaderWrapper.h"
#include "Magnum/GL/Shader.h"
namespace Magnum { namespace Shaders { namespace Implementation {
GLShaderWrapper::GLShaderWrapper(GL::Shader&& shader) noexcept: type{GLenum(shader.type())}, id{shader.release()} {}
GLShaderWrapper::GLShaderWrapper(GLShaderWrapper&& other) noexcept: type{other.type}, id{other.id} {
other.id = 0;
}
GLShaderWrapper& GLShaderWrapper::operator=(GLShaderWrapper&& other) noexcept {
using std::swap;
swap(other.type, type);
swap(other.id, id);
return *this;
}
GLShaderWrapper::~GLShaderWrapper() {
/* Convert itself to a temporary GL::Shader, triggering deletion in its
destructor */
if(id) GL::Shader{std::move(*this)};
}
GLShaderWrapper::operator GL::Shader() & noexcept {
return GL::Shader::wrap(GL::Shader::Type(type), id);
}
GLShaderWrapper::operator GL::Shader() && noexcept {
GL::Shader out = GL::Shader::wrap(GL::Shader::Type(type), id, GL::ObjectFlag::DeleteOnDestruction);
id = 0;
return out;
}
}}}

62
src/Magnum/Shaders/glShaderWrapper.h

@ -0,0 +1,62 @@
#ifndef Magnum_Shaders_glShaderWrapper_h
#define Magnum_Shaders_glShaderWrapper_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021, 2022 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "Magnum/Tags.h"
#include "Magnum/GL/GL.h"
#include "Magnum/Shaders/visibility.h"
namespace Magnum { namespace Shaders { namespace Implementation {
/* A lightweight alternative to GL::Shader that holds just the type and ID,
used by CompileState instances of all shaders. There it's used just to
retrieve error messages in case of a compilation failures, so it doesn't
make sense to pull in stuff needed to store shader sources such as strings
and vectors/arrays.
Might get revisited once GL::Shader gets the deSTLification treatment, but
even then this class seems significantly lighter weight. */
struct MAGNUM_SHADERS_EXPORT GLShaderWrapper {
/*implicit*/ GLShaderWrapper(NoCreateT) noexcept: type{}, id{} {}
/*implicit*/ GLShaderWrapper(GL::Shader&& shader) noexcept;
GLShaderWrapper(const GLShaderWrapper&) = delete;
GLShaderWrapper(GLShaderWrapper&& other) noexcept;
GLShaderWrapper& operator=(const GLShaderWrapper&) = delete;
GLShaderWrapper& operator=(GLShaderWrapper&& other) noexcept;
~GLShaderWrapper();
/*implicit*/ operator GL::Shader() & noexcept;
/*implicit*/ operator GL::Shader() && noexcept;
GLenum type;
GLuint id;
};
}}}
#endif
Loading…
Cancel
Save