From 5ad98d41cafc0ce41dbf8745237133e8466ab544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 9 Jan 2014 01:34:17 +0100 Subject: [PATCH] Expose vertex attribute size as vector size + vector count. Makes it possible to properly compute offset when adding matrix attributes to mesh. The matrix-related test cases in Mesh test are now passing. The vector count is now enum value to make it more clear that that is compile-time constant independent of what was said in constructor. --- src/AbstractShaderProgram.h | 23 ++++-- src/Mesh.h | 12 +-- src/Test/AbstractShaderProgramTest.cpp | 102 ++++++++++++++++++------- 3 files changed, 98 insertions(+), 39 deletions(-) diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index edc16ea46..a345ac209 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -1166,7 +1166,14 @@ See @ref AbstractShaderProgram-subclassing for example usage in shaders and template class AbstractShaderProgram::Attribute { public: enum: UnsignedInt { - Location = location /**< Location to which the attribute is bound */ + Location = location, /**< Location to which the attribute is bound */ + + /** + * Count of vectors in this type + * + * @see @ref vectorSize() + */ + VectorCount = Implementation::Attribute::VectorCount }; /** @@ -1340,9 +1347,13 @@ template class AbstractShaderProgram::Attribute { /** @brief Type of passed data */ constexpr DataType dataType() const { return _dataType; } - /** @brief Size of passed data */ - std::size_t dataSize() const { - return Implementation::Attribute::size(GLint(_components)*Implementation::Attribute::vectorCount(), _dataType); + /** + * @brief Size of each vector in passed data + * + * @see @ref VectorCount + */ + UnsignedInt vectorSize() const { + return Implementation::Attribute::size(GLint(_components), _dataType); } /** @brief Data options */ @@ -1369,7 +1380,7 @@ template struct SizedAttribute; /* Vector attribute sizes */ template struct SizedVectorAttribute { - constexpr static std::size_t vectorCount() { return cols; } + enum: UnsignedInt { VectorCount = UnsignedInt(cols) }; }; template<> struct SizedAttribute<1, 1>: SizedVectorAttribute<1> { enum class Components: GLint { One = 1 }; @@ -1565,7 +1576,7 @@ template<> struct Attribute> { }; typedef Containers::EnumSet DataOptions; - constexpr static std::size_t vectorCount() { return 1; } + enum: UnsignedInt { VectorCount = 1 }; static std::size_t MAGNUM_EXPORT size(GLint components, DataType dataType); }; diff --git a/src/Mesh.h b/src/Mesh.h index f8c7fc9ba..ed7a78b9f 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -655,7 +655,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { /* Computing stride of interleaved vertex attributes */ template inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { - return attribute.dataSize() + strideOfInterleaved(attributes...); + return attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount + strideOfInterleaved(attributes...); } template inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { return gap + strideOfInterleaved(attributes...); @@ -667,7 +667,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { addVertexAttribute(buffer, attribute, offset, stride); /* Add size of this attribute to offset for next attribute */ - addVertexBufferInternal(buffer, offset+attribute.dataSize(), stride, attributes...); + addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount, stride, attributes...); } template inline void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { /* Add the gap to offset for next attribute */ @@ -676,14 +676,14 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { inline void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} template inline void addVertexAttribute(typename std::enable_if::Type, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { - for(UnsignedInt i = 0; i != Implementation::Attribute::vectorCount(); ++i) + for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) (this->*attributePointerImplementation)(Attribute{ &buffer, location+i, GLint(attribute.components()), GLenum(attribute.dataType()), bool(attribute.dataOptions() & AbstractShaderProgram::Attribute::DataOption::Normalized), - offset, + offset+i*attribute.vectorSize(), stride }); } @@ -702,13 +702,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #ifndef MAGNUM_TARGET_GLES template inline void addVertexAttribute(typename std::enable_if::Type, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { - for(UnsignedInt i = 0; i != Implementation::Attribute::vectorCount(); ++i) + for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) (this->*attributeLPointerImplementation)(LongAttribute{ &buffer, location+i, GLint(attribute.components()), GLenum(attribute.dataType()), - offset, + offset+i*attribute.vectorSize(), stride }); } diff --git a/src/Test/AbstractShaderProgramTest.cpp b/src/Test/AbstractShaderProgramTest.cpp index 20d77a1dd..4df6e4eb9 100644 --- a/src/Test/AbstractShaderProgramTest.cpp +++ b/src/Test/AbstractShaderProgramTest.cpp @@ -44,8 +44,12 @@ class AbstractShaderProgramTest: public TestSuite::Tester { void attributeVector4(); void attributeVectorBGRA(); - void attributeMatrix(); - void attributeMatrixDouble(); + void attributeMatrixNxN(); + #ifndef MAGNUM_TARGET_GLES2 + void attributeMatrixMxN(); + #endif + void attributeMatrixNxNd(); + void attributeMatrixMxNd(); }; AbstractShaderProgramTest::AbstractShaderProgramTest() { @@ -61,38 +65,44 @@ AbstractShaderProgramTest::AbstractShaderProgramTest() { &AbstractShaderProgramTest::attributeVector4, &AbstractShaderProgramTest::attributeVectorBGRA, - &AbstractShaderProgramTest::attributeMatrix, - &AbstractShaderProgramTest::attributeMatrixDouble}); + &AbstractShaderProgramTest::attributeMatrixNxN, + #ifndef MAGNUM_TARGET_GLES2 + &AbstractShaderProgramTest::attributeMatrixMxN, + #endif + &AbstractShaderProgramTest::attributeMatrixNxNd, + &AbstractShaderProgramTest::attributeMatrixMxNd}); } void AbstractShaderProgramTest::attributeScalar() { typedef AbstractShaderProgram::Attribute<3, Float> Attribute; CORRADE_COMPARE(Attribute::Location, 3); + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::One); CORRADE_VERIFY(!a.dataOptions()); - CORRADE_COMPARE(a.dataSize(), 4); + CORRADE_COMPARE(a.vectorSize(), 4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); /* Options */ Attribute b(Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized); - CORRADE_COMPARE(b.dataSize(), 2); + CORRADE_COMPARE(b.vectorSize(), 2); CORRADE_VERIFY(b.dataOptions() <= Attribute::DataOption::Normalized); } void AbstractShaderProgramTest::attributeScalarInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Int> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; - CORRADE_COMPARE(a.dataSize(), 4); + CORRADE_COMPARE(a.vectorSize(), 4); /* Options */ Attribute b(Attribute::DataType::Short); - CORRADE_COMPARE(b.dataSize(), 2); + CORRADE_COMPARE(b.vectorSize(), 2); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -101,14 +111,15 @@ void AbstractShaderProgramTest::attributeScalarInt() { void AbstractShaderProgramTest::attributeScalarUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, UnsignedInt> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; - CORRADE_COMPARE(a.dataSize(), 4); + CORRADE_COMPARE(a.vectorSize(), 4); /* Options */ Attribute b(Attribute::DataType::UnsignedByte); - CORRADE_COMPARE(b.dataSize(), 1); + CORRADE_COMPARE(b.vectorSize(), 1); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -117,10 +128,11 @@ void AbstractShaderProgramTest::attributeScalarUnsignedInt() { void AbstractShaderProgramTest::attributeScalarDouble() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Double> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; - CORRADE_COMPARE(a.dataSize(), 8); + CORRADE_COMPARE(a.vectorSize(), 8); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif @@ -128,38 +140,40 @@ void AbstractShaderProgramTest::attributeScalarDouble() { void AbstractShaderProgramTest::attributeVector() { typedef AbstractShaderProgram::Attribute<3, Vector3> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Three); - CORRADE_COMPARE(a.dataSize(), 3*4); + CORRADE_COMPARE(a.vectorSize(), 3*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); /* Options */ #ifndef MAGNUM_TARGET_GLES Attribute b(Attribute::Components::Two, Attribute::DataType::Double); CORRADE_COMPARE(b.components(), Attribute::Components::Two); - CORRADE_COMPARE(b.dataSize(), 2*8); + CORRADE_COMPARE(b.vectorSize(), 2*8); #else Attribute b(Attribute::Components::Two, Attribute::DataType::Float); CORRADE_COMPARE(b.components(), Attribute::Components::Two); - CORRADE_COMPARE(b.dataSize(), 2*4); + CORRADE_COMPARE(b.vectorSize(), 2*4); #endif } void AbstractShaderProgramTest::attributeVectorInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Vector2i> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Two); - CORRADE_COMPARE(a.dataSize(), 2*4); + CORRADE_COMPARE(a.vectorSize(), 2*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Int); /* Options */ Attribute b(Attribute::Components::One, Attribute::DataType::Int); - CORRADE_COMPARE(b.dataSize(), 4); + CORRADE_COMPARE(b.vectorSize(), 4); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -168,16 +182,17 @@ void AbstractShaderProgramTest::attributeVectorInt() { void AbstractShaderProgramTest::attributeVectorUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef AbstractShaderProgram::Attribute<3, Vector4ui> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Four); - CORRADE_COMPARE(a.dataSize(), 4*4); + CORRADE_COMPARE(a.vectorSize(), 4*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::UnsignedInt); /* Options */ Attribute b(Attribute::Components::Three, Attribute::DataType::UnsignedShort); - CORRADE_COMPARE(b.dataSize(), 3*2); + CORRADE_COMPARE(b.vectorSize(), 3*2); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -186,16 +201,17 @@ void AbstractShaderProgramTest::attributeVectorUnsignedInt() { void AbstractShaderProgramTest::attributeVectorDouble() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Vector2d> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Two); - CORRADE_COMPARE(a.dataSize(), 2*8); + CORRADE_COMPARE(a.vectorSize(), 2*8); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); /* Options */ Attribute b(Attribute::Components::One); - CORRADE_COMPARE(b.dataSize(), 8); + CORRADE_COMPARE(b.vectorSize(), 8); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif @@ -203,47 +219,79 @@ void AbstractShaderProgramTest::attributeVectorDouble() { void AbstractShaderProgramTest::attributeVector4() { typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* Custom type */ #ifndef MAGNUM_TARGET_GLES Attribute a(Attribute::DataType::UnsignedInt2101010Rev); - CORRADE_COMPARE(a.dataSize(), 4); + CORRADE_COMPARE(a.vectorSize(), 4); #else Attribute a(Attribute::DataType::HalfFloat); - CORRADE_COMPARE(a.dataSize(), 8); + CORRADE_COMPARE(a.vectorSize(), 8); #endif } void AbstractShaderProgramTest::attributeVectorBGRA() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Vector4> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 1); /* BGRA */ Attribute a(Attribute::Components::BGRA); - CORRADE_COMPARE(a.dataSize(), 4*4); + CORRADE_COMPARE(a.vectorSize(), 4*4); #else CORRADE_SKIP("BGRA attribute component ordering is not available in OpenGL ES."); #endif } -void AbstractShaderProgramTest::attributeMatrix() { +void AbstractShaderProgramTest::attributeMatrixNxN() { typedef AbstractShaderProgram::Attribute<3, Matrix3> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 3); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Three); - CORRADE_COMPARE(a.dataSize(), 3*3*4); + CORRADE_COMPARE(a.vectorSize(), 3*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); } -void AbstractShaderProgramTest::attributeMatrixDouble() { +#ifndef MAGNUM_TARGET_GLES2 +void AbstractShaderProgramTest::attributeMatrixMxN() { + typedef AbstractShaderProgram::Attribute<3, Matrix3x4> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 3); + + /* Default constructor */ + Attribute a; + CORRADE_COMPARE(a.components(), Attribute::Components::Four); + CORRADE_COMPARE(a.vectorSize(), 4*4); + CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); +} +#endif + +void AbstractShaderProgramTest::attributeMatrixNxNd() { #ifndef MAGNUM_TARGET_GLES typedef AbstractShaderProgram::Attribute<3, Matrix4d> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 4); /* Default constructor */ Attribute a; CORRADE_COMPARE(a.components(), Attribute::Components::Four); - CORRADE_COMPARE(a.dataSize(), 4*4*8); + CORRADE_COMPARE(a.vectorSize(), 4*8); + CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); + #else + CORRADE_SKIP("Double attributes are not available in OpenGL ES."); + #endif +} + +void AbstractShaderProgramTest::attributeMatrixMxNd() { + #ifndef MAGNUM_TARGET_GLES + typedef AbstractShaderProgram::Attribute<3, Matrix4x2d> Attribute; + CORRADE_COMPARE(Attribute::VectorCount, 4); + + /* Default constructor */ + Attribute a; + CORRADE_COMPARE(a.components(), Attribute::Components::Two); + CORRADE_COMPARE(a.vectorSize(), 2*8); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES.");