summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-09-19 17:00:01 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-09-26 14:22:27 +0200
commit637a9d688a85c452ac0a20378961081a08980cf6 (patch)
tree3025090aa573c390dc8d8298d5f3811ae11f646c
parentb8435ca421d5612afabec1d717ea0a29be8a9c5c (diff)
Update QShaderProgramBuilder to use direct sync
Change-Id: Ia96175b95ad8e852e1c65deb34070e0ef7e30bd2 Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r--src/render/frontend/qrenderaspect.cpp2
-rw-r--r--src/render/materialsystem/shaderbuilder.cpp71
-rw-r--r--src/render/materialsystem/shaderbuilder_p.h3
-rw-r--r--tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp162
4 files changed, 114 insertions, 124 deletions
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index 804dbef6c..cea97be69 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -290,7 +290,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer));
q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers));
q->registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer));
- q->registerBackendType<QShaderProgramBuilder>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer));
+ q->registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer));
q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers));
q->registerBackendType<QShaderImage, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer));
diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp
index c1ec7f75a..b80a66a50 100644
--- a/src/render/materialsystem/shaderbuilder.cpp
+++ b/src/render/materialsystem/shaderbuilder.cpp
@@ -279,47 +279,46 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
notifyObservers(propertyChange);
}
-void ShaderBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
+void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
{
- if (e->type() == PropertyUpdated) {
- QPropertyUpdatedChangePtr propertyChange = e.staticCast<QPropertyUpdatedChange>();
- QVariant propertyValue = propertyChange->value();
-
- if (propertyChange->propertyName() == QByteArrayLiteral("shaderProgram"))
- m_shaderProgramId = propertyValue.value<Qt3DCore::QNodeId>();
- else if (propertyChange->propertyName() == QByteArrayLiteral("enabledLayers"))
- setEnabledLayers(propertyValue.toStringList());
- else if (propertyChange->propertyName() == QByteArrayLiteral("vertexShaderGraph"))
- setShaderGraph(Vertex, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlShaderGraph"))
- setShaderGraph(TessellationControl, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationShaderGraph"))
- setShaderGraph(TessellationEvaluation, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("geometryShaderGraph"))
- setShaderGraph(Geometry, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentShaderGraph"))
- setShaderGraph(Fragment, propertyValue.toUrl());
- else if (propertyChange->propertyName() == QByteArrayLiteral("computeShaderGraph"))
- setShaderGraph(Compute, propertyValue.toUrl());
+ const QShaderProgramBuilder *node = qobject_cast<const QShaderProgramBuilder *>(frontEnd);
+ if (!node)
+ return;
+
+ const bool oldEnabled = isEnabled();
+ BackendNode::syncFromFrontEnd(frontEnd, firstTime);
+ if (oldEnabled != isEnabled()) {
markDirty(AbstractRenderer::ShadersDirty);
}
- BackendNode::sceneChangeEvent(e);
-}
-void ShaderBuilder::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
-{
- const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderProgramBuilderData>>(change);
- const auto &data = typedChange->data;
-
- m_shaderProgramId = data.shaderProgramId;
- m_enabledLayers = data.enabledLayers;
- setShaderGraph(Vertex, data.vertexShaderGraph);
- setShaderGraph(TessellationControl, data.tessellationControlShaderGraph);
- setShaderGraph(TessellationEvaluation, data.tessellationEvaluationShaderGraph);
- setShaderGraph(Geometry, data.geometryShaderGraph);
- setShaderGraph(Fragment, data.fragmentShaderGraph);
- setShaderGraph(Compute, data.computeShaderGraph);
+ const Qt3DCore::QNodeId shaderProgramId = Qt3DCore::qIdForNode(node->shaderProgram());
+ if (shaderProgramId != m_shaderProgramId) {
+ m_shaderProgramId = shaderProgramId;
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+
+ if (node->enabledLayers() != m_enabledLayers) {
+ setEnabledLayers(node->enabledLayers());
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+
+ static const std::pair<ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = {
+ {Vertex, &QShaderProgramBuilder::vertexShaderGraph},
+ {TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph},
+ {TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph},
+ {Geometry, &QShaderProgramBuilder::geometryShaderGraph},
+ {Fragment, &QShaderProgramBuilder::fragmentShaderGraph},
+ {Compute, &QShaderProgramBuilder::computeShaderGraph},
+ };
+
+ for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) {
+ const QUrl url = (node->*(it->second))();
+ if (url != m_graphs.value(it->first)) {
+ setShaderGraph(it->first, url);
+ markDirty(AbstractRenderer::ShadersDirty);
+ }
+ }
}
} // namespace Render
diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h
index 00c4e1c28..12234bb6c 100644
--- a/src/render/materialsystem/shaderbuilder_p.h
+++ b/src/render/materialsystem/shaderbuilder_p.h
@@ -95,10 +95,9 @@ public:
void generateCode(ShaderType type);
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
+ void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override;
private:
- void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final;
void setEnabledLayers(const QStringList &layers);
GraphicsApiFilterData m_graphicsApi;
diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
index e365256cc..c9a290dbd 100644
--- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
+++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp
@@ -141,9 +141,11 @@ private slots:
// GIVEN
QFETCH(Qt3DRender::QShaderProgramBuilder*, frontend);
Qt3DRender::Render::ShaderBuilder backend;
+ TestRenderer renderer;
// WHEN
- simulateInitialization(frontend, &backend);
+ backend.setRenderer(&renderer);
+ simulateInitializationSync(frontend, &backend);
// THEN
QVERIFY(backend.isEnabled() == frontend->isEnabled());
@@ -199,25 +201,14 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
-
- // THEN
- QVERIFY(backend.isEnabled());
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
- renderer.resetDirty();
-
- // WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(false);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabled(false);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(!backend.isEnabled());
@@ -225,10 +216,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(true);
- updateChange->setPropertyName("enabled");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabled(true);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -242,26 +231,24 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
- const auto programId = Qt3DCore::QNodeId::createId();
+ simulateInitializationSync(&frontend, &backend);
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(programId));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ Qt3DRender::QShaderProgram prog;
+ frontend.setShaderProgram(&prog);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
- QCOMPARE(backend.shaderProgramId(), programId);
+ QCOMPARE(backend.shaderProgramId(), prog.id());
QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(Qt3DCore::QNodeId()));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ frontend.setShaderProgram(nullptr);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.shaderProgramId().isNull());
@@ -269,10 +256,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QVariant::fromValue(programId));
- updateChange->setPropertyName("shaderProgram");
- backend.sceneChangeEvent(updateChange);
+ frontend.setShaderProgram(&prog);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -286,21 +271,34 @@ private slots:
{
// GIVEN
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
const auto layers = QStringList() << "foo" << "bar";
- for (int i = 0; i <= Qt3DRender::Render::ShaderBuilder::Compute; i++) {
- const auto type = static_cast<Qt3DRender::Render::ShaderBuilder::ShaderType>(i);
+ static const std::pair<
+ Qt3DRender::Render::ShaderBuilder::ShaderType,
+ void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
+ >
+ shaderTypesToSetters[] = {
+ {Qt3DRender::Render::ShaderBuilder::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ };
+
+
+ for (auto it = std::begin(shaderTypesToSetters), end = std::end(shaderTypesToSetters); it != end; ++it) {
const auto graphUrl = QUrl::fromEncoded("qrc:/input.json");
- backend.setShaderGraph(type, graphUrl);
+ (frontend.*(it->second))(graphUrl);
}
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.enabledLayers(), layers);
@@ -313,10 +311,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.enabledLayers(), layers);
@@ -325,14 +321,12 @@ private slots:
QVERIFY(!backend.isShaderCodeDirty(type));
backend.generateCode(type); // Resets the dirty flag
}
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
+ QCOMPARE(renderer.dirtyBits(), 0);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QStringList());
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(QStringList());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QVERIFY(backend.shaderProgramId().isNull());
@@ -345,10 +339,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(layers);
- updateChange->setPropertyName("enabledLayers");
- backend.sceneChangeEvent(updateChange);
+ frontend.setEnabledLayers(layers);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();
@@ -365,64 +357,68 @@ private slots:
void shouldHandleShaderGraphPropertiesChanges_data()
{
- QTest::addColumn<QByteArray>("property");
QTest::addColumn<Qt3DRender::Render::ShaderBuilder::ShaderType>("type");
QTest::addColumn<QUrl>("graphUrl");
- QTest::newRow("vertex") << QByteArrayLiteral("vertexShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Vertex
+ QTest::newRow("vertex") << Qt3DRender::Render::ShaderBuilder::Vertex
<< QUrl::fromEncoded("qrc:/vertex.json");
- QTest::newRow("tessControl") << QByteArrayLiteral("tessellationControlShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::TessellationControl
+ QTest::newRow("tessControl") << Qt3DRender::Render::ShaderBuilder::TessellationControl
<< QUrl::fromEncoded("qrc:/tesscontrol.json");
- QTest::newRow("tessEval") << QByteArrayLiteral("tessellationEvaluationShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation
+ QTest::newRow("tessEval") << Qt3DRender::Render::ShaderBuilder::TessellationEvaluation
<< QUrl::fromEncoded("qrc:/tesseval.json");
- QTest::newRow("geometry") << QByteArrayLiteral("geometryShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Geometry
+ QTest::newRow("geometry") << Qt3DRender::Render::ShaderBuilder::Geometry
<< QUrl::fromEncoded("qrc:/geometry.json");
- QTest::newRow("fragment") << QByteArrayLiteral("fragmentShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Fragment
+ QTest::newRow("fragment") << Qt3DRender::Render::ShaderBuilder::Fragment
<< QUrl::fromEncoded("qrc:/fragment.json");
- QTest::newRow("compute") << QByteArrayLiteral("computeShaderGraph")
- << Qt3DRender::Render::ShaderBuilder::Compute
+ QTest::newRow("compute") << Qt3DRender::Render::ShaderBuilder::Compute
<< QUrl::fromEncoded("qrc:/compute.json");
}
void shouldHandleShaderGraphPropertiesChanges()
{
// GIVEN
- QFETCH(QByteArray, property);
QFETCH(Qt3DRender::Render::ShaderBuilder::ShaderType, type);
QFETCH(QUrl, graphUrl);
Qt3DRender::Render::ShaderBuilder backend;
+ Qt3DRender::QShaderProgramBuilder frontend;
TestRenderer renderer;
backend.setRenderer(&renderer);
+ simulateInitializationSync(&frontend, &backend);
+
+ static const QHash<
+ Qt3DRender::Render::ShaderBuilder::ShaderType,
+ void (Qt3DRender::QShaderProgramBuilder::*)(const QUrl &)
+ >
+ shaderTypesToSetters = {
+ {Qt3DRender::Render::ShaderBuilder::Vertex, &Qt3DRender::QShaderProgramBuilder::setVertexShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::TessellationControl, &Qt3DRender::QShaderProgramBuilder::setTessellationControlShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::TessellationEvaluation, &Qt3DRender::QShaderProgramBuilder::setTessellationEvaluationShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Geometry, &Qt3DRender::QShaderProgramBuilder::setGeometryShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Fragment, &Qt3DRender::QShaderProgramBuilder::setFragmentShaderGraph},
+ {Qt3DRender::Render::ShaderBuilder::Compute, &Qt3DRender::QShaderProgramBuilder::setComputeShaderGraph},
+ };
// WHEN
- auto updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QUrl());
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+
+ (frontend.*(shaderTypesToSetters[type]))(QUrl());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), QUrl());
QVERIFY(!backend.isShaderCodeDirty(type));
QVERIFY(backend.shaderCode(type).isEmpty());
- QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty);
+ QCOMPARE(renderer.dirtyBits(), 0);
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(graphUrl);
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(graphUrl);
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), graphUrl);
@@ -432,10 +428,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(QUrl());
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(QUrl());
+ backend.syncFromFrontEnd(&frontend, false);
// THEN
QCOMPARE(backend.shaderGraph(type), QUrl());
@@ -445,10 +439,8 @@ private slots:
renderer.resetDirty();
// WHEN
- updateChange = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
- updateChange->setValue(graphUrl);
- updateChange->setPropertyName(property);
- backend.sceneChangeEvent(updateChange);
+ (frontend.*(shaderTypesToSetters[type]))(graphUrl);
+ backend.syncFromFrontEnd(&frontend, false);
// AND
backend.cleanup();