Browse Source

Ability to specify shader attribute properties fully at runtime.

There's a new DynamicAttribute class that is very similar to Attribute,
but it has the location and base type as runtime properties instead of
them being a part of template. This allows for more flexibility, but
OTOH also more typing and more responsibility on the user. See
MeshGLTest for details and usage comparison to the Attribute API.
pull/217/head
Vladimír Vondruš 9 years ago
parent
commit
f1982f2e1b
  1. 193
      src/Magnum/Attribute.h
  2. 31
      src/Magnum/Mesh.cpp
  3. 63
      src/Magnum/Mesh.h
  4. 516
      src/Magnum/Test/MeshGLTest.cpp

193
src/Magnum/Attribute.h

@ -101,6 +101,7 @@ template<UnsignedInt location, class T> class Attribute {
* Count of components passed to the shader. If passing smaller count * Count of components passed to the shader. If passing smaller count
* of components than corresponding type has, unspecified components * of components than corresponding type has, unspecified components
* are set to default values (second and third to `0`, fourth to `1`). * are set to default values (second and third to `0`, fourth to `1`).
* @see @ref Attribute()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
enum class Components: GLint { enum class Components: GLint {
@ -307,6 +308,198 @@ template<class T> Debug& operator<<(Debug& debug, Attribute<T>::Components);
template<class T> Debug& operator<<(Debug& debug, Attribute<T>::DataType); template<class T> Debug& operator<<(Debug& debug, Attribute<T>::DataType);
#endif #endif
/**
@brief Base class for dynamic attribute location and type
Counterpart to @ref Attribute that allows runtime specification of attribute
location and base type. Note that unlike the compile-time specification, this
class doesn't do any sanity verification and leaves most of the responsibility
on the user.
*/
class DynamicAttribute {
public:
/**
* @brief Attribute kind
*
* Specifies what kind of shader type matches the attribute.
* @see @ref DynamicAttribute()
*/
enum class Kind {
/** Generic, matches single-precision floating-point shader type */
Generic,
/**
* Normalized integral, matches single-precision floating-point
* shader type
*/
GenericNormalized,
#ifndef MAGNUM_TARGET_GLES2
/** Integral, matches integral shader type */
Integral,
#ifndef MAGNUM_TARGET_GLES
/** Long, matches double-precision shader type */
Long
#endif
#endif
};
/**
* @brief Component count
*
* Count of components passed to the shader. If passing smaller count
* of components than corresponding type has, unspecified components
* are set to default values (second and third to `0`, fourth to `1`).
* @see @ref DynamicAttribute()
*/
enum class Components: GLint {
/**
* Only first component is specified. Second, third and fourth
* component are set to `0`, `0`, `1`, respectively. Only for
* scalar and vector types, not matrices.
*/
One = 1,
/**
* First two components are specified. Third and fourth component
* are set to `0`, `1`, respectively. Only for two, three and
* four-component vector types and 2x2, 3x2 and 4x2 matrix types.
*/
Two = 2,
/**
* First three components are specified. Fourth component is set to
* `1`. Only for three and four-component vector types, 2x3, 3x3
* and 4x3 matrix types.
*/
Three = 3,
/**
* All four components are specified. Only for four-component
* vector types and 2x4, 3x4 and 4x4 matrix types.
*/
Four = 4,
#ifndef MAGNUM_TARGET_GLES
/**
* Four components with BGRA ordering. Only for four-component
* float vector type. Must be used along with @ref DataType::UnsignedByte
* and @ref Kind::GenericNormalized.
* @requires_gl32 Extension @extension{ARB,vertex_array_bgra}
* @requires_gl Only RGBA component ordering is supported in OpenGL
* ES and WebGL.
*/
BGRA = GL_BGRA
#endif
};
/**
* @brief Data type
*
* Type of data passed to shader.
* @see @ref Kind, @ref DynamicAttribute()
*/
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE, /**< Unsigned byte */
Byte = GL_BYTE, /**< Byte */
UnsignedShort = GL_UNSIGNED_SHORT, /**< Unsigned short */
Short = GL_SHORT, /**< Short */
UnsignedInt = GL_UNSIGNED_INT, /**< Unsigned int */
Int = GL_INT, /**< Int */
#ifndef MAGNUM_TARGET_WEBGL
/**
* Half float. Only for float attribute types.
* @requires_gl30 Extension @extension{ARB,half_float_vertex}
* @requires_gles30 Extension @extension{OES,vertex_half_float}
* in OpenGL ES 2.0
* @requires_webgl20 Half float vertex attributes are not available
* in WebGL 1.0.
*/
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
#endif
/** Float. Only for float attribute types. */
Float = GL_FLOAT,
#ifndef MAGNUM_TARGET_GLES
/**
* Double. Only for float and double attribute types.
* @requires_gl Only floats are available in OpenGL ES or WebGL.
*/
Double = GL_DOUBLE,
/**
* Unsigned 10.11.11 packed float. Only for three-component float
* vector attribute type.
* @requires_gl44 Extension @extension{ARB,vertex_type_10f_11f_11f_rev}
* @requires_gl Packed float attributes are not available in OpenGL
* ES or WebGL.
*/
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV,
#endif
/* GL_FIXED not supported */
#ifndef MAGNUM_TARGET_GLES2
/**
* Unsigned 2.10.10.10 packed integer. Only for four-component
* float vector attribute type.
* @todo How about (incompatible) @extension{OES,vertex_type_10_10_10_2}?
* @requires_gl33 Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0.
* @requires_webgl20 Packed attributes are not available in WebGL
* 1.0.
*/
UnsignedInt2101010Rev = GL_UNSIGNED_INT_2_10_10_10_REV,
/**
* Signed 2.10.10.10 packed integer. Only for four-component float
* vector attribute type.
* @requires_gl33 Extension @extension{ARB,vertex_type_2_10_10_10_rev}
* @requires_gles30 Packed attributes are not available in OpenGL
* ES 2.0.
* @requires_webgl20 Packed attributes are not available in WebGL
* 1.0.
*/
Int2101010Rev = GL_INT_2_10_10_10_REV
#endif
};
/**
* @brief Constructor
* @param kind Attribute kind
* @param location Attribute location
* @param components Component count
* @param dataType Type of passed data
*/
constexpr DynamicAttribute(Kind kind, UnsignedInt location, Components components, DataType dataType): _kind{kind}, _location{location}, _components{components}, _dataType{dataType} {}
/** @brief Attribute kind */
constexpr Kind kind() const { return _kind; }
/** @brief Attribute location */
constexpr UnsignedInt location() const { return _location; }
/** @brief Component count of passed data */
constexpr Components components() const { return _components; }
/** @brief Type of passed data */
constexpr DataType dataType() const { return _dataType; }
private:
Kind _kind;
UnsignedInt _location;
Components _components;
DataType _dataType;
};
namespace Implementation { namespace Implementation {
/* Base for sized attributes */ /* Base for sized attributes */

31
src/Magnum/Mesh.cpp

@ -45,7 +45,7 @@
namespace Magnum { namespace Magnum {
struct Mesh::AttributeLayout { struct Mesh::AttributeLayout {
explicit AttributeLayout(const Buffer& buffer, GLuint location, GLint size, GLenum type, AttributeKind kind, GLintptr offset, GLsizei stride, GLuint divisor) noexcept: buffer{Buffer::wrap(buffer.id())}, location{location}, size{size}, type{type}, kind{kind}, offset{offset}, stride{stride}, divisor{divisor} {} explicit AttributeLayout(const Buffer& buffer, GLuint location, GLint size, GLenum type, DynamicAttribute::Kind kind, GLintptr offset, GLsizei stride, GLuint divisor) noexcept: buffer{Buffer::wrap(buffer.id())}, location{location}, size{size}, type{type}, kind{kind}, offset{offset}, stride{stride}, divisor{divisor} {}
explicit AttributeLayout(const AttributeLayout& other): buffer{Buffer::wrap(other.buffer.id())}, location{other.location}, size{other.size}, type{other.type}, kind{other.kind}, offset{other.offset}, stride{other.stride}, divisor{other.divisor} {} explicit AttributeLayout(const AttributeLayout& other): buffer{Buffer::wrap(other.buffer.id())}, location{other.location}, size{other.size}, type{other.type}, kind{other.kind}, offset{other.offset}, stride{other.stride}, divisor{other.divisor} {}
@ -53,7 +53,7 @@ struct Mesh::AttributeLayout {
GLuint location; GLuint location;
GLint size; GLint size;
GLenum type; GLenum type;
AttributeKind kind; DynamicAttribute::Kind kind;
GLintptr offset; GLintptr offset;
GLsizei stride; GLsizei stride;
GLuint divisor; GLuint divisor;
@ -227,6 +227,19 @@ Mesh& Mesh::setLabelInternal(const Containers::ArrayView<const char> label) {
} }
#endif #endif
Mesh& Mesh::addVertexBufferInstanced(Buffer& buffer, const UnsignedInt divisor, const GLintptr offset, const GLsizei stride, const DynamicAttribute& attribute) {
AttributeLayout l{buffer,
attribute.location(),
GLint(attribute.components()),
GLenum(attribute.dataType()),
attribute.kind(),
offset,
stride,
divisor};
attributePointerInternal(l);
return *this;
}
Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) { Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) {
#if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL)
CORRADE_ASSERT(buffer.targetHint() == Buffer::TargetHint::ElementArray, CORRADE_ASSERT(buffer.targetHint() == Buffer::TargetHint::ElementArray,
@ -455,7 +468,7 @@ void Mesh::destroyImplementationVAO() {
#endif #endif
} }
void Mesh::attributePointerInternal(const Buffer& buffer, const GLuint location, const GLint size, const GLenum type, const AttributeKind kind, const GLintptr offset, const GLsizei stride, const GLuint divisor) { void Mesh::attributePointerInternal(const Buffer& buffer, const GLuint location, const GLint size, const GLenum type, const DynamicAttribute::Kind kind, const GLintptr offset, const GLsizei stride, const GLuint divisor) {
AttributeLayout l{buffer, location, size, type, kind, offset, stride, divisor}; AttributeLayout l{buffer, location, size, type, kind, offset, stride, divisor};
attributePointerInternal(l); attributePointerInternal(l);
} }
@ -489,16 +502,16 @@ void Mesh::attributePointerImplementationDSAEXT(AttributeLayout& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location); glEnableVertexArrayAttribEXT(_id, attribute.location);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(attribute.kind == AttributeKind::Integral) if(attribute.kind == DynamicAttribute::Kind::Integral)
glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
else if(attribute.kind == AttributeKind::Long) else if(attribute.kind == DynamicAttribute::Kind::Long)
glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
#endif #endif
else else
#endif #endif
{ {
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.kind == AttributeKind::GenericNormalized, attribute.stride, attribute.offset); glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer.id(), attribute.location, attribute.size, attribute.type, attribute.kind == DynamicAttribute::Kind::GenericNormalized, attribute.stride, attribute.offset);
} }
if(attribute.divisor) if(attribute.divisor)
@ -511,16 +524,16 @@ void Mesh::vertexAttribPointer(AttributeLayout& attribute) {
attribute.buffer.bindInternal(Buffer::TargetHint::Array); attribute.buffer.bindInternal(Buffer::TargetHint::Array);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(attribute.kind == AttributeKind::Integral) if(attribute.kind == DynamicAttribute::Kind::Integral)
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
else if(attribute.kind == AttributeKind::Long) else if(attribute.kind == DynamicAttribute::Kind::Long)
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
#endif #endif
else else
#endif #endif
{ {
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.kind == AttributeKind::GenericNormalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset)); glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.kind == DynamicAttribute::Kind::GenericNormalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
} }
if(attribute.divisor) { if(attribute.divisor) {

63
src/Magnum/Mesh.h

@ -308,6 +308,24 @@ mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color{
MyShader::Color::DataOption::Normalized}); MyShader::Color::DataOption::Normalized});
@endcode @endcode
@anchor Mesh-configuration-dynamic
#### Dynamically specified attributes
In some cases, for example when the shader code is fully generated at runtime,
it's not possible to know attribute locations and types at compile time. In
that case, there are overloads of @ref addVertexBuffer() and
@ref addVertexBufferInstanced() that take @ref DynamicAttribute instead of
@ref Attribute typedefs. Adding a RGB attribute at location 3 normalized from
unsigned byte to float with one byte padding at the end could then look like
this:
@code
mesh.addVertexBuffer(colorBuffer, 0, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 3,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedByte});
});
@endcode
## Rendering meshes ## Rendering meshes
Basic workflow is: bind specific framebuffer for drawing (if needed), set up Basic workflow is: bind specific framebuffer for drawing (if needed), set up
@ -794,6 +812,32 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
return *this; return *this;
} }
/**
* @brief Add buffer with dynamic vertex attributes for use with given shader
* @return Reference to self (for method chaining)
*
* Equivalent to @ref addVertexBuffer(Buffer&, GLintptr, const T&...)
* but with the possibility to fully specify the attribute properties
* at runtime, including base type and location. See
* @ref Mesh-configuration-dynamic "class documentation" for usage
* example.
*/
Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute) {
return addVertexBufferInstanced(buffer, 0, offset, stride, attribute);
}
/**
* @brief Add buffer with dynamic vertex attributes for use with given shader
* @return Reference to self (for method chaining)
*
* Equivalent to @ref addVertexBufferInstanced(Buffer&, UnsignedInt, GLintptr, const T&...)
* but with the possibility to fully specify the attribute properties
* at runtime, including base type and location. See
* @ref Mesh-configuration-dynamic "class documentation" for usage
* example.
*/
Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute);
/** /**
* @brief Set index buffer * @brief Set index buffer
* @param buffer Index buffer * @param buffer Index buffer
@ -922,17 +966,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
private: private:
enum class AttributeKind {
Generic,
GenericNormalized,
#ifndef MAGNUM_TARGET_GLES2
Integral,
#ifndef MAGNUM_TARGET_GLES
Long
#endif
#endif
};
struct MAGNUM_LOCAL AttributeLayout; struct MAGNUM_LOCAL AttributeLayout;
explicit Mesh(GLuint id, MeshPrimitive primitive, ObjectFlags flags); explicit Mesh(GLuint id, MeshPrimitive primitive, ObjectFlags flags);
@ -971,7 +1004,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location+i, location+i,
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
attribute.dataOptions() & Attribute<location, T>::DataOption::Normalized ? AttributeKind::GenericNormalized : AttributeKind::Generic, attribute.dataOptions() & Attribute<location, T>::DataOption::Normalized ? DynamicAttribute::Kind::GenericNormalized : DynamicAttribute::Kind::Generic,
GLintptr(offset+i*attribute.vectorSize()), GLintptr(offset+i*attribute.vectorSize()),
stride, stride,
divisor); divisor);
@ -983,7 +1016,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location, location,
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
AttributeKind::Integral, DynamicAttribute::Kind::Integral,
offset, offset,
stride, stride,
divisor); divisor);
@ -996,7 +1029,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
location+i, location+i,
GLint(attribute.components()), GLint(attribute.components()),
GLenum(attribute.dataType()), GLenum(attribute.dataType()),
AttributeKind::Long, DynamicAttribute::Kind::Long,
GLintptr(offset+i*attribute.vectorSize()), GLintptr(offset+i*attribute.vectorSize()),
stride, stride,
divisor); divisor);
@ -1027,7 +1060,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationDefault();
void MAGNUM_LOCAL destroyImplementationVAO(); void MAGNUM_LOCAL destroyImplementationVAO();
void attributePointerInternal(const Buffer& buffer, GLuint location, GLint size, GLenum type, AttributeKind kind, GLintptr offset, GLsizei stride, GLuint divisor); void attributePointerInternal(const Buffer& buffer, GLuint location, GLint size, GLenum type, DynamicAttribute::Kind kind, GLintptr offset, GLsizei stride, GLuint divisor);
void MAGNUM_LOCAL attributePointerInternal(AttributeLayout& attribute); void MAGNUM_LOCAL attributePointerInternal(AttributeLayout& attribute);
void MAGNUM_LOCAL attributePointerImplementationDefault(AttributeLayout& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(AttributeLayout& attribute);
void MAGNUM_LOCAL attributePointerImplementationVAO(AttributeLayout& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(AttributeLayout& attribute);

516
src/Magnum/Test/MeshGLTest.cpp

@ -147,58 +147,61 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::constructMove, &MeshGLTest::constructMove,
&MeshGLTest::wrap, &MeshGLTest::wrap,
&MeshGLTest::label, &MeshGLTest::label});
#ifndef MAGNUM_TARGET_GLES2 /* First instance is always using Attribute, second DynamicAttribute */
&MeshGLTest::addVertexBufferUnsignedInt, addInstancedTests({
&MeshGLTest::addVertexBufferInt, #ifndef MAGNUM_TARGET_GLES2
#endif &MeshGLTest::addVertexBufferUnsignedInt,
&MeshGLTest::addVertexBufferFloat, &MeshGLTest::addVertexBufferInt,
#ifndef MAGNUM_TARGET_GLES #endif
&MeshGLTest::addVertexBufferDouble, &MeshGLTest::addVertexBufferFloat,
#endif #ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 &MeshGLTest::addVertexBufferDouble,
&MeshGLTest::addVertexBufferVectorNui, #endif
&MeshGLTest::addVertexBufferVectorNi, #ifndef MAGNUM_TARGET_GLES2
#endif &MeshGLTest::addVertexBufferVectorNui,
&MeshGLTest::addVertexBufferVectorN, &MeshGLTest::addVertexBufferVectorNi,
#ifndef MAGNUM_TARGET_GLES #endif
&MeshGLTest::addVertexBufferVectorNd, &MeshGLTest::addVertexBufferVectorN,
#endif #ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixNxN, &MeshGLTest::addVertexBufferVectorNd,
#ifndef MAGNUM_TARGET_GLES #endif
&MeshGLTest::addVertexBufferMatrixNxNd, &MeshGLTest::addVertexBufferMatrixNxN,
#endif #ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 &MeshGLTest::addVertexBufferMatrixNxNd,
&MeshGLTest::addVertexBufferMatrixMxN, #endif
#endif #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_GLES &MeshGLTest::addVertexBufferMatrixMxN,
&MeshGLTest::addVertexBufferMatrixMxNd, #endif
#endif #ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferMatrixMxNd,
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort, &MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort,
&MeshGLTest::addVertexBufferUnsignedIntWithShort, &MeshGLTest::addVertexBufferUnsignedIntWithShort,
&MeshGLTest::addVertexBufferIntWithUnsignedShort, &MeshGLTest::addVertexBufferIntWithUnsignedShort,
&MeshGLTest::addVertexBufferIntWithShort, &MeshGLTest::addVertexBufferIntWithShort,
#endif #endif
&MeshGLTest::addVertexBufferFloatWithHalfFloat, &MeshGLTest::addVertexBufferFloatWithHalfFloat,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferFloatWithDouble, &MeshGLTest::addVertexBufferFloatWithDouble,
&MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev, &MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev,
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev, &MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev,
&MeshGLTest::addVertexBufferVector4WithInt2101010Rev, &MeshGLTest::addVertexBufferVector4WithInt2101010Rev,
#endif #endif
&MeshGLTest::addVertexBufferLessVectorComponents, &MeshGLTest::addVertexBufferLessVectorComponents,
&MeshGLTest::addVertexBufferNormalized, &MeshGLTest::addVertexBufferNormalized,
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferBGRA, &MeshGLTest::addVertexBufferBGRA
#endif #endif
}, 2);
&MeshGLTest::addVertexBufferMultiple, addTests({&MeshGLTest::addVertexBufferMultiple,
&MeshGLTest::addVertexBufferMultipleGaps, &MeshGLTest::addVertexBufferMultipleGaps,
&MeshGLTest::setIndexBuffer, &MeshGLTest::setIndexBuffer,
@ -545,15 +548,23 @@ void MeshGLTest::addVertexBufferUnsignedInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = { 0, 157, 35681 }; constexpr UnsignedInt data[] = { 0, 157, 35681 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, UnsignedInt>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedInt});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -570,15 +581,23 @@ void MeshGLTest::addVertexBufferInt() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Int> Attribute;
constexpr Int data[] = { 0, 457931, 27530 }; constexpr Int data[] = { 0, 457931, 27530 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Int>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Int});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -591,15 +610,23 @@ void MeshGLTest::addVertexBufferInt() {
#endif #endif
void MeshGLTest::addVertexBufferFloat() { void MeshGLTest::addVertexBufferFloat() {
typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::unpack<Float, UnsignedByte>(96) }; const Float data[] = { 0.0f, -0.7f, Math::unpack<Float, UnsignedByte>(96) };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Float>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -620,15 +647,23 @@ void MeshGLTest::addVertexBufferDouble() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Double> Attribute;
const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedShort>(45828) }; const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedShort>(45828) };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 8, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 8, Attribute<0, Double>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 8, 8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -647,15 +682,23 @@ void MeshGLTest::addVertexBufferVectorNui() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector3ui> Attribute;
constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} }; constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector3ui>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedInt});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -672,15 +715,23 @@ void MeshGLTest::addVertexBufferVectorNi() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector2i> Attribute;
constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} }; constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2*4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2*4, Attribute<0, Vector2i>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 2*4, 2*4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::Two,
DynamicAttribute::DataType::Int});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -693,15 +744,23 @@ void MeshGLTest::addVertexBufferVectorNi() {
#endif #endif
void MeshGLTest::addVertexBufferVectorN() { void MeshGLTest::addVertexBufferVectorN() {
typedef Attribute<0, Vector3> Attribute;
const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::unpack<Vector3>(Color3ub(96, 24, 156)) }; const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::unpack<Vector3>(Color3ub(96, 24, 156)) };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector3>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -722,8 +781,6 @@ void MeshGLTest::addVertexBufferVectorNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Vector4d> Attribute;
const Vector4d data[] = { const Vector4d data[] = {
{}, {0.0, -0.9, 1.0, 1.25}, {}, {0.0, -0.9, 1.0, 1.25},
Math::unpack<Vector4d>(Math::Vector4<UnsignedShort>(315, 65201, 2576, 12)) Math::unpack<Vector4d>(Math::Vector4<UnsignedShort>(315, 65201, 2576, 12))
@ -732,8 +789,18 @@ void MeshGLTest::addVertexBufferVectorNd() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4*8, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4*8, Attribute<0, Vector4d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4*8, 4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -746,8 +813,6 @@ void MeshGLTest::addVertexBufferVectorNd() {
#endif #endif
void MeshGLTest::addVertexBufferMatrixNxN() { void MeshGLTest::addVertexBufferMatrixNxN() {
typedef Attribute<0, Matrix3x3> Attribute;
const Matrix3x3 data[] = { const Matrix3x3 data[] = {
{}, {},
Matrix3x3::fromDiagonal({0.0f, -0.9f, 1.0f}), Matrix3x3::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -757,8 +822,26 @@ void MeshGLTest::addVertexBufferMatrixNxN() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*3*4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*3*4, Attribute<0, Matrix3x3>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*3*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*3*4 + 3*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 1,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*3*4 + 6*4, 3*3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 2,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -775,8 +858,6 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Matrix3x3d> Attribute;
const Matrix3x3d data[] = { const Matrix3x3d data[] = {
{}, {},
Matrix3x3d::fromDiagonal({0.0, -0.9, 1.0}), Matrix3x3d::fromDiagonal({0.0, -0.9, 1.0}),
@ -786,8 +867,26 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*3*8, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*3*8, Attribute<0, Matrix3x3d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*3*8, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*3*8 + 3*8, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 1,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*3*8 + 6*4, 3*3*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 2,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -811,8 +910,6 @@ void MeshGLTest::addVertexBufferMatrixNxNd() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::addVertexBufferMatrixMxN() { void MeshGLTest::addVertexBufferMatrixMxN() {
typedef Attribute<0, Matrix3x4> Attribute;
const Matrix3x4 data[] = { const Matrix3x4 data[] = {
{}, {},
Matrix3x4::fromDiagonal({0.0f, -0.9f, 1.0f}), Matrix3x4::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -822,8 +919,26 @@ void MeshGLTest::addVertexBufferMatrixMxN() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*4*4, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4*4, Attribute<0, Matrix3x4>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*4*4 + 4*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 1,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float})
.addVertexBuffer(buffer, 3*4*4 + 8*4, 3*4*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 2,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -841,8 +956,6 @@ void MeshGLTest::addVertexBufferMatrixMxNd() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>()) if(!Context::current().isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef Attribute<0, Matrix3x4d> Attribute;
const Matrix3x4d data[] = { const Matrix3x4d data[] = {
{}, {},
Matrix3x4d::fromDiagonal({0.0f, -0.9f, 1.0f}), Matrix3x4d::fromDiagonal({0.0f, -0.9f, 1.0f}),
@ -852,8 +965,26 @@ void MeshGLTest::addVertexBufferMatrixMxNd() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*4*8, Attribute());
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4*8, Attribute<0, Matrix3x4d>{});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*4*8 + 4*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 1,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double})
.addVertexBuffer(buffer, 3*4*8 + 8*8, 3*4*8, DynamicAttribute{
DynamicAttribute::Kind::Long, 2,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -882,15 +1013,23 @@ void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 }; constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::UnsignedShort));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, UnsignedInt>{Attribute<0, UnsignedInt>::DataType::UnsignedShort});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedShort});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -907,15 +1046,23 @@ void MeshGLTest::addVertexBufferUnsignedIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, UnsignedInt> Attribute;
constexpr Short data[] = { 0, 24563, 2128, 3821, 16583 }; constexpr Short data[] = { 0, 24563, 2128, 3821, 16583 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::Short));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, UnsignedInt>{Attribute<0, UnsignedInt>::DataType::Short});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Short});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -932,15 +1079,23 @@ void MeshGLTest::addVertexBufferIntWithUnsignedShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Int> Attribute;
constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 }; constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::UnsignedShort));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, Int>{Attribute<0, Int>::DataType::UnsignedShort});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::UnsignedShort});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -957,15 +1112,23 @@ void MeshGLTest::addVertexBufferIntWithShort() {
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Int> Attribute;
constexpr Short data[] = { 0, 24563, 2128, 3821, -16583 }; constexpr Short data[] = { 0, 24563, 2128, 3821, -16583 };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2, 2, Attribute(Attribute::DataType::Short));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, 2, Attribute<0, Int>{Attribute<0, Int>::DataType::Short});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Integral, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Short});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -988,15 +1151,23 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
using namespace Math::Literals; using namespace Math::Literals;
typedef Attribute<0, Float> Attribute;
const Half data[] = { 0.0_h, -0.7_h, Half(Math::unpack<Float, UnsignedByte>(186)) }; const Half data[] = { 0.0_h, -0.7_h, Half(Math::unpack<Float, UnsignedByte>(186)) };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::HalfFloat));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 2, Attribute<0, Float>{Attribute<0, Float>::DataType::HalfFloat});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 2, 2, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::HalfFloat});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -1009,15 +1180,24 @@ void MeshGLTest::addVertexBufferFloatWithHalfFloat() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
void MeshGLTest::addVertexBufferFloatWithDouble() { void MeshGLTest::addVertexBufferFloatWithDouble() {
typedef Attribute<0, Float> Attribute;
const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedByte>(186) }; const Double data[] = { 0.0, -0.7, Math::unpack<Double, UnsignedByte>(186) };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1)
.addVertexBuffer(buffer, 8, Attribute(Attribute::DataType::Double)); .addVertexBuffer(buffer, 8, Attribute<0, Float>(Attribute<0, Float>::DataType::Double));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 8, Attribute<0, Float>{Attribute<0, Float>::DataType::Double});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 8, 8, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::One,
DynamicAttribute::DataType::Double});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -1034,14 +1214,22 @@ void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector3> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt10f11f11fRev));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector3>{Attribute<0, Vector3>::DataType::UnsignedInt10f11f11fRev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedInt10f11f11fRev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */ /* Won't test the actual values */
@ -1055,14 +1243,22 @@ void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector4> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt2101010Rev));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector4>{Attribute<0, Vector4>::DataType::UnsignedInt2101010Rev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::UnsignedInt2101010Rev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */ /* Won't test the actual values */
@ -1074,14 +1270,22 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector4> Attribute;
Buffer buffer; Buffer buffer;
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); buffer.setData({nullptr, 12}, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::Int2101010Rev));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 4, Attribute<0, Vector4>{Attribute<0, Vector4>::DataType::Int2101010Rev});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Four,
DynamicAttribute::DataType::Int2101010Rev});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
/* Won't test the actual values */ /* Won't test the actual values */
@ -1089,8 +1293,6 @@ void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() {
#endif #endif
void MeshGLTest::addVertexBufferLessVectorComponents() { void MeshGLTest::addVertexBufferLessVectorComponents() {
typedef Attribute<0, Vector4> Attribute;
const Vector3 data[] = { const Vector3 data[] = {
{}, {0.0f, -0.9f, 1.0f}, {}, {0.0f, -0.9f, 1.0f},
Math::unpack<Vector3>(Color3ub(96, 24, 156)) Math::unpack<Vector3>(Color3ub(96, 24, 156))
@ -1099,8 +1301,18 @@ void MeshGLTest::addVertexBufferLessVectorComponents() {
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 3*4, Attribute(Attribute::Components::Three));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
mesh.addVertexBuffer(buffer, 3*4, Attribute<0, Vector4>{Attribute<0, Vector4>::Components::Three});
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 3*4, 3*4, DynamicAttribute{
DynamicAttribute::Kind::Generic, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::Float});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -1117,15 +1329,24 @@ void MeshGLTest::addVertexBufferLessVectorComponents() {
} }
void MeshGLTest::addVertexBufferNormalized() { void MeshGLTest::addVertexBufferNormalized() {
typedef Attribute<0, Vector3> Attribute;
constexpr Color4ub data[] = { {}, {0, 128, 64}, {32, 156, 228} }; constexpr Color4ub data[] = { {}, {0, 128, 64}, {32, 156, 228} };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized), 1);
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
typedef Attribute<0, Vector3> Attribute;
mesh.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized), 1);
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 0,
DynamicAttribute::Components::Three,
DynamicAttribute::DataType::UnsignedByte});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();
@ -1148,15 +1369,24 @@ void MeshGLTest::addVertexBufferBGRA() {
CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available.")); CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available."));
#endif #endif
typedef Attribute<0, Vector4> Attribute;
constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} }; constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} };
Buffer buffer; Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw); buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh; Mesh mesh;
mesh.setBaseVertex(1) mesh.setBaseVertex(1);
.addVertexBuffer(buffer, 4, Attribute(Attribute::Components::BGRA, Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized));
if(testCaseInstanceId() == 0) {
setTestCaseDescription("Attribute");
typedef Attribute<0, Vector4> Attribute;
mesh.addVertexBuffer(buffer, 4, Attribute(Attribute::Components::BGRA, Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized));
} else if(testCaseInstanceId() == 1) {
setTestCaseDescription("DynamicAttribute");
mesh.addVertexBuffer(buffer, 4, 4, DynamicAttribute{
DynamicAttribute::Kind::GenericNormalized, 0,
DynamicAttribute::Components::BGRA,
DynamicAttribute::DataType::UnsignedByte});
} else CORRADE_ASSERT_UNREACHABLE();
MAGNUM_VERIFY_NO_ERROR(); MAGNUM_VERIFY_NO_ERROR();

Loading…
Cancel
Save