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/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
@ -63,22 +62,16 @@ namespace {
#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
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount},
_drawCount{drawCount}
#endif
{
) {
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::DistanceFieldVectorGL: draw count can't be zero", );
"Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES
@ -142,9 +135,17 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
frag.addSource(rs.getString("generic.glsl"))
.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 */
#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))
#endif
{
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
{
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
_colorUniform = uniformLocation("color");
_outlineColorUniform = uniformLocation("outlineColor");
@ -185,11 +196,11 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
{
setUniform(uniformLocation("vectorTexture"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
}
#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) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
{
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
setColor(Color4{1.0f});
/* Outline color is zero by default */
@ -212,10 +223,22 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
setSmoothness(0.04f);
}
#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
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
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/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.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} {}
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 */
DistanceFieldVectorGL(const DistanceFieldVectorGL<dimensions>&) = delete;
@ -602,6 +617,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif
private:
explicit DistanceFieldVectorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
@ -627,6 +644,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#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
@m_since_latest

105
src/Magnum/Shaders/FlatGL.cpp

@ -31,7 +31,6 @@
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
@ -68,16 +67,11 @@ namespace {
#endif
}
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
) {
#ifndef CORRADE_NO_ASSERT
{
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured
@ -86,22 +80,22 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#endif
;
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
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::FlatGL: draw count can't be zero", );
"Shaders::FlatGL: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES2
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),
"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
#ifndef MAGNUM_TARGET_GLES
@ -195,9 +189,17 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
frag.addSource(rs.getString("generic.glsl"))
.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
bindFragmentDataLocation() */
@ -206,53 +208,64 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif
{
bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(Position::Location, "position");
if(flags & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
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
if(flags & Flag::ObjectId) {
bindFragmentDataLocation(ColorOutput, "color");
bindFragmentDataLocation(ObjectIdOutput, "objectId");
out.bindFragmentDataLocation(ColorOutput, "color");
out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
}
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
{
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays)
if(_flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer");
#endif
_colorUniform = uniformLocation("color");
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif
}
}
@ -261,13 +274,13 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
if(!context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version))
#endif
{
if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit);
if(_flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
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) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
{
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */
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 */
}
#endif
static_cast<void>(version);
static_cast<void>(context);
}
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(Flags flags): FlatGL{compile(flags)} {}
#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
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(NoInitT) {}
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

31
src/Magnum/Shaders/FlatGL.h

@ -32,6 +32,7 @@
#include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.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} {}
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 */
FlatGL(const FlatGL<dimensions>&) = delete;
@ -1011,6 +1026,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#endif
private:
/* Creates the GL shader program object but nothing else. Internal, used by compile(). */
explicit FlatGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
@ -1038,6 +1056,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#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
@m_since_latest

308
src/Magnum/Shaders/MeshVisualizerGL.cpp

@ -26,7 +26,6 @@
#include "MeshVisualizerGL.h"
#include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Reference.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Resource.h>
@ -72,17 +71,7 @@ namespace {
namespace Implementation {
MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount},
_drawCount{drawCount}
#endif
{
void MeshVisualizerGLBase::assertExtensions(const FlagsBase flags) {
#ifndef MAGNUM_TARGET_GLES2
#ifndef CORRADE_NO_ASSERT
Int countMutuallyExclusive = 0;
@ -120,7 +109,7 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#endif
#ifndef MAGNUM_TARGET_GLES2
if(_flags & FlagBase::Wireframe && !(_flags & FlagBase::NoGeometryShader)) {
if(flags & FlagBase::Wireframe && !(flags & FlagBase::NoGeometryShader)) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320);
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::geometry_shader4);
@ -129,12 +118,12 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#endif
}
#else
if(_flags & FlagBase::Wireframe)
if(flags & FlagBase::Wireframe)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::OES::standard_derivatives);
#endif
#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
MAGNUM_ASSERT_GL_VERSION_SUPPORTED(GL::Version::GL320);
#else
@ -150,18 +139,23 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags
#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();
#ifndef MAGNUM_TARGET_GLES
const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210});
/* 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)
/* 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});
/* 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
const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200});
#endif
@ -169,18 +163,18 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra
vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
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
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(flags & FlagBase::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
.addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif
.addSource(_flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
.addSource(flags & FlagBase::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(_flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "")
.addSource(flags >= FlagBase::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "")
.addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(flags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "")
#endif
#ifdef MAGNUM_TARGET_WEBGL
.addSource("#define SUBSCRIPTING_WORKAROUND\n")
@ -190,38 +184,38 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra
#endif
;
#ifndef MAGNUM_TARGET_GLES2
if(_flags >= FlagBase::UniformBuffers) {
if(flags >= FlagBase::UniformBuffers) {
vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n",
_drawCount,
_materialCount));
vert.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
drawCount,
materialCount));
vert.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
}
#endif
frag.addSource(_flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
frag.addSource(flags & FlagBase::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ?
.addSource(flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(flags >= FlagBase::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
.addSource(flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(flags & FlagBase::PrimitiveId ?
(flags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "")
#endif
;
#ifndef MAGNUM_TARGET_GLES2
if(_flags >= FlagBase::UniformBuffers) {
if(flags >= FlagBase::UniformBuffers) {
frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n",
_drawCount,
_materialCount));
frag.addSource(_flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
drawCount,
materialCount));
frag.addSource(flags >= FlagBase::MultiDraw ? "#define MULTI_DRAW\n" : "");
}
#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
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags))
#ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount
#endif
} {
) {
FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
assertExtensions(baseFlags);
#ifndef MAGNUM_TARGET_GLES2
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
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
/* 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 */
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::MeshVisualizerGL2D: draw count can't be zero", );
"Shaders::MeshVisualizerGL2D: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES
@ -416,7 +409,12 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
Utility::Resource rs{"MagnumShadersGL"};
GL::Shader vert{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")
/* 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"))
.addSource(rs.getString("MeshVisualizer.frag"));
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
Containers::Optional<GL::Shader> geom;
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry);
(*geom)
.addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ?
.addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(baseFlags & FlagBase::PrimitiveId ?
(baseFlags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "");
#ifndef MAGNUM_TARGET_GLES2
@ -461,8 +459,8 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
"#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n",
_drawCount,
_materialCount));
drawCount,
materialCount));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
}
#endif
@ -472,48 +470,75 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
static_cast<void>(version);
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag}));
else
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
vert.submitCompile();
frag.submitCompile();
if (geom) geom->submitCompile();
attachShaders({vert, frag});
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(geom) attachShader(*geom);
MeshVisualizerGL2D out{NoInit};
out._flags = baseFlags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
out.attachShaders({vert, frag});
if (geom) out.attachShader(*geom);
/* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif
{
bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation)
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES
if(!context.isVersionSupported(GL::Version::GL310))
#endif
{
bindAttributeLocation(VertexIndex::Location, "vertexIndex");
out.bindAttributeLocation(VertexIndex::Location, "vertexIndex");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
@ -608,11 +633,10 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags
#endif
}
#endif
}
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{flags, 1, 1} {}
#endif
static_cast<void>(context);
static_cast<void>(version);
}
MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) {
/* Not asserting here, since the relation to wireframe is a bit vague.
@ -674,33 +698,32 @@ MeshVisualizerGL2D& MeshVisualizerGL2D::bindDrawBuffer(GL::Buffer& buffer, const
}
#endif
MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags))
#ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount
#endif
} {
) {
FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
assertExtensions(baseFlags);
#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),
"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)),
"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),
"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)
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
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
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
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
/* 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 */
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::MeshVisualizerGL3D: draw count can't be zero", );
"Shaders::MeshVisualizerGL3D: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES
@ -720,7 +743,12 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
Utility::Resource rs{"MagnumShadersGL"};
GL::Shader vert{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 */
#ifndef MAGNUM_TARGET_GLES
@ -768,7 +796,6 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
.addSource(rs.getString("MeshVisualizer.frag"));
#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)) {
Int maxVertices = 0;
if(flags & Flag::Wireframe) maxVertices += 3;
@ -781,13 +808,13 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
(*geom)
.addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices))
.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(_flags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(_flags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(_flags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(_flags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(_flags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(_flags & FlagBase::PrimitiveId ?
(_flags >= FlagBase::PrimitiveIdFromVertexId ?
.addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(baseFlags >= FlagBase::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(baseFlags & FlagBase::VertexId ? "#define VERTEX_ID\n" : "")
.addSource(baseFlags & FlagBase::PrimitiveId ?
(baseFlags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "")
.addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "")
@ -800,8 +827,8 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
"#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n",
_drawCount,
_materialCount));
drawCount,
materialCount));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
}
#endif
@ -811,50 +838,53 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
static_cast<void>(version);
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, *geom, frag}));
else
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
vert.submitCompile();
frag.submitCompile();
if (geom) geom->submitCompile();
attachShaders({vert, frag});
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(geom) attachShader(*geom);
MeshVisualizerGL3D out{NoInit};
out._flags = baseFlags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
out.attachShaders({vert, frag});
if (geom) out.attachShader(*geom);
/* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif
{
bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection))
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
#endif
}
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & Flag::TangentDirection ||
flags & Flag::BitangentFromTangentDirection)
bindAttributeLocation(Tangent4::Location, "tangent");
out.bindAttributeLocation(Tangent4::Location, "tangent");
if(flags & Flag::BitangentDirection)
bindAttributeLocation(Bitangent::Location, "bitangent");
out.bindAttributeLocation(Bitangent::Location, "bitangent");
if(flags & Flag::NormalDirection ||
flags & Flag::BitangentFromTangentDirection)
bindAttributeLocation(Normal::Location, "normal");
out.bindAttributeLocation(Normal::Location, "normal");
#endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
@ -862,13 +892,25 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
if(!context.isVersionSupported(GL::Version::GL310))
#endif
{
bindAttributeLocation(VertexIndex::Location, "vertexIndex");
out.bindAttributeLocation(VertexIndex::Location, "vertexIndex");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
@ -996,10 +1038,20 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags
#endif
}
#endif
static_cast<void>(context);
static_cast<void>(version);
}
MeshVisualizerGL3D::MeshVisualizerGL3D(Flags flags) : MeshVisualizerGL3D{compile(flags)} {}
#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
MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) {

79
src/Magnum/Shaders/MeshVisualizerGL.h

@ -32,8 +32,10 @@
#include <Corrade/Utility/Utility.h>
#include <Corrade/Containers/Optional.h>
#include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/visibility.h"
@ -69,14 +71,17 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgr
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
, UnsignedInt materialCount, UnsignedInt drawCount
#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
MeshVisualizerGLBase& setTextureMatrix(const Matrix3& matrix);
@ -505,6 +510,20 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
*/
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 */
MeshVisualizerGL2D(const MeshVisualizerGL2D&) = delete;
@ -862,9 +881,26 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
#endif
private:
explicit MeshVisualizerGL2D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {}
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
@m_since_latest
@ -1639,7 +1675,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
* @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags)
* instead.
*/
explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{{}} {}
explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{Flags{}} {}
#endif
#ifndef MAGNUM_TARGET_GLES2
@ -1698,6 +1734,21 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
*/
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 */
MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete;
@ -2326,6 +2377,8 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
#endif
private:
explicit MeshVisualizerGL3D(NoInitT) : Implementation::MeshVisualizerGLBase{NoInit} {}
Int _transformationMatrixUniform{9},
_projectionMatrixUniform{10};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
@ -2335,6 +2388,22 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
#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} */
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/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
@ -74,21 +73,12 @@ namespace {
#endif
}
PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags},
_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)}
{
) {
#ifndef CORRADE_NO_ASSERT
{
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture))
#ifndef MAGNUM_TARGET_GLES2
@ -96,32 +86,33 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#endif
;
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
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
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::PhongGL: draw count can't be zero", );
"Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES2
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),
"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),
"Shaders::PhongGL: light culling requires uniform buffers to be enabled", );
"Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate});
#endif
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
if(flags >= Flag::UniformBuffers)
@ -154,7 +145,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES
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
#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});
#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 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_RANGES_LOCATION {}\n",
lightCount,
_lightPositionsUniform + lightCount,
_lightPositionsUniform + 2*lightCount,
_lightPositionsUniform + 3*lightCount));
out._lightPositionsUniform + lightCount,
out._lightPositionsUniform + 2*lightCount,
out._lightPositionsUniform + 3*lightCount));
}
#ifndef MAGNUM_TARGET_GLES
if(!(flags >= Flag::UniformBuffers) && lightCount)
@ -294,9 +296,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
frag.addSource(rs.getString("generic.glsl"))
.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
bindFragmentDataLocation() */
@ -305,103 +308,114 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif
{
bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(Position::Location, "position");
if(lightCount)
bindAttributeLocation(Normal::Location, "normal");
out.bindAttributeLocation(Normal::Location, "normal");
if((flags & Flag::NormalTexture) && lightCount) {
bindAttributeLocation(Tangent::Location, "tangent");
out.bindAttributeLocation(Tangent::Location, "tangent");
if(flags & Flag::Bitangent)
bindAttributeLocation(Bitangent::Location, "bitangent");
out.bindAttributeLocation(Bitangent::Location, "bitangent");
}
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)
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) {
bindFragmentDataLocation(ColorOutput, "color");
bindFragmentDataLocation(ObjectIdOutput, "objectId");
out.bindFragmentDataLocation(ColorOutput, "color");
out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
}
if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId");
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif
if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(lightCount)
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
}
if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
{
_transformationMatrixUniform = uniformLocation("transformationMatrix");
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays)
if(_flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer");
#endif
_projectionMatrixUniform = uniformLocation("projectionMatrix");
_ambientColorUniform = uniformLocation("ambientColor");
if(lightCount) {
if(_lightCount) {
_normalMatrixUniform = uniformLocation("normalMatrix");
_diffuseColorUniform = uniformLocation("diffuseColor");
if(!(flags & Flag::NoSpecular)) {
if(!(_flags & Flag::NoSpecular)) {
_specularColorUniform = uniformLocation("specularColor");
_shininessUniform = uniformLocation("shininess");
}
if(flags & Flag::NormalTexture)
if(_flags & Flag::NormalTexture)
_normalTextureScaleUniform = uniformLocation("normalTextureScale");
_lightPositionsUniform = uniformLocation("lightPositions");
_lightColorsUniform = uniformLocation("lightColors");
if(!(flags & Flag::NoSpecular))
if(!(_flags & Flag::NoSpecular))
_lightSpecularColorsUniform = uniformLocation("lightSpecularColors");
_lightRangesUniform = uniformLocation("lightRanges");
}
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif
}
}
#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
{
if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit);
if(lightCount) {
if(flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit);
if(flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit);
if(flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit);
if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit);
if(_lightCount) {
if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit);
if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit);
if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit);
}
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
if(lightCount)
if(_lightCount)
setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding);
}
#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) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
{
/* 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});
setTransformationMatrix(Matrix4{Math::IdentityInit});
setProjectionMatrix(Matrix4{Math::IdentityInit});
if(lightCount) {
if(_lightCount) {
setDiffuseColor(Magnum::Color4{1.0f});
if(!(flags & Flag::NoSpecular)) {
if(!(_flags & Flag::NoSpecular)) {
setSpecularColor(Magnum::Color4{1.0f, 0.0f});
setShininess(80.0f);
}
if(flags & Flag::NormalTexture)
if(_flags & Flag::NormalTexture)
setNormalTextureScale(1.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}};
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}};
setLightColors(colors);
if(!(flags & Flag::NoSpecular))
if(!(_flags & Flag::NoSpecular))
setLightSpecularColors(colors);
setLightRanges(Containers::Array<Float>{DirectInit, lightCount, Constants::inf()});
setLightRanges(Containers::Array<Float>{DirectInit, _lightCount, Constants::inf()});
/* Light position is zero by default */
setNormalMatrix(Matrix3x3{Math::IdentityInit});
}
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
/* 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 */
}
#endif
static_cast<void>(context);
static_cast<void>(version);
}
PhongGL::PhongGL(Flags flags, UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {}
#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
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/Shader.h"
#include "Magnum/Shaders/GenericGL.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} {}
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 */
PhongGL(const PhongGL&) = delete;
@ -1744,6 +1759,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif
private:
explicit PhongGL(NoInitT) {}
/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
@ -1784,6 +1801,19 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#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} */
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/Utility/DebugStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
@ -84,8 +85,10 @@ struct DistanceFieldVectorGLTest: GL::OpenGLTester {
explicit DistanceFieldVectorGLTest();
template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif
template<UnsignedInt dimensions> void constructMove();
@ -251,11 +254,19 @@ DistanceFieldVectorGLTest::DistanceFieldVectorGLTest() {
&DistanceFieldVectorGLTest::construct<3>},
Containers::arraySize(ConstructData));
addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructAsync<2>,
&DistanceFieldVectorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffers<2>,
&DistanceFieldVectorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData));
addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<2>,
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<3>});
#endif
addTests<DistanceFieldVectorGLTest>({
@ -374,6 +385,29 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::construct() {
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
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -413,6 +447,39 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUnifor
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
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructMove() {

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

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
@ -83,8 +84,10 @@ struct FlatGLTest: GL::OpenGLTester {
explicit FlatGLTest();
template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif
template<UnsignedInt dimensions> void constructMove();
@ -600,11 +603,19 @@ FlatGLTest::FlatGLTest() {
&FlatGLTest::construct<3>},
Containers::arraySize(ConstructData));
addTests<FlatGLTest>({
&FlatGLTest::constructAsync<2>,
&FlatGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<FlatGLTest>({
&FlatGLTest::constructUniformBuffers<2>,
&FlatGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData));
addTests<FlatGLTest>({
&FlatGLTest::constructUniformBuffersAsync<2>,
&FlatGLTest::constructUniformBuffersAsync<3>});
#endif
addTests<FlatGLTest>({
@ -853,6 +864,28 @@ template<UnsignedInt dimensions> void FlatGLTest::construct() {
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
template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -896,6 +929,38 @@ template<UnsignedInt dimensions> void FlatGLTest::constructUniformBuffers() {
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
template<UnsignedInt dimensions> void FlatGLTest::constructMove() {

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

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
@ -88,12 +89,16 @@ struct MeshVisualizerGLTest: GL::OpenGLTester {
explicit MeshVisualizerGLTest();
void construct2D();
void construct2DAsync();
#ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers2D();
void constructUniformBuffers2DAsync();
#endif
void construct3D();
void construct3DAsync();
#ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers3D();
void constructUniformBuffers3DAsync();
#endif
void construct2DInvalid();
@ -1055,17 +1060,23 @@ MeshVisualizerGLTest::MeshVisualizerGLTest() {
addInstancedTests({&MeshVisualizerGLTest::construct2D},
Containers::arraySize(ConstructData2D));
addTests({&MeshVisualizerGLTest::construct2DAsync});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers2D},
Containers::arraySize(ConstructUniformBuffersData2D));
addTests({&MeshVisualizerGLTest::constructUniformBuffers2DAsync});
#endif
addInstancedTests({&MeshVisualizerGLTest::construct3D},
Containers::arraySize(ConstructData3D));
addTests({&MeshVisualizerGLTest::construct3DAsync});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&MeshVisualizerGLTest::constructUniformBuffers3D},
Containers::arraySize(ConstructUniformBuffersData3D));
addTests({&MeshVisualizerGLTest::constructUniformBuffers3DAsync});
#endif
addInstancedTests({&MeshVisualizerGLTest::construct2DInvalid},
@ -1403,6 +1414,28 @@ void MeshVisualizerGLTest::construct2D() {
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
void MeshVisualizerGLTest::constructUniformBuffers2D() {
auto&& data = ConstructUniformBuffersData2D[testCaseInstanceId()];
@ -1480,8 +1513,40 @@ void MeshVisualizerGLTest::constructUniformBuffers2D() {
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
void MeshVisualizerGLTest::construct3D() {
auto&& data = ConstructData3D[testCaseInstanceId()];
setTestCaseDescription(data.name);
@ -1541,6 +1606,27 @@ void MeshVisualizerGLTest::construct3D() {
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
void MeshVisualizerGLTest::constructUniformBuffers3D() {
auto&& data = ConstructUniformBuffersData3D[testCaseInstanceId()];
@ -1618,6 +1704,36 @@ void MeshVisualizerGLTest::constructUniformBuffers3D() {
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
void MeshVisualizerGLTest::construct2DInvalid() {

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

@ -31,12 +31,12 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Compare/Numeric.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
#include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/System.h> /* isSandboxed() */
#endif
#include "Magnum/Image.h"
@ -83,8 +83,10 @@ struct PhongGLTest: GL::OpenGLTester {
explicit PhongGLTest();
void construct();
void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers();
void constructUniformBuffersAsync();
#endif
void constructMove();
@ -927,9 +929,13 @@ PhongGLTest::PhongGLTest() {
addInstancedTests({&PhongGLTest::construct},
Containers::arraySize(ConstructData));
addTests({&PhongGLTest::constructAsync});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&PhongGLTest::constructUniformBuffers},
Containers::arraySize(ConstructUniformBuffersData));
addTests({&PhongGLTest::constructUniformBuffersAsync});
#endif
addTests({
@ -1192,6 +1198,29 @@ void PhongGLTest::construct() {
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
void PhongGLTest::constructUniformBuffers() {
auto&& data = ConstructUniformBuffersData[testCaseInstanceId()];
@ -1234,6 +1263,38 @@ void PhongGLTest::constructUniformBuffers() {
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
void PhongGLTest::constructMove() {

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

@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
@ -83,8 +84,10 @@ struct VectorGLTest: GL::OpenGLTester {
explicit VectorGLTest();
template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif
template<UnsignedInt dimensions> void constructMove();
@ -247,11 +250,19 @@ VectorGLTest::VectorGLTest() {
&VectorGLTest::construct<3>},
Containers::arraySize(ConstructData));
addTests<VectorGLTest>({
&VectorGLTest::constructAsync<2>,
&VectorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<VectorGLTest>({
&VectorGLTest::constructUniformBuffers<2>,
&VectorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData));
addTests<VectorGLTest>({
&VectorGLTest::constructUniformBuffersAsync<2>,
&VectorGLTest::constructUniformBuffersAsync<3>});
#endif
addTests<VectorGLTest>({
@ -370,6 +381,30 @@ template<UnsignedInt dimensions> void VectorGLTest::construct() {
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
template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -408,6 +443,38 @@ template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() {
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
template<UnsignedInt dimensions> void VectorGLTest::constructMove() {

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

@ -29,6 +29,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE
@ -74,8 +75,10 @@ struct VertexColorGLTest: GL::OpenGLTester {
explicit VertexColorGLTest();
template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif
template<UnsignedInt dimensions> void constructMove();
@ -190,13 +193,19 @@ constexpr struct {
VertexColorGLTest::VertexColorGLTest() {
addTests<VertexColorGLTest>({
&VertexColorGLTest::construct<2>,
&VertexColorGLTest::construct<3>});
&VertexColorGLTest::construct<3>,
&VertexColorGLTest::constructAsync<2>,
&VertexColorGLTest::constructAsync<3>});
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<VertexColorGLTest>({
&VertexColorGLTest::constructUniformBuffers<2>,
&VertexColorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData));
addTests<VertexColorGLTest>({
&VertexColorGLTest::constructUniformBuffersAsync<2>,
&VertexColorGLTest::constructUniformBuffersAsync<3>});
#endif
addTests<VertexColorGLTest>({
@ -309,6 +318,28 @@ template<UnsignedInt dimensions> void VertexColorGLTest::construct() {
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
template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
@ -347,6 +378,36 @@ template<UnsignedInt dimensions> void VertexColorGLTest::constructUniformBuffers
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
template<UnsignedInt dimensions> void VertexColorGLTest::constructMove() {

69
src/Magnum/Shaders/VectorGL.cpp

@ -63,21 +63,16 @@ namespace {
#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
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
) {
#ifndef MAGNUM_TARGET_GLES2
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,
"Shaders::VectorGL: draw count can't be zero", );
"Shaders::VectorGL: draw count can't be zero", CompileState{NoCreate});
#endif
#ifndef MAGNUM_TARGET_GLES
@ -141,9 +136,17 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
frag.addSource(rs.getString("generic.glsl"))
.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 */
#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))
#endif
{
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
{
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
_backgroundColorUniform = uniformLocation("backgroundColor");
_colorUniform = uniformLocation("color");
@ -182,10 +197,10 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
{
setUniform(uniformLocation("vectorTexture"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
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) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
{
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
/* Background color is zero by default */
setColor(Color4{1.0f});
}
#endif
static_cast<void>(context);
static_cast<void>(version);
}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(Flags flags): VectorGL{compile(flags)} {}
#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
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(NoInitT) {}
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

31
src/Magnum/Shaders/VectorGL.h

@ -32,6 +32,7 @@
#include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.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} {}
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 */
VectorGL(const VectorGL<dimensions>&) = delete;
@ -554,6 +569,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
#endif
private:
/* Creates the GL shader program object but nothing else. Internal, used by compile(). */
explicit VectorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
@ -577,6 +595,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
#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
@m_since_latest

60
src/Magnum/Shaders/VertexColorGL.cpp

@ -31,7 +31,6 @@
#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
#include "Magnum/Math/Matrix4.h"
@ -57,19 +56,14 @@ namespace {
#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
, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _drawCount{drawCount}
#endif
{
) {
#ifndef MAGNUM_TARGET_GLES2
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
#ifndef MAGNUM_TARGET_GLES
@ -121,9 +115,16 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
frag.addSource(rs.getString("generic.glsl"))
.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 */
#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))
#endif
{
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */
out.bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(Color3::Location, "color"); /* Color4 is the same */
}
#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
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
@ -153,7 +165,7 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
}
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers
if(_flags >= Flag::UniformBuffers
#ifndef MAGNUM_TARGET_GLES
&& !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version)
#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) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
@ -173,12 +185,24 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
}
#endif
static_cast<void>(context);
static_cast<void>(version);
}
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(Flags flags): VertexColorGL{compile(flags)} {}
#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
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(NoInitT) {}
template<UnsignedInt dimensions> VertexColorGL<dimensions>& VertexColorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

30
src/Magnum/Shaders/VertexColorGL.h

@ -32,6 +32,7 @@
#include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.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} {}
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 */
VertexColorGL(const VertexColorGL<dimensions>&) = delete;
@ -406,6 +421,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
#endif
private:
explicit VertexColorGL(NoInitT);
/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
@ -426,6 +443,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
#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
@m_since_latest

Loading…
Cancel
Save