Browse Source

GL: create a macro for AbstractShaderProgram subclass method chaining.

A bunch of new GLES- and WebGL-specific draw() variants got added in
b30d313ecd over a year ago, but so far
they weren't exposed in any of the Shaders because it'd mean a lot of
nasty copypasting and I just didn't like that.

So instead, there's a new macro to handle this messy work, and also
tested in order to ensure everything is still as it should be and that
it works even outside the Magnum namespace. This makes it much easier to
add new draw() variants (such as indirect draws, *finally*), without
having to update every shader implementation under the sun.

One difference is that I'm now allowing drawTransformFeedback() always
-- because that makes sense. It *is* possible to use a regular shader to
draw a result of a XFB, so it doesn't make sense to attempt to block
that.

The change to Shaders will be done in the next commit.
pull/610/head
Vladimír Vondruš 4 years ago
parent
commit
fb0a970ecd
  1. 4
      doc/Doxyfile
  2. 4
      doc/changelog.dox
  3. 35
      doc/snippets/MagnumGL.cpp
  4. 157
      src/Magnum/GL/AbstractShaderProgram.h
  5. 123
      src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp

4
doc/Doxyfile

@ -2260,7 +2260,9 @@ PREDEFINED = DOXYGEN_GENERATING_OUTPUT \
CORRADE_VISIBILITY_LOCAL= CORRADE_VISIBILITY_IMPORT= \
CORRADE_IGNORE_DEPRECATED_PUSH= CORRADE_IGNORE_DEPRECATED_POP= \
CORRADE_ENUMSET_OPERATORS(message)= MAGNUM_BUILD_DEPRECATED \
MAGNUM_TARGET_GL MAGNUM_TARGET_VK
MAGNUM_TARGET_GL MAGNUM_TARGET_VK \
MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION(type)= \
MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION(type)=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

4
doc/changelog.dox

@ -445,6 +445,10 @@ See also:
@relativeref{GL::Framebuffer::InvalidationAttachment,Stencil} (see
[mosra/magnum#554](https://github.com/mosra/magnum/pull/554))
- Added @ref GL::Shader::wrap() and @relativeref{GL::Shader,release()}
- New @ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION() and
@ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION()
macros for easier and more robust implementation of method chaining in
@ref GL::AbstractShaderProgram subclasses
@subsubsection changelog-latest-changes-math Math library

35
doc/snippets/MagnumGL.cpp

@ -107,38 +107,9 @@ enum: UnsignedInt {
};
/* [AbstractShaderProgram-output-attributes] */
#if !defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL)
/* [AbstractShaderProgram-return-hide-irrelevant] */
public:
MyShader& draw(GL::Mesh& mesh) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(mesh));
}
MyShader& draw(GL::Mesh&& mesh) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(mesh));
}
MyShader& draw(GL::MeshView& mesh) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(mesh));
}
MyShader& draw(GL::MeshView&& mesh) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(mesh));
}
/* Omit these if the shader is not ready for multidraw */
MyShader& draw(GL::Mesh& mesh, const Containers::StridedArrayView1D<const UnsignedInt>& counts, const Containers::StridedArrayView1D<const UnsignedInt>& vertexOffsets, const Containers::StridedArrayView1D<const UnsignedInt>& indexOffsets) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(mesh, counts, vertexOffsets, indexOffsets));
}
MyShader& draw(Containers::ArrayView<const Containers::Reference<GL::MeshView>> meshes) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(meshes));
}
MyShader& draw(std::initializer_list<Containers::Reference<GL::MeshView>> meshes) {
return static_cast<MyShader&>(GL::AbstractShaderProgram::draw(meshes));
}
private:
using GL::AbstractShaderProgram::drawTransformFeedback;
using GL::AbstractShaderProgram::dispatchCompute;
/* [AbstractShaderProgram-return-hide-irrelevant] */
public:
#endif
/* [AbstractShaderProgram-subclass-macro] */
MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION(MyShader)
/* [AbstractShaderProgram-subclass-macro] */
/* [AbstractShaderProgram-constructor] */
explicit MyShader() {

157
src/Magnum/GL/AbstractShaderProgram.h

@ -28,7 +28,7 @@
*/
/** @file
* @brief Class @ref Magnum::GL::AbstractShaderProgram
* @brief Class @ref Magnum::GL::AbstractShaderProgram, macro @ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION(), @ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION()
*/
#include <string>
@ -108,13 +108,16 @@ functions and properties:
@snippet MagnumGL.cpp AbstractShaderProgram-xfb
</li>
<li>And optionally, **return derived type from relevant draw/dispatch functions**
to make it possible for users to easily chain draw calls, and on the other
to make it possible for users to easily chain draw calls; and on the other
hand **hide the irrelevant APIs** to prevent users from accidentally
calling @ref draw() on compute shaders, @ref drawTransformFeedback() on
shaders that don't have transform feedback or @ref dispatchCompute() on
shaders that aren't compute. For example:
@snippet MagnumGL.cpp AbstractShaderProgram-return-hide-irrelevant
calling @ref draw() / @ref drawTransformFeedback() on compute shaders, or
@ref dispatchCompute() on shaders that aren't compute. Because there's many
overloads of those APIs and they differ based on target platform, it's
recommended to be done via either
@ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION() or
@ref MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION():
@snippet MagnumGL.cpp AbstractShaderProgram-subclass-macro
</ul>
@subsection GL-AbstractShaderProgram-attribute-location Binding attribute and fragment data location
@ -2015,6 +2018,146 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
#endif
};
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef CORRADE_TARGET_32BIT
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_32BIT(...) \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedLong>& indexOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, vertexOffsets, indexOffsets)); \
} \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, std::nullptr_t) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, vertexOffsets, nullptr)); \
}
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_32BIT(...)
#endif
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
#ifndef CORRADE_TARGET_32BIT
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2_NOT_32BIT(...) \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedLong>& indexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets, instanceOffsets)); \
} \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, std::nullptr_t, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, nullptr, instanceOffsets)); \
}
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2_NOT_32BIT(...)
#endif
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2(...) \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& indexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets, instanceOffsets)); \
} \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2_NOT_32BIT(__VA_ARGS__)
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2(...)
#endif
#ifndef CORRADE_TARGET_32BIT
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_32BIT(...) \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedLong>& indexOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets)); \
} \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, std::nullptr_t) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, nullptr)); \
}
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_32BIT(...)
#endif
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES(...) \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_GLES2(__VA_ARGS__) \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES_NOT_32BIT(__VA_ARGS__) \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& instanceCounts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& indexOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets)); \
}
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_GLES(...)
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES(...)
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_GLES(...) \
__VA_ARGS__& drawTransformFeedback(Magnum::GL::Mesh& mesh, Magnum::GL::TransformFeedback& xfb, Magnum::UnsignedInt stream = 0) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::drawTransformFeedback(mesh, xfb, stream)); \
} \
__VA_ARGS__& drawTransformFeedback(Magnum::GL::MeshView& mesh, Magnum::GL::TransformFeedback& xfb, Magnum::UnsignedInt stream = 0) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::drawTransformFeedback(mesh, xfb, stream)); \
}
#endif
#ifndef MAGNUM_TARGET_GLES
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_XFB \
using Magnum::GL::AbstractShaderProgram::drawTransformFeedback;
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_XFB
#endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_COMPUTE \
using Magnum::GL::AbstractShaderProgram::dispatchCompute;
#else
#define _MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_COMPUTE
#endif
#endif
/**
@brief @relativeref{Magnum::GL,AbstractShaderProgram} subclass method chaining implementation for draws
@m_since_latest
Overrides all variants of @relativeref{Magnum::GL,AbstractShaderProgram::draw()}
and @relativeref{Magnum::GL::AbstractShaderProgram,drawTransformFeedback()} in
given subclass to return a reference to that class type instead of
@relativeref{Magnum::GL,AbstractShaderProgram}, and additionally prevents
accidental calls to
@relativeref{Magnum::GL,AbstractShaderProgram::dispatchCompute()}. See
@ref GL-AbstractShaderProgram-subclassing for more information.
*/
#define MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION(...) \
private: \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_COMPUTE \
public: \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh)); \
} \
__VA_ARGS__& draw(Magnum::GL::Mesh&& mesh) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh)); \
} \
__VA_ARGS__& draw(Magnum::GL::MeshView& mesh) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh)); \
} \
__VA_ARGS__& draw(Magnum::GL::MeshView&& mesh) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh)); \
} \
__VA_ARGS__& draw(Magnum::GL::Mesh& mesh, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& counts, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& vertexOffsets, const Corrade::Containers::StridedArrayView1D<const Magnum::UnsignedInt>& indexOffsets) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(mesh, counts, vertexOffsets, indexOffsets)); \
} \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_32BIT(__VA_ARGS__) \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_GLES(__VA_ARGS__) \
__VA_ARGS__& draw(Corrade::Containers::ArrayView<const Corrade::Containers::Reference<Magnum::GL::MeshView>> meshes) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(meshes)); \
} \
__VA_ARGS__& draw(std::initializer_list<Corrade::Containers::Reference<Magnum::GL::MeshView>> meshes) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::draw(meshes)); \
} \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_NOT_GLES(__VA_ARGS__)
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
/**
@brief @relativeref{Magnum::GL,AbstractShaderProgram} subclass method chaining implementation for compute dispatch
@m_since_latest
Overrides @relativeref{Magnum::GL,AbstractShaderProgram::dispatchCompute()} in
given subclass to return a reference to that class type instead of
@relativeref{Magnum::GL,AbstractShaderProgram}, and additionally prevents
accidental calls to @relativeref{Magnum::GL,AbstractShaderProgram::draw()} and
@relativeref{Magnum::GL::AbstractShaderProgram,drawTransformFeedback()}. See
@ref GL-AbstractShaderProgram-subclassing for more information.
@requires_gles31 Not defined on OpenGL ES 2.0 builds.
@requires_gles Not defined on WebGL builds.
*/
#define MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION(...) \
private: \
using Magnum::GL::AbstractShaderProgram::draw; \
_MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION_HIDE_XFB \
public: \
__VA_ARGS__& dispatchCompute(const Magnum::Vector3ui& workgroupCount) { \
return static_cast<__VA_ARGS__&>(Magnum::GL::AbstractShaderProgram::dispatchCompute(workgroupCount)); \
}
#endif
}}
#endif

123
src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp

@ -26,6 +26,7 @@
#include <sstream>
#include <Corrade/Containers/Iterable.h>
#include <Corrade/Containers/Reference.h>
#include <Corrade/Containers/StridedArrayView.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove when Shader is <string>-free */
#include <Corrade/TestSuite/Compare/Container.h>
#include <Corrade/TestSuite/Compare/String.h>
@ -41,11 +42,16 @@
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#include "Magnum/GL/ImageFormat.h"
#endif
#include "Magnum/GL/Mesh.h"
#include "Magnum/GL/MeshView.h"
#include "Magnum/GL/OpenGLTester.h"
#include "Magnum/GL/PixelFormat.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/GL/TextureFormat.h"
#include "Magnum/GL/OpenGLTester.h"
#ifndef MAGNUM_TARGET_GLES
#include "Magnum/GL/TransformFeedback.h"
#endif
#include "Magnum/Math/Matrix.h"
#include "Magnum/Math/Vector4.h"
#include "Magnum/Math/Color.h"
@ -99,6 +105,11 @@ struct AbstractShaderProgramGLTest: OpenGLTester {
void compute();
#endif
#endif
void subclassDraw();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void subclassDispatch();
#endif
};
AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() {
@ -138,8 +149,13 @@ AbstractShaderProgramGLTest::AbstractShaderProgramGLTest() {
&AbstractShaderProgramGLTest::uniformBlock,
#ifndef MAGNUM_TARGET_WEBGL
&AbstractShaderProgramGLTest::compute
&AbstractShaderProgramGLTest::compute,
#endif
#endif
&AbstractShaderProgramGLTest::subclassDraw,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
&AbstractShaderProgramGLTest::subclassDispatch
#endif
});
}
@ -1103,4 +1119,107 @@ void AbstractShaderProgramGLTest::compute() {
}}}}
/* These are outside of any namespace to verify the macros fully qualify all
names */
namespace {
struct ShaderSubclassDraw: Magnum::GL::AbstractShaderProgram {
MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DRAW_IMPLEMENTATION(ShaderSubclassDraw)
};
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
struct ShaderSubclassDispatch: Magnum::GL::AbstractShaderProgram {
MAGNUM_GL_ABSTRACTSHADERPROGRAM_SUBCLASS_DISPATCH_IMPLEMENTATION(ShaderSubclassDispatch)
};
#endif
}
namespace Magnum { namespace GL { namespace Test { namespace {
void AbstractShaderProgramGLTest::subclassDraw() {
ShaderSubclassDraw shader;
Mesh mesh;
mesh
.setCount(0);
MeshView meshView{mesh};
meshView
.setCount(0);
Mesh meshNoInstances;
meshNoInstances
.setInstanceCount(0);
Mesh meshViewNoInstances;
meshViewNoInstances
.setInstanceCount(0);
#ifndef MAGNUM_TARGET_GLES
TransformFeedback xfb{NoCreate};
#endif
Containers::StridedArrayView1D<const UnsignedInt> counts;
#ifdef MAGNUM_TARGET_GLES
Containers::StridedArrayView1D<const UnsignedInt> instanceCounts;
#endif
Containers::StridedArrayView1D<const UnsignedInt> vertexOffsets;
Containers::StridedArrayView1D<const UnsignedInt> indexOffsets;
#ifndef CORRADE_TARGET_32BIT
Containers::StridedArrayView1D<const UnsignedLong> indexOffsetsLong;
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
Containers::StridedArrayView1D<const UnsignedInt> instanceOffsets;
#endif
/* These should all be a no-op because the mesh is empty and/or because we
specify no multidraw items. And if everything is alright, the returned
type should still be ShaderSubclassDraw& even after all these. */
ShaderSubclassDraw& out = shader
.draw(mesh)
.draw(std::move(mesh))
.draw(meshView)
.draw(std::move(meshView))
.draw(mesh, counts, vertexOffsets, indexOffsets)
#ifndef CORRADE_TARGET_32BIT
.draw(mesh, counts, vertexOffsets, indexOffsetsLong)
.draw(mesh, counts, vertexOffsets, nullptr)
#endif
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
.draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets, instanceOffsets)
#ifndef CORRADE_TARGET_32BIT
.draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsetsLong, instanceOffsets)
.draw(mesh, counts, instanceCounts, vertexOffsets, nullptr, instanceOffsets)
#endif
#endif
.draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsets)
#ifndef CORRADE_TARGET_32BIT
.draw(mesh, counts, instanceCounts, vertexOffsets, indexOffsetsLong)
.draw(mesh, counts, instanceCounts, vertexOffsets, nullptr)
#endif
#endif
.draw(Containers::arrayView<Containers::Reference<MeshView>>({}))
.draw(std::initializer_list<Containers::Reference<MeshView>>{})
#ifndef MAGNUM_TARGET_GLES
.drawTransformFeedback(meshNoInstances, xfb)
.drawTransformFeedback(meshNoInstances, xfb, 0)
.drawTransformFeedback(meshViewNoInstances, xfb)
.drawTransformFeedback(meshViewNoInstances, xfb, 0)
#endif
;
CORRADE_VERIFY(out.id());
MAGNUM_VERIFY_NO_GL_ERROR();
}
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void AbstractShaderProgramGLTest::subclassDispatch() {
ShaderSubclassDispatch shader;
/* These should all be a no-op because the count is empty. And if
everything is alright, the returned type should still be
ShaderSubclassDispatch& again. */
ShaderSubclassDispatch& out = shader.dispatchCompute({});
CORRADE_VERIFY(out.id());
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif
}}}}
CORRADE_TEST_MAIN(Magnum::GL::Test::AbstractShaderProgramGLTest)

Loading…
Cancel
Save