summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2017-08-24 07:20:26 +0200
committerPaul Lemire <paul.lemire@kdab.com>2020-02-03 13:33:50 +0100
commit17822c91e7f128b5d9af525cd638c9a4d35ea8fb (patch)
tree619c0aae6b82fc84ab7ba7c47663045b8b9514f7
parent9124a61eb1c10ed3bb7251baf2f42ac4a865e514 (diff)
QShaderProgram: add a format property
Can be either GLSL (default) or SPIRV at the moment. This variable will be used by the rendering backend to know what type of shader code was provided (e.g with Vulkan, the GLSL could be internally converted to SPIRV) Change-Id: I1f9b734a675c581ef0721edc4464e466a18afbb0 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/quick3d/imports/render/qt3dquick3drenderplugin.cpp1
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp44
-rw-r--r--src/render/materialsystem/qshaderprogram.h11
-rw-r--r--src/render/materialsystem/qshaderprogram_p.h2
-rw-r--r--src/render/materialsystem/shader.cpp13
-rw-r--r--src/render/materialsystem/shader_p.h4
-rw-r--r--tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp65
-rw-r--r--tests/auto/render/shader/tst_shader.cpp48
8 files changed, 185 insertions, 3 deletions
diff --git a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
index e47d28f7c..8acd71715 100644
--- a/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
+++ b/src/quick3d/imports/render/qt3dquick3drenderplugin.cpp
@@ -187,6 +187,7 @@ void Qt3DQuick3DRenderPlugin::registerTypes(const char *uri)
Qt3DRender::Quick::registerExtendedType<Qt3DRender::QRenderPass, Qt3DRender::Render::Quick::Quick3DRenderPass>("QRenderPass", "Qt3D.Render/RenderPass", uri, 2, 0, "RenderPass");
qmlRegisterType<Qt3DRender::QShaderProgram>(uri, 2, 0, "ShaderProgram");
qmlRegisterType<Qt3DRender::QShaderProgram, 9>(uri, 2, 9, "ShaderProgram");
+ qmlRegisterType<Qt3DRender::QShaderProgram, 15>(uri, 2, 15, "ShaderProgram");
qmlRegisterType<Qt3DRender::QShaderProgramBuilder>(uri, 2, 10, "ShaderProgramBuilder");
qmlRegisterType<Qt3DRender::QShaderProgramBuilder, 13>(uri, 2, 13, "ShaderProgramBuilder");
qmlRegisterUncreatableType<Qt3DRender::QShaderData>(uri, 2, 0, "QShaderData", "Quick3D should instantiate Quick3DShaderData only");
diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp
index c4e14ea2c..49117dd98 100644
--- a/src/render/materialsystem/qshaderprogram.cpp
+++ b/src/render/materialsystem/qshaderprogram.cpp
@@ -332,6 +332,17 @@
\value Error An error occurred while compiling the shader
*/
+/*!
+ \enum QShaderProgram::Format
+
+ This enum identifies the format of the shader code used.
+
+ \value GLSL OpenGL
+ \value SPIRV Vulkan, OpenGL 5
+
+ \since 5.15
+*/
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -339,6 +350,7 @@ namespace Qt3DRender {
QShaderProgramPrivate::QShaderProgramPrivate()
: QNodePrivate()
, m_status(QShaderProgram::NotReady)
+ , m_format(QShaderProgram::GLSL)
{
}
@@ -617,7 +629,7 @@ QString QShaderProgram::log() const
}
/*!
- \qmlproperty string ShaderProgram::status
+ \qmlproperty enumeration ShaderProgram::status
Holds the status of the current shader program.
*/
@@ -635,6 +647,35 @@ QShaderProgram::Status QShaderProgram::status() const
return d->m_status;
}
+void QShaderProgram::setFormat(QShaderProgram::Format format)
+{
+ Q_D(QShaderProgram);
+ if (format != d->m_format) {
+ d->m_format = format;
+ emit formatChanged(format);
+ }
+}
+
+/*!
+ \qmlproperty enumeration ShaderProgram::format
+ \since 5.15
+
+ Holds the format of the code provided on the ShaderProgram.
+ The default is ShaderProgram.GLSL
+*/
+/*!
+ \property QShaderProgram::format
+ \since 5.15
+
+ Holds the format of the code provided on the ShaderProgram.
+ The default is ShaderProgram.GLSL
+*/
+QShaderProgram::Format QShaderProgram::format() const
+{
+ Q_D(const QShaderProgram);
+ return d->m_format;
+}
+
QByteArray QShaderProgramPrivate::deincludify(const QString &filePath)
{
QFile f(filePath);
@@ -699,6 +740,7 @@ Qt3DCore::QNodeCreatedChangeBasePtr QShaderProgram::createNodeCreationChange() c
data.geometryShaderCode = d->m_geometryShaderCode;
data.fragmentShaderCode = d->m_fragmentShaderCode;
data.computeShaderCode = d->m_computeShaderCode;
+ data.format = d->m_format;
return creationChange;
}
diff --git a/src/render/materialsystem/qshaderprogram.h b/src/render/materialsystem/qshaderprogram.h
index 49c1076e5..1fc40a216 100644
--- a/src/render/materialsystem/qshaderprogram.h
+++ b/src/render/materialsystem/qshaderprogram.h
@@ -60,6 +60,7 @@ class Q_3DRENDERSHARED_EXPORT QShaderProgram : public Qt3DCore::QNode
Q_PROPERTY(QByteArray computeShaderCode READ computeShaderCode WRITE setComputeShaderCode NOTIFY computeShaderCodeChanged)
Q_PROPERTY(QString log READ log NOTIFY logChanged REVISION 9)
Q_PROPERTY(Status status READ status NOTIFY statusChanged REVISION 9)
+ Q_PROPERTY(Format format READ format WRITE setFormat NOTIFY formatChanged REVISION 15)
public:
explicit QShaderProgram(Qt3DCore::QNode *parent = nullptr);
@@ -82,6 +83,12 @@ public:
};
Q_ENUM(Status) // LCOV_EXCL_LINE
+ enum Format {
+ GLSL = 0,
+ SPIRV
+ };
+ Q_ENUM(Format) // LCOV_EXCL_LINE
+
// Source code in-line
QByteArray vertexShaderCode() const;
QByteArray tessellationControlShaderCode() const;
@@ -96,6 +103,9 @@ public:
QString log() const;
Status status() const;
+ void setFormat(Format format);
+ Format format() const;
+
Q_INVOKABLE static QByteArray loadSource(const QUrl &sourceUrl);
public Q_SLOTS:
@@ -115,6 +125,7 @@ Q_SIGNALS:
void computeShaderCodeChanged(const QByteArray &computeShaderCode);
void logChanged(const QString &log);
void statusChanged(Status status);
+ void formatChanged(Format format);
protected:
explicit QShaderProgram(QShaderProgramPrivate &dd, Qt3DCore::QNode *parent = nullptr);
diff --git a/src/render/materialsystem/qshaderprogram_p.h b/src/render/materialsystem/qshaderprogram_p.h
index f09b2a30e..d377ef039 100644
--- a/src/render/materialsystem/qshaderprogram_p.h
+++ b/src/render/materialsystem/qshaderprogram_p.h
@@ -72,6 +72,7 @@ public:
QByteArray m_computeShaderCode;
QString m_log;
QShaderProgram::Status m_status;
+ QShaderProgram::Format m_format;
void setLog(const QString &log);
void setStatus(QShaderProgram::Status status);
@@ -88,6 +89,7 @@ struct QShaderProgramData
QByteArray geometryShaderCode;
QByteArray fragmentShaderCode;
QByteArray computeShaderCode;
+ QShaderProgram::Format format;
};
} // namespace Qt3DRender
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index 00d9d334f..d0069bb4a 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -86,6 +86,7 @@ Shader::Shader()
: BackendNode(ReadWrite)
, m_requiresFrontendSync(false)
, m_status(QShaderProgram::NotReady)
+ , m_format(QShaderProgram::GLSL)
, m_dirty(false)
{
m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1);
@@ -99,6 +100,7 @@ void Shader::cleanup()
{
QBackendNode::setEnabled(false);
m_status = QShaderProgram::NotReady;
+ m_format = QShaderProgram::GLSL;
m_log.clear();
m_dirty = false;
}
@@ -121,6 +123,7 @@ void Shader::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (code != m_shaderCode.value(shaderType))
setShaderCode(shaderType, code);
}
+ setFormat(node->format());
}
void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &code)
@@ -135,6 +138,16 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co
markDirty(AbstractRenderer::ShadersDirty);
}
+void Shader::setFormat(QShaderProgram::Format format)
+{
+ if (format == m_format)
+ return;
+ m_format = format;
+ m_dirty = true;
+ setStatus(QShaderProgram::NotReady);
+ markDirty(AbstractRenderer::ShadersDirty);
+}
+
QVector<QByteArray> Shader::shaderCode() const
{
return m_shaderCode;
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index 8b1941d2c..23d57f25d 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -105,6 +105,9 @@ public:
inline QString log() const { return m_log; }
inline QShaderProgram::Status status() const { return m_status; }
+
+ void setFormat(QShaderProgram::Format format);
+ QShaderProgram::Format format() const { return m_format; }
bool isDirty() const { return m_dirty; }
void unsetDirty() { m_dirty = false; }
@@ -117,6 +120,7 @@ private:
QString m_log;
QShaderProgram::Status m_status;
bool m_requiresFrontendSync;
+ QShaderProgram::Format m_format;
bool m_dirty;
void initializeFromReference(const Shader &other);
diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
index 18dd1306a..15be26e8e 100644
--- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
+++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
@@ -45,6 +45,13 @@ class tst_QShaderProgram : public Qt3DRender::QShaderProgram
{
Q_OBJECT
+public:
+ tst_QShaderProgram()
+ : Qt3DRender::QShaderProgram()
+ {
+ qRegisterMetaType<Qt3DRender::QShaderProgram::Format>("Format");
+ }
+
private Q_SLOTS:
void checkDefaultConstruction()
@@ -61,6 +68,7 @@ private Q_SLOTS:
QCOMPARE(shaderProgram.computeShaderCode(), QByteArray());
QCOMPARE(shaderProgram.log(), QString());
QCOMPARE(shaderProgram.status(), Qt3DRender::QShaderProgram::NotReady);
+ QCOMPARE(shaderProgram.format(), Qt3DRender::QShaderProgram::GLSL);
}
void checkPropertyChanges()
@@ -182,6 +190,25 @@ private Q_SLOTS:
QCOMPARE(shaderProgram.computeShaderCode(), newValue);
QCOMPARE(spy.count(), 0);
}
+ {
+ // WHEN
+ QSignalSpy spy(&shaderProgram, SIGNAL(formatChanged(Format)));
+ const QShaderProgram::Format newValue = QShaderProgram::SPIRV;
+ shaderProgram.setFormat(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(shaderProgram.format(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ shaderProgram.setFormat(newValue);
+
+ // THEN
+ QCOMPARE(shaderProgram.format(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
}
void checkCreationData()
@@ -195,6 +222,7 @@ private Q_SLOTS:
shaderProgram.setGeometryShaderCode(QByteArrayLiteral("Geometry"));
shaderProgram.setFragmentShaderCode(QByteArrayLiteral("Fragment"));
shaderProgram.setComputeShaderCode(QByteArrayLiteral("Compute"));
+ shaderProgram.setFormat(QShaderProgram::SPIRV);
// WHEN
QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
@@ -217,6 +245,7 @@ private Q_SLOTS:
QCOMPARE(shaderProgram.geometryShaderCode(), cloneData.geometryShaderCode);
QCOMPARE(shaderProgram.fragmentShaderCode(), cloneData.fragmentShaderCode);
QCOMPARE(shaderProgram.computeShaderCode(), cloneData.computeShaderCode);
+ QCOMPARE(shaderProgram.format(), cloneData.format);
QCOMPARE(shaderProgram.id(), creationChangeData->subjectId());
QCOMPARE(shaderProgram.isEnabled(), true);
QCOMPARE(shaderProgram.isEnabled(), creationChangeData->isNodeEnabled());
@@ -532,6 +561,42 @@ private Q_SLOTS:
// THEN
QVERIFY(mainContent.indexOf(includedContent) == 0);
}
+
+ void checkFormatPropertyUpdate()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DRender::QShaderProgram shaderProgram;
+ arbiter.setArbiterOnNode(&shaderProgram);
+
+ QSignalSpy spy(&shaderProgram, SIGNAL(formatChanged(Format)));
+
+ // THEN
+ QVERIFY(spy.isValid());
+
+ {
+ // WHEN
+ shaderProgram.setFormat(QShaderProgram::SPIRV);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(arbiter.events.size(), 0);
+
+ spy.clear();
+ }
+
+ {
+ // WHEN
+ shaderProgram.setFormat(QShaderProgram::SPIRV);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(spy.count(), 0);
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+ }
+
};
QTEST_MAIN(tst_QShaderProgram)
diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp
index 3f0714907..a1f837010 100644
--- a/tests/auto/render/shader/tst_shader.cpp
+++ b/tests/auto/render/shader/tst_shader.cpp
@@ -42,15 +42,17 @@ private slots:
void cleanupLeavesACoherentState();
void dealWithPropertyChanges_data();
void dealWithPropertyChanges();
+ void dealWithFormatChanges();
void checkSetRendererDirtyOnInitialization();
void allowToChangeShaderCode_data();
void allowToChangeShaderCode();
};
-Qt3DRender::QShaderProgram *createFrontendShader()
+Qt3DRender::QShaderProgram *createFrontendShader(Qt3DRender::QShaderProgram::Format format = Qt3DRender::QShaderProgram::GLSL)
{
Qt3DRender::QShaderProgram *shader = new Qt3DRender::QShaderProgram();
+ shader->setFormat(format);
shader->setVertexShaderCode(QByteArrayLiteral(
"#version 150"\
@@ -80,6 +82,7 @@ void tst_RenderShader::hasCoherentInitialState()
Qt3DRender::Render::Shader *shader = new Qt3DRender::Render::Shader();
QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady);
+ QCOMPARE(shader->format(), Qt3DRender::QShaderProgram::GLSL);
QVERIFY(shader->log().isEmpty());
QCOMPARE(shader->isDirty(), false);
}
@@ -97,11 +100,12 @@ void tst_RenderShader::matchesFrontendPeer()
for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i)
QCOMPARE(backend.shaderCode()[i],
frontend->shaderCode(static_cast<Qt3DRender::QShaderProgram::ShaderType>(i)));
+ QCOMPARE(backend.format(), frontend->format());
}
void tst_RenderShader::cleanupLeavesACoherentState()
{
- QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader());
+ QScopedPointer<Qt3DRender::QShaderProgram> frontend(createFrontendShader(Qt3DRender::QShaderProgram::SPIRV));
TestRenderer renderer;
Qt3DRender::Render::Shader shader;
@@ -112,6 +116,7 @@ void tst_RenderShader::cleanupLeavesACoherentState()
QCOMPARE(shader.isDirty(), false);
QCOMPARE(shader.status(), Qt3DRender::QShaderProgram::NotReady);
+ QCOMPARE(shader.format(), Qt3DRender::QShaderProgram::GLSL);
}
void tst_RenderShader::dealWithPropertyChanges_data()
@@ -176,6 +181,45 @@ void tst_RenderShader::dealWithPropertyChanges()
QCOMPARE(backend.isDirty(), true);
}
+void tst_RenderShader::dealWithFormatChanges()
+{
+ // GIVEN
+ Qt3DRender::Render::Shader backend;
+ Qt3DRender::QShaderProgram shader;
+ TestRenderer renderer;
+ backend.setRenderer(&renderer);
+ simulateInitializationSync(&shader, &backend);
+
+ // WHEN
+ shader.setFormat(Qt3DRender::QShaderProgram::GLSL);
+ backend.syncFromFrontEnd(&shader, false);
+
+ // THEN
+ QCOMPARE(backend.format(), Qt3DRender::QShaderProgram::GLSL);
+ QCOMPARE(backend.isDirty(), false);
+ QCOMPARE(renderer.dirtyBits(), 0);
+
+ // WHEN
+ shader.setFormat(Qt3DRender::QShaderProgram::SPIRV);
+ backend.syncFromFrontEnd(&shader, false);
+
+ // THEN
+ QCOMPARE(backend.format(), Qt3DRender::QShaderProgram::SPIRV);
+ QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
+ QCOMPARE(backend.isDirty(), true);
+
+ renderer.resetDirty();
+ backend.unsetDirty();
+
+ // WHEN
+ shader.setFormat(Qt3DRender::QShaderProgram::SPIRV);
+ backend.syncFromFrontEnd(&shader, false);
+
+ // THEN
+ QCOMPARE(backend.isDirty(), false);
+ QCOMPARE(renderer.dirtyBits(), 0);
+}
+
void tst_RenderShader::checkSetRendererDirtyOnInitialization()
{
// GIVEN