Browse Source

Enable embedding implementation-specific values in VertexFormat.

Similarly to PixelFormat. Will be useful for Vulkan, unfortunately not
so much for GL because there the format is specified by three orthogonal
values and it's a terrible mess.
pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
31d3cdcdb6
  1. 8
      src/Magnum/Test/CMakeLists.txt
  2. 102
      src/Magnum/Test/VertexFormatTest.cpp
  3. 19
      src/Magnum/VertexFormat.cpp
  4. 66
      src/Magnum/VertexFormat.h

8
src/Magnum/Test/CMakeLists.txt

@ -29,10 +29,8 @@ corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(MeshTest MeshTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib)
target_compile_definitions(PixelFormatTest PRIVATE "CORRADE_GRACEFUL_ASSERT")
corrade_add_test(PixelStorageTest PixelStorageTest.cpp LIBRARIES Magnum)
corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum)
target_compile_definitions(ResourceManagerTest PRIVATE "CORRADE_GRACEFUL_ASSERT")
corrade_add_test(SamplerTest SamplerTest.cpp LIBRARIES MagnumTestLib)
corrade_add_test(TagsTest TagsTest.cpp LIBRARIES Magnum)
corrade_add_test(VertexFormatTest VertexFormatTest.cpp LIBRARIES MagnumTestLib)
@ -49,3 +47,9 @@ set_target_properties(
TagsTest
VertexFormatTest
PROPERTIES FOLDER "Magnum/Test")
set_property(TARGET
PixelFormatTest
ResourceManagerTest
VertexFormatTest
APPEND PROPERTY COMPILE_DEFINITIONS "CORRADE_GRACEFUL_ASSERT")

102
src/Magnum/Test/VertexFormatTest.cpp

@ -38,21 +38,32 @@ struct VertexFormatTest: TestSuite::Tester {
void mapping();
void isImplementationSpecific();
void wrap();
void wrapInvalid();
void unwrap();
void unwrapInvalid();
void size();
void sizeInvalid();
void sizeImplementationSpecific();
void componentCount();
void componentCountInvalid();
void componentCountImplementationSpecific();
void componentFormat();
void componentFormatInvalid();
void componentFormatImplementationSpecific();
void isNormalized();
void isNormalizedInvalid();
void isNormalizedImplementationSpecific();
void assemble();
void assembleRoundtrip();
void assembleCantNormalize();
void assembleInvalidComponentCount();
void assembleImplementationSpecific();
void debug();
void debugImplementationSpecific();
void configuration();
};
@ -77,14 +88,23 @@ constexpr struct {
VertexFormatTest::VertexFormatTest() {
addTests({&VertexFormatTest::mapping,
&VertexFormatTest::isImplementationSpecific,
&VertexFormatTest::wrap,
&VertexFormatTest::wrapInvalid,
&VertexFormatTest::unwrap,
&VertexFormatTest::unwrapInvalid,
&VertexFormatTest::size,
&VertexFormatTest::sizeInvalid,
&VertexFormatTest::sizeImplementationSpecific,
&VertexFormatTest::componentCount,
&VertexFormatTest::componentCountInvalid,
&VertexFormatTest::componentCountImplementationSpecific,
&VertexFormatTest::componentFormat,
&VertexFormatTest::componentFormatInvalid,
&VertexFormatTest::componentFormatImplementationSpecific,
&VertexFormatTest::isNormalized,
&VertexFormatTest::isNormalizedInvalid,
&VertexFormatTest::isNormalizedImplementationSpecific,
&VertexFormatTest::assemble});
@ -93,8 +113,10 @@ VertexFormatTest::VertexFormatTest() {
addTests({&VertexFormatTest::assembleCantNormalize,
&VertexFormatTest::assembleInvalidComponentCount,
&VertexFormatTest::assembleImplementationSpecific,
&VertexFormatTest::debug,
&VertexFormatTest::debugImplementationSpecific,
&VertexFormatTest::configuration});
}
@ -137,6 +159,41 @@ void VertexFormatTest::mapping() {
CORRADE_COMPARE(firstUnhandled, 0xffff);
}
void VertexFormatTest::isImplementationSpecific() {
constexpr bool a = isVertexFormatImplementationSpecific(VertexFormat::Vector2sNormalized);
constexpr bool b = isVertexFormatImplementationSpecific(VertexFormat(0x8000dead));
CORRADE_VERIFY(!a);
CORRADE_VERIFY(b);
}
void VertexFormatTest::wrap() {
constexpr VertexFormat a = Magnum::vertexFormatWrap(0xdead);
CORRADE_COMPARE(UnsignedInt(a), 0x8000dead);
}
void VertexFormatTest::wrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
Magnum::vertexFormatWrap(0xdeadbeef);
CORRADE_COMPARE(out.str(), "vertexFormatWrap(): implementation-specific value 0xdeadbeef already wrapped or too large\n");
}
void VertexFormatTest::unwrap() {
constexpr UnsignedInt a = Magnum::vertexFormatUnwrap(VertexFormat(0x8000dead));
CORRADE_COMPARE(a, 0xdead);
}
void VertexFormatTest::unwrapInvalid() {
std::ostringstream out;
Error redirectError{&out};
Magnum::vertexFormatUnwrap(VertexFormat::Float);
CORRADE_COMPARE(out.str(), "vertexFormatUnwrap(): VertexFormat::Float isn't a wrapped implementation-specific value\n");
}
void VertexFormatTest::size() {
CORRADE_COMPARE(Magnum::vertexFormatSize(VertexFormat::Vector2), sizeof(Vector2));
CORRADE_COMPARE(Magnum::vertexFormatSize(VertexFormat::Vector3), sizeof(Vector3));
@ -155,6 +212,13 @@ void VertexFormatTest::sizeInvalid() {
"vertexFormatSize(): invalid format VertexFormat(0xdead)\n");
}
void VertexFormatTest::sizeImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
Magnum::vertexFormatSize(Magnum::vertexFormatWrap(0xdead));
CORRADE_COMPARE(out.str(), "vertexFormatSize(): can't determine size of an implementation-specific format 0xdead\n");
}
void VertexFormatTest::componentCount() {
CORRADE_COMPARE(Magnum::vertexFormatComponentCount(VertexFormat::UnsignedByteNormalized), 1);
CORRADE_COMPARE(Magnum::vertexFormatComponentCount(VertexFormat::Vector2us), 2);
@ -174,6 +238,14 @@ void VertexFormatTest::componentCountInvalid() {
"vertexFormatComponentCount(): invalid format VertexFormat(0xdead)\n");
}
void VertexFormatTest::componentCountImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
Magnum::vertexFormatComponentCount(Magnum::vertexFormatWrap(0xdead));
CORRADE_COMPARE(out.str(),
"vertexFormatComponentCount(): can't determine component count of an implementation-specific format 0xdead\n");
}
void VertexFormatTest::componentFormat() {
CORRADE_COMPARE(Magnum::vertexFormatComponentFormat(VertexFormat::Vector4), VertexFormat::Float);
CORRADE_COMPARE(Magnum::vertexFormatComponentFormat(VertexFormat::Vector3h), VertexFormat::Half);
@ -199,6 +271,14 @@ void VertexFormatTest::componentFormatInvalid() {
"vertexFormatComponentType(): invalid format VertexFormat(0xdead)\n");
}
void VertexFormatTest::componentFormatImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
Magnum::vertexFormatComponentFormat(Magnum::vertexFormatWrap(0xdead));
CORRADE_COMPARE(out.str(),
"vertexFormatComponentFormat(): can't determine component format of an implementation-specific format 0xdead\n");
}
void VertexFormatTest::isNormalized() {
CORRADE_VERIFY(isVertexFormatNormalized(VertexFormat::UnsignedByteNormalized));
CORRADE_VERIFY(!isVertexFormatNormalized(VertexFormat::Vector2us));
@ -218,6 +298,14 @@ void VertexFormatTest::isNormalizedInvalid() {
"isVertexFormatNormalized(): invalid format VertexFormat(0xdead)\n");
}
void VertexFormatTest::isNormalizedImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
isVertexFormatNormalized(Magnum::vertexFormatWrap(0xdead));
CORRADE_COMPARE(out.str(),
"isVertexFormatNormalized(): can't determine normalization of an implementation-specific format 0xdead\n");
}
void VertexFormatTest::assemble() {
CORRADE_COMPARE(vertexFormat(VertexFormat::UnsignedShort, 3, true),
VertexFormat::Vector3usNormalized);
@ -269,12 +357,26 @@ void VertexFormatTest::assembleInvalidComponentCount() {
"vertexFormat(): invalid component count 5\n");
}
void VertexFormatTest::assembleImplementationSpecific() {
std::ostringstream out;
Error redirectError{&out};
vertexFormat(Magnum::vertexFormatWrap(0xdead), 1, true);
CORRADE_COMPARE(out.str(),
"vertexFormat(): can't assemble a format out of an implementation-specific format 0xdead\n");
}
void VertexFormatTest::debug() {
std::ostringstream o;
Debug(&o) << VertexFormat::Vector4 << VertexFormat(0xdead);
CORRADE_COMPARE(o.str(), "VertexFormat::Vector4 VertexFormat(0xdead)\n");
}
void VertexFormatTest::debugImplementationSpecific() {
std::ostringstream o;
Debug(&o) << Magnum::vertexFormatWrap(0xdead);
CORRADE_COMPARE(o.str(), "VertexFormat::ImplementationSpecific(0xdead)\n");
}
void VertexFormatTest::configuration() {
Utility::Configuration c;

19
src/Magnum/VertexFormat.cpp

@ -33,6 +33,9 @@
namespace Magnum {
UnsignedInt vertexFormatSize(const VertexFormat format) {
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"vertexFormatSize(): can't determine size of an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), {});
switch(format) {
case VertexFormat::UnsignedByte:
case VertexFormat::UnsignedByteNormalized:
@ -102,6 +105,9 @@ UnsignedInt vertexFormatSize(const VertexFormat format) {
}
UnsignedInt vertexFormatComponentCount(const VertexFormat format) {
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"vertexFormatComponentCount(): can't determine component count of an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), {});
switch(format) {
case VertexFormat::Float:
case VertexFormat::Half:
@ -168,6 +174,9 @@ UnsignedInt vertexFormatComponentCount(const VertexFormat format) {
}
VertexFormat vertexFormatComponentFormat(const VertexFormat format) {
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"vertexFormatComponentFormat(): can't determine component format of an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), {});
switch(format) {
case VertexFormat::Float:
case VertexFormat::Vector2:
@ -244,6 +253,9 @@ VertexFormat vertexFormatComponentFormat(const VertexFormat format) {
}
bool isVertexFormatNormalized(const VertexFormat format) {
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"isVertexFormatNormalized(): can't determine normalization of an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), {});
switch(format) {
case VertexFormat::Float:
case VertexFormat::Half:
@ -306,6 +318,9 @@ bool isVertexFormatNormalized(const VertexFormat format) {
}
VertexFormat vertexFormat(const VertexFormat format, UnsignedInt componentCount, bool normalized) {
CORRADE_ASSERT(!isVertexFormatImplementationSpecific(format),
"vertexFormat(): can't assemble a format out of an implementation-specific format" << reinterpret_cast<void*>(vertexFormatUnwrap(format)), {});
VertexFormat componentFormat = vertexFormatComponentFormat(format);
/* First turn the format into a normalized one, if requested */
@ -360,6 +375,10 @@ constexpr const char* VertexFormatNames[] {
Debug& operator<<(Debug& debug, const VertexFormat value) {
debug << "VertexFormat" << Debug::nospace;
if(isVertexFormatImplementationSpecific(value)) {
return debug << "::ImplementationSpecific(" << Debug::nospace << reinterpret_cast<void*>(vertexFormatUnwrap(value)) << Debug::nospace << ")";
}
if(UnsignedInt(value) - 1 < Containers::arraySize(VertexFormatNames)) {
return debug << "::" << Debug::nospace << VertexFormatNames[UnsignedInt(value) - 1];
}

66
src/Magnum/VertexFormat.h

@ -26,9 +26,10 @@
*/
/** @file
* @brief Enum @ref Magnum::VertexFormat, @ref Magnum::vertexFormatSize(), @ref Magnum::vertexFormatComponentCount(), @ref Magnum::vertexFormatComponentFormat(), @ref Magnum::isVertexFormatNormalized()
* @brief Enum @ref Magnum::VertexFormat, function @ref Magnum::isVertexFormatImplementationSpecific(), @ref Magnum::vertexFormatWrap(), @ref Magnum::vertexFormatUnwrap(), @ref Magnum::vertexFormatSize(), @ref Magnum::vertexFormatComponentCount(), @ref Magnum::vertexFormatComponentFormat(), @ref Magnum::isVertexFormatNormalized()
*/
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/StlForwardString.h>
#include "Magnum/Magnum.h"
@ -41,7 +42,12 @@ namespace Magnum {
@m_since_latest
Like @ref PixelFormat, but for mesh attributes --- including double-precision
types and matrices.
types and matrices. Can act also as a wrapper for implementation-specific mesh
attribute type values using @ref vertexFormatWrap() and
@ref vertexFormatUnwrap(). Distinction between generic and
implementation-specific types can be done using
@ref isVertexFormatImplementationSpecific().
@see @ref Trade::MeshData, @ref Trade::MeshAttributeData,
@ref Trade::MeshAttribute
*/
@ -311,6 +317,56 @@ enum class VertexFormat: UnsignedInt {
Vector4i
};
/**
@debugoperatorenum{VertexFormat}
@m_since_latest
*/
MAGNUM_EXPORT Debug& operator<<(Debug& debug, VertexFormat value);
/**
@brief Whether a @ref VertexFormat value wraps an implementation-specific identifier
@m_since_latest
Returns @cpp true @ce if value of @p format has its highest bit set,
@cpp false @ce otherwise. Use @ref vertexFormatWrap() and @ref vertexFormatUnwrap()
to wrap/unwrap an implementation-specific indentifier to/from
@ref VertexFormat.
*/
constexpr bool isVertexFormatImplementationSpecific(VertexFormat format) {
return UnsignedInt(format) & (1u << 31);
}
/**
@brief Wrap an implementation-specific vertex format identifier in @ref VertexFormat
@m_since_latest
Sets the highest bit on @p type to mark it as implementation-specific. Expects
that @p type fits into the remaining bits. Use @ref vertexFormatUnwrap()
for the inverse operation.
@see @ref isVertexFormatImplementationSpecific()
*/
template<class T> constexpr VertexFormat vertexFormatWrap(T implementationSpecific) {
static_assert(sizeof(T) <= 4, "types larger than 32bits are not supported");
return CORRADE_CONSTEXPR_ASSERT(!(UnsignedInt(implementationSpecific) & (1u << 31)),
"vertexFormatWrap(): implementation-specific value" << reinterpret_cast<void*>(implementationSpecific) << "already wrapped or too large"),
VertexFormat((1u << 31)|UnsignedInt(implementationSpecific));
}
/**
@brief Unwrap an implementation-specific vertex format identifier from @ref VertexFormat
@m_since_latest
Unsets the highest bit from @p type to extract the implementation-specific
value. Expects that @p type has it set. Use @ref vertexFormatWrap() for
the inverse operation.
@see @ref isVertexFormatImplementationSpecific()
*/
template<class T = UnsignedInt> constexpr T vertexFormatUnwrap(VertexFormat format) {
return CORRADE_CONSTEXPR_ASSERT(UnsignedInt(format) & (1u << 31),
"vertexFormatUnwrap():" << format << "isn't a wrapped implementation-specific value"),
T(UnsignedInt(format) & ~(1u << 31));
}
/**
@brief Size of given vertex format
@m_since_latest
@ -370,12 +426,6 @@ normalization. Expects that @p componentCount is not larger than @cpp 4 @ce and
*/
MAGNUM_EXPORT VertexFormat vertexFormat(VertexFormat format, UnsignedInt componentCount, bool normalized);
/**
@debugoperatorenum{VertexFormat}
@m_since_latest
*/
MAGNUM_EXPORT Debug& operator<<(Debug& debug, VertexFormat value);
}
namespace Corrade { namespace Utility {

Loading…
Cancel
Save