Commit c8134efd authored by Paul Lemire's avatar Paul Lemire
Browse files

Convert Shader/ShaderBuilder jobs to use direct sync



Change-Id: Ia56ba6176c86e34904611ae57e682ac9d52c79f7
Reviewed-by: Mike Krus's avatarMike Krus <mike.krus@kdab.com>
parent ca48552b
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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 &notification : 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
......
......@@ -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();
......
......@@ -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) {
......
......@@ -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
......
......@@ -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);
}
}
......
......@@ -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)
{
......
......@@ -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