Browse Source

GL: support custom stride between vectors in matrix Attributes.

Needed so e.g. Matrix3x3s can have four-byte-aligned columns.
pull/430/head
Vladimír Vondruš 6 years ago
parent
commit
e3fcf9db57
  1. 4
      doc/changelog.dox
  2. 57
      src/Magnum/GL/Attribute.h
  3. 8
      src/Magnum/GL/Mesh.h
  4. 80
      src/Magnum/GL/Test/AttributeTest.cpp

4
doc/changelog.dox

@ -251,6 +251,8 @@ See also:
[mosra/magnum#403](https://github.com/mosra/magnum/pull/403))
- Added an ability to remove a buffer from a @ref GL::BufferTexture using
@ref GL::BufferTexture::resetBuffer() "resetBuffer()"
- Matrix @ref GL::Attribute instances can now specify custom stride between
column vectors in order to control alignment in packed 8- and 16-bit types
@subsubsection changelog-latest-changes-math Math library
@ -422,6 +424,8 @@ See also:
@ref GL::Attribute::DataType::Half,
@ref GL::DynamicAttribute::DataType::Half and @ref GL::PixelType::Half that
are consistent with the @ref Half type used elsewhere.
- @cpp GL::Attribute::vectorSize() @ce is deprecated as the name is
misleading now, use @ref GL::Attribute::vectorStride() instead
- @cpp Trade::AbstractImporter::mesh2D() @ce,
@cpp Trade::MeshData2D @ce, @cpp Trade::MeshData3D @ce,
@cpp Trade::AbstractImporter::mesh2D() @ce,

57
src/Magnum/GL/Attribute.h

@ -286,25 +286,56 @@ template<UnsignedInt location, class T> class Attribute {
/**
* @brief Constructor
* @param components Component count
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for
* @ref Magnum::Vector4i "Vector4i").
* @param dataOptions Data options. Default is no options.
*
* Component count is set to the same value as in type used in shader
* (e.g. @ref Components::Three for @ref Magnum::Vector3 "Vector3").
*/
constexpr Attribute(Components components, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(components), _dataType(dataType), _dataOptions(dataOptions) {}
constexpr Attribute(DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{Implementation::Attribute<T>::DefaultComponents, dataType, dataOptions} {}
/**
* @brief Constructor
* @param components Component count
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for
* @ref Magnum::Vector4i "Vector4i").
* @param dataOptions Data options. Default is no options.
*
* Vector stride is set to the size of the vector type (e.g. 9 for a
* @ref Magnum::Matrix3 "Matrix3").
*/
constexpr Attribute(Components components, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{components, Implementation::Attribute<T>::size(GLint(components), dataType), dataType, dataOptions} {}
/**
* @brief Construct with a custom vector stride
* @param vectorStride Stride between consecutive matrix column
* vectors
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for
* @ref Magnum::Vector4i "Vector4i").
* @param dataOptions Data options. Default is no options.
* @m_since_latest
*
* Component count is set to the same value as in type used in shader
* (e.g. @ref Components::Three for @ref Magnum::Vector3 "Vector3").
*/
constexpr Attribute(DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components(Implementation::Attribute<T>::DefaultComponents), _dataType(dataType), _dataOptions(dataOptions) {}
constexpr Attribute(UnsignedInt vectorStride, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): Attribute{Implementation::Attribute<T>::DefaultComponents, vectorStride, dataType, dataOptions} {}
/**
* @brief Construct with a custom vector stride
* @param components Component count
* @param vectorStride Stride between consecutive matrix column
* vectors
* @param dataType Type of passed data. Default is the same as
* type used in shader (e.g. @ref DataType::Int for
* @ref Magnum::Vector4i "Vector4i").
* @param dataOptions Data options. Default is no options.
* @m_since_latest
*/
constexpr Attribute(Components components, UnsignedInt vectorStride, DataType dataType = Implementation::Attribute<T>::DefaultDataType, DataOptions dataOptions = DataOptions()): _components{components}, _vectorStride{vectorStride}, _dataType{dataType}, _dataOptions{dataOptions} {}
/** @brief Component count of passed data */
constexpr Components components() const { return _components; }
@ -312,20 +343,36 @@ template<UnsignedInt location, class T> class Attribute {
/** @brief Type of passed data */
constexpr DataType dataType() const { return _dataType; }
/**
* @brief Stride between consecutive vector elements
* @m_since_latest
*
* Used for describing matrix attributes. Implicitly the same as size
* of given vector type (e.g. @cpp 9 @ce for a
* @ref Magnum::Matrix3 "Matrix3"), but can be overriden for example to
* ensure four-byte column alignment with 1- and 2-byte data types.
* @see @ref Vectors
*/
constexpr UnsignedInt vectorStride() const { return _vectorStride; }
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Size of each vector in passed data
* @m_deprecated_since_latest Use @ref vectorStride() instead.
*
* @see @ref VectorCount
*/
UnsignedInt vectorSize() const {
return Implementation::Attribute<T>::size(GLint(_components), _dataType);
constexpr CORRADE_DEPRECATED("use vectorStride() instead") UnsignedInt vectorSize() const {
return vectorStride();
}
#endif
/** @brief Data options */
constexpr DataOptions dataOptions() const { return _dataOptions; }
private:
Components _components;
UnsignedInt _vectorStride;
DataType _dataType;
DataOptions _dataOptions;
};

8
src/Magnum/GL/Mesh.h

@ -1002,7 +1002,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
/* Computing stride of interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> static GLsizei strideOfInterleaved(const Attribute<location, T>& attribute, const U&... attributes) {
return attribute.vectorSize()*Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...);
return attribute.vectorStride()*Attribute<location, T>::VectorCount + strideOfInterleaved(attributes...);
}
template<class ...T> static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) {
return gap + strideOfInterleaved(attributes...);
@ -1014,7 +1014,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
addVertexAttribute(buffer, attribute, offset, stride, divisor);
/* Add size of this attribute to offset for next attribute */
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*Attribute<location, T>::VectorCount, stride, divisor, attributes...);
addVertexBufferInternal(buffer, offset+attribute.vectorStride()*Attribute<location, T>::VectorCount, stride, divisor, attributes...);
}
template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */
@ -1029,7 +1029,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
GLint(attribute.components()),
GLenum(attribute.dataType()),
Implementation::kindFor<location, T>(attribute.dataOptions()),
GLintptr(offset+i*attribute.vectorSize()),
GLintptr(offset+i*attribute.vectorStride()),
stride,
divisor);
}
@ -1054,7 +1054,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
GLint(attribute.components()),
GLenum(attribute.dataType()),
Implementation::kindFor<location, T>(attribute.dataOptions()),
GLintptr(offset+i*attribute.vectorSize()),
GLintptr(offset+i*attribute.vectorStride()),
stride,
divisor);
}

80
src/Magnum/GL/Test/AttributeTest.cpp

@ -51,6 +51,7 @@ struct AttributeTest: TestSuite::Tester {
#ifndef MAGNUM_TARGET_GLES2
void attributeMatrixMxN();
#endif
void attributeMatrixNxNCustomStride();
void attributeMatrixNxNd();
void attributeMatrixMxNd();
@ -116,6 +117,7 @@ AttributeTest::AttributeTest() {
#ifndef MAGNUM_TARGET_GLES2
&AttributeTest::attributeMatrixMxN,
#endif
&AttributeTest::attributeMatrixNxNCustomStride,
&AttributeTest::attributeMatrixNxNd,
&AttributeTest::attributeMatrixMxNd,
@ -174,7 +176,7 @@ void AttributeTest::attributeScalar() {
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::One);
CORRADE_VERIFY(!a.dataOptions());
CORRADE_COMPARE(a.vectorSize(), 4);
CORRADE_COMPARE(a.vectorStride(), 4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
DynamicAttribute da{a};
@ -185,7 +187,7 @@ void AttributeTest::attributeScalar() {
/* Options */
Attribute b(Attribute::DataType::UnsignedShort, Attribute::DataOption::Normalized);
CORRADE_COMPARE(b.vectorSize(), 2);
CORRADE_COMPARE(b.vectorStride(), 2);
CORRADE_VERIFY(b.dataOptions() <= Attribute::DataOption::Normalized);
DynamicAttribute db{b};
@ -203,7 +205,7 @@ void AttributeTest::attributeScalarInt() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.vectorSize(), 4);
CORRADE_COMPARE(a.vectorStride(), 4);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral);
@ -213,7 +215,7 @@ void AttributeTest::attributeScalarInt() {
/* Options */
Attribute b(Attribute::DataType::Short);
CORRADE_COMPARE(b.vectorSize(), 2);
CORRADE_COMPARE(b.vectorStride(), 2);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral);
@ -233,7 +235,7 @@ void AttributeTest::attributeScalarUnsignedInt() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.vectorSize(), 4);
CORRADE_COMPARE(a.vectorStride(), 4);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Integral);
@ -243,7 +245,7 @@ void AttributeTest::attributeScalarUnsignedInt() {
/* Options */
Attribute b(Attribute::DataType::UnsignedByte);
CORRADE_COMPARE(b.vectorSize(), 1);
CORRADE_COMPARE(b.vectorStride(), 1);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral);
@ -263,7 +265,7 @@ void AttributeTest::attributeScalarDouble() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.vectorSize(), 8);
CORRADE_COMPARE(a.vectorStride(), 8);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Long);
@ -283,7 +285,7 @@ void AttributeTest::attributeVector() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Three);
CORRADE_COMPARE(a.vectorSize(), 3*4);
CORRADE_COMPARE(a.vectorStride(), 3*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
DynamicAttribute da{a};
@ -296,7 +298,7 @@ void AttributeTest::attributeVector() {
#ifndef MAGNUM_TARGET_GLES
Attribute b(Attribute::Components::Two, Attribute::DataType::Double);
CORRADE_COMPARE(b.components(), Attribute::Components::Two);
CORRADE_COMPARE(b.vectorSize(), 2*8);
CORRADE_COMPARE(b.vectorStride(), 2*8);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic);
@ -306,7 +308,7 @@ void AttributeTest::attributeVector() {
#else
Attribute b(Attribute::Components::Two, Attribute::DataType::Float);
CORRADE_COMPARE(b.components(), Attribute::Components::Two);
CORRADE_COMPARE(b.vectorSize(), 2*4);
CORRADE_COMPARE(b.vectorStride(), 2*4);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic);
@ -325,7 +327,7 @@ void AttributeTest::attributeVectorInt() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Two);
CORRADE_COMPARE(a.vectorSize(), 2*4);
CORRADE_COMPARE(a.vectorStride(), 2*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Int);
DynamicAttribute da{a};
@ -336,7 +338,7 @@ void AttributeTest::attributeVectorInt() {
/* Options */
Attribute b(Attribute::Components::One, Attribute::DataType::Int);
CORRADE_COMPARE(b.vectorSize(), 4);
CORRADE_COMPARE(b.vectorStride(), 4);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral);
@ -357,7 +359,7 @@ void AttributeTest::attributeVectorUnsignedInt() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Four);
CORRADE_COMPARE(a.vectorSize(), 4*4);
CORRADE_COMPARE(a.vectorStride(), 4*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::UnsignedInt);
DynamicAttribute da{a};
@ -368,7 +370,7 @@ void AttributeTest::attributeVectorUnsignedInt() {
/* Options */
Attribute b(Attribute::Components::Three, Attribute::DataType::UnsignedShort);
CORRADE_COMPARE(b.vectorSize(), 3*2);
CORRADE_COMPARE(b.vectorStride(), 3*2);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Integral);
@ -389,7 +391,7 @@ void AttributeTest::attributeVectorDouble() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Two);
CORRADE_COMPARE(a.vectorSize(), 2*8);
CORRADE_COMPARE(a.vectorStride(), 2*8);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double);
DynamicAttribute da{a};
@ -400,7 +402,7 @@ void AttributeTest::attributeVectorDouble() {
/* Options */
Attribute b(Attribute::Components::One);
CORRADE_COMPARE(b.vectorSize(), 8);
CORRADE_COMPARE(b.vectorStride(), 8);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Long);
@ -420,7 +422,7 @@ void AttributeTest::attributeVector4() {
/* Custom type */
#ifndef MAGNUM_TARGET_GLES
Attribute a(Attribute::DataType::UnsignedInt2101010Rev);
CORRADE_COMPARE(a.vectorSize(), 4);
CORRADE_COMPARE(a.vectorStride(), 4);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic);
@ -429,7 +431,7 @@ void AttributeTest::attributeVector4() {
CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::UnsignedInt2101010Rev);
#elif !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Attribute a(Attribute::DataType::Half);
CORRADE_COMPARE(a.vectorSize(), 8);
CORRADE_COMPARE(a.vectorStride(), 8);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic);
@ -438,7 +440,7 @@ void AttributeTest::attributeVector4() {
CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Half);
#else
Attribute a(Attribute::DataType::Float);
CORRADE_COMPARE(a.vectorSize(), 16);
CORRADE_COMPARE(a.vectorStride(), 16);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic);
@ -456,7 +458,7 @@ void AttributeTest::attributeVectorBGRA() {
/* BGRA */
Attribute a(Attribute::Components::BGRA);
CORRADE_COMPARE(a.vectorSize(), 4*4);
CORRADE_COMPARE(a.vectorStride(), 4*4);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic);
@ -476,7 +478,7 @@ void AttributeTest::attributeMatrixNxN() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Three);
CORRADE_COMPARE(a.vectorSize(), 3*4);
CORRADE_COMPARE(a.vectorStride(), 3*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
DynamicAttribute da{a};
@ -486,6 +488,36 @@ void AttributeTest::attributeMatrixNxN() {
CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Float);
}
void AttributeTest::attributeMatrixNxNCustomStride() {
typedef Attribute<3, Matrix3> Attribute;
CORRADE_VERIFY((std::is_same<Attribute::ScalarType, Float>{}));
CORRADE_COMPARE(Attribute::VectorCount, 3);
/* Default stride */
Attribute a{Attribute::DataType::Short};
CORRADE_COMPARE(a.components(), Attribute::Components::Three);
CORRADE_COMPARE(a.vectorStride(), 6);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Short);
DynamicAttribute da{a};
CORRADE_COMPARE(da.kind(), DynamicAttribute::Kind::Generic);
CORRADE_COMPARE(da.location(), 3);
CORRADE_COMPARE(da.components(), DynamicAttribute::Components::Three);
CORRADE_COMPARE(da.dataType(), DynamicAttribute::DataType::Short);
/* Custom stride */
Attribute b{8, Attribute::DataType::Short};
CORRADE_COMPARE(b.components(), Attribute::Components::Three);
CORRADE_COMPARE(b.vectorStride(), 8);
CORRADE_COMPARE(b.dataType(), Attribute::DataType::Short);
DynamicAttribute db{b};
CORRADE_COMPARE(db.kind(), DynamicAttribute::Kind::Generic);
CORRADE_COMPARE(db.location(), 3);
CORRADE_COMPARE(db.components(), DynamicAttribute::Components::Three);
CORRADE_COMPARE(db.dataType(), DynamicAttribute::DataType::Short);
}
#ifndef MAGNUM_TARGET_GLES2
void AttributeTest::attributeMatrixMxN() {
typedef Attribute<3, Matrix3x4> Attribute;
@ -495,7 +527,7 @@ void AttributeTest::attributeMatrixMxN() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Four);
CORRADE_COMPARE(a.vectorSize(), 4*4);
CORRADE_COMPARE(a.vectorStride(), 4*4);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Float);
DynamicAttribute da{a};
@ -515,7 +547,7 @@ void AttributeTest::attributeMatrixNxNd() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Four);
CORRADE_COMPARE(a.vectorSize(), 4*8);
CORRADE_COMPARE(a.vectorStride(), 4*8);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double);
DynamicAttribute da{a};
@ -537,7 +569,7 @@ void AttributeTest::attributeMatrixMxNd() {
/* Default constructor */
Attribute a;
CORRADE_COMPARE(a.components(), Attribute::Components::Two);
CORRADE_COMPARE(a.vectorSize(), 2*8);
CORRADE_COMPARE(a.vectorStride(), 2*8);
CORRADE_COMPARE(a.dataType(), Attribute::DataType::Double);
DynamicAttribute da{a};

Loading…
Cancel
Save