Browse Source

Shaders: implement async shader compilation for all shaders.

pull/589/head
Vladislav Oleshko 4 years ago committed by Vladimír Vondruš
parent
commit
eb17d77562
  1. 69
      src/Magnum/Shaders/DistanceFieldVectorGL.cpp
  2. 31
      src/Magnum/Shaders/DistanceFieldVectorGL.h
  3. 105
      src/Magnum/Shaders/FlatGL.cpp
  4. 31
      src/Magnum/Shaders/FlatGL.h
  5. 308
      src/Magnum/Shaders/MeshVisualizerGL.cpp
  6. 79
      src/Magnum/Shaders/MeshVisualizerGL.h
  7. 166
      src/Magnum/Shaders/PhongGL.cpp
  8. 30
      src/Magnum/Shaders/PhongGL.h
  9. 67
      src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp
  10. 65
      src/Magnum/Shaders/Test/FlatGLTest.cpp
  11. 116
      src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp
  12. 63
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  13. 67
      src/Magnum/Shaders/Test/VectorGLTest.cpp
  14. 63
      src/Magnum/Shaders/Test/VertexColorGLTest.cpp
  15. 69
      src/Magnum/Shaders/VectorGL.cpp
  16. 31
      src/Magnum/Shaders/VectorGL.h
  17. 60
      src/Magnum/Shaders/VertexColorGL.cpp
  18. 30
      src/Magnum/Shaders/VertexColorGL.h

69
src/Magnum/Shaders/DistanceFieldVectorGL.cpp

@ -31,7 +31,6 @@
#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"
@ -63,22 +62,16 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount},
_drawCount{drawCount}
#endif
{
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::DistanceFieldVectorGL: material count can't be zero", ); "Shaders::DistanceFieldVectorGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::DistanceFieldVectorGL: draw count can't be zero", ); "Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -142,9 +135,17 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("DistanceFieldVector.frag")); .addSource(rs.getString("DistanceFieldVector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
DistanceFieldVectorGL<dimensions> out{NoInit};
out._flags = flags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
attachShaders({vert, frag}); out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly */ /* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
@ -152,25 +153,35 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(CompileState&& cs): DistanceFieldVectorGL{static_cast<DistanceFieldVectorGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
{ {
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix"); _textureMatrixUniform = uniformLocation("textureMatrix");
_colorUniform = uniformLocation("color"); _colorUniform = uniformLocation("color");
_outlineColorUniform = uniformLocation("outlineColor"); _outlineColorUniform = uniformLocation("outlineColor");
@ -185,11 +196,11 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
{ {
setUniform(uniformLocation("vectorTexture"), TextureUnit); setUniform(uniformLocation("vectorTexture"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
} }
#endif #endif
@ -198,13 +209,13 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
{ {
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit}); setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit}); setTextureMatrix(Matrix3{Math::IdentityInit});
setColor(Color4{1.0f}); setColor(Color4{1.0f});
/* Outline color is zero by default */ /* Outline color is zero by default */
@ -212,10 +223,22 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
setSmoothness(0.04f); setSmoothness(0.04f);
} }
#endif #endif
static_cast<void>(context);
static_cast<void>(version);
} }
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(NoInitT) {}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{flags, 1, 1} {} template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags) {
return compile(flags, 1, 1);
}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount):
DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {}
#endif #endif
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>& DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) { template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>& DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {

31
src/Magnum/Shaders/DistanceFieldVectorGL.h

@ -32,6 +32,7 @@
#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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -280,6 +281,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
*/ */
explicit DistanceFieldVectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} explicit DistanceFieldVectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit DistanceFieldVectorGL(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
DistanceFieldVectorGL(const DistanceFieldVectorGL<dimensions>&) = delete; DistanceFieldVectorGL(const DistanceFieldVectorGL<dimensions>&) = delete;
@ -602,6 +617,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif #endif
private: private:
explicit DistanceFieldVectorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -627,6 +644,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif #endif
}; };
template<UnsignedInt dimensions> class DistanceFieldVectorGL<dimensions>::CompileState: public DistanceFieldVectorGL<dimensions> {
private:
friend class DistanceFieldVectorGL;
explicit CompileState(NoCreateT): DistanceFieldVectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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;
GL::Version _version;
};
/** /**
@brief Two-dimensional distance field vector OpenGL shader @brief Two-dimensional distance field vector OpenGL shader
@m_since_latest @m_since_latest

105
src/Magnum/Shaders/FlatGL.cpp

@ -31,7 +31,6 @@
#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"
@ -68,16 +67,11 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , UnsignedInt materialCount, UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
{ {
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured
@ -86,22 +80,22 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#endif #endif
; ;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
"Shaders::FlatGL: texture transformation enabled but the shader is not textured", ); "Shaders::FlatGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate});
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::FlatGL: material count can't be zero", ); "Shaders::FlatGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::FlatGL: draw count can't be zero", ); "Shaders::FlatGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || flags & Flag::Textured || flags >= Flag::ObjectIdTexture, CORRADE_ASSERT(!(flags & Flag::TextureArrays) || flags & Flag::Textured || flags >= Flag::ObjectIdTexture,
"Shaders::FlatGL: texture arrays enabled but the shader is not textured", ); "Shaders::FlatGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation),
"Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", ); "Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -195,9 +189,17 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Flat.frag")); .addSource(rs.getString("Flat.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
attachShaders({vert, frag}); FlatGL<dimensions> out{NoInit};
out._flags = flags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly and doesn't even provide /* ES3 has this done in the shader directly and doesn't even provide
bindFragmentDataLocation() */ bindFragmentDataLocation() */
@ -206,53 +208,64 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
if(flags & Flag::Textured if(flags & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || flags >= Flag::ObjectIdTexture
#endif #endif
) )
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags & Flag::VertexColor) if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) { if(flags & Flag::ObjectId) {
bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ColorOutput, "color");
bindFragmentDataLocation(ObjectIdOutput, "objectId"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
} }
if(flags >= Flag::InstancedObjectId) if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(CompileState&& cs): FlatGL{static_cast<FlatGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
{ {
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix"); _textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays) if(_flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer"); _textureLayerUniform = uniformLocation("textureLayer");
#endif #endif
_colorUniform = uniformLocation("color"); _colorUniform = uniformLocation("color");
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif #endif
} }
} }
@ -261,13 +274,13 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
if(!context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version))
#endif #endif
{ {
if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit); if(_flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
} }
@ -277,26 +290,38 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
{ {
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit}); setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit}); setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */ /* Texture layer is zero by default */
setColor(Magnum::Color4{1.0f}); setColor(Magnum::Color4{1.0f});
if(flags & Flag::AlphaMask) setAlphaMask(0.5f); if(_flags & Flag::AlphaMask) setAlphaMask(0.5f);
/* Object ID is zero by default */ /* Object ID is zero by default */
} }
#endif #endif
static_cast<void>(version);
static_cast<void>(context);
} }
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(Flags flags): FlatGL{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags): FlatGL{flags, 1, 1} {} template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(Flags flags) {
return compile(flags, 1, 1);
}
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount):
FlatGL{compile(flags, materialCount, drawCount)} {}
#endif #endif
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(NoInitT) {}
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) { template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

31
src/Magnum/Shaders/FlatGL.h

@ -32,6 +32,7 @@
#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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -602,6 +603,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
*/ */
explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit FlatGL(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
FlatGL(const FlatGL<dimensions>&) = delete; FlatGL(const FlatGL<dimensions>&) = delete;
@ -1011,6 +1026,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#endif #endif
private: private:
/* Creates the GL shader program object but nothing else. Internal, used by compile(). */
explicit FlatGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -1038,6 +1056,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#endif #endif
}; };
template<UnsignedInt dimensions> class FlatGL<dimensions>::CompileState: public FlatGL<dimensions> {
private:
friend class FlatGL;
explicit CompileState(NoCreateT): FlatGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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;
GL::Version _version;
};
/** /**
@brief 2D flat OpenGL shader @brief 2D flat OpenGL shader
@m_since_latest @m_since_latest

308
src/Magnum/Shaders/MeshVisualizerGL.cpp

@ -26,7 +26,6 @@
#include "MeshVisualizerGL.h" #include "MeshVisualizerGL.h"
#include <Corrade/Containers/EnumSet.hpp> #include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Reference.h> #include <Corrade/Containers/Reference.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Resource.h> #include <Corrade/Utility/Resource.h>
@ -72,17 +71,7 @@ namespace {
namespace Implementation { namespace Implementation {
MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags void MeshVisualizerGLBase::assertExtensions(const FlagsBase flags) {
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount},
_drawCount{drawCount}
#endif
{
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef CORRADE_NO_ASSERT #ifndef CORRADE_NO_ASSERT
Int countMutuallyExclusive = 0; Int countMutuallyExclusive = 0;
@ -120,7 +109,7 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(_flags & FlagBase::Wireframe && !(_flags & FlagBase::NoGeometryShader)) { if(flags & FlagBase::Wireframe && !(flags & FlagBase::NoGeometryShader)) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320); MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320);
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::geometry_shader4); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::geometry_shader4);
@ -129,12 +118,12 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#endif #endif
} }
#else #else
if(_flags & FlagBase::Wireframe) if(flags & FlagBase::Wireframe)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::standard_derivatives); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::standard_derivatives);
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(_flags & FlagBase::PrimitiveId && !(_flags >= FlagBase::PrimitiveIdFromVertexId)) { if(flags & FlagBase::PrimitiveId && !(flags >= FlagBase::PrimitiveIdFromVertexId)) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320); MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320);
#else #else
@ -150,18 +139,23 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#endif #endif
} }
GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const { GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs,
const FlagsBase flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
) {
GL::Context& context = GL::Context::current(); GL::Context& context = GL::Context::current();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210});
/* Extended in MeshVisualizerGL3D for TBN visualization */ /* Extended in MeshVisualizerGL3D for TBN visualization */
CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GL320); CORRADE_INTERNAL_ASSERT(!(flags & FlagBase::Wireframe) || flags & FlagBase::NoGeometryShader || version >= GL::Version::GL320);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
/* ES 3.2 needed for gl_PrimitiveID */ /* ES 3.2 needed for gl_PrimitiveID */
const GL::Version version = context.supportedVersion({GL::Version::GLES320, GL::Version::GLES310, GL::Version::GLES300, GL::Version::GLES200}); const GL::Version version = context.supportedVersion({GL::Version::GLES320, GL::Version::GLES310, GL::Version::GLES300, GL::Version::GLES200});
/* Extended in MeshVisualizerGL3D for TBN visualization */ /* Extended in MeshVisualizerGL3D for TBN visualization */
CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GLES310); CORRADE_INTERNAL_ASSERT(!(flags & FlagBase::Wireframe) || flags & FlagBase::NoGeometryShader || version >= GL::Version::GLES310);
#else #else
const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200});
#endif #endif
@ -169,18 +163,18 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra
vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
vert.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") vert.addSource(flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") .addSource(flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif #endif
.addSource(_flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") .addSource(flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(_flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "") .addSource(flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "") .addSource(flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "")
#endif #endif
#ifdef MAGNUM_TARGET_WEBGL #ifdef MAGNUM_TARGET_WEBGL
.addSource("#define SUBSCRIPTING_WORKAROUND\n") .addSource("#define SUBSCRIPTING_WORKAROUND\n")
@ -190,38 +184,38 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra
#endif #endif
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(_flags >= FlagBase::UniformBuffers) { if(flags >= FlagBase::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
_drawCount, drawCount,
_materialCount)); materialCount));
vert.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
frag.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") frag.addSource(flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") .addSource(flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ? .addSource(flags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ? (flags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "") "#define PRIMITIVE_ID\n") : "")
#endif #endif
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(_flags >= FlagBase::UniformBuffers) { if(flags >= FlagBase::UniformBuffers) {
frag.addSource(Utility::formatString( frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
_drawCount, drawCount,
_materialCount)); materialCount));
frag.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : ""); frag.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
@ -382,21 +376,20 @@ MeshVisualizerGLBase& MeshVisualizerGLBase::bindObjectIdTexture(GL::Texture2DArr
} }
MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)) ) {
#ifndef MAGNUM_TARGET_GLES2 FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
, materialCount, drawCount assertExtensions(baseFlags);
#endif
} {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader),
"Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", ); "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", CompileState{NoCreate});
#else #else
CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader),
"Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", ); "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate});
#endif #endif
/* Has to be here and not in the base class in order to have it exit the /* Has to be here and not in the base class in order to have it exit the
@ -404,9 +397,9 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
otherwise */ otherwise */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::MeshVisualizerGL2D: material count can't be zero", ); "Shaders::MeshVisualizerGL2D: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::MeshVisualizerGL2D: draw count can't be zero", ); "Shaders::MeshVisualizerGL2D: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -416,7 +409,12 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
Utility::Resource rs{"MagnumShadersGL"}; Utility::Resource rs{"MagnumShadersGL"};
GL::Shader vert{NoCreate}; GL::Shader vert{NoCreate};
GL::Shader frag{NoCreate}; GL::Shader frag{NoCreate};
const GL::Version version = setupShaders(vert, frag, rs); const GL::Version version = setupShaders(vert, frag, rs, baseFlags
#ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount
#endif
);
Containers::Optional<GL::Shader> geom;
vert.addSource("#define TWO_DIMENSIONS\n") vert.addSource("#define TWO_DIMENSIONS\n")
/* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when
@ -439,19 +437,19 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("MeshVisualizer.frag")); .addSource(rs.getString("MeshVisualizer.frag"));
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::Optional<GL::Shader> geom;
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry); geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry);
(*geom) (*geom)
.addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n") .addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") .addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ? .addSource(baseFlags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ? (baseFlags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : ""); "#define PRIMITIVE_ID\n") : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -461,8 +459,8 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
_drawCount, drawCount,
_materialCount)); materialCount));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
@ -472,48 +470,75 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
static_cast<void>(version); static_cast<void>(version);
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) vert.submitCompile();
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag})); frag.submitCompile();
else if (geom) geom->submitCompile();
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
attachShaders({vert, frag}); MeshVisualizerGL2D out{NoInit};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) out._flags = baseFlags;
if(geom) attachShader(*geom); #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif #endif
out.attachShaders({vert, frag});
if (geom) out.attachShader(*geom);
/* ES3 has this done in the shader directly */ /* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) if(flags >= Flag::ObjectIdTexture)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId) if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif #endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isVersionSupported(GL::Version::GL310)) if(!context.isVersionSupported(GL::Version::GL310))
#endif #endif
{ {
bindAttributeLocation(VertexIndex::Location, "vertexIndex"); out.bindAttributeLocation(VertexIndex::Location, "vertexIndex");
} }
#endif #endif
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version};
}
MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags) : MeshVisualizerGL2D{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags) {
return compile(flags, 1, 1);
}
MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount)
: MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {}
#endif
MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& cs)
: MeshVisualizerGL2D{static_cast<MeshVisualizerGL2D&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
Flags flags = cs._flags;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
@ -608,11 +633,10 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
#endif #endif
} }
#endif #endif
}
#ifndef MAGNUM_TARGET_GLES2 static_cast<void>(context);
MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{flags, 1, 1} {} static_cast<void>(version);
#endif }
MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) { MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) {
/* Not asserting here, since the relation to wireframe is a bit vague. /* Not asserting here, since the relation to wireframe is a bit vague.
@ -674,33 +698,32 @@ MeshVisualizerGL2D& MeshVisualizerGL2D::bindDrawBuffer(GL::Buffer& buffer, const
} }
#endif #endif
MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)) ) {
#ifndef MAGNUM_TARGET_GLES2 FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
, materialCount, drawCount assertExtensions(baseFlags);
#endif
} {
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader),
"Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)),
"Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", ); "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::BitangentDirection && flags & Flag::BitangentFromTangentDirection), CORRADE_ASSERT(!(flags & Flag::BitangentDirection && flags & Flag::BitangentFromTangentDirection),
"Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", ); "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", CompileState{NoCreate});
#elif !defined(MAGNUM_TARGET_GLES2) #elif !defined(MAGNUM_TARGET_GLES2)
CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader),
"Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate});
#else #else
CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader),
"Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", ); "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate});
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::BitangentDirection), CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::BitangentDirection),
"Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", ); "Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate});
#endif #endif
/* Has to be here and not in the base class in order to have it exit the /* Has to be here and not in the base class in order to have it exit the
@ -708,9 +731,9 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
otherwise */ otherwise */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::MeshVisualizerGL3D: material count can't be zero", ); "Shaders::MeshVisualizerGL3D: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::MeshVisualizerGL3D: draw count can't be zero", ); "Shaders::MeshVisualizerGL3D: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -720,7 +743,12 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
Utility::Resource rs{"MagnumShadersGL"}; Utility::Resource rs{"MagnumShadersGL"};
GL::Shader vert{NoCreate}; GL::Shader vert{NoCreate};
GL::Shader frag{NoCreate}; GL::Shader frag{NoCreate};
const GL::Version version = setupShaders(vert, frag, rs); const GL::Version version = setupShaders(vert, frag, rs, baseFlags
#ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount
#endif
);
Containers::Optional<GL::Shader> geom;
/* Expands the check done for wireframe in MeshVisualizerBase with TBN */ /* Expands the check done for wireframe in MeshVisualizerBase with TBN */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -768,7 +796,6 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
.addSource(rs.getString("MeshVisualizer.frag")); .addSource(rs.getString("MeshVisualizer.frag"));
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::Optional<GL::Shader> geom;
if(flags & (Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) && !(flags & Flag::NoGeometryShader)) { if(flags & (Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) && !(flags & Flag::NoGeometryShader)) {
Int maxVertices = 0; Int maxVertices = 0;
if(flags & Flag::Wireframe) maxVertices += 3; if(flags & Flag::Wireframe) maxVertices += 3;
@ -781,13 +808,13 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
(*geom) (*geom)
.addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices)) .addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices))
.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") .addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "") .addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ? .addSource(baseFlags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ? (baseFlags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "") "#define PRIMITIVE_ID\n") : "")
.addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") .addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "")
@ -800,8 +827,8 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
_drawCount, drawCount,
_materialCount)); materialCount));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
@ -811,50 +838,53 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
static_cast<void>(version); static_cast<void>(version);
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) vert.submitCompile();
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag})); frag.submitCompile();
else if (geom) geom->submitCompile();
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
attachShaders({vert, frag}); MeshVisualizerGL3D out{NoInit};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) out._flags = baseFlags;
if(geom) attachShader(*geom); #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif #endif
out.attachShaders({vert, frag});
if (geom) out.attachShader(*geom);
/* ES3 has this done in the shader directly */ /* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) if(flags >= Flag::ObjectIdTexture)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId) if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) { if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)) if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection))
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & Flag::TangentDirection || if(flags & Flag::TangentDirection ||
flags & Flag::BitangentFromTangentDirection) flags & Flag::BitangentFromTangentDirection)
bindAttributeLocation(Tangent4::Location, "tangent"); out.bindAttributeLocation(Tangent4::Location, "tangent");
if(flags & Flag::BitangentDirection) if(flags & Flag::BitangentDirection)
bindAttributeLocation(Bitangent::Location, "bitangent"); out.bindAttributeLocation(Bitangent::Location, "bitangent");
if(flags & Flag::NormalDirection || if(flags & Flag::NormalDirection ||
flags & Flag::BitangentFromTangentDirection) flags & Flag::BitangentFromTangentDirection)
bindAttributeLocation(Normal::Location, "normal"); out.bindAttributeLocation(Normal::Location, "normal");
#endif #endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
@ -862,13 +892,25 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
if(!context.isVersionSupported(GL::Version::GL310)) if(!context.isVersionSupported(GL::Version::GL310))
#endif #endif
{ {
bindAttributeLocation(VertexIndex::Location, "vertexIndex"); out.bindAttributeLocation(VertexIndex::Location, "vertexIndex");
} }
#endif #endif
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), std::move(geom), flags, version};
}
MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& cs): MeshVisualizerGL3D{static_cast<MeshVisualizerGL3D&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
Flags flags = cs._flags;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
@ -996,10 +1038,20 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
#endif #endif
} }
#endif #endif
static_cast<void>(context);
static_cast<void>(version);
} }
MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{flags, 1, 1} {} MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags) {
return compile(flags, 1, 1);
}
MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount):
MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {}
#endif #endif
MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) {

79
src/Magnum/Shaders/MeshVisualizerGL.h

@ -32,8 +32,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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -69,14 +71,17 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgr
CORRADE_ENUMSET_FRIEND_OPERATORS(FlagsBase) CORRADE_ENUMSET_FRIEND_OPERATORS(FlagsBase)
explicit MeshVisualizerGLBase(FlagsBase flags explicit MeshVisualizerGLBase(NoInitT) {}
explicit MeshVisualizerGLBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
static MAGNUM_SHADERS_LOCAL void assertExtensions(const FlagsBase flags);
static MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs,
const FlagsBase flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount , UnsignedInt materialCount, UnsignedInt drawCount
#endif #endif
); );
explicit MeshVisualizerGLBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGLBase& setTextureMatrix(const Matrix3& matrix); MeshVisualizerGLBase& setTextureMatrix(const Matrix3& matrix);
@ -505,6 +510,20 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
*/ */
explicit MeshVisualizerGL2D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} explicit MeshVisualizerGL2D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {}
class CompileState;
explicit MeshVisualizerGL2D(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
MeshVisualizerGL2D(const MeshVisualizerGL2D&) = delete; MeshVisualizerGL2D(const MeshVisualizerGL2D&) = delete;
@ -862,9 +881,26 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
#endif #endif
private: private:
explicit MeshVisualizerGL2D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {}
Int _transformationProjectionMatrixUniform{9}; Int _transformationProjectionMatrixUniform{9};
}; };
class MeshVisualizerGL2D::CompileState: public MeshVisualizerGL2D {
private:
friend class MeshVisualizerGL2D;
explicit CompileState(NoCreateT): MeshVisualizerGL2D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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} {}
GL::Shader _vert, _frag;
Containers::Optional<GL::Shader> _geom;
Flags _flags;
GL::Version _version;
};
/** /**
@brief 3D mesh visualization OpenGL shader @brief 3D mesh visualization OpenGL shader
@m_since_latest @m_since_latest
@ -1639,7 +1675,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
* @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags) * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags)
* instead. * instead.
*/ */
explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{{}} {} explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{Flags{}} {}
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -1698,6 +1734,21 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
*/ */
explicit MeshVisualizerGL3D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} explicit MeshVisualizerGL3D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {}
class CompileState;
explicit MeshVisualizerGL3D(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete;
@ -2326,6 +2377,8 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
#endif #endif
private: private:
explicit MeshVisualizerGL3D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {}
Int _transformationMatrixUniform{9}, Int _transformationMatrixUniform{9},
_projectionMatrixUniform{10}; _projectionMatrixUniform{10};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
@ -2335,6 +2388,22 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
#endif #endif
}; };
class MeshVisualizerGL3D::CompileState : public MeshVisualizerGL3D {
private:
friend class MeshVisualizerGL3D;
explicit CompileState(NoCreateT) : MeshVisualizerGL3D{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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} {}
GL::Shader _vert, _frag;
Containers::Optional<GL::Shader> _geom;
Flags _flags;
GL::Version _version;
};
/** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flag} */ /** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flag} */
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flag value); MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flag value);

166
src/Magnum/Shaders/PhongGL.cpp

@ -37,7 +37,6 @@
#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"
@ -74,21 +73,12 @@ namespace {
#endif #endif
} }
PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags}, #ifndef CORRADE_NO_ASSERT
_lightCount{lightCount},
#ifndef MAGNUM_TARGET_GLES2
_materialCount{materialCount},
_drawCount{drawCount},
#endif
_lightColorsUniform{_lightPositionsUniform + Int(lightCount)},
_lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)},
_lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)}
{
{ {
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture))
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -96,32 +86,33 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#endif #endif
; ;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
"Shaders::PhongGL: texture transformation enabled but the shader is not textured", ); "Shaders::PhongGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate});
} }
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent), CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent),
"Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", ); "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::PhongGL: material count can't be zero", ); "Shaders::PhongGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::PhongGL: draw count can't be zero", ); "Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture, CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture,
"Shaders::PhongGL: texture arrays enabled but the shader is not textured", ); "Shaders::PhongGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation),
"Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", ); "Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers), CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers),
"Shaders::PhongGL: light culling requires uniform buffers to be enabled", ); "Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate});
#endif #endif
CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)), CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)),
"Shaders::PhongGL: specular texture requires the shader to not have specular disabled", ); "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", CompileState{NoCreate});
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(flags >= Flag::UniformBuffers)
@ -154,7 +145,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(), CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(),
"Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), ); "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -163,6 +154,17 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200});
#endif #endif
PhongGL out{NoInit};
out._flags = flags;
out._lightCount = lightCount;
out._lightColorsUniform = out._lightPositionsUniform + Int(lightCount);
out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(lightCount);
out._lightRangesUniform = out._lightPositionsUniform + 3*Int(lightCount);
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
@ -283,9 +285,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
"#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n"
"#define LIGHT_RANGES_LOCATION {}\n", "#define LIGHT_RANGES_LOCATION {}\n",
lightCount, lightCount,
_lightPositionsUniform + lightCount, out._lightPositionsUniform + lightCount,
_lightPositionsUniform + 2*lightCount, out._lightPositionsUniform + 2*lightCount,
_lightPositionsUniform + 3*lightCount)); out._lightPositionsUniform + 3*lightCount));
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!(flags >= Flag::UniformBuffers) && lightCount) if(!(flags >= Flag::UniformBuffers) && lightCount)
@ -294,9 +296,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Phong.frag")); .addSource(rs.getString("Phong.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
attachShaders({vert, frag}); out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly and doesn't even provide /* ES3 has this done in the shader directly and doesn't even provide
bindFragmentDataLocation() */ bindFragmentDataLocation() */
@ -305,103 +308,114 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
if(lightCount) if(lightCount)
bindAttributeLocation(Normal::Location, "normal"); out.bindAttributeLocation(Normal::Location, "normal");
if((flags & Flag::NormalTexture) && lightCount) { if((flags & Flag::NormalTexture) && lightCount) {
bindAttributeLocation(Tangent::Location, "tangent"); out.bindAttributeLocation(Tangent::Location, "tangent");
if(flags & Flag::Bitangent) if(flags & Flag::Bitangent)
bindAttributeLocation(Bitangent::Location, "bitangent"); out.bindAttributeLocation(Bitangent::Location, "bitangent");
} }
if(flags & Flag::VertexColor) if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture) if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || flags >= Flag::ObjectIdTexture
#endif #endif
) )
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) { if(flags & Flag::ObjectId) {
bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ColorOutput, "color");
bindFragmentDataLocation(ObjectIdOutput, "objectId"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
} }
if(flags >= Flag::InstancedObjectId) if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) { if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(lightCount) if(lightCount)
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
} }
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
PhongGL::PhongGL(CompileState&& cs): PhongGL{static_cast<PhongGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
{ {
_transformationMatrixUniform = uniformLocation("transformationMatrix"); _transformationMatrixUniform = uniformLocation("transformationMatrix");
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix"); _textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays) if(_flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer"); _textureLayerUniform = uniformLocation("textureLayer");
#endif #endif
_projectionMatrixUniform = uniformLocation("projectionMatrix"); _projectionMatrixUniform = uniformLocation("projectionMatrix");
_ambientColorUniform = uniformLocation("ambientColor"); _ambientColorUniform = uniformLocation("ambientColor");
if(lightCount) { if(_lightCount) {
_normalMatrixUniform = uniformLocation("normalMatrix"); _normalMatrixUniform = uniformLocation("normalMatrix");
_diffuseColorUniform = uniformLocation("diffuseColor"); _diffuseColorUniform = uniformLocation("diffuseColor");
if(!(flags & Flag::NoSpecular)) { if(!(_flags & Flag::NoSpecular)) {
_specularColorUniform = uniformLocation("specularColor"); _specularColorUniform = uniformLocation("specularColor");
_shininessUniform = uniformLocation("shininess"); _shininessUniform = uniformLocation("shininess");
} }
if(flags & Flag::NormalTexture) if(_flags & Flag::NormalTexture)
_normalTextureScaleUniform = uniformLocation("normalTextureScale"); _normalTextureScaleUniform = uniformLocation("normalTextureScale");
_lightPositionsUniform = uniformLocation("lightPositions"); _lightPositionsUniform = uniformLocation("lightPositions");
_lightColorsUniform = uniformLocation("lightColors"); _lightColorsUniform = uniformLocation("lightColors");
if(!(flags & Flag::NoSpecular)) if(!(_flags & Flag::NoSpecular))
_lightSpecularColorsUniform = uniformLocation("lightSpecularColors"); _lightSpecularColorsUniform = uniformLocation("lightSpecularColors");
_lightRangesUniform = uniformLocation("lightRanges"); _lightRangesUniform = uniformLocation("lightRanges");
} }
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif #endif
} }
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags && !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version)) if(_flags && !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version))
#endif #endif
{ {
if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit); if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit);
if(lightCount) { if(_lightCount) {
if(flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit); if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit);
if(flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit); if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit);
if(flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit); if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit);
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
if(lightCount) if(_lightCount)
setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding); setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding);
} }
#endif #endif
@ -410,44 +424,54 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
{ {
/* Default to fully opaque white so we can see the textures */ /* Default to fully opaque white so we can see the textures */
if(flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f}); if(_flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f});
else setAmbientColor(Magnum::Color4{0.0f}); else setAmbientColor(Magnum::Color4{0.0f});
setTransformationMatrix(Matrix4{Math::IdentityInit}); setTransformationMatrix(Matrix4{Math::IdentityInit});
setProjectionMatrix(Matrix4{Math::IdentityInit}); setProjectionMatrix(Matrix4{Math::IdentityInit});
if(lightCount) { if(_lightCount) {
setDiffuseColor(Magnum::Color4{1.0f}); setDiffuseColor(Magnum::Color4{1.0f});
if(!(flags & Flag::NoSpecular)) { if(!(_flags & Flag::NoSpecular)) {
setSpecularColor(Magnum::Color4{1.0f, 0.0f}); setSpecularColor(Magnum::Color4{1.0f, 0.0f});
setShininess(80.0f); setShininess(80.0f);
} }
if(flags & Flag::NormalTexture) if(_flags & Flag::NormalTexture)
setNormalTextureScale(1.0f); setNormalTextureScale(1.0f);
setLightPositions(Containers::Array<Vector4>{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); setLightPositions(Containers::Array<Vector4>{DirectInit, _lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}});
Containers::Array<Magnum::Color3> colors{DirectInit, lightCount, Magnum::Color3{1.0f}}; Containers::Array<Magnum::Color3> colors{DirectInit, _lightCount, Magnum::Color3{1.0f}};
setLightColors(colors); setLightColors(colors);
if(!(flags & Flag::NoSpecular)) if(!(_flags & Flag::NoSpecular))
setLightSpecularColors(colors); setLightSpecularColors(colors);
setLightRanges(Containers::Array<Float>{DirectInit, lightCount, Constants::inf()}); setLightRanges(Containers::Array<Float>{DirectInit, _lightCount, Constants::inf()});
/* Light position is zero by default */ /* Light position is zero by default */
setNormalMatrix(Matrix3x3{Math::IdentityInit}); setNormalMatrix(Matrix3x3{Math::IdentityInit});
} }
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit}); setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */ /* Texture layer is zero by default */
if(flags & Flag::AlphaMask) setAlphaMask(0.5f); if(_flags & Flag::AlphaMask) setAlphaMask(0.5f);
/* Object ID is zero by default */ /* Object ID is zero by default */
} }
#endif #endif
static_cast<void>(context);
static_cast<void>(version);
} }
PhongGL::PhongGL(Flags flags, UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{flags, lightCount, 1, 1} {} PhongGL::CompileState PhongGL::compile(Flags flags, UnsignedInt lightCount) {
return compile(flags, lightCount, 1, 1);
}
PhongGL::PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount):
PhongGL{compile(flags, lightCount, materialCount, drawCount)} {}
#endif #endif
PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) {

30
src/Magnum/Shaders/PhongGL.h

@ -31,6 +31,7 @@
*/ */
#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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -821,6 +822,20 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*/ */
explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit PhongGL(CompileState&& cs);
static CompileState compile(Flags flags, UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags, UnsignedInt lightCount);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
PhongGL(const PhongGL&) = delete; PhongGL(const PhongGL&) = delete;
@ -1744,6 +1759,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif #endif
private: private:
explicit PhongGL(NoInitT) {}
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -1784,6 +1801,19 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif #endif
}; };
class PhongGL::CompileState: public PhongGL {
private:
friend class PhongGL;
explicit CompileState(NoCreateT): PhongGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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;
GL::Version _version;
};
/** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */ /** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value); MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value);

67
src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Format.h> #include <Corrade/Utility/Format.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -84,8 +85,10 @@ struct DistanceFieldVectorGLTest: GL::OpenGLTester {
explicit DistanceFieldVectorGLTest(); explicit DistanceFieldVectorGLTest();
template<UnsignedInt dimensions> void construct(); template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers(); template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif #endif
template<UnsignedInt dimensions> void constructMove(); template<UnsignedInt dimensions> void constructMove();
@ -251,11 +254,19 @@ DistanceFieldVectorGLTest::DistanceFieldVectorGLTest() {
&DistanceFieldVectorGLTest::construct<3>}, &DistanceFieldVectorGLTest::construct<3>},
Containers::arraySize(ConstructData)); Containers::arraySize(ConstructData));
addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructAsync<2>,
&DistanceFieldVectorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests<DistanceFieldVectorGLTest>({ addInstancedTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffers<2>, &DistanceFieldVectorGLTest::constructUniformBuffers<2>,
&DistanceFieldVectorGLTest::constructUniformBuffers<3>}, &DistanceFieldVectorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<2>,
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<3>});
#endif #endif
addTests<DistanceFieldVectorGLTest>({ addTests<DistanceFieldVectorGLTest>({
@ -374,6 +385,29 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
auto compileState = DistanceFieldVectorGL<dimensions>::compile(DistanceFieldVectorGL2D::Flag::TextureTransformation);
CORRADE_COMPARE(compileState.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
DistanceFieldVectorGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::TextureTransformation);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffers() { template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions)); setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -413,6 +447,39 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUnifor
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffersAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = DistanceFieldVectorGL<dimensions>::compile(DistanceFieldVectorGL2D::Flag::UniformBuffers, 16, 4);
CORRADE_COMPARE(compileState.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers);
CORRADE_COMPARE(compileState.materialCount(), 16);
CORRADE_COMPARE(compileState.drawCount(), 4);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
DistanceFieldVectorGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), DistanceFieldVectorGL2D::Flag::UniformBuffers);
CORRADE_COMPARE(shader.materialCount(), 16);
CORRADE_COMPARE(shader.drawCount(), 4);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructMove() { template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructMove() {

65
src/Magnum/Shaders/Test/FlatGLTest.cpp

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -83,8 +84,10 @@ struct FlatGLTest: GL::OpenGLTester {
explicit FlatGLTest(); explicit FlatGLTest();
template<UnsignedInt dimensions> void construct(); template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers(); template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif #endif
template<UnsignedInt dimensions> void constructMove(); template<UnsignedInt dimensions> void constructMove();
@ -600,11 +603,19 @@ FlatGLTest::FlatGLTest() {
&FlatGLTest::construct<3>}, &FlatGLTest::construct<3>},
Containers::arraySize(ConstructData)); Containers::arraySize(ConstructData));
addTests<FlatGLTest>({
&FlatGLTest::constructAsync<2>,
&FlatGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests<FlatGLTest>({ addInstancedTests<FlatGLTest>({
&FlatGLTest::constructUniformBuffers<2>, &FlatGLTest::constructUniformBuffers<2>,
&FlatGLTest::constructUniformBuffers<3>}, &FlatGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests<FlatGLTest>({
&FlatGLTest::constructUniformBuffersAsync<2>,
&FlatGLTest::constructUniformBuffersAsync<3>});
#endif #endif
addTests<FlatGLTest>({ addTests<FlatGLTest>({
@ -853,6 +864,28 @@ template<UnsignedInt dimensions> void FlatGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void FlatGLTest::constructAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
auto compileState = FlatGL<dimensions>::compile(FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation);
CORRADE_COMPARE(compileState.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
FlatGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation);
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffers() { template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions)); setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -896,6 +929,38 @@ template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffers() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffersAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = FlatGL<dimensions>::compile(FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, 1, 1);
CORRADE_COMPARE(compileState.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask);
CORRADE_COMPARE(compileState.materialCount(), 1);
CORRADE_COMPARE(compileState.drawCount(), 1);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
FlatGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask);
CORRADE_COMPARE(shader.materialCount(), 1);
CORRADE_COMPARE(shader.drawCount(), 1);
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
template<UnsignedInt dimensions> void FlatGLTest::constructMove() { template<UnsignedInt dimensions> void FlatGLTest::constructMove() {

116
src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -88,12 +89,16 @@ struct MeshVisualizerGLTest: GL::OpenGLTester {
explicit MeshVisualizerGLTest(); explicit MeshVisualizerGLTest();
void construct2D(); void construct2D();
void construct2DAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers2D(); void constructUniformBuffers2D();
void constructUniformBuffers2DAsync();
#endif #endif
void construct3D(); void construct3D();
void construct3DAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers3D(); void constructUniformBuffers3D();
void constructUniformBuffers3DAsync();
#endif #endif
void construct2DInvalid(); void construct2DInvalid();
@ -1055,17 +1060,23 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() {
addInstancedTests({&MeshVisualizerGLTest::construct2D}, addInstancedTests({&MeshVisualizerGLTest::construct2D},
Containers::arraySize(ConstructData2D)); Containers::arraySize(ConstructData2D));
addTests({&MeshVisualizerGLTest::construct2DAsync});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers2D}, addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers2D},
Containers::arraySize(ConstructUniformBuffersData2D)); Containers::arraySize(ConstructUniformBuffersData2D));
addTests({&MeshVisualizerGLTest::constructUniformBuffers2DAsync});
#endif #endif
addInstancedTests({&MeshVisualizerGLTest::construct3D}, addInstancedTests({&MeshVisualizerGLTest::construct3D},
Containers::arraySize(ConstructData3D)); Containers::arraySize(ConstructData3D));
addTests({&MeshVisualizerGLTest::construct3DAsync});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers3D}, addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers3D},
Containers::arraySize(ConstructUniformBuffersData3D)); Containers::arraySize(ConstructUniformBuffersData3D));
addTests({&MeshVisualizerGLTest::constructUniformBuffers3DAsync});
#endif #endif
addInstancedTests({&MeshVisualizerGLTest::construct2DInvalid}, addInstancedTests({&MeshVisualizerGLTest::construct2DInvalid},
@ -1403,6 +1414,28 @@ void MeshVisualizerGLTest::construct2D() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void MeshVisualizerGLTest::construct2DAsync() {
auto compileState = MeshVisualizerGL2D::compile(MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader);
CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
MeshVisualizerGL2D shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MeshVisualizerGLTest::constructUniformBuffers2D() { void MeshVisualizerGLTest::constructUniformBuffers2D() {
auto&& data = ConstructUniformBuffersData2D[testCaseInstanceId()]; auto&& data = ConstructUniformBuffersData2D[testCaseInstanceId()];
@ -1480,8 +1513,40 @@ void MeshVisualizerGLTest::constructUniformBuffers2D() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void MeshVisualizerGLTest::constructUniformBuffers2DAsync() {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = MeshVisualizerGL2D::compile( MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader, 8, 55);
CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader);
CORRADE_COMPARE(compileState.materialCount(), 8);
CORRADE_COMPARE(compileState.drawCount(), 55);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
MeshVisualizerGL2D shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::UniformBuffers|MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader);
CORRADE_COMPARE(shader.materialCount(), 8);
CORRADE_COMPARE(shader.drawCount(), 55);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
void MeshVisualizerGLTest::construct3D() { void MeshVisualizerGLTest::construct3D() {
auto&& data = ConstructData3D[testCaseInstanceId()]; auto&& data = ConstructData3D[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -1541,6 +1606,27 @@ void MeshVisualizerGLTest::construct3D() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void MeshVisualizerGLTest::construct3DAsync() {
auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader);
CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
MeshVisualizerGL3D shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MeshVisualizerGLTest::constructUniformBuffers3D() { void MeshVisualizerGLTest::constructUniformBuffers3D() {
auto&& data = ConstructUniformBuffersData3D[testCaseInstanceId()]; auto&& data = ConstructUniformBuffersData3D[testCaseInstanceId()];
@ -1618,6 +1704,36 @@ void MeshVisualizerGLTest::constructUniformBuffers3D() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void MeshVisualizerGLTest::constructUniformBuffers3DAsync() {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = MeshVisualizerGL3D::compile(MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader, 6, 28);
CORRADE_COMPARE(compileState.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader);
CORRADE_COMPARE(compileState.materialCount(), 6);
CORRADE_COMPARE(compileState.drawCount(), 28);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
MeshVisualizerGL3D shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flag::UniformBuffers|MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader);
CORRADE_COMPARE(compileState.materialCount(), 6);
CORRADE_COMPARE(compileState.drawCount(), 28);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
void MeshVisualizerGLTest::construct2DInvalid() { void MeshVisualizerGLTest::construct2DInvalid() {

63
src/Magnum/Shaders/Test/PhongGLTest.cpp

@ -31,12 +31,12 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
#include <Corrade/Containers/Pair.h> #include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/System.h> /* isSandboxed() */
#endif #endif
#include "Magnum/Image.h" #include "Magnum/Image.h"
@ -83,8 +83,10 @@ struct PhongGLTest: GL::OpenGLTester {
explicit PhongGLTest(); explicit PhongGLTest();
void construct(); void construct();
void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers(); void constructUniformBuffers();
void constructUniformBuffersAsync();
#endif #endif
void constructMove(); void constructMove();
@ -927,9 +929,13 @@ PhongGLTest::PhongGLTest() {
addInstancedTests({&PhongGLTest::construct}, addInstancedTests({&PhongGLTest::construct},
Containers::arraySize(ConstructData)); Containers::arraySize(ConstructData));
addTests({&PhongGLTest::constructAsync});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&PhongGLTest::constructUniformBuffers}, addInstancedTests({&PhongGLTest::constructUniformBuffers},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests({&PhongGLTest::constructUniformBuffersAsync});
#endif #endif
addTests({ addTests({
@ -1192,6 +1198,29 @@ void PhongGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void PhongGLTest::constructAsync() {
auto compileState = PhongGL::compile(PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3);
CORRADE_COMPARE(compileState.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset);
CORRADE_COMPARE(compileState.lightCount(), 3);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
PhongGL shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset);
CORRADE_COMPARE(shader.lightCount(), 3);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void PhongGLTest::constructUniformBuffers() { void PhongGLTest::constructUniformBuffers() {
auto&& data = ConstructUniformBuffersData[testCaseInstanceId()]; auto&& data = ConstructUniformBuffersData[testCaseInstanceId()];
@ -1234,6 +1263,38 @@ void PhongGLTest::constructUniformBuffers() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void PhongGLTest::constructUniformBuffersAsync() {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = PhongGL::compile(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24);
CORRADE_COMPARE(compileState.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling);
CORRADE_COMPARE(compileState.lightCount(), 8);
CORRADE_COMPARE(compileState.materialCount(), 8);
CORRADE_COMPARE(compileState.drawCount(), 24);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
PhongGL shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling);
CORRADE_COMPARE(shader.lightCount(), 8);
CORRADE_COMPARE(shader.materialCount(), 8);
CORRADE_COMPARE(shader.drawCount(), 24);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
void PhongGLTest::constructMove() { void PhongGLTest::constructMove() {

67
src/Magnum/Shaders/Test/VectorGLTest.cpp

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -83,8 +84,10 @@ struct VectorGLTest: GL::OpenGLTester {
explicit VectorGLTest(); explicit VectorGLTest();
template<UnsignedInt dimensions> void construct(); template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers(); template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif #endif
template<UnsignedInt dimensions> void constructMove(); template<UnsignedInt dimensions> void constructMove();
@ -247,11 +250,19 @@ VectorGLTest::VectorGLTest() {
&VectorGLTest::construct<3>}, &VectorGLTest::construct<3>},
Containers::arraySize(ConstructData)); Containers::arraySize(ConstructData));
addTests<VectorGLTest>({
&VectorGLTest::constructAsync<2>,
&VectorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests<VectorGLTest>({ addInstancedTests<VectorGLTest>({
&VectorGLTest::constructUniformBuffers<2>, &VectorGLTest::constructUniformBuffers<2>,
&VectorGLTest::constructUniformBuffers<3>}, &VectorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests<VectorGLTest>({
&VectorGLTest::constructUniformBuffersAsync<2>,
&VectorGLTest::constructUniformBuffersAsync<3>});
#endif #endif
addTests<VectorGLTest>({ addTests<VectorGLTest>({
@ -370,6 +381,30 @@ template<UnsignedInt dimensions> void VectorGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void VectorGLTest::constructAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
auto compileState = VectorGL<dimensions>::compile(VectorGL2D::Flag::TextureTransformation);
CORRADE_COMPARE(compileState.flags(), VectorGL2D::Flag::TextureTransformation);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
VectorGL<dimensions> shader{std::move(compileState)};
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::TextureTransformation);
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() { template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions)); setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -408,6 +443,38 @@ template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffersAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = VectorGL<dimensions>::compile(VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1);
CORRADE_COMPARE(compileState.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation);
CORRADE_COMPARE(compileState.materialCount(), 1);
CORRADE_COMPARE(compileState.drawCount(), 1);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
VectorGL<dimensions> shader{std::move(compileState)};
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_COMPARE(shader.flags(), VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation);
CORRADE_COMPARE(shader.materialCount(), 1);
CORRADE_COMPARE(shader.drawCount(), 1);
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
template<UnsignedInt dimensions> void VectorGLTest::constructMove() { template<UnsignedInt dimensions> void VectorGLTest::constructMove() {

63
src/Magnum/Shaders/Test/VertexColorGLTest.cpp

@ -29,6 +29,7 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Format.h> #include <Corrade/Utility/Format.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
@ -74,8 +75,10 @@ struct VertexColorGLTest: GL::OpenGLTester {
explicit VertexColorGLTest(); explicit VertexColorGLTest();
template<UnsignedInt dimensions> void construct(); template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers(); template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif #endif
template<UnsignedInt dimensions> void constructMove(); template<UnsignedInt dimensions> void constructMove();
@ -190,13 +193,19 @@ constexpr struct {
VertexColorGLTest::VertexColorGLTest() { VertexColorGLTest::VertexColorGLTest() {
addTests<VertexColorGLTest>({ addTests<VertexColorGLTest>({
&VertexColorGLTest::construct<2>, &VertexColorGLTest::construct<2>,
&VertexColorGLTest::construct<3>}); &VertexColorGLTest::construct<3>,
&VertexColorGLTest::constructAsync<2>,
&VertexColorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests<VertexColorGLTest>({ addInstancedTests<VertexColorGLTest>({
&VertexColorGLTest::constructUniformBuffers<2>, &VertexColorGLTest::constructUniformBuffers<2>,
&VertexColorGLTest::constructUniformBuffers<3>}, &VertexColorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests<VertexColorGLTest>({
&VertexColorGLTest::constructUniformBuffersAsync<2>,
&VertexColorGLTest::constructUniformBuffersAsync<3>});
#endif #endif
addTests<VertexColorGLTest>({ addTests<VertexColorGLTest>({
@ -309,6 +318,28 @@ template<UnsignedInt dimensions> void VertexColorGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void VertexColorGLTest::constructAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
auto compileState = VertexColorGL<dimensions>::compile({});
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
VertexColorGL<dimensions> shader{std::move(compileState)};
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffers() { template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions)); setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -347,6 +378,36 @@ template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffers
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffersAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
auto compileState = VertexColorGL<dimensions>::compile(VertexColorGL2D::Flag::UniformBuffers, 63);
CORRADE_COMPARE(compileState.flags(), VertexColorGL2D::Flag::UniformBuffers);
CORRADE_COMPARE(compileState.drawCount(), 63);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
VertexColorGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), VertexColorGL2D::Flag::UniformBuffers);
CORRADE_COMPARE(shader.drawCount(), 63);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
template<UnsignedInt dimensions> void VertexColorGLTest::constructMove() { template<UnsignedInt dimensions> void VertexColorGLTest::constructMove() {

69
src/Magnum/Shaders/VectorGL.cpp

@ -63,21 +63,16 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::VectorGL: material count can't be zero", ); "Shaders::VectorGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::VectorGL: draw count can't be zero", ); "Shaders::VectorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -141,9 +136,17 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Vector.frag")); .addSource(rs.getString("Vector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
VectorGL out{NoInit};
out._flags = flags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
attachShaders({vert, frag}); out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly */ /* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
@ -151,25 +154,37 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(CompileState&& cs): VectorGL{static_cast<VectorGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
{ {
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix"); _textureMatrixUniform = uniformLocation("textureMatrix");
_backgroundColorUniform = uniformLocation("backgroundColor"); _backgroundColorUniform = uniformLocation("backgroundColor");
_colorUniform = uniformLocation("color"); _colorUniform = uniformLocation("color");
@ -182,10 +197,10 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
{ {
setUniform(uniformLocation("vectorTexture"), TextureUnit); setUniform(uniformLocation("vectorTexture"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
} }
@ -195,24 +210,36 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
{ {
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit}); setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit}); setTextureMatrix(Matrix3{Math::IdentityInit});
/* Background color is zero by default */ /* Background color is zero by default */
setColor(Color4{1.0f}); setColor(Color4{1.0f});
} }
#endif #endif
static_cast<void>(context);
static_cast<void>(version);
} }
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(Flags flags): VectorGL{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags): VectorGL{flags, 1, 1} {} template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(Flags flags) {
return compile(flags, 1, 1);
}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount):
VectorGL{compile(flags, materialCount, drawCount)} {}
#endif #endif
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(NoInitT) {}
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) { template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

31
src/Magnum/Shaders/VectorGL.h

@ -32,6 +32,7 @@
#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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -273,6 +274,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
*/ */
explicit VectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} explicit VectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit VectorGL(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
VectorGL(const VectorGL<dimensions>&) = delete; VectorGL(const VectorGL<dimensions>&) = delete;
@ -554,6 +569,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
#endif #endif
private: private:
/* Creates the GL shader program object but nothing else. Internal, used by compile(). */
explicit VectorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -577,6 +595,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
#endif #endif
}; };
template<UnsignedInt dimensions> class VectorGL<dimensions>::CompileState: public VectorGL<dimensions> {
private:
friend class VectorGL;
explicit CompileState(NoCreateT): VectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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;
GL::Version _version;
};
/** /**
@brief Two-dimensional vector OpenGL shader @brief Two-dimensional vector OpenGL shader
@m_since_latest @m_since_latest

60
src/Magnum/Shaders/VertexColorGL.cpp

@ -31,7 +31,6 @@
#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/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h" #include "Magnum/Math/Matrix4.h"
@ -57,19 +56,14 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Flags flags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt drawCount , const UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _drawCount{drawCount}
#endif
{
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::VertexColorGL: draw count can't be zero", ); "Shaders::VertexColorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -121,9 +115,16 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("VertexColor.frag")); .addSource(rs.getString("VertexColor.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
VertexColorGL<dimensions> out{NoInit};
out._flags = flags;
#ifndef MAGNUM_TARGET_GLES2
out._drawCount = drawCount;
#endif
attachShaders({vert, frag}); out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly */ /* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
@ -131,19 +132,30 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */ out.bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(CompileState&& cs): VertexColorGL{static_cast<VertexColorGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
@ -153,7 +165,7 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers if(_flags >= Flag::UniformBuffers
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&& !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version) && !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version)
#endif #endif
@ -165,7 +177,7 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
@ -173,12 +185,24 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit}); setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
} }
#endif #endif
static_cast<void>(context);
static_cast<void>(version);
} }
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(Flags flags): VertexColorGL{compile(flags)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags): VertexColorGL{flags, 1} {} template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(Flags flags) {
return compile(flags, 1);
}
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(Flags flags, UnsignedInt drawCount):
VertexColorGL{compile(flags, drawCount)} {}
#endif #endif
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(NoInitT) {}
template<UnsignedInt dimensions> VertexColorGL<dimensions>& VertexColorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) { template<UnsignedInt dimensions> VertexColorGL<dimensions>& VertexColorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

30
src/Magnum/Shaders/VertexColorGL.h

@ -32,6 +32,7 @@
#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/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -264,6 +265,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
*/ */
explicit VertexColorGL(NoCreateT) noexcept: AbstractShaderProgram{NoCreate} {} explicit VertexColorGL(NoCreateT) noexcept: AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit VertexColorGL(CompileState&& cs);
static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
VertexColorGL(const VertexColorGL<dimensions>&) = delete; VertexColorGL(const VertexColorGL<dimensions>&) = delete;
@ -406,6 +421,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
#endif #endif
private: private:
explicit VertexColorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -426,6 +443,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
#endif #endif
}; };
template<UnsignedInt dimensions> class VertexColorGL<dimensions>::CompileState: public VertexColorGL<dimensions> {
private:
friend class VertexColorGL;
explicit CompileState(NoCreateT): VertexColorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
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;
GL::Version _version;
};
/** /**
@brief 2D vertex color OpenGL shader @brief 2D vertex color OpenGL shader
@m_since_latest @m_since_latest

Loading…
Cancel
Save