diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2019-10-08 08:08:21 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2019-10-14 08:04:40 +0200 |
commit | c8134efd470482e2254e7b232deb386828af5610 (patch) | |
tree | dda08eedc773b84b02b40660a61e987126815c7f /src/render | |
parent | ca48552bf2c150886fe1b064a061bb77bc76f230 (diff) |
Convert Shader/ShaderBuilder jobs to use direct sync
Change-Id: Ia56ba6176c86e34904611ae57e682ac9d52c79f7
Reviewed-by: Mike Krus <mike.krus@kdab.com>
Diffstat (limited to 'src/render')
-rw-r--r-- | src/render/materialsystem/qshaderprogrambuilder.cpp | 88 | ||||
-rw-r--r-- | src/render/materialsystem/qshaderprogrambuilder.h | 1 | ||||
-rw-r--r-- | src/render/materialsystem/qshaderprogrambuilder_p.h | 6 | ||||
-rw-r--r-- | src/render/materialsystem/shader.cpp | 38 | ||||
-rw-r--r-- | src/render/materialsystem/shader_p.h | 7 | ||||
-rw-r--r-- | src/render/materialsystem/shaderbuilder.cpp | 62 | ||||
-rw-r--r-- | src/render/materialsystem/shaderbuilder_p.h | 36 | ||||
-rw-r--r-- | src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp | 5 | ||||
-rw-r--r-- | src/render/renderers/opengl/renderer/renderer.cpp | 90 | ||||
-rw-r--r-- | src/render/renderers/opengl/renderer/renderer_p.h | 22 |
10 files changed, 160 insertions, 195 deletions
diff --git a/src/render/materialsystem/qshaderprogrambuilder.cpp b/src/render/materialsystem/qshaderprogrambuilder.cpp index cafe23ee4..6613661d1 100644 --- a/src/render/materialsystem/qshaderprogrambuilder.cpp +++ b/src/render/materialsystem/qshaderprogrambuilder.cpp @@ -79,6 +79,47 @@ QShaderProgramBuilderPrivate::QShaderProgramBuilderPrivate() { } +void QShaderProgramBuilderPrivate::setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type) +{ + Q_Q(QShaderProgramBuilder); + const bool blocked = q->blockNotifications(true); + + switch (type) { + case QShaderProgram::Vertex: { + m_vertexShaderCode = code; + emit q->vertexShaderCodeChanged(m_vertexShaderCode); + break; + } + case QShaderProgram::Fragment:{ + m_fragmentShaderCode = code; + emit q->fragmentShaderCodeChanged(m_fragmentShaderCode); + break; + } + case QShaderProgram::Geometry: { + m_geometryShaderCode = code; + emit q->geometryShaderCodeChanged(m_geometryShaderCode); + break; + } + case QShaderProgram::Compute: { + m_computeShaderCode = code; + emit q->computeShaderCodeChanged(m_computeShaderCode); + break; + } + case QShaderProgram::TessellationControl: { + m_tessControlShaderCode = code; + emit q->tessellationControlShaderCodeChanged(m_tessControlShaderCode); + break; + } + case QShaderProgram::TessellationEvaluation: { + m_tessEvalShaderCode = code; + emit q->tessellationEvaluationShaderCodeChanged(m_tessEvalShaderCode); + break; + } + } + + q->blockNotifications(blocked); +} + QShaderProgramBuilder::QShaderProgramBuilder(QNode *parent) : QNode(*new QShaderProgramBuilderPrivate, parent) { @@ -94,53 +135,6 @@ QShaderProgramBuilder::QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Q { } -void QShaderProgramBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) -{ - Q_D(QShaderProgramBuilder); - if (change->type() == Qt3DCore::PropertyUpdated) { - const Qt3DCore::QPropertyUpdatedChangePtr e = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(change); - if (e->propertyName() == QByteArrayLiteral("generatedShaderCode")) { - const bool blocked = blockNotifications(true); - const QPair<int, QByteArray> data = e->value().value<QPair<int, QByteArray>>(); - - switch (data.first) { - case QShaderProgram::Vertex: { - d->m_vertexShaderCode = data.second; - emit vertexShaderCodeChanged(d->m_vertexShaderCode); - break; - } - case QShaderProgram::Fragment:{ - d->m_fragmentShaderCode = data.second; - emit fragmentShaderCodeChanged(d->m_fragmentShaderCode); - break; - } - case QShaderProgram::Geometry: { - d->m_geometryShaderCode = data.second; - emit geometryShaderCodeChanged(d->m_geometryShaderCode); - break; - } - case QShaderProgram::Compute: { - d->m_computeShaderCode = data.second; - emit computeShaderCodeChanged(d->m_computeShaderCode); - break; - } - case QShaderProgram::TessellationControl: { - d->m_tessControlShaderCode = data.second; - emit tessellationControlShaderCodeChanged(d->m_tessControlShaderCode); - break; - } - case QShaderProgram::TessellationEvaluation: { - d->m_tessEvalShaderCode = data.second; - emit tessellationEvaluationShaderCodeChanged(d->m_tessEvalShaderCode); - break; - } - } - - blockNotifications(blocked); - } - } -} - /*! \qmlproperty string ShaderProgramBuilder::shaderProgram diff --git a/src/render/materialsystem/qshaderprogrambuilder.h b/src/render/materialsystem/qshaderprogrambuilder.h index 184093730..5dc6b54ff 100644 --- a/src/render/materialsystem/qshaderprogrambuilder.h +++ b/src/render/materialsystem/qshaderprogrambuilder.h @@ -117,7 +117,6 @@ Q_SIGNALS: protected: explicit QShaderProgramBuilder(QShaderProgramBuilderPrivate &dd, Qt3DCore::QNode *parent = nullptr); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override; private: Q_DECLARE_PRIVATE(QShaderProgramBuilder) diff --git a/src/render/materialsystem/qshaderprogrambuilder_p.h b/src/render/materialsystem/qshaderprogrambuilder_p.h index 2ac765a1d..22f8e6e58 100644 --- a/src/render/materialsystem/qshaderprogrambuilder_p.h +++ b/src/render/materialsystem/qshaderprogrambuilder_p.h @@ -52,6 +52,8 @@ // #include <private/qnode_p.h> +#include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DRender/qshaderprogram.h> #include <Qt3DRender/qshaderprogrambuilder.h> #include <QtCore/qurl.h> @@ -60,7 +62,7 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { -class QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate +class Q_3DRENDERSHARED_PRIVATE_EXPORT QShaderProgramBuilderPrivate : public Qt3DCore::QNodePrivate { public: QShaderProgramBuilderPrivate(); @@ -80,6 +82,8 @@ public: QByteArray m_geometryShaderCode; QByteArray m_fragmentShaderCode; QByteArray m_computeShaderCode; + + void setShaderCode(const QByteArray &code, QShaderProgram::ShaderType type); }; struct QShaderProgramBuilderData diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp index f35fba9fa..58709b37e 100644 --- a/src/render/materialsystem/shader.cpp +++ b/src/render/materialsystem/shader.cpp @@ -64,6 +64,7 @@ Shader::Shader() , m_dna(0) , m_graphicsContext(nullptr) , m_status(QShaderProgram::NotReady) + , m_requiresFrontendSync(false) { m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1); } @@ -170,8 +171,9 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co m_shaderCode[type] = code; m_isLoaded = false; - setStatus(QShaderProgram::NotReady); + m_status = QShaderProgram::NotReady; updateDNA(); + m_requiresFrontendSync = true; markDirty(AbstractRenderer::ShadersDirty); } @@ -237,20 +239,13 @@ ShaderStorageBlock Shader::storageBlockForBlockName(const QString &blockName) return ShaderStorageBlock(); } -// To be called from a worker thread -void Shader::submitPendingNotifications() -{ - const QVector<Qt3DCore::QPropertyUpdatedChangePtr> notifications = std::move(m_pendingNotifications); - for (const Qt3DCore::QPropertyUpdatedChangePtr ¬ification : notifications) - notifyObservers(notification); -} - void Shader::prepareUniforms(ShaderParameterPack &pack) { const PackUniformHash &values = pack.uniforms(); auto it = values.cbegin(); const auto end = values.cend(); + while (it != end) { // Find if there's a uniform with the same name id for (const ShaderUniform &uniform : qAsConst(m_uniforms)) { @@ -412,32 +407,21 @@ void Shader::initializeFromReference(const Shader &other) m_shaderStorageBlockNames = other.m_shaderStorageBlockNames; m_shaderStorageBlocks = other.m_shaderStorageBlocks; m_isLoaded = other.m_isLoaded; - setStatus(other.status()); - setLog(other.log()); + m_status = other.m_status; + m_log = other.m_log; + m_requiresFrontendSync = true; } void Shader::setLog(const QString &log) { - if (log != m_log) { - m_log = log; - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("log"); - e->setValue(QVariant::fromValue(m_log)); - m_pendingNotifications.push_back(e); - } + m_log = log; + m_requiresFrontendSync = true; } void Shader::setStatus(QShaderProgram::Status status) { - if (status != m_status) { - m_status = status; - Qt3DCore::QPropertyUpdatedChangePtr e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - e->setPropertyName("status"); - e->setValue(QVariant::fromValue(m_status)); - m_pendingNotifications.push_back(e); - } + m_status = status; + m_requiresFrontendSync = true; } } // namespace Render diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h index f8cdde3b7..fe1a401d9 100644 --- a/src/render/materialsystem/shader_p.h +++ b/src/render/materialsystem/shader_p.h @@ -122,8 +122,8 @@ public: inline QString log() const { return m_log; } inline QShaderProgram::Status status() const { return m_status; } - void submitPendingNotifications(); - inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); } + inline bool requiresFrontendSync() const { return m_requiresFrontendSync; } + inline void unsetRequiresFrontendSync() { m_requiresFrontendSync = false; } private: QVector<QString> m_uniformsNames; @@ -155,8 +155,7 @@ private: QMetaObject::Connection m_contextConnection; QString m_log; QShaderProgram::Status m_status; - - QVector<Qt3DCore::QPropertyUpdatedChangePtr> m_pendingNotifications; + bool m_requiresFrontendSync; void updateDNA(); diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index 6116ca56b..4e9327003 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -115,31 +115,6 @@ using namespace Qt3DCore; namespace Qt3DRender { namespace Render { - -namespace { - -QShaderProgram::ShaderType toQShaderProgramType(ShaderBuilder::ShaderType type) -{ - switch (type) { - case ShaderBuilder::ShaderType::Vertex: - return QShaderProgram::Vertex; - case ShaderBuilder::ShaderType::TessellationControl: - return QShaderProgram::TessellationControl; - case ShaderBuilder::ShaderType::TessellationEvaluation: - return QShaderProgram::TessellationEvaluation; - case ShaderBuilder::ShaderType::Geometry: - return QShaderProgram::Geometry; - case ShaderBuilder::ShaderType::Fragment: - return QShaderProgram::Fragment; - case ShaderBuilder::ShaderType::Compute: - return QShaderProgram::Compute; - default: - Q_UNREACHABLE(); - } -} - -} // anonymous - QString ShaderBuilder::getPrototypesFile() { return qt3dGlobalShaderPrototypes->prototypesFile(); @@ -191,7 +166,7 @@ void ShaderBuilder::setEnabledLayers(const QStringList &layers) m_enabledLayers = layers; - for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) { + for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) { if (!it.value().isEmpty()) m_dirtyTypes.insert(it.key()); } @@ -208,18 +183,18 @@ void ShaderBuilder::setGraphicsApi(const GraphicsApiFilterData &graphicsApi) return; m_graphicsApi = graphicsApi; - for (QHash<ShaderType, QUrl>::const_iterator it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) { + for (auto it = m_graphs.cbegin(); it != m_graphs.cend(); ++it) { if (!it.value().isEmpty()) m_dirtyTypes.insert(it.key()); } } -QUrl ShaderBuilder::shaderGraph(ShaderBuilder::ShaderType type) const +QUrl ShaderBuilder::shaderGraph(QShaderProgram::ShaderType type) const { return m_graphs.value(type); } -void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &url) +void ShaderBuilder::setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url) { if (url != m_graphs.value(type)) { m_graphs.insert(type, url); @@ -227,17 +202,17 @@ void ShaderBuilder::setShaderGraph(ShaderBuilder::ShaderType type, const QUrl &u } } -QByteArray ShaderBuilder::shaderCode(ShaderBuilder::ShaderType type) const +QByteArray ShaderBuilder::shaderCode(QShaderProgram::ShaderType type) const { return m_codes.value(type); } -bool ShaderBuilder::isShaderCodeDirty(ShaderBuilder::ShaderType type) const +bool ShaderBuilder::isShaderCodeDirty(QShaderProgram::ShaderType type) const { return m_dirtyTypes.contains(type); } -void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type) +void ShaderBuilder::generateCode(QShaderProgram::ShaderType type) { const auto graphPath = QUrlHelper::urlToLocalFileOrQrc(shaderGraph(type)); QFile file(graphPath); @@ -273,12 +248,9 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type) m_codes.insert(type, QShaderProgramPrivate::deincludify(code, graphPath + QStringLiteral(".glsl"))); m_dirtyTypes.remove(type); - // Send notification to the frontend - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); - propertyChange->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - propertyChange->setPropertyName("generatedShaderCode"); - propertyChange->setValue(QVariant::fromValue(qMakePair(int(toQShaderProgramType(type)), m_codes.value(type)))); - notifyObservers(propertyChange); + m_pendingUpdates.push_back({ peerId(), + type, + m_codes.value(type) }); } void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) @@ -305,13 +277,13 @@ void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) 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}, + static const std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = { + {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph}, + {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph}, + {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph}, + {QShaderProgram::Geometry, &QShaderProgramBuilder::geometryShaderGraph}, + {QShaderProgram::Fragment, &QShaderProgramBuilder::fragmentShaderGraph}, + {QShaderProgram::Compute, &QShaderProgramBuilder::computeShaderGraph}, }; for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) { diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h index 6b92d3114..ac7a165b8 100644 --- a/src/render/materialsystem/shaderbuilder_p.h +++ b/src/render/materialsystem/shaderbuilder_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <Qt3DRender/qshaderprogram.h> #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DRender/private/qgraphicsapifilter_p.h> @@ -60,18 +61,16 @@ namespace Qt3DRender { namespace Render { +struct ShaderBuilderUpdate +{ + Qt3DCore::QNodeId builderId; + Qt3DRender::QShaderProgram::ShaderType shaderType; + QByteArray shaderCode; +}; + class Q_3DRENDERSHARED_PRIVATE_EXPORT ShaderBuilder : public BackendNode { public: - enum ShaderType { - Vertex = 0, - TessellationControl, - TessellationEvaluation, - Geometry, - Fragment, - Compute - }; - static QString getPrototypesFile(); static void setPrototypesFile(const QString &file); static QStringList getPrototypeNames(); @@ -86,25 +85,28 @@ public: GraphicsApiFilterData graphicsApi() const; void setGraphicsApi(const GraphicsApiFilterData &graphicsApi); - QUrl shaderGraph(ShaderType type) const; - void setShaderGraph(ShaderType type, const QUrl &url); + QUrl shaderGraph(QShaderProgram::ShaderType type) const; + void setShaderGraph(QShaderProgram::ShaderType type, const QUrl &url); - QByteArray shaderCode(ShaderType type) const; - bool isShaderCodeDirty(ShaderType type) const; + QByteArray shaderCode(QShaderProgram::ShaderType type) const; + bool isShaderCodeDirty(QShaderProgram::ShaderType type) const; - void generateCode(ShaderType type); + void generateCode(QShaderProgram::ShaderType type); void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + QVector<ShaderBuilderUpdate> &updates() { return m_pendingUpdates; } + private: void setEnabledLayers(const QStringList &layers); GraphicsApiFilterData m_graphicsApi; Qt3DCore::QNodeId m_shaderProgramId; QStringList m_enabledLayers; - QHash<ShaderType, QUrl> m_graphs; - QHash<ShaderType, QByteArray> m_codes; - QSet<ShaderType> m_dirtyTypes; + QHash<QShaderProgram::ShaderType, QUrl> m_graphs; + QHash<QShaderProgram::ShaderType, QByteArray> m_codes; + QSet<QShaderProgram::ShaderType> m_dirtyTypes; + QVector<ShaderBuilderUpdate> m_pendingUpdates; }; } // namespace Render diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp index f4bd8b871..333453ac7 100644 --- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp @@ -279,7 +279,7 @@ void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderPro } -// Called by GL Command Thread +// Called by Renderer::updateGLResources void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager) { bool wasPresent = false; @@ -317,7 +317,8 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager) shader->setGraphicsContext(this); shader->setLoaded(true); - shader->markDirty(AbstractRenderer::AllDirty); + // Will force notifications to be sent to frontend at next frame + shader->markDirty(AbstractRenderer::ShadersDirty); } } diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 42af03d11..3da9b6c48 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -91,6 +91,8 @@ #include <Qt3DRender/private/renderviewbuilder_p.h> #include <Qt3DRender/private/setfence_p.h> #include <Qt3DRender/private/subtreeenabler_p.h> +#include <Qt3DRender/private/qshaderprogrambuilder_p.h> +#include <Qt3DRender/private/qshaderprogram_p.h> #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/private/qeventfilterservice_p.h> @@ -191,16 +193,18 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create()) , m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create()) , m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create()) - , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) - , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) - , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) - , m_sendTextureChangesToFrontendJob(decltype(m_sendTextureChangesToFrontendJob)::create([] {}, - [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); }, - JobTypes::SendTextureChangesToFrontend)) - , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) - , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend)) - , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) - , m_syncLoadingJobs(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncLoadingJobs)) + , m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) + , m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) + , m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) + , m_sendTextureChangesToFrontendJob(SynchronizerPostFramePtr::create([] {}, + [this] (Qt3DCore::QAspectManager *m) { sendTextureChangesToFrontend(m); }, + JobTypes::SendTextureChangesToFrontend)) + , m_sendSetFenceHandlesToFrontendJob(SynchronizerJobPtr::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) + , m_sendDisablesToFrontendJob(SynchronizerJobPtr::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend)) + , m_introspectShaderJob(SynchronizerPostFramePtr::create([this] { reloadDirtyShaders(); }, + [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); }, + JobTypes::DirtyShaderGathering)) + , m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs)) , m_ownedContext(false) , m_offscreenHelper(nullptr) , m_shouldSwapBuffers(true) @@ -1104,45 +1108,22 @@ void Renderer::reloadDirtyShaders() if (shaderBuilder) { shaderBuilder->setGraphicsApi(*technique->graphicsApiFilter()); - for (int i = 0; i <= ShaderBuilder::Compute; i++) { - const auto builderType = static_cast<ShaderBuilder::ShaderType>(i); - if (!shaderBuilder->shaderGraph(builderType).isValid()) + for (int i = 0; i <= QShaderProgram::Compute; i++) { + const auto shaderType = static_cast<QShaderProgram::ShaderType>(i); + if (!shaderBuilder->shaderGraph(shaderType).isValid()) continue; - if (shaderBuilder->isShaderCodeDirty(builderType)) { - shaderBuilder->generateCode(builderType); + if (shaderBuilder->isShaderCodeDirty(shaderType)) { + shaderBuilder->generateCode(shaderType); + m_shaderBuilderUpdates.append(std::move(shaderBuilder->updates())); } - QShaderProgram::ShaderType shaderType = QShaderProgram::Vertex; - switch (builderType) { - case ShaderBuilder::Vertex: - shaderType = QShaderProgram::Vertex; - break; - case ShaderBuilder::TessellationControl: - shaderType = QShaderProgram::TessellationControl; - break; - case ShaderBuilder::TessellationEvaluation: - shaderType = QShaderProgram::TessellationEvaluation; - break; - case ShaderBuilder::Geometry: - shaderType = QShaderProgram::Geometry; - break; - case ShaderBuilder::Fragment: - shaderType = QShaderProgram::Fragment; - break; - case ShaderBuilder::Compute: - shaderType = QShaderProgram::Compute; - break; - } - - const auto code = shaderBuilder->shaderCode(builderType); + const auto code = shaderBuilder->shaderCode(shaderType); shader->setShaderCode(shaderType, code); } } - if (Q_UNLIKELY(shader->hasPendingNotifications())) - shader->submitPendingNotifications(); - // If the shader hasn't be loaded, load it + // If the shader hasn't been loaded, load it if (shader != nullptr && !shader->isLoaded()) loadShader(shader, shaderHandle); } @@ -1150,6 +1131,33 @@ void Renderer::reloadDirtyShaders() } } +// Executed in job postFrame +void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) +{ + Q_ASSERT(isRunning()); + + // Sync Shader + const QVector<HShader> activeShaders = m_nodesManager->shaderManager()->activeHandles(); + for (const HShader &handle :activeShaders) { + Shader *s = m_nodesManager->shaderManager()->data(handle); + if (s->requiresFrontendSync()) { + QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId())); + QShaderProgramPrivate *dFrontend = static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend)); + dFrontend->setStatus(s->status()); + dFrontend->setLog(s->log()); + s->unsetRequiresFrontendSync(); + } + } + + // Sync ShaderBuilder + const QVector<ShaderBuilderUpdate> shaderBuilderUpdates = std::move(m_shaderBuilderUpdates); + for (const ShaderBuilderUpdate &update : shaderBuilderUpdates) { + QShaderProgramBuilder *builder = static_cast<decltype(builder)>(manager->lookupNode(update.builderId)); + QShaderProgramBuilderPrivate *dBuilder = static_cast<decltype(dBuilder)>(QNodePrivate::get(builder)); + dBuilder->setShaderCode(update.shaderCode, update.shaderType); + } +} + // Executed in a job (as postFrame) void Renderer::sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager) { diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index 41a071290..29aece008 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -81,6 +81,7 @@ #include <Qt3DRender/private/renderercache_p.h> #include <Qt3DRender/private/texture_p.h> #include <Qt3DRender/private/glfence_p.h> +#include <Qt3DRender/private/shaderbuilder_p.h> #include <QHash> #include <QMatrix4x4> @@ -154,7 +155,7 @@ class UpdateLevelOfDetailJob; typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; -using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>; +using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>; class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer { @@ -220,7 +221,7 @@ public: inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; } inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; } inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; } - inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; } + inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; } inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; } inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; } inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; } @@ -374,14 +375,13 @@ private: HVao *previousVAOHandle, OpenGLVertexArrayObject **vao); - GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; - GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>> m_sendTextureChangesToFrontendJob; - GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob; - GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob; - IntrospectShadersJobPtr m_introspectShaderJob; - + SynchronizerJobPtr m_bufferGathererJob; + SynchronizerJobPtr m_vaoGathererJob; + SynchronizerJobPtr m_textureGathererJob; + SynchronizerPostFramePtr m_sendTextureChangesToFrontendJob; + SynchronizerJobPtr m_sendSetFenceHandlesToFrontendJob; + SynchronizerJobPtr m_sendDisablesToFrontendJob; + SynchronizerPostFramePtr m_introspectShaderJob; SynchronizerJobPtr m_syncLoadingJobs; void lookForAbandonedVaos(); @@ -389,6 +389,7 @@ private: void lookForDownloadableBuffers(); void lookForDirtyTextures(); void reloadDirtyShaders(); + void sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager); void sendTextureChangesToFrontend(Qt3DCore::QAspectManager *manager); void sendSetFenceHandlesToFrontend(); void sendDisablesToFrontend(); @@ -404,6 +405,7 @@ private: QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences; QVector<Qt3DCore::QNodeId> m_updatedDisables; Qt3DCore::QNodeIdVector m_textureIdsToCleanup; + QVector<ShaderBuilderUpdate> m_shaderBuilderUpdates; bool m_ownedContext; |