Browse Source

Trade: assert that MeshAttributeData vertex count fits into 32 bits.

Given the recent issues with vertex data with size over 4 GB, I feel
this limit might get hit soon as well. So far GPUs don't support vertex
counts larger than 32 bits, so storing them in a 32-bit number matches
the limitation there. Also, a vertex is usually at least 6 bytes (for
3-component positions quantized into 16-bit ints), thus a mesh hitting
this limit would be 24 GB in size. Which fits only on the beefiest
contemporary GPUs.

However I imagine the limit might get raised eventually, for example to
support a use case of a huge sparse mesh where only sub-parts of it are
drawn, and the sub-parts have counts that fit into 32 bits.
pull/617/head
Vladimír Vondruš 3 years ago
parent
commit
47dfb94467
  1. 18
      src/Magnum/Trade/MeshData.h
  2. 23
      src/Magnum/Trade/Test/MeshDataTest.cpp

18
src/Magnum/Trade/MeshData.h

@ -448,11 +448,12 @@ class MAGNUM_TRADE_EXPORT MeshAttributeData {
* @param arraySize Array size. Use @cpp 0 @ce for non-array
* attributes.
*
* Expects that @p data stride fits into a signed 16-bit value, and for
* builtin attributes that @p format corresponds to @p name,
* @p arraySize is either zero for non-array attributes or non-zero for
* array attributes. The stride can be zero or negative, but note that
* such data layouts are not commonly supported by GPU APIs.
* Expects that @p data stride fits into a signed 16-bit value, that
* vertex count fits into 32 bits, and for builtin attributes that
* @p format corresponds to @p name, @p arraySize is either zero for
* non-array attributes or non-zero for array attributes. The stride
* can be zero or negative, but note that such data layouts are not
* commonly supported by GPU APIs.
*/
explicit MeshAttributeData(MeshAttribute name, VertexFormat format, const Containers::StridedArrayView1D<const void>& data, UnsignedShort arraySize = 0) noexcept;
@ -2429,7 +2430,12 @@ constexpr MeshAttributeData::MeshAttributeData(std::nullptr_t, const MeshAttribu
_format{format},
_name{(CORRADE_CONSTEXPR_ASSERT(Implementation::isVertexFormatCompatibleWithAttribute(name, format),
"Trade::MeshAttributeData:" << format << "is not a valid format for" << name), name)},
_isOffsetOnly{false}, _vertexCount{UnsignedInt(data.size())},
_isOffsetOnly{false},
_vertexCount{(
#ifndef CORRADE_TARGET_32BIT
CORRADE_CONSTEXPR_ASSERT(data.size() <= 0xffffffffu, "Trade::MeshAttributeData: expected vertex count to fit into 32 bits but got" << data.size()),
#endif
UnsignedInt(data.size()))},
_stride{(CORRADE_CONSTEXPR_ASSERT(data.stride() >= -32768 && data.stride() <= 32767,
"Trade::MeshAttributeData: expected stride to fit into 16 bits but got" << data.stride()),
Short(data.stride()))},

23
src/Magnum/Trade/Test/MeshDataTest.cpp

@ -75,6 +75,9 @@ struct MeshDataTest: TestSuite::Tester {
void constructAttributeOffsetOnly();
void constructAttributeImplementationSpecificFormat();
void constructAttributeWrongFormat();
#ifndef CORRADE_TARGET_32BIT
void constructAttributeWrongSize();
#endif
void constructAttributeWrongStride();
void constructAttributeWrongDataAccess();
void constructAttributeOnlyArrayAllowed();
@ -262,6 +265,9 @@ MeshDataTest::MeshDataTest() {
&MeshDataTest::constructAttributeOffsetOnly,
&MeshDataTest::constructAttributeImplementationSpecificFormat,
&MeshDataTest::constructAttributeWrongFormat,
#ifndef CORRADE_TARGET_32BIT
&MeshDataTest::constructAttributeWrongSize,
#endif
&MeshDataTest::constructAttributeWrongStride,
&MeshDataTest::constructAttributeWrongDataAccess,
&MeshDataTest::constructAttributeOnlyArrayAllowed,
@ -992,6 +998,23 @@ void MeshDataTest::constructAttributeWrongFormat() {
"Trade::MeshAttributeData: VertexFormat::Vector2 is not a valid format for Trade::MeshAttribute::Color\n");
}
#ifndef CORRADE_TARGET_32BIT
void MeshDataTest::constructAttributeWrongSize() {
CORRADE_SKIP_IF_NO_ASSERT();
/* This should be fine */
MeshAttributeData{MeshAttribute::Position, Containers::ArrayView<Vector2>{nullptr, 0xffffffffu}};
std::ostringstream out;
Error redirectError{&out};
MeshAttributeData{MeshAttribute::Position, Containers::ArrayView<Vector2>{nullptr, 0x100000000ull}};
/* The offset-only constructors takes the count as an UnsignedInt already,
nothing to check there */
CORRADE_COMPARE(out.str(),
"Trade::MeshAttributeData: expected vertex count to fit into 32 bits but got 4294967296\n");
}
#endif
void MeshDataTest::constructAttributeWrongStride() {
CORRADE_SKIP_IF_NO_ASSERT();

Loading…
Cancel
Save