diff --git a/src/Magnum/Trade/SceneData.cpp b/src/Magnum/Trade/SceneData.cpp index b5599796c..cc83bb710 100644 --- a/src/Magnum/Trade/SceneData.cpp +++ b/src/Magnum/Trade/SceneData.cpp @@ -82,6 +82,24 @@ UnsignedInt sceneObjectTypeSize(const SceneObjectType type) { CORRADE_ASSERT_UNREACHABLE("Trade::sceneObjectTypeSize(): invalid type" << type, {}); } +UnsignedInt sceneObjectTypeAlignment(const SceneObjectType type) { + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(type) { + case SceneObjectType::UnsignedByte: return 1; + case SceneObjectType::UnsignedShort: return 2; + case SceneObjectType::UnsignedInt: return 4; + case SceneObjectType::UnsignedLong: return 8; + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("Trade::sceneObjectTypeAlignment(): invalid type" << type, {}); +} + Debug& operator<<(Debug& debug, const SceneField value) { debug << "Trade::SceneField" << Debug::nospace; @@ -343,6 +361,118 @@ UnsignedInt sceneFieldTypeSize(const SceneFieldType type) { CORRADE_ASSERT_UNREACHABLE("Trade::sceneFieldTypeSize(): invalid type" << type, {}); } +UnsignedInt sceneFieldTypeAlignment(const SceneFieldType type) { + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(type) { + case SceneFieldType::UnsignedByte: + case SceneFieldType::Vector2ub: + case SceneFieldType::Vector3ub: + case SceneFieldType::Vector4ub: + case SceneFieldType::Byte: + case SceneFieldType::Vector2b: + case SceneFieldType::Vector3b: + case SceneFieldType::Vector4b: + return 1; + case SceneFieldType::UnsignedShort: + case SceneFieldType::Vector2us: + case SceneFieldType::Vector3us: + case SceneFieldType::Vector4us: + case SceneFieldType::Short: + case SceneFieldType::Vector2s: + case SceneFieldType::Vector3s: + case SceneFieldType::Vector4s: + case SceneFieldType::Half: + case SceneFieldType::Vector2h: + case SceneFieldType::Vector3h: + case SceneFieldType::Vector4h: + case SceneFieldType::Matrix2x2h: + case SceneFieldType::Matrix2x3h: + case SceneFieldType::Matrix2x4h: + case SceneFieldType::Matrix3x2h: + case SceneFieldType::Matrix3x3h: + case SceneFieldType::Matrix3x4h: + case SceneFieldType::Matrix4x2h: + case SceneFieldType::Matrix4x3h: + case SceneFieldType::Matrix4x4h: + case SceneFieldType::Range1Dh: + case SceneFieldType::Range2Dh: + case SceneFieldType::Range3Dh: + case SceneFieldType::Degh: + case SceneFieldType::Radh: + return 2; + case SceneFieldType::UnsignedInt: + case SceneFieldType::Vector2ui: + case SceneFieldType::Vector3ui: + case SceneFieldType::Vector4ui: + case SceneFieldType::Int: + case SceneFieldType::Vector2i: + case SceneFieldType::Vector3i: + case SceneFieldType::Vector4i: + case SceneFieldType::Float: + case SceneFieldType::Vector2: + case SceneFieldType::Vector3: + case SceneFieldType::Vector4: + case SceneFieldType::Matrix2x2: + case SceneFieldType::Matrix2x3: + case SceneFieldType::Matrix2x4: + case SceneFieldType::Matrix3x2: + case SceneFieldType::Matrix3x3: + case SceneFieldType::Matrix3x4: + case SceneFieldType::Matrix4x2: + case SceneFieldType::Matrix4x3: + case SceneFieldType::Matrix4x4: + case SceneFieldType::Range1Di: + case SceneFieldType::Range2Di: + case SceneFieldType::Range3Di: + case SceneFieldType::Range1D: + case SceneFieldType::Range2D: + case SceneFieldType::Range3D: + case SceneFieldType::Complex: + case SceneFieldType::Quaternion: + case SceneFieldType::DualComplex: + case SceneFieldType::DualQuaternion: + case SceneFieldType::Deg: + case SceneFieldType::Rad: + return 4; + case SceneFieldType::UnsignedLong: + case SceneFieldType::Long: + case SceneFieldType::Double: + case SceneFieldType::Vector2d: + case SceneFieldType::Vector3d: + case SceneFieldType::Vector4d: + case SceneFieldType::Matrix2x2d: + case SceneFieldType::Matrix2x3d: + case SceneFieldType::Matrix2x4d: + case SceneFieldType::Matrix3x2d: + case SceneFieldType::Matrix3x3d: + case SceneFieldType::Matrix3x4d: + case SceneFieldType::Matrix4x2d: + case SceneFieldType::Matrix4x3d: + case SceneFieldType::Matrix4x4d: + case SceneFieldType::Range1Dd: + case SceneFieldType::Range2Dd: + case SceneFieldType::Range3Dd: + case SceneFieldType::Complexd: + case SceneFieldType::Quaterniond: + case SceneFieldType::DualComplexd: + case SceneFieldType::DualQuaterniond: + case SceneFieldType::Degd: + case SceneFieldType::Radd: + return 8; + case SceneFieldType::Pointer: + case SceneFieldType::MutablePointer: + return sizeof(void*); + } + #ifdef CORRADE_TARGET_GCC + #pragma GCC diagnostic pop + #endif + + CORRADE_ASSERT_UNREACHABLE("Trade::sceneFieldTypeAlignment(): invalid type" << type, {}); +} + SceneFieldData::SceneFieldData(const SceneField name, const Containers::StridedArrayView2D& objectData, const SceneFieldType fieldType, const Containers::StridedArrayView2D& fieldData, const UnsignedShort fieldArraySize) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D{{objectData.data(), ~std::size_t{}}, objectData.size()[0], objectData.stride()[0]}, fieldType, Containers::StridedArrayView1D{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, fieldArraySize} { /* Yes, this calls into a constexpr function defined in the header -- because I feel that makes more sense than duplicating the full assert diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index e6e4a4344..a3f825854 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/src/Magnum/Trade/SceneData.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Trade::SceneData, @ref Magnum::Trade::SceneFieldData, enum @ref Magnum::Trade::SceneObjectType, @ref Magnum::Trade::SceneField, @ref Magnum::Trade::SceneFieldType, function @ref Magnum::sceneObjectTypeSize(), @ref Magnum::sceneFieldTypeSize(), @ref Magnum::Trade::isSceneFieldCustom(), @ref Magnum::sceneFieldCustom() + * @brief Class @ref Magnum::Trade::SceneData, @ref Magnum::Trade::SceneFieldData, enum @ref Magnum::Trade::SceneObjectType, @ref Magnum::Trade::SceneField, @ref Magnum::Trade::SceneFieldType, function @ref Magnum::sceneObjectTypeSize(), @ref Magnum::sceneObjectTypeAlignment(), @ref Magnum::sceneFieldTypeSize(), @ref Magnum::sceneFieldTypeAlignment(), @ref Magnum::Trade::isSceneFieldCustom(), @ref Magnum::sceneFieldCustom() */ #include @@ -51,7 +51,8 @@ Type used for mapping fields to corresponding objects. Unlike @ref SceneFieldType that is different for different fields, the object type is the same for all fields, and is guaranteed to be large enough to fit all @ref SceneData::objectCount() objects. -@see @ref SceneData::objectType(), @ref sceneObjectTypeSize() +@see @ref SceneData::objectType(), @ref sceneObjectTypeSize(), + @ref sceneObjectTypeAlignment() */ enum class SceneObjectType: UnsignedByte { /* Zero used for an invalid value */ @@ -80,9 +81,19 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneObjectType value); /** @brief Size of given scene object type @m_since_latest + +@see @ref sceneObjectTypeAlignment() */ MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeSize(SceneObjectType type); +/** +@brief Alignment of given scene object type +@m_since_latest + +Returns the same value as @ref sceneObjectTypeSize(). +*/ +MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeAlignment(SceneObjectType type); + /** @brief Scene field name @m_since_latest @@ -368,7 +379,8 @@ constexpr UnsignedInt sceneFieldCustom(SceneField name) { A type in which a @ref SceneField is stored. See @ref SceneData for more information. -@see @ref SceneFieldData, @ref sceneFieldTypeSize() +@see @ref SceneFieldData, @ref sceneFieldTypeSize(), + @ref sceneFieldTypeAlignment() */ enum class SceneFieldType: UnsignedShort { /* Zero used for an invalid value */ @@ -509,9 +521,19 @@ MAGNUM_TRADE_EXPORT Debug& operator<<(Debug& debug, SceneFieldType value); /** @brief Size of given scene field type @m_since_latest + +@see @ref sceneFieldTypeAlignment() */ MAGNUM_TRADE_EXPORT UnsignedInt sceneFieldTypeSize(SceneFieldType type); +/** +@brief Alignment of given scene field type +@m_since_latest + +@see @ref sceneFieldTypeSize() +*/ +MAGNUM_TRADE_EXPORT UnsignedInt sceneFieldTypeAlignment(SceneFieldType type); + /** @brief Scene field data @m_since_latest diff --git a/src/Magnum/Trade/Test/SceneDataTest.cpp b/src/Magnum/Trade/Test/SceneDataTest.cpp index ecf3f3f51..e990ccf65 100644 --- a/src/Magnum/Trade/Test/SceneDataTest.cpp +++ b/src/Magnum/Trade/Test/SceneDataTest.cpp @@ -50,8 +50,8 @@ namespace Magnum { namespace Trade { namespace Test { namespace { struct SceneDataTest: TestSuite::Tester { explicit SceneDataTest(); - void objectTypeSize(); - void objectTypeSizeInvalid(); + void objectTypeSizeAlignment(); + void objectTypeSizeAlignmentInvalid(); void debugObjectType(); void customFieldName(); @@ -59,8 +59,8 @@ struct SceneDataTest: TestSuite::Tester { void customFieldNameNotCustom(); void debugFieldName(); - void fieldTypeSize(); - void fieldTypeSizeInvalid(); + void fieldTypeSizeAlignment(); + void fieldTypeSizeAlignmentInvalid(); void debugFieldType(); void constructField(); @@ -223,8 +223,8 @@ const struct { #endif SceneDataTest::SceneDataTest() { - addTests({&SceneDataTest::objectTypeSize, - &SceneDataTest::objectTypeSizeInvalid, + addTests({&SceneDataTest::objectTypeSizeAlignment, + &SceneDataTest::objectTypeSizeAlignmentInvalid, &SceneDataTest::debugObjectType, &SceneDataTest::customFieldName, @@ -232,8 +232,8 @@ SceneDataTest::SceneDataTest() { &SceneDataTest::customFieldNameNotCustom, &SceneDataTest::debugFieldName, - &SceneDataTest::fieldTypeSize, - &SceneDataTest::fieldTypeSizeInvalid, + &SceneDataTest::fieldTypeSizeAlignment, + &SceneDataTest::fieldTypeSizeAlignmentInvalid, &SceneDataTest::debugFieldType, &SceneDataTest::constructField, @@ -427,14 +427,18 @@ SceneDataTest::SceneDataTest() { using namespace Math::Literals; -void SceneDataTest::objectTypeSize() { +void SceneDataTest::objectTypeSizeAlignment() { CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedByte), 1); + CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedByte), 1); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedShort), 2); + CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedShort), 2); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedInt), 4); + CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedInt), 4); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedLong), 8); + CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedLong), 8); } -void SceneDataTest::objectTypeSizeInvalid() { +void SceneDataTest::objectTypeSizeAlignmentInvalid() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -443,11 +447,15 @@ void SceneDataTest::objectTypeSizeInvalid() { Error redirectError{&out}; sceneObjectTypeSize(SceneObjectType{}); + sceneObjectTypeAlignment(SceneObjectType{}); sceneObjectTypeSize(SceneObjectType(0x73)); + sceneObjectTypeAlignment(SceneObjectType(0x73)); CORRADE_COMPARE(out.str(), "Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x0)\n" - "Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x73)\n"); + "Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x0)\n" + "Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x73)\n" + "Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x73)\n"); } void SceneDataTest::debugObjectType() { @@ -506,7 +514,7 @@ void SceneDataTest::debugFieldName() { CORRADE_COMPARE(out.str(), "Trade::SceneField::Transformation Trade::SceneField::Custom(73) Trade::SceneField(0xdeadda7)\n"); } -void SceneDataTest::fieldTypeSize() { +void SceneDataTest::fieldTypeSizeAlignment() { /* Test at least one of every size */ CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Byte), sizeof(Byte)); CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Degh), sizeof(Degh)); @@ -526,9 +534,16 @@ void SceneDataTest::fieldTypeSize() { CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x4d), sizeof(Matrix3x4d)); CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x4d), sizeof(Matrix4x4d)); CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Pointer), sizeof(const void*)); + + /* Test at least one of every alignment */ + CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Vector3ub), alignof(UnsignedByte)); + CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Matrix3x3h), alignof(Half)); + CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Range3Di), alignof(UnsignedInt)); + CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::DualComplexd), alignof(Double)); + CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Pointer), alignof(const void*)); } -void SceneDataTest::fieldTypeSizeInvalid() { +void SceneDataTest::fieldTypeSizeAlignmentInvalid() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -537,11 +552,15 @@ void SceneDataTest::fieldTypeSizeInvalid() { Error redirectError{&out}; sceneFieldTypeSize(SceneFieldType{}); + sceneFieldTypeAlignment(SceneFieldType{}); sceneFieldTypeSize(SceneFieldType(0xdead)); + sceneFieldTypeAlignment(SceneFieldType(0xdead)); CORRADE_COMPARE(out.str(), "Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0x0)\n" - "Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0xdead)\n"); + "Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0x0)\n" + "Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0xdead)\n" + "Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0xdead)\n"); } void SceneDataTest::debugFieldType() {