From 7ca7e5a62b6556e553dc8fefaf9fbb2c3d5e8dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 30 Sep 2024 14:00:59 +0200 Subject: [PATCH] GL: pin down constexpr [Dynamic]Attribute constructors. Some of them were marked as constexpr even though they were calling into a deinlined function internally. Making sure the default construction is constexpr at least, and testing that all constexpr functions actually behave like that. --- src/Magnum/GL/Attribute.h | 33 ++- src/Magnum/GL/Test/AttributeTest.cpp | 420 ++++++++++++++++++++++++--- 2 files changed, 403 insertions(+), 50 deletions(-) diff --git a/src/Magnum/GL/Attribute.h b/src/Magnum/GL/Attribute.h index d03379962..2de02f868 100644 --- a/src/Magnum/GL/Attribute.h +++ b/src/Magnum/GL/Attribute.h @@ -306,15 +306,24 @@ template class Attribute { /** * @brief Constructor - * @param dataType Type of passed data. Default is the same as - * type used in shader (e.g. @ref DataType::Int for - * @ref Magnum::Vector4i "Vector4i"). + * @param dataOptions Data options. Default is no options. + * + * Data type is the same as type used in shader (e.g. + * @ref DataType::Int for @ref Magnum::Vector4i "Vector4i"). Component + * count is set to the same value as in type used in shader (e.g. + * @ref Components::Three for @ref Magnum::Vector3 "Vector3"). + */ + constexpr Attribute(DataOptions dataOptions = DataOptions()): Attribute{Implementation::Attribute::DefaultComponents, Implementation::Attribute::DefaultComponentCount*Implementation::Attribute::DefaultDataTypeSize, Implementation::Attribute::DefaultDataType, dataOptions} {} + + /** + * @brief Constructor + * @param dataType Type of passed data * @param dataOptions Data options. Default is no options. * * Component count is set to the same value as in type used in shader * (e.g. @ref Components::Three for @ref Magnum::Vector3 "Vector3"). */ - constexpr Attribute(DataType dataType = Implementation::Attribute::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{Implementation::Attribute::DefaultComponents, dataType, dataOptions} {} + /*implicit*/ Attribute(DataType dataType, DataOptions dataOptions = DataOptions()): Attribute{Implementation::Attribute::DefaultComponents, dataType, dataOptions} {} /** * @brief Constructor @@ -327,7 +336,7 @@ template class Attribute { * Vector stride is set to the size of the vector type (e.g. * @cpp 12 @ce for a @ref Magnum::Matrix3 "Matrix3"). */ - constexpr Attribute(Components components, DataType dataType = Implementation::Attribute::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{components, Implementation::Attribute::size(GLint(components), dataType), dataType, dataOptions} {} + /*implicit*/ Attribute(Components components, DataType dataType = Implementation::Attribute::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{components, Implementation::Attribute::size(GLint(components), dataType), dataType, dataOptions} {} /** * @brief Construct with a custom vector stride @@ -769,18 +778,22 @@ template struct SizedVectorAttribute { template<> struct SizedAttribute<1, 1>: SizedVectorAttribute<1> { enum class Components: GLint { One = 1 }; constexpr static Components DefaultComponents = Components::One; + enum: UnsignedInt { DefaultComponentCount = 1 }; }; template<> struct SizedAttribute<1, 2>: SizedVectorAttribute<1> { enum class Components: GLint { One = 1, Two = 2 }; constexpr static Components DefaultComponents = Components::Two; + enum: UnsignedInt { DefaultComponentCount = 2 }; }; template<> struct SizedAttribute<1, 3>: SizedVectorAttribute<1> { enum class Components: GLint { One = 1, Two = 2, Three = 3 }; constexpr static Components DefaultComponents = Components::Three; + enum: UnsignedInt { DefaultComponentCount = 3 }; }; template<> struct SizedAttribute<1, 4>: SizedVectorAttribute<1> { enum class Components: GLint { One = 1, Two = 2, Three = 3, Four = 4 }; constexpr static Components DefaultComponents = Components::Four; + enum: UnsignedInt { DefaultComponentCount = 4 }; }; MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, SizedAttribute<1, 1>::Components value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, SizedAttribute<1, 2>::Components value); @@ -792,14 +805,17 @@ template struct SizedMatrixAttribute; template<> struct SizedMatrixAttribute<2> { enum class Components: GLint { Two = 2 }; constexpr static Components DefaultComponents = Components::Two; + enum: UnsignedInt { DefaultComponentCount = 2 }; }; template<> struct SizedMatrixAttribute<3> { enum class Components: GLint { Three = 3 }; constexpr static Components DefaultComponents = Components::Three; + enum: UnsignedInt { DefaultComponentCount = 3 }; }; template<> struct SizedMatrixAttribute<4> { enum class Components: GLint { Four = 4 }; constexpr static Components DefaultComponents = Components::Four; + enum: UnsignedInt { DefaultComponentCount = 4 }; }; MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, SizedMatrixAttribute<2>::Components value); MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, SizedMatrixAttribute<3>::Components value); @@ -848,6 +864,7 @@ struct FloatAttribute { #endif }; constexpr static DataType DefaultDataType = DataType::Float; + enum: UnsignedInt { DefaultDataTypeSize = 4 }; enum class DataOption: UnsignedByte { Normalized = 1 << 0 @@ -875,6 +892,7 @@ struct IntAttribute { Int = GL_INT }; constexpr static DataType DefaultDataType = DataType::Int; + enum: UnsignedInt { DefaultDataTypeSize = 4 }; enum class DataOption: UnsignedByte {}; typedef Containers::EnumSet DataOptions; @@ -892,6 +910,7 @@ struct UnsignedIntAttribute { typedef IntAttribute::DataType DataType; constexpr static DataType DefaultDataType = DataType::UnsignedInt; + enum: UnsignedInt { DefaultDataTypeSize = 4 }; typedef IntAttribute::DataOption DataOption; typedef IntAttribute::DataOptions DataOptions; @@ -911,6 +930,7 @@ struct DoubleAttribute { Double = GL_DOUBLE }; constexpr static DataType DefaultDataType = DataType::Double; + enum: UnsignedInt { DefaultDataTypeSize = 8 }; typedef IntAttribute::DataOption DataOption; typedef IntAttribute::DataOptions DataOptions; @@ -952,6 +972,7 @@ template<> struct Attribute>: SizedAttribute<1, 3> { #endif }; constexpr static DataType DefaultDataType = DataType::Float; + enum: UnsignedInt { DefaultDataTypeSize = 4 }; typedef FloatAttribute::DataOption DataOption; typedef FloatAttribute::DataOptions DataOptions; @@ -976,6 +997,7 @@ template<> struct Attribute> { #endif }; constexpr static Components DefaultComponents = Components::Four; + enum: UnsignedInt { DefaultComponentCount = 4 }; enum class DataType: GLenum { UnsignedByte = GL_UNSIGNED_BYTE, @@ -1006,6 +1028,7 @@ template<> struct Attribute> { #endif }; constexpr static DataType DefaultDataType = DataType::Float; + enum: UnsignedInt { DefaultDataTypeSize = 4 }; typedef FloatAttribute::DataOption DataOption; typedef FloatAttribute::DataOptions DataOptions; diff --git a/src/Magnum/GL/Test/AttributeTest.cpp b/src/Magnum/GL/Test/AttributeTest.cpp index cb22c88d8..60cdb09ad 100644 --- a/src/Magnum/GL/Test/AttributeTest.cpp +++ b/src/Magnum/GL/Test/AttributeTest.cpp @@ -55,6 +55,9 @@ struct AttributeTest: TestSuite::Tester { void attributeMatrixNxNd(); void attributeMatrixMxNd(); + void dynamicAttribute(); + void dynamicAttributeMatrix(); + void attributeFromGenericFormat(); #ifndef MAGNUM_TARGET_GLES2 void attributeFromGenericFormatIntegral(); @@ -126,6 +129,9 @@ AttributeTest::AttributeTest() { &AttributeTest::attributeMatrixNxNd, &AttributeTest::attributeMatrixMxNd, + &AttributeTest::dynamicAttribute, + &AttributeTest::dynamicAttributeMatrix, + &AttributeTest::attributeFromGenericFormat, #ifndef MAGNUM_TARGET_GLES2 &AttributeTest::attributeFromGenericFormatIntegral, @@ -184,31 +190,63 @@ void AttributeTest::attributeScalar() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::One); + CORRADE_COMPARE(ca.components(), Attribute::Components::One); CORRADE_VERIFY(!a.dataOptions()); + CORRADE_VERIFY(!ca.dataOptions()); CORRADE_COMPARE(a.vectorStride(), 4); + CORRADE_COMPARE(ca.vectorStride(), 4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Float); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(da.vectorStride(), 4); + CORRADE_COMPARE(cda.vectorStride(), 4); CORRADE_COMPARE(da.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Float); /* Options */ - Attribute b(Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized); + Attribute b{Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized}; CORRADE_COMPARE(b.vectorStride(), 2); CORRADE_VERIFY(b.dataOptions() <= Attribute::DataOption::Normalized); + /* The constexpr variant needs to specify vector stride explicitly. + Constexpr accessors tested just here, other variants don't have any + difference. */ + constexpr Attribute cb{3, Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized}; + constexpr Attribute::Components components = cb.components(); + constexpr Attribute::DataType dataType = cb.dataType(); + constexpr UnsignedInt vectorStride = cb.vectorStride(); + constexpr Attribute::DataOptions dataOptions = cb.dataOptions(); + CORRADE_COMPARE(components, Attribute::Components::One); + CORRADE_COMPARE(dataType, Attribute::DataType::UnsignedShort); + CORRADE_COMPARE(vectorStride, 3); + CORRADE_VERIFY(dataOptions <= Attribute::DataOption::Normalized); + + /* Constexpr dynamic attribute accessors tested in dynamicAttributeMatrix() */ DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::GenericNormalized); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::GenericNormalized); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(db.vectorStride(), 2); + CORRADE_COMPARE(cdb.vectorStride(), 3); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::UnsignedShort); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::UnsignedShort); } void AttributeTest::attributeScalarInt() { @@ -219,27 +257,46 @@ void AttributeTest::attributeScalarInt() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.vectorStride(), 4); + CORRADE_COMPARE(ca.vectorStride(), 4); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(da.location(), 2); + CORRADE_COMPARE(cda.location(), 2); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(da.vectorStride(), 4); + CORRADE_COMPARE(cda.vectorStride(), 4); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Int); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Int); - /* Options */ - Attribute b(Attribute::DataType::Short); + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute b{Attribute::DataType::Short}; + constexpr Attribute cb{3, Attribute::DataType::Short}; CORRADE_COMPARE(b.vectorStride(), 2); + CORRADE_COMPARE(cb.vectorStride(), 3); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(db.location(), 2); + CORRADE_COMPARE(cdb.location(), 2); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(db.vectorStride(), 2); + CORRADE_COMPARE(cdb.vectorStride(), 3); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Short); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Short); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -253,27 +310,46 @@ void AttributeTest::attributeScalarUnsignedInt() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.vectorStride(), 4); + CORRADE_COMPARE(ca.vectorStride(), 4); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(da.vectorStride(), 4); + CORRADE_COMPARE(cda.vectorStride(), 4); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::UnsignedInt); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::UnsignedInt); - /* Options */ - Attribute b(Attribute::DataType::UnsignedByte); + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute b{Attribute::DataType::UnsignedByte}; + constexpr Attribute cb{2, Attribute::DataType::UnsignedByte}; CORRADE_COMPARE(b.vectorStride(), 1); + CORRADE_COMPARE(cb.vectorStride(), 2); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(db.vectorStride(), 1); + CORRADE_COMPARE(cdb.vectorStride(), 2); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::UnsignedByte); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::UnsignedByte); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -287,15 +363,24 @@ void AttributeTest::attributeScalarDouble() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.vectorStride(), 8); + CORRADE_COMPARE(ca.vectorStride(), 8); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Long); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Long); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(da.vectorStride(), 8); + CORRADE_COMPARE(cda.vectorStride(), 8); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Double); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif @@ -308,43 +393,75 @@ void AttributeTest::attributeVector() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Three); + CORRADE_COMPARE(ca.components(), Attribute::Components::Three); CORRADE_COMPARE(a.vectorStride(), 3*4); + CORRADE_COMPARE(ca.vectorStride(), 3*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Float); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Three); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Three); CORRADE_COMPARE(da.vectorStride(), 3*4); + CORRADE_COMPARE(cda.vectorStride(), 3*4); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Float); - /* Options */ + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ #ifndef MAGNUM_TARGET_GLES - Attribute b(Attribute::Components::Two, Attribute::DataType::Double); + Attribute b{Attribute::Components::Two, Attribute::DataType::Double}; + constexpr Attribute cb{Attribute::Components::Two, 18, Attribute::DataType::Double}; CORRADE_COMPARE(b.components(), Attribute::Components::Two); + CORRADE_COMPARE(cb.components(), Attribute::Components::Two); CORRADE_COMPARE(b.vectorStride(), 2*8); + CORRADE_COMPARE(cb.vectorStride(), 18); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Two); CORRADE_COMPARE(db.vectorStride(), 2*8); + CORRADE_COMPARE(cdb.vectorStride(), 18); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Double); #else - Attribute b(Attribute::Components::Two, Attribute::DataType::Float); + Attribute b{Attribute::Components::Two, Attribute::DataType::Float}; + constexpr Attribute cb{Attribute::Components::Two, 14, Attribute::DataType::Float}; CORRADE_COMPARE(b.components(), Attribute::Components::Two); + CORRADE_COMPARE(cb.components(), Attribute::Components::Two); CORRADE_COMPARE(b.vectorStride(), 2*4); + CORRADE_COMPARE(cb.vectorStride(), 14); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Two); CORRADE_COMPARE(db.vectorStride(), 2*4); + CORRADE_COMPARE(cdb.vectorStride(), 14); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Float); #endif } @@ -356,29 +473,50 @@ void AttributeTest::attributeVectorInt() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Two); + CORRADE_COMPARE(ca.components(), Attribute::Components::Two); CORRADE_COMPARE(a.vectorStride(), 2*4); + CORRADE_COMPARE(ca.vectorStride(), 2*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Int); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Int); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Two); CORRADE_COMPARE(da.vectorStride(), 2*4); + CORRADE_COMPARE(cda.vectorStride(), 2*4); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Int); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Int); - /* Options */ - Attribute b(Attribute::Components::One, Attribute::DataType::Int); + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute b{Attribute::Components::One, Attribute::DataType::Int}; + constexpr Attribute cb{Attribute::Components::One, 6, Attribute::DataType::Int}; CORRADE_COMPARE(b.vectorStride(), 4); + CORRADE_COMPARE(cb.vectorStride(), 6); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(db.vectorStride(), 4); + CORRADE_COMPARE(cdb.vectorStride(), 6); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Int); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Int); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -392,29 +530,50 @@ void AttributeTest::attributeVectorUnsignedInt() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Four); + CORRADE_COMPARE(ca.components(), Attribute::Components::Four); CORRADE_COMPARE(a.vectorStride(), 4*4); + CORRADE_COMPARE(ca.vectorStride(), 4*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::UnsignedInt); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::UnsignedInt); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Four); CORRADE_COMPARE(da.vectorStride(), 4*4); + CORRADE_COMPARE(cda.vectorStride(), 4*4); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::UnsignedInt); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::UnsignedInt); - /* Options */ - Attribute b(Attribute::Components::Three, Attribute::DataType::UnsignedShort); + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute b{Attribute::Components::Three, Attribute::DataType::UnsignedShort}; + constexpr Attribute cb{Attribute::Components::Three, 7, Attribute::DataType::UnsignedShort}; CORRADE_COMPARE(b.vectorStride(), 3*2); + CORRADE_COMPARE(cb.vectorStride(), 7); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Integral); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Three); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Three); CORRADE_COMPARE(db.vectorStride(), 3*2); + CORRADE_COMPARE(cdb.vectorStride(), 7); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::UnsignedShort); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::UnsignedShort); #else CORRADE_SKIP("Integer attributes are not available in OpenGL ES 2."); #endif @@ -428,29 +587,50 @@ void AttributeTest::attributeVectorDouble() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Two); + CORRADE_COMPARE(ca.components(), Attribute::Components::Two); CORRADE_COMPARE(a.vectorStride(), 2*8); + CORRADE_COMPARE(ca.vectorStride(), 2*8); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Double); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Long); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Long); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Two); CORRADE_COMPARE(da.vectorStride(), 2*8); + CORRADE_COMPARE(cda.vectorStride(), 2*8); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Double); - /* Options */ - Attribute b(Attribute::Components::One); + /* Options. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute b{Attribute::Components::One}; + constexpr Attribute cb{Attribute::Components::One, 10}; CORRADE_COMPARE(b.vectorStride(), 8); + CORRADE_COMPARE(cb.vectorStride(), 10); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Long); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Long); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::One); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::One); CORRADE_COMPARE(db.vectorStride(), 8); + CORRADE_COMPARE(cdb.vectorStride(), 10); CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Double); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif @@ -461,40 +641,78 @@ void AttributeTest::attributeVector4() { CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); - /* Custom type */ + /* Default constructor */ + Attribute a; + constexpr Attribute ca; + CORRADE_COMPARE(a.components(), Attribute::Components::Four); + CORRADE_COMPARE(ca.components(), Attribute::Components::Four); + CORRADE_COMPARE(a.vectorStride(), 4*4); + CORRADE_COMPARE(ca.vectorStride(), 4*4); + CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Float); + + /* Custom type. The constexpr variant needs to specify vector stride + explicitly. */ #ifndef MAGNUM_TARGET_GLES - Attribute a(Attribute::DataType::UnsignedInt2101010Rev); - CORRADE_COMPARE(a.vectorStride(), 4); + Attribute b{Attribute::DataType::UnsignedInt2101010Rev}; + constexpr Attribute cb{6, Attribute::DataType::UnsignedInt2101010Rev}; + CORRADE_COMPARE(b.vectorStride(), 4); + CORRADE_COMPARE(cb.vectorStride(), 6); - DynamicAttribute da{a}; - CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); - CORRADE_COMPARE(da.location(), 3); - CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); - CORRADE_COMPARE(da.vectorStride(), 4); - CORRADE_COMPARE(da.vectors(), 1); - CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::UnsignedInt2101010Rev); + DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; + CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); + CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(db.vectorStride(), 4); + CORRADE_COMPARE(cdb.vectorStride(), 6); + CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); + CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::UnsignedInt2101010Rev); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::UnsignedInt2101010Rev); #elif !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) - Attribute a(Attribute::DataType::Half); - CORRADE_COMPARE(a.vectorStride(), 8); + Attribute b(Attribute::DataType::Half); + constexpr Attribute cb(10, Attribute::DataType::Half); + CORRADE_COMPARE(b.vectorStride(), 8); + CORRADE_COMPARE(cb.vectorStride(), 10); - DynamicAttribute da{a}; - CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); - CORRADE_COMPARE(da.location(), 3); - CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); - CORRADE_COMPARE(da.vectorStride(), 8); - CORRADE_COMPARE(da.vectors(), 1); - CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Half); + DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; + CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); + CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(db.vectorStride(), 8); + CORRADE_COMPARE(cdb.vectorStride(), 10); + CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); + CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Half); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Half); #else - Attribute a(Attribute::DataType::Float); - CORRADE_COMPARE(a.vectorStride(), 16); + Attribute b{Attribute::DataType::Float}; + constexpr Attribute cb{18, Attribute::DataType::Float}; + CORRADE_COMPARE(b.vectorStride(), 16); + CORRADE_COMPARE(cb.vectorStride(), 18); - DynamicAttribute da{a}; - CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); - CORRADE_COMPARE(da.location(), 3); - CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); - CORRADE_COMPARE(da.vectorStride(), 16); - CORRADE_COMPARE(da.vectors(), 1); - CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; + CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); + CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(db.vectorStride(), 16); + CORRADE_COMPARE(cdb.vectorStride(), 18); + CORRADE_COMPARE(db.vectors(), 1); + CORRADE_COMPARE(cdb.vectors(), 1); + CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Float); #endif } @@ -504,17 +722,27 @@ void AttributeTest::attributeVectorBGRA() { CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); - /* BGRA */ - Attribute a(Attribute::Components::BGRA); + /* BGRA. The constexpr variant needs to specify vector stride + explicitly. */ + Attribute a{Attribute::Components::BGRA}; + constexpr Attribute ca{Attribute::Components::BGRA, 18}; CORRADE_COMPARE(a.vectorStride(), 4*4); + CORRADE_COMPARE(ca.vectorStride(), 18); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::BGRA); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::BGRA); CORRADE_COMPARE(da.vectorStride(), 4*4); + CORRADE_COMPARE(cda.vectorStride(), 18); CORRADE_COMPARE(da.vectors(), 1); + CORRADE_COMPARE(cda.vectors(), 1); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Float); #else CORRADE_SKIP("BGRA attribute component ordering is not available in OpenGL ES."); #endif @@ -527,17 +755,28 @@ void AttributeTest::attributeMatrixNxN() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Three); + CORRADE_COMPARE(ca.components(), Attribute::Components::Three); CORRADE_COMPARE(a.vectorStride(), 3*4); + CORRADE_COMPARE(ca.vectorStride(), 3*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Float); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Three); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Three); CORRADE_COMPARE(da.vectorStride(), 3*4); + CORRADE_COMPARE(cda.vectorStride(), 3*4); CORRADE_COMPARE(da.vectors(), 3); + CORRADE_COMPARE(cda.vectors(), 3); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Float); } void AttributeTest::attributeMatrixNxNCustomStride() { @@ -545,7 +784,7 @@ void AttributeTest::attributeMatrixNxNCustomStride() { CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 3); - /* Default stride */ + /* Default stride, not possible to do in a constexpr way */ Attribute a{Attribute::DataType::Short}; CORRADE_COMPARE(a.components(), Attribute::Components::Three); CORRADE_COMPARE(a.vectorStride(), 6); @@ -561,17 +800,28 @@ void AttributeTest::attributeMatrixNxNCustomStride() { /* Custom stride */ Attribute b{8, Attribute::DataType::Short}; + constexpr Attribute cb{8, Attribute::DataType::Short}; CORRADE_COMPARE(b.components(), Attribute::Components::Three); + CORRADE_COMPARE(cb.components(), Attribute::Components::Three); CORRADE_COMPARE(b.vectorStride(), 8); + CORRADE_COMPARE(cb.vectorStride(), 8); CORRADE_COMPARE(b.dataType(), Attribute::DataType::Short); + CORRADE_COMPARE(cb.dataType(), Attribute::DataType::Short); DynamicAttribute db{b}; + constexpr DynamicAttribute cdb{cb}; CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cdb.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(db.location(), 3); + CORRADE_COMPARE(cdb.location(), 3); CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Three); + CORRADE_COMPARE(cdb.components(), DynamicAttribute::Components::Three); CORRADE_COMPARE(db.vectorStride(), 8); + CORRADE_COMPARE(cdb.vectorStride(), 8); CORRADE_COMPARE(db.vectors(), 3); + CORRADE_COMPARE(cdb.vectors(), 3); CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Short); + CORRADE_COMPARE(cdb.dataType(), DynamicAttribute::DataType::Short); } #ifndef MAGNUM_TARGET_GLES2 @@ -582,17 +832,28 @@ void AttributeTest::attributeMatrixMxN() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Four); + CORRADE_COMPARE(ca.components(), Attribute::Components::Four); CORRADE_COMPARE(a.vectorStride(), 4*4); + CORRADE_COMPARE(ca.vectorStride(), 4*4); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Float); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Generic); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Four); CORRADE_COMPARE(da.vectorStride(), 4*4); + CORRADE_COMPARE(cda.vectorStride(), 4*4); CORRADE_COMPARE(da.vectors(), 3); + CORRADE_COMPARE(cda.vectors(), 3); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Float); } #endif @@ -604,17 +865,28 @@ void AttributeTest::attributeMatrixNxNd() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Four); + CORRADE_COMPARE(ca.components(), Attribute::Components::Four); CORRADE_COMPARE(a.vectorStride(), 4*8); + CORRADE_COMPARE(ca.vectorStride(), 4*8); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Double); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Long); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Long); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Four); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Four); CORRADE_COMPARE(da.vectorStride(), 4*8); + CORRADE_COMPARE(cda.vectorStride(), 4*8); CORRADE_COMPARE(da.vectors(), 4); + CORRADE_COMPARE(cda.vectors(), 4); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Double); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif @@ -628,22 +900,80 @@ void AttributeTest::attributeMatrixMxNd() { /* Default constructor */ Attribute a; + constexpr Attribute ca; CORRADE_COMPARE(a.components(), Attribute::Components::Two); + CORRADE_COMPARE(ca.components(), Attribute::Components::Two); CORRADE_COMPARE(a.vectorStride(), 2*8); + CORRADE_COMPARE(ca.vectorStride(), 2*8); CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double); + CORRADE_COMPARE(ca.dataType(), Attribute::DataType::Double); DynamicAttribute da{a}; + constexpr DynamicAttribute cda{ca}; CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Long); + CORRADE_COMPARE(cda.kind(), DynamicAttribute::Kind::Long); CORRADE_COMPARE(da.location(), 3); + CORRADE_COMPARE(cda.location(), 3); CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(cda.components(), DynamicAttribute::Components::Two); CORRADE_COMPARE(da.vectorStride(), 2*8); + CORRADE_COMPARE(cda.vectorStride(), 2*8); CORRADE_COMPARE(da.vectors(), 4); + CORRADE_COMPARE(cda.vectors(), 4); CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Double); + CORRADE_COMPARE(cda.dataType(), DynamicAttribute::DataType::Double); #else CORRADE_SKIP("Double attributes are not available in OpenGL ES."); #endif } +void AttributeTest::dynamicAttribute() { + /* This one isn't constexpr as the vector stride has to be calculated */ + DynamicAttribute a{DynamicAttribute::Kind::GenericNormalized, 3, + DynamicAttribute::Components::Two, DynamicAttribute::DataType::Byte}; + CORRADE_COMPARE(a.kind(), DynamicAttribute::Kind::GenericNormalized); + CORRADE_COMPARE(a.location(), 3); + CORRADE_COMPARE(a.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(a.vectors(), 1); + CORRADE_COMPARE(a.vectorStride(), 2); + CORRADE_COMPARE(a.dataType(), DynamicAttribute::DataType::Byte); +} + +void AttributeTest::dynamicAttributeMatrix() { + DynamicAttribute a{DynamicAttribute::Kind::GenericNormalized, 3, + DynamicAttribute::Components::Two, 3, DynamicAttribute::DataType::Byte}; + CORRADE_COMPARE(a.kind(), DynamicAttribute::Kind::GenericNormalized); + CORRADE_COMPARE(a.location(), 3); + CORRADE_COMPARE(a.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(a.vectors(), 3); + CORRADE_COMPARE(a.vectorStride(), 2); + CORRADE_COMPARE(a.dataType(), DynamicAttribute::DataType::Byte); + + DynamicAttribute b{DynamicAttribute::Kind::GenericNormalized, 3, + DynamicAttribute::Components::Two, 3, 4, DynamicAttribute::DataType::Byte}; + CORRADE_COMPARE(b.kind(), DynamicAttribute::Kind::GenericNormalized); + CORRADE_COMPARE(b.location(), 3); + CORRADE_COMPARE(b.components(), DynamicAttribute::Components::Two); + CORRADE_COMPARE(b.vectors(), 3); + CORRADE_COMPARE(b.vectorStride(), 4); + CORRADE_COMPARE(b.dataType(), DynamicAttribute::DataType::Byte); + + constexpr DynamicAttribute cb{DynamicAttribute::Kind::GenericNormalized, 3, + DynamicAttribute::Components::Two, 3, 4, DynamicAttribute::DataType::Byte}; + constexpr DynamicAttribute::Kind kind = cb.kind(); + constexpr UnsignedInt location = cb.location(); + constexpr DynamicAttribute::Components components = cb.components(); + constexpr UnsignedInt vectors = cb.vectors(); + constexpr UnsignedInt vectorStride = cb.vectorStride(); + constexpr DynamicAttribute::DataType dataType = cb.dataType(); + CORRADE_COMPARE(kind, DynamicAttribute::Kind::GenericNormalized); + CORRADE_COMPARE(location, 3); + CORRADE_COMPARE(components, DynamicAttribute::Components::Two); + CORRADE_COMPARE(vectors, 3); + CORRADE_COMPARE(vectorStride, 4); + CORRADE_COMPARE(dataType, DynamicAttribute::DataType::Byte); +} + void AttributeTest::attributeFromGenericFormat() { DynamicAttribute a{DynamicAttribute::Kind::Generic, 3, VertexFormat::UnsignedShort};