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>2019-12-19 07:31:15 +0100
commit082ded6a34b88c2d0b6c2a30e0d2ee9a5cee9a4d (patch)
tree2bd3d7d329c964d4087c381e50ff5edc473307a0
parentd3042802000902add8662b2fb66e76cc9abb6b5c (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
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp42
-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
7 files changed, 182 insertions, 3 deletions
diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp
index c4e14ea2c..6f59e6be0 100644
--- a/src/render/materialsystem/qshaderprogram.cpp
+++ b/src/render/materialsystem/qshaderprogram.cpp
@@ -332,6 +332,15 @@
\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
+*/
+
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
@@ -339,6 +348,7 @@ namespace Qt3DRender {
QShaderProgramPrivate::QShaderProgramPrivate()
: QNodePrivate()
, m_status(QShaderProgram::NotReady)
+ , m_format(QShaderProgram::GLSL)
{
}
@@ -617,7 +627,7 @@ QString QShaderProgram::log() const
}
/*!
- \qmlproperty string ShaderProgram::status
+ \qmlproperty enumeration ShaderProgram::status
Holds the status of the current shader program.
*/
@@ -635,6 +645,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 6.0
+
+ Holds the format of the code provided on the ShaderProgram.
+ The default is ShaderProgram.GLSL
+*/
+/*!
+ \property QShaderProgram::format
+ \since 6.0
+
+ 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 +738,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..ba51cec2f 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)
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 20883f03a..8a14255a8 100644
--- a/src/render/materialsystem/qshaderprogram_p.h
+++ b/src/render/materialsystem/qshaderprogram_p.h
@@ -73,6 +73,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);
@@ -89,6 +90,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 afa70ed41..f3570f78d 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -85,6 +85,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);
@@ -98,6 +99,7 @@ void Shader::cleanup()
{
QBackendNode::setEnabled(false);
m_status = QShaderProgram::NotReady;
+ m_format = QShaderProgram::GLSL;
m_log.clear();
m_dirty = false;
}
@@ -120,6 +122,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)
@@ -134,6 +137,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 6f5383e88..9065a6524 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -106,6 +106,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; }
@@ -118,6 +121,7 @@ private:
QString m_log;
QShaderProgram::Status m_status;
bool m_requiresFrontendSync;
+ QShaderProgram::Format m_format;
bool m_dirty;
QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications;
diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
index a261d0860..7b96847a3 100644
--- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
+++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
@@ -42,6 +42,13 @@ class tst_QShaderProgram : public Qt3DRender::QShaderProgram
{
Q_OBJECT
+public:
+ tst_QShaderProgram()
+ : Qt3DRender::QShaderProgram()
+ {
+ qRegisterMetaType<Qt3DRender::QShaderProgram::Format>("Format");
+ }
+
private Q_SLOTS:
void checkDefaultConstruction()
@@ -58,6 +65,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()
@@ -179,6 +187,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()
@@ -192,6 +219,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;
@@ -214,6 +242,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());
@@ -529,6 +558,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