Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async GL shader compilation #576

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
51c8ba7
Basic async shader compilation for FlatGL
dranikpg Jul 8, 2022
1ae63af
Merge branch 'master' into async-shader-compile
dranikpg Jul 18, 2022
37b47f1
Refactor FlatGL::CompileState
dranikpg Jul 25, 2022
66015a2
Move shader compilation/linking to member functions
dranikpg Jul 25, 2022
8bcd04a
Refactor FlatGL::CompileState
dranikpg Jul 27, 2022
89582ef
Update doc comments
dranikpg Jul 27, 2022
05d49d6
Implement completion status fallback & fixes
dranikpg Jul 27, 2022
fa26cfc
More small fixes
dranikpg Jul 28, 2022
0acc265
Fix wrong access
dranikpg Jul 29, 2022
6fe87cc
Implement tests for compile/link/flat
dranikpg Aug 1, 2022
1a1c045
Fixes: docs, tests
dranikpg Aug 6, 2022
fefb99d
VectorGL & tests
dranikpg Aug 9, 2022
e1ec1a6
MeshVisualizerGL3D & tests
dranikpg Aug 11, 2022
3c899c1
Small fixes
dranikpg Aug 13, 2022
cf9b90f
PhongGL & tests
dranikpg Aug 13, 2022
09ab0ef
Fixes
dranikpg Aug 13, 2022
fdb1dca
VertexColor & tests
dranikpg Aug 15, 2022
e3e05cd
Small fix in PhongGL construct
dranikpg Aug 15, 2022
511d869
DistanceFieldVector & tests. Fix deprecated references
dranikpg Aug 21, 2022
1d6c99d
Move FlatGL impls from header
dranikpg Aug 23, 2022
b086162
Move VectorGL impls from header
dranikpg Aug 23, 2022
b5da1e2
Move VertexColorGL impls from header
dranikpg Aug 23, 2022
3ab4b6f
Refactor tests
dranikpg Aug 23, 2022
b592fcb
Fix formatting
dranikpg Aug 24, 2022
dd51e27
Fix MeshVisualizer & tests
dranikpg Aug 24, 2022
9a0af4d
Fix unused vars
dranikpg Aug 24, 2022
1e363fd
Fix MeshVisualizer test case
dranikpg Aug 24, 2022
ebbed67
Fixes
dranikpg Sep 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 45 additions & 23 deletions src/Magnum/Shaders/DistanceFieldVectorGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

#include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h"
Expand Down Expand Up @@ -63,22 +62,16 @@ namespace {
#endif
}

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
):
_flags{flags}
#ifndef MAGNUM_TARGET_GLES2
, _materialCount{materialCount},
_drawCount{drawCount}
#endif
{
) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::DistanceFieldVectorGL: material count can't be zero", );
"Shaders::DistanceFieldVectorGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::DistanceFieldVectorGL: draw count can't be zero", );
"Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate});
#endif

#ifndef MAGNUM_TARGET_GLES
Expand Down Expand Up @@ -142,35 +135,56 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("DistanceFieldVector.frag"));

CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
vert.submitCompile();
frag.submitCompile();

DistanceFieldVectorGL<dimensions> out{NoInit};
out._flags = flags;
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif

attachShaders({vert, frag});
out.attachShaders({vert, frag});

/* ES3 has this done in the shader directly */
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif
{
bindAttributeLocation(Position::Location, "position");
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
out.bindAttributeLocation(Position::Location, "position");
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
}
#endif

CORRADE_INTERNAL_ASSERT_OUTPUT(link());
out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(CompileState&& cs)
: DistanceFieldVectorGL{static_cast<DistanceFieldVectorGL&&>(std::move(cs))} {
if (id() == 0) return;

CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
CORRADE_INTERNAL_ASSERT_OUTPUT(cs._vert.checkCompile());
CORRADE_INTERNAL_ASSERT_OUTPUT(cs._frag.checkCompile());

const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;

#ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif
{
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else
#endif
{
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
_colorUniform = uniformLocation("color");
_outlineColorUniform = uniformLocation("outlineColor");
Expand All @@ -185,11 +199,11 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
{
setUniform(uniformLocation("vectorTexture"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
}
#endif
Expand All @@ -198,13 +212,13 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) {
if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */
} else
#endif
{
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation)
if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
setColor(Color4{1.0f});
/* Outline color is zero by default */
Expand All @@ -214,8 +228,16 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
#endif
}

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(NoInitT) {}

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(flags)} {}

#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{flags, 1, 1} {}
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags) {
return compile(flags, 1, 1);
}

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {}
#endif

template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>& DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
Expand Down
31 changes: 31 additions & 0 deletions src/Magnum/Shaders/DistanceFieldVectorGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#include "Magnum/DimensionTraits.h"
#include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/visibility.h"

Expand Down Expand Up @@ -280,6 +281,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
*/
explicit DistanceFieldVectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}

class CompileState;

explicit DistanceFieldVectorGL(CompileState&& cs);

static CompileState compile(Flags flags
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);

#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags);
#endif

/** @brief Copying is not allowed */
DistanceFieldVectorGL(const DistanceFieldVectorGL<dimensions>&) = delete;

Expand Down Expand Up @@ -602,6 +617,8 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif

private:
explicit DistanceFieldVectorGL(NoInitT);

/* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback;
Expand All @@ -627,6 +644,20 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif
};


template<UnsignedInt dimensions> class DistanceFieldVectorGL<dimensions>::CompileState : public DistanceFieldVectorGL<dimensions> {
private:
friend class DistanceFieldVectorGL;

explicit CompileState(NoCreateT) : DistanceFieldVectorGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}

CompileState(DistanceFieldVectorGL<dimensions>&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) :
DistanceFieldVectorGL<dimensions>{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}

GL::Shader _vert, _frag;
GL::Version _version;
};

/**
@brief Two-dimensional distance field vector OpenGL shader
@m_since_latest
Expand Down
4 changes: 2 additions & 2 deletions src/Magnum/Shaders/MeshVisualizerGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,15 +522,15 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags
MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags) : MeshVisualizerGL2D{compile(flags)} {}

#ifndef MAGNUM_TARGET_GLES2
MeshVisualizer2D::CompileState MeshVisualizer2D::compile(Flags flags) {
MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(Flags flags) {
return compile(flags, 1, 1);
}

MeshVisualizerGL2D::MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount)
: MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {}
#endif

MeshVisualizer2D::MeshVisualizerGL2D(CompileState&& cs)
MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& cs)
: MeshVisualizerGL2D{static_cast<MeshVisualizerGL2D&&>(std::move(cs))} {
if (id() == 0) return;

Expand Down
95 changes: 95 additions & 0 deletions src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <Corrade/PluginManager/Manager.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/Path.h>

#ifdef CORRADE_TARGET_APPLE
Expand Down Expand Up @@ -84,8 +85,10 @@ struct DistanceFieldVectorGLTest: GL::OpenGLTester {
explicit DistanceFieldVectorGLTest();

template<UnsignedInt dimensions> void construct();
template<UnsignedInt dimensions> void constructAsync();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void constructUniformBuffers();
template<UnsignedInt dimensions> void constructUniformBuffersAsync();
#endif

template<UnsignedInt dimensions> void constructMove();
Expand Down Expand Up @@ -251,11 +254,19 @@ DistanceFieldVectorGLTest::DistanceFieldVectorGLTest() {
&DistanceFieldVectorGLTest::construct<3>},
Containers::arraySize(ConstructData));

addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructAsync<2>,
&DistanceFieldVectorGLTest::constructAsync<3>});

#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffers<2>,
&DistanceFieldVectorGLTest::constructUniformBuffers<3>},
Containers::arraySize(ConstructUniformBuffersData));

addTests<DistanceFieldVectorGLTest>({
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<2>,
&DistanceFieldVectorGLTest::constructUniformBuffersAsync<3>});
#endif

addTests<DistanceFieldVectorGLTest>({
Expand Down Expand Up @@ -374,6 +385,37 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR();
}

template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));

constexpr struct {
const char* name;
DistanceFieldVectorGL2D::Flags flags;
} data{
"texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation
};
setTestCaseDescription(data.name);

auto compileState = DistanceFieldVectorGL<dimensions>::compile(data.flags);
CORRADE_COMPARE(compileState.flags(), data.flags);

while(!compileState.isLinkFinished())
Utility::System::sleep(100);

DistanceFieldVectorGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}

MAGNUM_VERIFY_NO_GL_ERROR();
}

#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffers() {
setTestCaseTemplateName(Utility::format("{}", dimensions));
Expand Down Expand Up @@ -413,6 +455,59 @@ template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUnifor

MAGNUM_VERIFY_NO_GL_ERROR();
}

template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructUniformBuffersAsync() {
setTestCaseTemplateName(Utility::format("{}", dimensions));

constexpr struct {
const char* name;
DistanceFieldVectorGL2D::Flags flags;
UnsignedInt materialCount, drawCount;
} data {
"multidraw with all the things", DistanceFieldVectorGL2D::Flag::MultiDraw|DistanceFieldVectorGL2D::Flag::TextureTransformation, 16, 48
};
setTestCaseDescription(data.name);

#ifndef MAGNUM_TARGET_GLES
if((data.flags & DistanceFieldVectorGL2D::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
#endif

if(data.flags >= DistanceFieldVectorGL2D::Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::shader_draw_parameters>())
CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported.");
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::multi_draw>())
CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::WEBGL::multi_draw>())
CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported.");
#endif
}
auto compileState = DistanceFieldVectorGL<dimensions>::compile(data.flags, data.materialCount, data.drawCount);
CORRADE_COMPARE(compileState.flags(), data.flags);
CORRADE_COMPARE(compileState.materialCount(), data.materialCount);
CORRADE_COMPARE(compileState.drawCount(), data.drawCount);
dranikpg marked this conversation as resolved.
Show resolved Hide resolved

while(!compileState.isLinkFinished())
Utility::System::sleep(100);

DistanceFieldVectorGL<dimensions> shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.materialCount(), data.materialCount);
CORRADE_COMPARE(shader.drawCount(), data.drawCount);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}

MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif

template<UnsignedInt dimensions> void DistanceFieldVectorGLTest::constructMove() {
Expand Down