Browse Source

Shaders: supply Vector material information in a separate UBO as well.

So it's all having the same workflow. This one results in even more
saved UBO slots per-draw than in the case of Flat, and the slowdown on
Intel is as bad as expected.
pull/518/head
Vladimír Vondruš 5 years ago
parent
commit
8077681388
  1. 23
      src/Magnum/Shaders/Test/ShadersGLBenchmark.cpp
  2. 167
      src/Magnum/Shaders/Test/VectorGLTest.cpp
  3. 91
      src/Magnum/Shaders/Test/VectorTest.cpp
  4. 24
      src/Magnum/Shaders/Vector.frag
  5. 145
      src/Magnum/Shaders/Vector.h
  6. 32
      src/Magnum/Shaders/VectorGL.cpp
  7. 65
      src/Magnum/Shaders/VectorGL.h

23
src/Magnum/Shaders/Test/ShadersGLBenchmark.cpp

@ -204,16 +204,16 @@ const struct {
const struct {
const char* name;
VectorGL2D::Flags flags;
UnsignedInt drawCount;
UnsignedInt materialCount, drawCount;
} VectorData[] {
{"", {}, 1},
{"texture transformation", VectorGL2D::Flag::TextureTransformation, 1},
{"", {}, 1, 1},
{"texture transformation", VectorGL2D::Flag::TextureTransformation, 1, 1},
#ifndef MAGNUM_TARGET_GLES2
{"UBO single", VectorGL2D::Flag::UniformBuffers, 1},
{"UBO single, texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1},
{"UBO multi", VectorGL2D::Flag::UniformBuffers, 128},
{"UBO multi, texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 128},
{"multidraw", VectorGL2D::Flag::MultiDraw, 128},
{"UBO single", VectorGL2D::Flag::UniformBuffers, 1, 1},
{"UBO single, texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1},
{"UBO multi", VectorGL2D::Flag::UniformBuffers, 32, 128},
{"UBO multi, texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 32, 128},
{"multidraw", VectorGL2D::Flag::MultiDraw, 32, 128},
#endif
};
@ -826,7 +826,7 @@ template<UnsignedInt dimensions> void ShadersGLBenchmark::vector() {
VectorGL<dimensions> shader{data.flags
#ifndef MAGNUM_TARGET_GLES2
, data.drawCount
, data.materialCount, data.drawCount
#endif
};
shader.bindVectorTexture(_textureWhite);
@ -835,11 +835,14 @@ template<UnsignedInt dimensions> void ShadersGLBenchmark::vector() {
GL::Buffer transformationProjectionUniform{NoCreate};
GL::Buffer drawUniform{NoCreate};
GL::Buffer textureTransformationUniform{NoCreate};
GL::Buffer materialUniform{NoCreate};
if(data.flags & VectorGL2D::Flag::UniformBuffers) {
transformationProjectionUniform = GL::Buffer{GL::Buffer::TargetHint::Uniform, Containers::Array<typename UniformTraits<dimensions>::TransformationProjection>{data.drawCount}};
drawUniform = GL::Buffer{GL::Buffer::TargetHint::Uniform, Containers::Array<VectorDrawUniform>{data.drawCount}};
materialUniform = GL::Buffer{GL::Buffer::TargetHint::Uniform, Containers::Array<VectorMaterialUniform>{data.materialCount}};
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform);
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform);
if(data.flags & VectorGL2D::Flag::TextureTransformation) {
textureTransformationUniform = GL::Buffer{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}

167
src/Magnum/Shaders/Test/VectorGLTest.cpp

@ -29,6 +29,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/Directory.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/FormatStl.h>
#include "Magnum/Image.h"
#include "Magnum/ImageView.h"
@ -85,7 +86,7 @@ struct VectorGLTest: GL::OpenGLTester {
#endif
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffersZeroDraws();
template<UnsignedInt dimensions> void constructUniformBuffersInvalid();
#endif
#ifndef MAGNUM_TARGET_GLES2
@ -165,15 +166,29 @@ constexpr struct {
constexpr struct {
const char* name;
VectorGL2D::Flags flags;
UnsignedInt drawCount;
UnsignedInt materialCount, drawCount;
} ConstructUniformBuffersData[]{
{"classic fallback", {}, 1},
{"", VectorGL2D::Flag::UniformBuffers, 1},
{"texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1},
/* SwiftShader has 256 uniform vectors at most, per-draw is 4+3 in 3D case
and 3+3 in 2D */
{"multiple draws", VectorGL2D::Flag::UniformBuffers, 36},
{"multidraw with all the things", VectorGL2D::Flag::MultiDraw|VectorGL2D::Flag::TextureTransformation, 36}
{"classic fallback", {}, 1, 1},
{"", VectorGL2D::Flag::UniformBuffers, 1, 1},
{"texture transformation", VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation, 1, 1},
/* SwiftShader has 256 uniform vectors at most, per-draw is 4+1 in 3D case
and 3+1 in 2D, per-material 3 */
{"multiple materials, draws", VectorGL2D::Flag::UniformBuffers, 15, 42},
{"multidraw with all the things", VectorGL2D::Flag::MultiDraw|VectorGL2D::Flag::TextureTransformation, 15, 42}
};
#endif
#ifndef MAGNUM_TARGET_GLES2
constexpr struct {
const char* name;
VectorGL2D::Flags flags;
UnsignedInt materialCount, drawCount;
const char* message;
} ConstructUniformBuffersInvalidData[]{
{"zero draws", VectorGL2D::Flag::UniformBuffers, 1, 0,
"draw count can't be zero"},
{"zero materials", VectorGL2D::Flag::UniformBuffers, 0, 1,
"material count can't be zero"},
};
#endif
@ -200,20 +215,20 @@ constexpr struct {
const char* expected2D;
const char* expected3D;
VectorGL2D::Flags flags;
UnsignedInt drawCount;
UnsignedInt materialCount, drawCount;
UnsignedInt uniformIncrement;
Float maxThreshold, meanThreshold;
} RenderMultiData[] {
{"bind with offset", "multidraw2D.tga", "multidraw3D.tga",
{}, 1, 16,
{}, 1, 1, 16,
/* Minor differences on ARM Mali */
1.34f, 0.02f},
{"draw offset", "multidraw2D.tga", "multidraw3D.tga",
{}, 3, 1,
{}, 2, 3, 1,
/* Minor differences on ARM Mali */
1.34f, 0.02f},
{"multidraw", "multidraw2D.tga", "multidraw3D.tga",
VectorGL2D::Flag::MultiDraw, 3, 1,
VectorGL2D::Flag::MultiDraw, 2, 3, 1,
/* Minor differences on ARM Mali */
1.34f, 0.02f},
};
@ -240,12 +255,16 @@ VectorGLTest::VectorGLTest() {
&VectorGLTest::constructMoveUniformBuffers<2>,
&VectorGLTest::constructMoveUniformBuffers<3>,
#endif
});
#ifndef MAGNUM_TARGET_GLES2
&VectorGLTest::constructUniformBuffersZeroDraws<2>,
&VectorGLTest::constructUniformBuffersZeroDraws<3>,
#endif
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<VectorGLTest>({
&VectorGLTest::constructUniformBuffersInvalid<2>,
&VectorGLTest::constructUniformBuffersInvalid<3>},
Containers::arraySize(ConstructUniformBuffersInvalidData));
#endif
addTests<VectorGLTest>({
#ifndef MAGNUM_TARGET_GLES2
&VectorGLTest::setUniformUniformBuffersEnabled<2>,
&VectorGLTest::setUniformUniformBuffersEnabled<3>,
@ -369,7 +388,7 @@ template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffers() {
#endif
}
VectorGL<dimensions> shader{data.flags, data.drawCount};
VectorGL<dimensions> shader{data.flags, data.materialCount, data.drawCount};
CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.drawCount(), data.drawCount);
CORRADE_VERIFY(shader.id());
@ -414,7 +433,7 @@ template<UnsignedInt dimensions> void VectorGLTest::constructMoveUniformBuffers(
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif
VectorGL<dimensions> a{VectorGL<dimensions>::Flag::UniformBuffers, 5};
VectorGL<dimensions> a{VectorGL<dimensions>::Flag::UniformBuffers, 2, 5};
const GLuint id = a.id();
CORRADE_VERIFY(id);
@ -423,6 +442,7 @@ template<UnsignedInt dimensions> void VectorGLTest::constructMoveUniformBuffers(
VectorGL<dimensions> b{std::move(a)};
CORRADE_COMPARE(b.id(), id);
CORRADE_COMPARE(b.flags(), VectorGL<dimensions>::Flag::UniformBuffers);
CORRADE_COMPARE(b.materialCount(), 2);
CORRADE_COMPARE(b.drawCount(), 5);
CORRADE_VERIFY(!a.id());
@ -430,14 +450,17 @@ template<UnsignedInt dimensions> void VectorGLTest::constructMoveUniformBuffers(
c = std::move(b);
CORRADE_COMPARE(c.id(), id);
CORRADE_COMPARE(c.flags(), VectorGL<dimensions>::Flag::UniformBuffers);
CORRADE_COMPARE(c.materialCount(), 2);
CORRADE_COMPARE(c.drawCount(), 5);
CORRADE_VERIFY(!b.id());
}
#endif
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffersZeroDraws() {
template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffersInvalid() {
auto&& data = ConstructUniformBuffersInvalidData[testCaseInstanceId()];
setTestCaseTemplateName(std::to_string(dimensions));
setTestCaseDescription(data.name);
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -450,9 +473,9 @@ template<UnsignedInt dimensions> void VectorGLTest::constructUniformBuffersZeroD
std::ostringstream out;
Error redirectError{&out};
VectorGL<dimensions>{VectorGL<dimensions>::Flag::UniformBuffers, 0};
CORRADE_COMPARE(out.str(),
"Shaders::VectorGL: draw count can't be zero\n");
VectorGL<dimensions>{data.flags, data.materialCount, data.drawCount};
CORRADE_COMPARE(out.str(), Utility::formatString(
"Shaders::VectorGL: {}\n", data.message));
}
#endif
@ -502,6 +525,8 @@ template<UnsignedInt dimensions> void VectorGLTest::bindBufferUniformBuffersNotE
.bindDrawBuffer(buffer, 0, 16)
.bindTextureTransformationBuffer(buffer)
.bindTextureTransformationBuffer(buffer, 0, 16)
.bindMaterialBuffer(buffer)
.bindMaterialBuffer(buffer, 0, 16)
.setDrawOffset(0);
CORRADE_COMPARE(out.str(),
"Shaders::VectorGL::bindTransformationProjectionBuffer(): the shader was not created with uniform buffers enabled\n"
@ -510,6 +535,8 @@ template<UnsignedInt dimensions> void VectorGLTest::bindBufferUniformBuffersNotE
"Shaders::VectorGL::bindDrawBuffer(): the shader was not created with uniform buffers enabled\n"
"Shaders::VectorGL::bindTextureTransformationBuffer(): the shader was not created with uniform buffers enabled\n"
"Shaders::VectorGL::bindTextureTransformationBuffer(): the shader was not created with uniform buffers enabled\n"
"Shaders::VectorGL::bindMaterialBuffer(): the shader was not created with uniform buffers enabled\n"
"Shaders::VectorGL::bindMaterialBuffer(): the shader was not created with uniform buffers enabled\n"
"Shaders::VectorGL::setDrawOffset(): the shader was not created with uniform buffers enabled\n");
}
#endif
@ -572,7 +599,7 @@ template<UnsignedInt dimensions> void VectorGLTest::setWrongDrawOffset() {
std::ostringstream out;
Error redirectError{&out};
VectorGL<dimensions>{VectorGL<dimensions>::Flag::UniformBuffers, 5}
VectorGL<dimensions>{VectorGL<dimensions>::Flag::UniformBuffers, 2, 5}
.setDrawOffset(5);
CORRADE_COMPARE(out.str(),
"Shaders::VectorGL::setDrawOffset(): draw offset 5 is out of bounds for 5 draws\n");
@ -665,8 +692,12 @@ template<VectorGL2D::Flag flag> void VectorGLTest::renderDefaults2D() {
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
VectorDrawUniform{}
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
VectorMaterialUniform{}
}};
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(square);
}
#endif
@ -740,8 +771,12 @@ template<VectorGL3D::Flag flag> void VectorGLTest::renderDefaults3D() {
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
VectorDrawUniform{}
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
VectorMaterialUniform{}
}};
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(plane);
}
#endif
@ -829,17 +864,21 @@ template<VectorGL2D::Flag flag> void VectorGLTest::render2D() {
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
VectorDrawUniform{}
.setBackgroundColor(data.backgroundColor)
.setColor(data.color)
}};
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}
.setTextureMatrix(data.textureTransformation)
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
VectorMaterialUniform{}
.setBackgroundColor(data.backgroundColor)
.setColor(data.color)
}};
if(data.flags & VectorGL2D::Flag::TextureTransformation)
shader.bindTextureTransformationBuffer(textureTransformationUniform);
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(square);
}
#endif
@ -934,17 +973,21 @@ template<VectorGL3D::Flag flag> void VectorGLTest::render3D() {
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
VectorDrawUniform{}
.setBackgroundColor(data.backgroundColor)
.setColor(data.color)
}};
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}
.setTextureMatrix(data.textureTransformation)
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
VectorMaterialUniform{}
.setBackgroundColor(data.backgroundColor)
.setColor(data.color)
}};
if(data.flags & VectorGL3D::Flag::TextureTransformation)
shader.bindTextureTransformationBuffer(textureTransformationUniform);
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
.draw(plane);
}
#endif
@ -1031,6 +1074,15 @@ void VectorGLTest::renderMulti2D() {
The data.uniformIncrement is set high enough to ensure that, in the
non-offset-bind case this value is 1. */
Containers::Array<VectorMaterialUniform> materialData{data.uniformIncrement + 1};
materialData[0*data.uniformIncrement] = VectorMaterialUniform{}
.setColor(0xff0000_rgbf)
.setBackgroundColor(0xffcccc_rgbf);
materialData[1*data.uniformIncrement] = VectorMaterialUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, materialData};
Containers::Array<TransformationProjectionUniform2D> transformationProjectionData{2*data.uniformIncrement + 1};
transformationProjectionData[0*data.uniformIncrement] = TransformationProjectionUniform2D{}
.setTransformationProjectionMatrix(
@ -1069,22 +1121,24 @@ void VectorGLTest::renderMulti2D() {
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, textureTransformationData};
Containers::Array<VectorDrawUniform> drawData{2*data.uniformIncrement + 1};
/* Material offsets are zero if we have single draw, as those are done with
UBO offset bindings instead. */
drawData[0*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 1);
drawData[1*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0xff0000_rgbf)
.setBackgroundColor(0xffcccc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 0);
drawData[2*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 1);
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, drawData};
VectorGL2D shader{VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation|data.flags, data.drawCount};
VectorGL2D shader{VectorGL2D::Flag::UniformBuffers|VectorGL2D::Flag::TextureTransformation|data.flags, data.materialCount, data.drawCount};
shader.bindVectorTexture(vector);
/* Just one draw, rebinding UBOs each time */
if(data.drawCount == 1) {
shader.bindMaterialBuffer(materialUniform,
1*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
0*data.uniformIncrement*sizeof(TransformationProjectionUniform2D),
sizeof(TransformationProjectionUniform2D));
@ -1096,6 +1150,9 @@ void VectorGLTest::renderMulti2D() {
sizeof(TextureTransformationUniform));
shader.draw(circle);
shader.bindMaterialBuffer(materialUniform,
0*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
1*data.uniformIncrement*sizeof(TransformationProjectionUniform2D),
sizeof(TransformationProjectionUniform2D));
@ -1107,6 +1164,9 @@ void VectorGLTest::renderMulti2D() {
sizeof(TextureTransformationUniform));
shader.draw(square);
shader.bindMaterialBuffer(materialUniform,
1*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
2*data.uniformIncrement*sizeof(TransformationProjectionUniform2D),
sizeof(TransformationProjectionUniform2D));
@ -1122,7 +1182,8 @@ void VectorGLTest::renderMulti2D() {
} else {
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindTextureTransformationBuffer(textureTransformationUniform);
.bindTextureTransformationBuffer(textureTransformationUniform)
.bindMaterialBuffer(materialUniform);
if(data.flags >= VectorGL2D::Flag::MultiDraw)
shader.draw({circle, square, triangle});
@ -1209,6 +1270,15 @@ void VectorGLTest::renderMulti3D() {
The data.uniformIncrement is set high enough to ensure that, in the
non-offset-bind case this value is 1. */
Containers::Array<VectorMaterialUniform> materialData{data.uniformIncrement + 1};
materialData[0*data.uniformIncrement] = VectorMaterialUniform{}
.setColor(0xff0000_rgbf)
.setBackgroundColor(0xffcccc_rgbf);
materialData[1*data.uniformIncrement] = VectorMaterialUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, materialData};
Containers::Array<TransformationProjectionUniform3D> transformationProjectionData{2*data.uniformIncrement + 1};
transformationProjectionData[0*data.uniformIncrement] = TransformationProjectionUniform3D{}
.setTransformationProjectionMatrix(
@ -1252,22 +1322,24 @@ void VectorGLTest::renderMulti3D() {
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, textureTransformationData};
Containers::Array<VectorDrawUniform> drawData{2*data.uniformIncrement + 1};
/* Material offsets are zero if we have single draw, as those are done with
UBO offset bindings instead. */
drawData[0*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 1);
drawData[1*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0xff0000_rgbf)
.setBackgroundColor(0xffcccc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 0);
drawData[2*data.uniformIncrement] = VectorDrawUniform{}
.setColor(0x00ff00_rgbf)
.setBackgroundColor(0xccffcc_rgbf);
.setMaterialId(data.drawCount == 1 ? 0 : 1);
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, drawData};
VectorGL3D shader{VectorGL3D::Flag::UniformBuffers|VectorGL3D::Flag::TextureTransformation|data.flags, data.drawCount};
VectorGL3D shader{VectorGL3D::Flag::UniformBuffers|VectorGL3D::Flag::TextureTransformation|data.flags, data.materialCount, data.drawCount};
shader.bindVectorTexture(vector);
/* Just one draw, rebinding UBOs each time */
if(data.drawCount == 1) {
shader.bindMaterialBuffer(materialUniform,
1*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
0*data.uniformIncrement*sizeof(TransformationProjectionUniform3D),
sizeof(TransformationProjectionUniform3D));
@ -1279,6 +1351,9 @@ void VectorGLTest::renderMulti3D() {
sizeof(TextureTransformationUniform));
shader.draw(sphere);
shader.bindMaterialBuffer(materialUniform,
0*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
1*data.uniformIncrement*sizeof(TransformationUniform3D),
sizeof(TransformationUniform3D));
@ -1290,6 +1365,9 @@ void VectorGLTest::renderMulti3D() {
sizeof(TextureTransformationUniform));
shader.draw(plane);
shader.bindMaterialBuffer(materialUniform,
1*data.uniformIncrement*sizeof(VectorMaterialUniform),
sizeof(VectorMaterialUniform));
shader.bindTransformationProjectionBuffer(transformationProjectionUniform,
2*data.uniformIncrement*sizeof(TransformationUniform3D),
sizeof(TransformationUniform3D));
@ -1305,7 +1383,8 @@ void VectorGLTest::renderMulti3D() {
} else {
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindTextureTransformationBuffer(textureTransformationUniform);
.bindTextureTransformationBuffer(textureTransformationUniform)
.bindMaterialBuffer(materialUniform);
if(data.flags >= VectorGL3D::Flag::MultiDraw)
shader.draw({sphere, plane, cone});

91
src/Magnum/Shaders/Test/VectorTest.cpp

@ -38,14 +38,25 @@ struct VectorTest: TestSuite::Tester {
void drawUniformConstructDefault();
void drawUniformConstructNoInit();
void drawUniformSetters();
void drawUniformMaterialIdPacking();
void materialUniformConstructDefault();
void materialUniformConstructNoInit();
void materialUniformSetters();
};
VectorTest::VectorTest() {
addTests({&VectorTest::uniformSizeAlignment<VectorDrawUniform>,
&VectorTest::uniformSizeAlignment<VectorMaterialUniform>,
&VectorTest::drawUniformConstructDefault,
&VectorTest::drawUniformConstructNoInit,
&VectorTest::drawUniformSetters});
&VectorTest::drawUniformSetters,
&VectorTest::drawUniformMaterialIdPacking,
&VectorTest::materialUniformConstructDefault,
&VectorTest::materialUniformConstructNoInit,
&VectorTest::materialUniformSetters});
}
using namespace Math::Literals;
@ -54,6 +65,9 @@ template<class> struct UniformTraits;
template<> struct UniformTraits<VectorDrawUniform> {
static const char* name() { return "VectorDrawUniform"; }
};
template<> struct UniformTraits<VectorMaterialUniform> {
static const char* name() { return "VectorMaterialUniform"; }
};
template<class T> void VectorTest::uniformSizeAlignment() {
setTestCaseTemplateName(UniformTraits<T>::name());
@ -72,17 +86,13 @@ template<class T> void VectorTest::uniformSizeAlignment() {
void VectorTest::drawUniformConstructDefault() {
VectorDrawUniform a;
VectorDrawUniform b{DefaultInit};
CORRADE_COMPARE(a.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(b.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(a.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(b.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(a.materialId, 0);
CORRADE_COMPARE(b.materialId, 0);
constexpr VectorDrawUniform ca;
constexpr VectorDrawUniform cb{DefaultInit};
CORRADE_COMPARE(ca.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(cb.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(ca.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(cb.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(ca.materialId, 0);
CORRADE_COMPARE(cb.materialId, 0);
CORRADE_VERIFY(std::is_nothrow_default_constructible<VectorDrawUniform>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<VectorDrawUniform, DefaultInitT>::value);
@ -94,16 +104,14 @@ void VectorTest::drawUniformConstructDefault() {
void VectorTest::drawUniformConstructNoInit() {
/* Testing only some fields, should be enough */
VectorDrawUniform a;
a.color = 0x354565fc_rgbaf;
a.backgroundColor = 0x98769facb_rgbaf;
a.materialId = 5;
new(&a) VectorDrawUniform{NoInit};
{
#if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__
CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value.");
#endif
CORRADE_COMPARE(a.color, 0x354565fc_rgbaf);
CORRADE_COMPARE(a.backgroundColor, 0x98769facb_rgbaf);
CORRADE_COMPARE(a.materialId, 5);
}
CORRADE_VERIFY(std::is_nothrow_constructible<VectorDrawUniform, NoInitT>::value);
@ -114,6 +122,63 @@ void VectorTest::drawUniformConstructNoInit() {
void VectorTest::drawUniformSetters() {
VectorDrawUniform a;
a.setMaterialId(5);
CORRADE_COMPARE(a.materialId, 5);
}
void VectorTest::drawUniformMaterialIdPacking() {
VectorDrawUniform a;
a.setMaterialId(13765);
/* materialId should be right at the beginning, in the low 16 bits on both
LE and BE */
CORRADE_COMPARE(reinterpret_cast<UnsignedInt*>(&a)[0] & 0xffff, 13765);
}
void VectorTest::materialUniformConstructDefault() {
VectorMaterialUniform a;
VectorMaterialUniform b{DefaultInit};
CORRADE_COMPARE(a.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(b.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(a.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(b.backgroundColor, 0x00000000_rgbaf);
constexpr VectorMaterialUniform ca;
constexpr VectorMaterialUniform cb{DefaultInit};
CORRADE_COMPARE(ca.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(cb.color, 0xffffffff_rgbaf);
CORRADE_COMPARE(ca.backgroundColor, 0x00000000_rgbaf);
CORRADE_COMPARE(cb.backgroundColor, 0x00000000_rgbaf);
CORRADE_VERIFY(std::is_nothrow_default_constructible<VectorMaterialUniform>::value);
CORRADE_VERIFY(std::is_nothrow_constructible<VectorMaterialUniform, DefaultInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<DefaultInitT, VectorMaterialUniform>::value);
}
void VectorTest::materialUniformConstructNoInit() {
/* Testing only some fields, should be enough */
VectorMaterialUniform a;
a.color = 0x354565fc_rgbaf;
a.backgroundColor = 0x98769facb_rgbaf;
new(&a) VectorMaterialUniform{NoInit};
{
#if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__
CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value.");
#endif
CORRADE_COMPARE(a.color, 0x354565fc_rgbaf);
CORRADE_COMPARE(a.backgroundColor, 0x98769facb_rgbaf);
}
CORRADE_VERIFY(std::is_nothrow_constructible<VectorMaterialUniform, NoInitT>::value);
/* Implicit construction is not allowed */
CORRADE_VERIFY(!std::is_convertible<NoInitT, VectorMaterialUniform>::value);
}
void VectorTest::materialUniformSetters() {
VectorMaterialUniform a;
a.setColor(0x354565fc_rgbaf)
.setBackgroundColor(0x98769facb_rgbaf);
CORRADE_COMPARE(a.color, 0x354565fc_rgbaf);

24
src/Magnum/Shaders/Vector.frag

@ -66,9 +66,8 @@ uniform highp uint drawOffset
#endif
struct DrawUniform {
lowp vec4 color;
lowp vec4 backgroundColor;
lowp uvec4 reserved;
highp uvec4 materialIdReservedReservedReservedReserved;
#define draw_materialIdReserved materialIdReservedReservedReservedReserved.x
};
layout(std140
@ -78,6 +77,20 @@ layout(std140
) uniform Draw {
DrawUniform draws[DRAW_COUNT];
};
struct MaterialUniform {
lowp vec4 color;
lowp vec4 backgroundColor;
lowp uvec4 reserved;
};
layout(std140
#ifdef EXPLICIT_BINDING
, binding = 4
#endif
) uniform Material {
MaterialUniform materials[MATERIAL_COUNT];
};
#endif
/* Textures */
@ -106,8 +119,9 @@ out lowp vec4 fragmentColor;
void main() {
#ifdef UNIFORM_BUFFERS
lowp const vec4 color = draws[drawId].color;
lowp const vec4 backgroundColor = draws[drawId].backgroundColor;
mediump const uint materialId = draws[drawId].draw_materialIdReserved & 0xffffu;
lowp const vec4 color = materials[materialId].color;
lowp const vec4 backgroundColor = materials[materialId].backgroundColor;
#endif
lowp float intensity = texture(vectorTexture, interpolatedTextureCoordinates).r;

145
src/Magnum/Shaders/Vector.h

@ -26,7 +26,7 @@
*/
/** @file
* @brief Struct @ref Magnum::Shaders::VectorDrawUniform
* @brief Struct @ref Magnum::Shaders::VectorDrawUniform, @ref Magnum::Shaders::VectorMaterialUniform
*/
#include "Magnum/Magnum.h"
@ -47,20 +47,121 @@ namespace Magnum { namespace Shaders {
Together with the generic @ref TransformationProjectionUniform2D /
@ref TransformationProjectionUniform3D contains parameters that are specific to
each draw call. Texture transformation, if needed, is supplied separately in a
@ref TextureTransformationUniform.
@ref TextureTransformationUniform; material-related properties are expected to
be shared among multiple draw calls and thus are provided in a separate
@ref VectorMaterialUniform structure, referenced by @ref materialId.
@see @ref VectorGL::bindDrawBuffer()
*/
struct VectorDrawUniform {
/** @brief Construct with default parameters */
constexpr explicit VectorDrawUniform(DefaultInitT = DefaultInit) noexcept: color{1.0f, 1.0f, 1.0f, 1.0f}, backgroundColor{0.0f, 0.0f, 0.0f, 0.0f}
constexpr explicit VectorDrawUniform(DefaultInitT = DefaultInit) noexcept:
#if ((defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)) && defined(CORRADE_TARGET_BIG_ENDIAN)
_pad0{}, /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
materialId{0}
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8) && !defined(CORRADE_TARGET_BIG_ENDIAN)
, _pad0{}, _pad1{}, _pad2{}, _pad3{}
#endif
{}
/** @brief Construct without initializing the contents */
explicit VectorDrawUniform(NoInitT) noexcept {}
/** @{
* @name Convenience setters
*
* Provided to allow the use of method chaining for populating a structure
* in a single expression, otherwise equivalent to accessing the fields
* directly. Also guaranteed to provide backwards compatibility when
* packing of the actual fields changes.
*/
/**
* @brief Set the @ref materialId field
* @return Reference to self (for method chaining)
*/
VectorDrawUniform& setMaterialId(UnsignedInt id) {
materialId = id;
return *this;
}
/**
* @}
*/
/** @var materialId
* @brief Material ID
*
* References a particular material from a @ref VectorMaterialUniform
* array. Useful when an UBO with more than one material is supplied or in
* a multi-draw scenario. Should be less than the material count passed to
* the @ref VectorGL::VectorGL(Flags, UnsignedInt, UnsignedInt)
* constructor. Default value is @cpp 0 @ce, meaning the first material
* gets used.
*/
/* This field is an UnsignedInt in the shader and materialId is extracted
as (value & 0xffff), so the order has to be different on BE */
#ifndef CORRADE_TARGET_BIG_ENDIAN
alignas(4) UnsignedShort materialId;
/* warning: Member __pad0__ is not documented. FFS DOXYGEN WHY DO YOU THINK
I MADE THOSE UNNAMED, YOU DUMB FOOL */
#ifndef DOXYGEN_GENERATING_OUTPUT
UnsignedShort
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad0 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16; /* reserved for skinOffset */
#endif
#else
alignas(4) UnsignedShort
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad0 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16; /* reserved for skinOffset */
UnsignedShort materialId;
#endif
/* warning: Member __pad1__ is not documented. FFS DOXYGEN WHY DO YOU THINK
I MADE THOSE UNNAMED, YOU DUMB FOOL */
#ifndef DOXYGEN_GENERATING_OUTPUT
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad1 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32; /* reserved for objectId */
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad2 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32;
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad3 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32;
#endif
};
/**
@brief Material uniform for vector shaders
@m_since_latest
Describes material properties referenced from
@ref VectorDrawUniform::materialId.
@see @ref VectorGL::bindMaterialBuffer()
*/
struct VectorMaterialUniform {
/** @brief Construct with default parameters */
constexpr explicit VectorMaterialUniform(DefaultInitT = DefaultInit) noexcept: color{1.0f, 1.0f, 1.0f, 1.0f}, backgroundColor{0.0f, 0.0f, 0.0f, 0.0f}
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
/* Otherwise it refuses to constexpr, on 3.8 at least */
, _pad0{}, _pad1{}, _pad2{}, _pad3{}, _pad4{}
, _pad0{}, _pad1{}, _pad2{}, _pad3{}
#endif
{}
/** @brief Construct without initializing the contents */
explicit VectorDrawUniform(NoInitT) noexcept: color{NoInit}, backgroundColor{NoInit} {}
explicit VectorMaterialUniform(NoInitT) noexcept: color{NoInit}, backgroundColor{NoInit} {}
/** @{
* @name Convenience setters
@ -75,7 +176,7 @@ struct VectorDrawUniform {
* @brief Set the @ref color field
* @return Reference to self (for method chaining)
*/
VectorDrawUniform& setColor(const Color4& color) {
VectorMaterialUniform& setColor(const Color4& color) {
this->color = color;
return *this;
}
@ -84,7 +185,7 @@ struct VectorDrawUniform {
* @brief Set the @ref backgroundColor field
* @return Reference to self (for method chaining)
*/
VectorDrawUniform& setBackgroundColor(const Color4& color) {
VectorMaterialUniform& setBackgroundColor(const Color4& color) {
backgroundColor = color;
return *this;
}
@ -112,45 +213,25 @@ struct VectorDrawUniform {
/* warning: Member __pad0__ is not documented. FFS DOXYGEN WHY DO YOU THINK
I MADE THOSE UNNAMED, YOU DUMB FOOL */
#ifndef DOXYGEN_GENERATING_OUTPUT
/* This field is an UnsignedInt in the shader and skinOffset is extracted
as (value >> 16), so the order has to be different on BE */
#ifndef CORRADE_TARGET_BIG_ENDIAN
UnsignedShort
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad0 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16;
UnsignedShort
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad1 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16; /* reserved for skinOffset */
#else
UnsignedShort
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad0 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16; /* reserved for skinOffset */
UnsignedShort
:32; /* reserved for alpha mask */
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad1 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:16;
#endif
:32;
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad2 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32; /* reserved for objectId */
:32;
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad3 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32; /* reserved for alphaMask */
Int
#if (defined(CORRADE_TARGET_CLANG) && __clang_major__ < 4) || (defined(CORRADE_TARGET_APPLE_CLANG) && __clang_major__ < 8)
_pad4 /* Otherwise it refuses to constexpr, on 3.8 at least */
#endif
:32;
#endif
};

32
src/Magnum/Shaders/VectorGL.cpp

@ -57,22 +57,25 @@ namespace {
bound to the same buffer for the whole time */
TransformationProjectionBufferBinding = 1,
DrawBufferBinding = 2,
TextureTransformationBufferBinding = 3
TextureTransformationBufferBinding = 3,
MaterialBufferBinding = 4
};
#endif
}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt drawCount
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _drawCount{drawCount}
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::VectorGL: material count can't be zero", );
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::VectorGL: draw count can't be zero", );
#endif
@ -128,8 +131,10 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
if(flags >= Flag::UniformBuffers) {
frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n",
drawCount));
"#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n",
drawCount,
materialCount));
frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
}
#endif
@ -182,6 +187,7 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
if(flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
}
#endif
}
@ -204,7 +210,7 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flag
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags): VectorGL{flags, 1} {}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags): VectorGL{flags, 1, 1} {}
#endif
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
@ -300,6 +306,20 @@ template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::bin
buffer.bind(GL::Buffer::Target::Uniform, TextureTransformationBufferBinding, offset, size);
return *this;
}
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::bindMaterialBuffer(GL::Buffer& buffer) {
CORRADE_ASSERT(_flags >= Flag::UniformBuffers,
"Shaders::VectorGL::bindMaterialBuffer(): the shader was not created with uniform buffers enabled", *this);
buffer.bind(GL::Buffer::Target::Uniform, MaterialBufferBinding);
return *this;
}
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::bindMaterialBuffer(GL::Buffer& buffer, const GLintptr offset, const GLsizeiptr size) {
CORRADE_ASSERT(_flags >= Flag::UniformBuffers,
"Shaders::VectorGL::bindMaterialBuffer(): the shader was not created with uniform buffers enabled", *this);
buffer.bind(GL::Buffer::Target::Uniform, MaterialBufferBinding, offset, size);
return *this;
}
#endif
template<UnsignedInt dimensions> VectorGL<dimensions>& VectorGL<dimensions>::bindVectorTexture(GL::Texture2D& texture) {

65
src/Magnum/Shaders/VectorGL.h

@ -127,8 +127,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
/**
* Use uniform buffers. Expects that uniform data are supplied via
* @ref bindTransformationProjectionBuffer(),
* @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer()
* instead of direct uniform setters.
* @ref bindDrawBuffer(), @ref bindTextureTransformationBuffer()
* and @ref bindMaterialBuffer() instead of direct uniform setters.
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0.
@ -185,7 +185,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
*
* While this function is meant mainly for the classic uniform
* scenario (without @ref Flag::UniformBuffers set), it's equivalent to
* @ref VectorGL(Flags, UnsignedInt) with @p drawCount set to @cpp 1 @ce.
* @ref VectorGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount
* and @p drawCount set to @cpp 1 @ce.
*/
explicit VectorGL(Flags flags = {});
@ -193,16 +194,19 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
/**
* @brief Construct for a multi-draw scenario
* @param flags Flags
* @param materialCount Size of a @ref VectorMaterialUniform buffer
* bound with @ref bindMaterialBuffer()
* @param drawCount Size of a @ref TransformationProjectionUniform2D
* / @ref TransformationProjectionUniform3D /
* @ref VectorDrawUniform / @ref TextureTransformationUniform
* buffer bound with @ref bindTransformationProjectionBuffer(),
* @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer()
*
* If @p flags contains @ref Flag::UniformBuffers @p drawCount
* describes the uniform buffer sizes as these are required to have a
* statically defined size. The draw offset is then set via
* @ref setDrawOffset().
* If @p flags contains @ref Flag::UniformBuffers, @p materialCount and
* @p drawCount describe the uniform buffer sizes as these are required
* to have a statically defined size. The draw offset is then set via
* @ref setDrawOffset() and the per-draw materials specified via
* @ref VectorDrawUniform::materialId.
*
* If @p flags don't contain @ref Flag::UniformBuffers, @p drawCount is
* ignored and the constructor behaves the same as @ref VectorGL(Flags).
@ -217,7 +221,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
(accepting pairs of parameter type and value like in GL context
creation, e.g., which will probably need a new enum as reusing Flag
for this might be too confusing) */
explicit VectorGL(Flags flags, UnsignedInt drawCount);
explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
#endif
/**
@ -253,6 +257,18 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
Flags flags() const { return _flags; }
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Material count
* @m_since_latest
*
* Statically defined size of the @ref VectorMaterialUniform uniform
* buffer. Has use only if @ref Flag::UniformBuffers is set.
* @see @ref bindMaterialBuffer()
* @requires_gles30 Not defined on OpenGL ES 2.0 builds.
* @requires_webgl20 Not defined on WebGL 1.0 builds.
*/
UnsignedInt materialCount() const { return _materialCount; }
/**
* @brief Draw count
* @m_since_latest
@ -310,8 +326,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
* Initial value is @cpp 0x00000000_rgbaf @ce.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref VectorDrawUniform::backgroundColor and call
* @ref bindDrawBuffer() instead.
* @ref VectorMaterialUniform::backgroundColor and call
* @ref bindMaterialBuffer() instead.
* @see @ref setColor()
*/
VectorGL<dimensions>& setBackgroundColor(const Color4& color);
@ -323,7 +339,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
* Initial value is @cpp 0xffffffff_rgbaf @ce.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref VectorDrawUniform::color and call @ref bindDrawBuffer()
* @ref VectorMaterialUniform::color and call @ref bindMaterialBuffer()
* instead.
* @see @ref setBackgroundColor()
*/
@ -373,7 +389,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
* expected to contain @ref drawCount() instances of
* @ref TransformationProjectionUniform2D /
* @ref TransformationProjectionUniform3D. At the very least you need
* to call also @ref bindDrawBuffer().
* to call also @ref bindDrawBuffer() and @ref bindMaterialBuffer().
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
@ -393,7 +409,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
* Expects that @ref Flag::UniformBuffers is set. The buffer is
* expected to contain @ref drawCount() instances of
* @ref VectorDrawUniform. At the very least you need to call also
* @ref bindTransformationProjectionBuffer().
* @ref bindTransformationProjectionBuffer() and
* @ref bindMaterialBuffer().
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
@ -425,6 +442,26 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
*/
VectorGL<dimensions>& bindTextureTransformationBuffer(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size);
/**
* @brief Set a material uniform buffer
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that @ref Flag::UniformBuffers is set. The buffer is
* expected to contain @ref materialCount() instances of
* @ref VectorMaterialUniform. At the very least you need to call also
* @ref bindTransformationProjectionBuffer() and @ref bindDrawBuffer().
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/
VectorGL<dimensions>& bindMaterialBuffer(GL::Buffer& buffer);
/**
* @overload
* @m_since_latest
*/
VectorGL<dimensions>& bindMaterialBuffer(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size);
/**
* @}
*/
@ -457,7 +494,7 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
Flags _flags;
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt _drawCount{};
UnsignedInt _materialCount{}, _drawCount{};
#endif
Int _transformationProjectionMatrixUniform{0},
_textureMatrixUniform{1},

Loading…
Cancel
Save