Browse Source

Trade: add scene{Object,Field}TypeAlignment().

Support utilities needed for SceneTools that will operate on arbitrary
SceneData (adding/removing fields, objects...) without having to know
what each field means and how it needs to be treated.

Honestly the same would make sense for the VertexFormat enum as well.
But not now, later.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
e858ab2dd8
  1. 130
      src/Magnum/Trade/SceneData.cpp
  2. 28
      src/Magnum/Trade/SceneData.h
  3. 47
      src/Magnum/Trade/Test/SceneDataTest.cpp

130
src/Magnum/Trade/SceneData.cpp

@ -82,6 +82,24 @@ UnsignedInt sceneObjectTypeSize(const SceneObjectType type) {
CORRADE_ASSERT_UNREACHABLE("Trade::sceneObjectTypeSize(): invalid type" << 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& operator<<(Debug& debug, const SceneField value) {
debug << "Trade::SceneField" << Debug::nospace; debug << "Trade::SceneField" << Debug::nospace;
@ -343,6 +361,118 @@ UnsignedInt sceneFieldTypeSize(const SceneFieldType type) {
CORRADE_ASSERT_UNREACHABLE("Trade::sceneFieldTypeSize(): invalid type" << 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<const char>& objectData, const SceneFieldType fieldType, const Containers::StridedArrayView2D<const char>& fieldData, const UnsignedShort fieldArraySize) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D<const void>{{objectData.data(), ~std::size_t{}}, objectData.size()[0], objectData.stride()[0]}, fieldType, Containers::StridedArrayView1D<const void>{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, fieldArraySize} { SceneFieldData::SceneFieldData(const SceneField name, const Containers::StridedArrayView2D<const char>& objectData, const SceneFieldType fieldType, const Containers::StridedArrayView2D<const char>& fieldData, const UnsignedShort fieldArraySize) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D<const void>{{objectData.data(), ~std::size_t{}}, objectData.size()[0], objectData.stride()[0]}, fieldType, Containers::StridedArrayView1D<const void>{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, fieldArraySize} {
/* Yes, this calls into a constexpr function defined in the header -- /* Yes, this calls into a constexpr function defined in the header --
because I feel that makes more sense than duplicating the full assert because I feel that makes more sense than duplicating the full assert

28
src/Magnum/Trade/SceneData.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @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 <Corrade/Containers/Array.h> #include <Corrade/Containers/Array.h>
@ -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 @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 the same for all fields, and is guaranteed to be large enough to fit all
@ref SceneData::objectCount() objects. @ref SceneData::objectCount() objects.
@see @ref SceneData::objectType(), @ref sceneObjectTypeSize() @see @ref SceneData::objectType(), @ref sceneObjectTypeSize(),
@ref sceneObjectTypeAlignment()
*/ */
enum class SceneObjectType: UnsignedByte { enum class SceneObjectType: UnsignedByte {
/* Zero used for an invalid value */ /* 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 @brief Size of given scene object type
@m_since_latest @m_since_latest
@see @ref sceneObjectTypeAlignment()
*/ */
MAGNUM_TRADE_EXPORT UnsignedInt sceneObjectTypeSize(SceneObjectType type); 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 @brief Scene field name
@m_since_latest @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 A type in which a @ref SceneField is stored. See @ref SceneData for more
information. information.
@see @ref SceneFieldData, @ref sceneFieldTypeSize() @see @ref SceneFieldData, @ref sceneFieldTypeSize(),
@ref sceneFieldTypeAlignment()
*/ */
enum class SceneFieldType: UnsignedShort { enum class SceneFieldType: UnsignedShort {
/* Zero used for an invalid value */ /* 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 @brief Size of given scene field type
@m_since_latest @m_since_latest
@see @ref sceneFieldTypeAlignment()
*/ */
MAGNUM_TRADE_EXPORT UnsignedInt sceneFieldTypeSize(SceneFieldType type); 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 @brief Scene field data
@m_since_latest @m_since_latest

47
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -50,8 +50,8 @@ namespace Magnum { namespace Trade { namespace Test { namespace {
struct SceneDataTest: TestSuite::Tester { struct SceneDataTest: TestSuite::Tester {
explicit SceneDataTest(); explicit SceneDataTest();
void objectTypeSize(); void objectTypeSizeAlignment();
void objectTypeSizeInvalid(); void objectTypeSizeAlignmentInvalid();
void debugObjectType(); void debugObjectType();
void customFieldName(); void customFieldName();
@ -59,8 +59,8 @@ struct SceneDataTest: TestSuite::Tester {
void customFieldNameNotCustom(); void customFieldNameNotCustom();
void debugFieldName(); void debugFieldName();
void fieldTypeSize(); void fieldTypeSizeAlignment();
void fieldTypeSizeInvalid(); void fieldTypeSizeAlignmentInvalid();
void debugFieldType(); void debugFieldType();
void constructField(); void constructField();
@ -223,8 +223,8 @@ const struct {
#endif #endif
SceneDataTest::SceneDataTest() { SceneDataTest::SceneDataTest() {
addTests({&SceneDataTest::objectTypeSize, addTests({&SceneDataTest::objectTypeSizeAlignment,
&SceneDataTest::objectTypeSizeInvalid, &SceneDataTest::objectTypeSizeAlignmentInvalid,
&SceneDataTest::debugObjectType, &SceneDataTest::debugObjectType,
&SceneDataTest::customFieldName, &SceneDataTest::customFieldName,
@ -232,8 +232,8 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::customFieldNameNotCustom, &SceneDataTest::customFieldNameNotCustom,
&SceneDataTest::debugFieldName, &SceneDataTest::debugFieldName,
&SceneDataTest::fieldTypeSize, &SceneDataTest::fieldTypeSizeAlignment,
&SceneDataTest::fieldTypeSizeInvalid, &SceneDataTest::fieldTypeSizeAlignmentInvalid,
&SceneDataTest::debugFieldType, &SceneDataTest::debugFieldType,
&SceneDataTest::constructField, &SceneDataTest::constructField,
@ -427,14 +427,18 @@ SceneDataTest::SceneDataTest() {
using namespace Math::Literals; using namespace Math::Literals;
void SceneDataTest::objectTypeSize() { void SceneDataTest::objectTypeSizeAlignment() {
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedByte), 1); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedByte), 1);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedByte), 1);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedShort), 2); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedShort), 2);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedShort), 2);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedInt), 4); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedInt), 4);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedInt), 4);
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedLong), 8); CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedLong), 8);
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedLong), 8);
} }
void SceneDataTest::objectTypeSizeInvalid() { void SceneDataTest::objectTypeSizeAlignmentInvalid() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
@ -443,11 +447,15 @@ void SceneDataTest::objectTypeSizeInvalid() {
Error redirectError{&out}; Error redirectError{&out};
sceneObjectTypeSize(SceneObjectType{}); sceneObjectTypeSize(SceneObjectType{});
sceneObjectTypeAlignment(SceneObjectType{});
sceneObjectTypeSize(SceneObjectType(0x73)); sceneObjectTypeSize(SceneObjectType(0x73));
sceneObjectTypeAlignment(SceneObjectType(0x73));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x0)\n" "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() { 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"); 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 */ /* Test at least one of every size */
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Byte), sizeof(Byte)); CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Byte), sizeof(Byte));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Degh), sizeof(Degh)); 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::Matrix3x4d), sizeof(Matrix3x4d));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x4d), sizeof(Matrix4x4d)); CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x4d), sizeof(Matrix4x4d));
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Pointer), sizeof(const void*)); 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 #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
@ -537,11 +552,15 @@ void SceneDataTest::fieldTypeSizeInvalid() {
Error redirectError{&out}; Error redirectError{&out};
sceneFieldTypeSize(SceneFieldType{}); sceneFieldTypeSize(SceneFieldType{});
sceneFieldTypeAlignment(SceneFieldType{});
sceneFieldTypeSize(SceneFieldType(0xdead)); sceneFieldTypeSize(SceneFieldType(0xdead));
sceneFieldTypeAlignment(SceneFieldType(0xdead));
CORRADE_COMPARE(out.str(), CORRADE_COMPARE(out.str(),
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0x0)\n" "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() { void SceneDataTest::debugFieldType() {

Loading…
Cancel
Save