Browse Source

Primitives: use offset-only attribs for Line and Gradient.

One less allocation for each.
pull/371/head
Vladimír Vondruš 6 years ago
parent
commit
eb98f13b72
  1. 72
      src/Magnum/Primitives/Gradient.cpp
  2. 22
      src/Magnum/Primitives/Line.cpp
  3. 32
      src/Magnum/Trade/MeshData.cpp
  4. 4
      src/Magnum/Trade/Test/MeshDataTest.cpp

72
src/Magnum/Primitives/Gradient.cpp

@ -32,14 +32,27 @@
namespace Magnum { namespace Primitives {
Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB) {
struct Vertex {
namespace {
struct Vertex2D {
Vector2 position;
Color4 color;
};
};
constexpr Trade::MeshAttributeData Attributes2D[]{
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector2, offsetof(Vertex2D, position),
4, sizeof(Vertex2D)},
Trade::MeshAttributeData{Trade::MeshAttribute::Color,
VertexFormat::Vector4, offsetof(Vertex2D, color),
4, sizeof(Vertex2D)},
};
Containers::Array<char> vertexData{sizeof(Vertex)*4};
auto vertices = Containers::arrayCast<Vertex>(vertexData);
}
Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2& b, const Color4& colorB) {
Containers::Array<char> vertexData{sizeof(Vertex2D)*4};
auto vertices = Containers::arrayCast<Vertex2D>(vertexData);
vertices[0].position = { 1.0f, -1.0f};
vertices[1].position = { 1.0f, 1.0f};
vertices[2].position = {-1.0f, -1.0f};
@ -56,14 +69,8 @@ Trade::MeshData gradient2D(const Vector2& a, const Color4& colorA, const Vector2
vertices[i].color = Math::lerp(colorA, colorB, t);
}
Trade::MeshAttributeData positions{Trade::MeshAttribute::Position,
Containers::stridedArrayView(vertices, &vertices[0].position,
vertices.size(), sizeof(Vertex))};
Trade::MeshAttributeData colors{Trade::MeshAttribute::Color,
Containers::stridedArrayView(vertices, &vertices[0].color,
vertices.size(), sizeof(Vertex))};
return Trade::MeshData{MeshPrimitive::TriangleStrip,
std::move(vertexData), {positions, colors}};
return Trade::MeshData{MeshPrimitive::TriangleStrip, std::move(vertexData),
Trade::meshAttributeDataNonOwningArray(Attributes2D)};
}
Trade::MeshData gradient2DHorizontal(const Color4& colorLeft, const Color4& colorRight) {
@ -74,15 +81,31 @@ Trade::MeshData gradient2DVertical(const Color4& colorBottom, const Color4& colo
return Primitives::gradient2D({0.0f, -1.0f}, colorBottom, {0.0f, 1.0f}, colorTop);
}
Trade::MeshData gradient3D(const Vector3& a, const Color4& colorA, const Vector3& b, const Color4& colorB) {
struct Vertex {
namespace {
struct Vertex3D {
Vector3 position;
Vector3 normal;
Color4 color;
};
};
constexpr Trade::MeshAttributeData Attributes3D[]{
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector3, offsetof(Vertex3D, position),
4, sizeof(Vertex3D)},
Trade::MeshAttributeData{Trade::MeshAttribute::Normal,
VertexFormat::Vector3, offsetof(Vertex3D, normal),
4, sizeof(Vertex3D)},
Trade::MeshAttributeData{Trade::MeshAttribute::Color,
VertexFormat::Vector4, offsetof(Vertex3D, color),
4, sizeof(Vertex3D)},
};
Containers::Array<char> vertexData{sizeof(Vertex)*4};
auto vertices = Containers::arrayCast<Vertex>(vertexData);
}
Trade::MeshData gradient3D(const Vector3& a, const Color4& colorA, const Vector3& b, const Color4& colorB) {
Containers::Array<char> vertexData{sizeof(Vertex3D)*4};
auto vertices = Containers::arrayCast<Vertex3D>(vertexData);
vertices[0].position = { 1.0f, -1.0f, 0};
vertices[1].position = { 1.0f, 1.0f, 0};
vertices[2].position = {-1.0f, -1.0f, 0};
@ -103,17 +126,8 @@ Trade::MeshData gradient3D(const Vector3& a, const Color4& colorA, const Vector3
vertices[i].color = Math::lerp(colorA, colorB, t);
}
Trade::MeshAttributeData positions{Trade::MeshAttribute::Position,
Containers::stridedArrayView(vertices, &vertices[0].position,
vertices.size(), sizeof(Vertex))};
Trade::MeshAttributeData normals{Trade::MeshAttribute::Normal,
Containers::stridedArrayView(vertices, &vertices[0].normal,
vertices.size(), sizeof(Vertex))};
Trade::MeshAttributeData colors{Trade::MeshAttribute::Color,
Containers::stridedArrayView(vertices, &vertices[0].color,
vertices.size(), sizeof(Vertex))};
return Trade::MeshData{MeshPrimitive::TriangleStrip,
std::move(vertexData), {positions, normals, colors}};
return Trade::MeshData{MeshPrimitive::TriangleStrip, std::move(vertexData),
Trade::meshAttributeDataNonOwningArray(Attributes3D)};
}
Trade::MeshData gradient3DHorizontal(const Color4& colorLeft, const Color4& colorRight) {

22
src/Magnum/Primitives/Line.cpp

@ -31,6 +31,15 @@
namespace Magnum { namespace Primitives {
namespace {
constexpr Trade::MeshAttributeData Attributes2D[]{
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector2, 0, 2, sizeof(Vector2)},
};
}
Trade::MeshData line2D(const Vector2& a, const Vector2& b) {
Containers::Array<char> vertexData{sizeof(Vector2)*2};
auto positions = Containers::arrayCast<Vector2>(vertexData);
@ -38,7 +47,16 @@ Trade::MeshData line2D(const Vector2& a, const Vector2& b) {
positions[1] = b;
return Trade::MeshData{MeshPrimitive::Lines, std::move(vertexData),
{Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}};
Trade::meshAttributeDataNonOwningArray(Attributes2D)};
}
namespace {
constexpr Trade::MeshAttributeData Attributes3D[]{
Trade::MeshAttributeData{Trade::MeshAttribute::Position,
VertexFormat::Vector3, 0, 2, sizeof(Vector3)},
};
}
Trade::MeshData line3D(const Vector3& a, const Vector3& b) {
@ -48,7 +66,7 @@ Trade::MeshData line3D(const Vector3& a, const Vector3& b) {
positions[1] = b;
return Trade::MeshData{MeshPrimitive::Lines, std::move(vertexData),
{Trade::MeshAttributeData{Trade::MeshAttribute::Position, positions}}};
Trade::meshAttributeDataNonOwningArray(Attributes3D)};
}
Trade::MeshData line2D() {

32
src/Magnum/Trade/MeshData.cpp

@ -302,12 +302,22 @@ UnsignedInt MeshData::attributeStride(MeshAttribute name, UnsignedInt id) const
return attributeStride(attributeId);
}
Containers::StridedArrayView1D<const void> MeshData::attributeDataViewInternal(const MeshAttributeData& attribute) const {
return Containers::StridedArrayView1D<const void>{
/* We're *sure* the view is correct, so faking the view size */
/** @todo better ideas for the StridedArrayView API? */
{attribute._isOffsetOnly ? _vertexData.data() + attribute._data.offset :
attribute._data.pointer, ~std::size_t{}},
/* Not using attribute._vertexCount because that gets stale after
releaseVertexData() gets called, and then we would need to slice the
result inside attribute() and elsewhere anyway */
_vertexCount, attribute._stride};
}
Containers::StridedArrayView2D<const char> MeshData::attribute(UnsignedInt id) const {
CORRADE_ASSERT(id < _attributes.size(),
"Trade::MeshData::attribute(): index" << id << "out of range for" << _attributes.size() << "attributes", nullptr);
/* Build a 2D view using information about attribute type size, return only
a prefix of the actual vertex count (which is zero in case vertex data
is released) */
/* Build a 2D view using information about attribute type size */
return Containers::arrayCast<2, const char>(
attributeDataViewInternal(_attributes[id]),
vertexFormatSize(_attributes[id]._format));
@ -318,9 +328,7 @@ Containers::StridedArrayView2D<char> MeshData::mutableAttribute(UnsignedInt id)
"Trade::MeshData::mutableAttribute(): vertex data not mutable", {});
CORRADE_ASSERT(id < _attributes.size(),
"Trade::MeshData::mutableAttribute(): index" << id << "out of range for" << _attributes.size() << "attributes", nullptr);
/* Build a 2D view using information about attribute type size, return only
a prefix of the actual vertex count (which is zero in case vertex data
is released) */
/* Build a 2D view using information about attribute type size */
auto out = Containers::arrayCast<2, const char>(
attributeDataViewInternal(_attributes[id]),
vertexFormatSize(_attributes[id]._format));
@ -378,18 +386,6 @@ Containers::Array<UnsignedInt> MeshData::indicesAsArray() const {
return output;
}
Containers::StridedArrayView1D<const void> MeshData::attributeDataViewInternal(const MeshAttributeData& attribute) const {
return Containers::StridedArrayView1D<const void>{
/* We're *sure* the view is correct, so faking the view size */
/** @todo better ideas for the StridedArrayView API? */
{attribute._isOffsetOnly ? _vertexData.data() + attribute._data.offset :
attribute._data.pointer, ~std::size_t{}},
/* Not using attribute._vertexCount because that gets stale after
releaseVertexData() gets called, and then we would need to slice the
result inside attribute() and elsewhere */
_vertexCount, attribute._stride};
}
void MeshData::positions2DInto(const Containers::StridedArrayView1D<Vector2> destination, const UnsignedInt id) const {
const UnsignedInt attributeId = attributeFor(MeshAttribute::Position, id);
CORRADE_ASSERT(attributeId != ~UnsignedInt{}, "Trade::MeshData::positions2DInto(): index" << id << "out of range for" << attributeCount(MeshAttribute::Position) << "position attributes", );

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

@ -486,6 +486,7 @@ void MeshDataTest::constructAttribute2D() {
{4, sizeof(Vector2)}}.every(2);
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, positionView};
CORRADE_VERIFY(!positions.isOffsetOnly());
CORRADE_COMPARE(positions.name(), MeshAttribute::Position);
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2);
CORRADE_COMPARE(positions.data().data(), positionView.data());
@ -516,6 +517,7 @@ void MeshDataTest::constructAttribute2DNonContiguous() {
void MeshDataTest::constructAttributeTypeErased() {
const Vector3 positionData[3]{};
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector3, Containers::arrayCast<const char>(Containers::stridedArrayView(positionData))};
CORRADE_VERIFY(!positions.isOffsetOnly());
CORRADE_COMPARE(positions.name(), MeshAttribute::Position);
CORRADE_COMPARE(positions.format(), VertexFormat::Vector3);
CORRADE_VERIFY(positions.data().data() == positionData);
@ -523,6 +525,7 @@ void MeshDataTest::constructAttributeTypeErased() {
void MeshDataTest::constructAttributeNullptr() {
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr};
CORRADE_VERIFY(!positions.isOffsetOnly());
CORRADE_COMPARE(positions.name(), MeshAttribute::Position);
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2);
CORRADE_VERIFY(!positions.data().data());
@ -530,6 +533,7 @@ void MeshDataTest::constructAttributeNullptr() {
void MeshDataTest::constructAttributePadding() {
MeshAttributeData padding{-35};
CORRADE_VERIFY(!padding.isOffsetOnly());
CORRADE_COMPARE(padding.name(), MeshAttribute{});
CORRADE_COMPARE(padding.format(), VertexFormat{});
CORRADE_COMPARE(padding.data().size(), 0);

Loading…
Cancel
Save