summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-11-02 03:02:38 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-11-02 03:02:38 +0100
commitbfeba7c431fd7bebbf7163853cb2e6a327e188aa (patch)
treef89b0abaef1cf74acb5cfe88648cd23c642a6a24
parentc9d4103e52b28c7a242d90433112bfaedb77f0cc (diff)
parentfae98c57264e78e62c5955559c7e513969462a79 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.15
-rw-r--r--src/core/aspects/qaspectmanager.cpp6
-rw-r--r--src/core/nodes/qnode.cpp5
-rw-r--r--src/doc/src/qmlextramaterials.qdoc35
-rw-r--r--src/quick3d/imports/scene3d/scene3ditem.cpp46
-rw-r--r--src/quick3d/imports/scene3d/scene3dview.cpp2
-rw-r--r--src/render/framegraph/qbuffercapture.cpp8
-rw-r--r--src/render/geometry/buffer.cpp29
-rw-r--r--src/render/geometry/geometryrenderer.cpp10
-rw-r--r--src/render/jobs/filterentitybycomponentjob_p.h4
-rw-r--r--src/render/jobs/lightgatherer.cpp3
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h4
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp6
-rw-r--r--src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h4
-rw-r--r--src/render/renderers/opengl/renderer/rendercommand_p.h53
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp112
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h20
-rw-r--r--src/render/renderers/opengl/renderer/renderercache_p.h13
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp35
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h6
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder.cpp226
-rw-r--r--src/render/renderers/opengl/renderer/renderviewbuilder_p.h27
-rw-r--r--src/render/renderers/opengl/textures/gltexture.cpp22
-rw-r--r--src/render/services/vsyncframeadvanceservice.cpp11
-rw-r--r--src/render/texture/qtexture.cpp18
-rw-r--r--src/render/texture/texture.cpp2
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp106
-rw-r--r--tests/auto/render/buffer/tst_buffer.cpp55
-rw-r--r--tests/auto/render/renderer/tst_renderer.cpp6
-rw-r--r--tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp76
-rw-r--r--tests/manual/sharedtexture/main.cpp3
-rw-r--r--tests/manual/sharedtexture/videoplayer.cpp28
-rw-r--r--tests/manual/sharedtexture/videoplayer.h10
-rw-r--r--tests/manual/sharedtextureqml/main.cpp3
33 files changed, 552 insertions, 442 deletions
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index dffdd1c1a..f24248399 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -414,6 +414,8 @@ bool QAspectManager::event(QEvent *e)
// the loop
if (m_simulationLoopRunning && m_driveMode == QAspectEngine::Automatic)
requestNextFrame();
+
+ return true;
}
return QObject::event(e);
@@ -424,7 +426,7 @@ void QAspectManager::requestNextFrame()
qCDebug(Aspects) << "Requesting new Frame";
// Post event in the event loop to force
// next frame to be processed
- qApp->postEvent(this, new RequestFrameEvent());
+ QCoreApplication::postEvent(this, new RequestFrameEvent());
}
void QAspectManager::processFrame()
@@ -436,6 +438,8 @@ void QAspectManager::processFrame()
m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
const qint64 t = frameAdvanceService->waitForNextFrame();
+ if (t < 0)
+ return;
// Distribute accumulated changes. This includes changes sent from the frontend
// to the backend nodes. We call this before the call to m_scheduler->update() to ensure
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp
index cfe83f4db..739b46cfe 100644
--- a/src/core/nodes/qnode.cpp
+++ b/src/core/nodes/qnode.cpp
@@ -683,6 +683,11 @@ void QNodePrivate::update()
void QNodePrivate::updateNode(QNode *node, const char *property, ChangeFlag change)
{
if (m_changeArbiter) {
+ // Ensure node has its postConstructorInit called if we reach this
+ // point, we could otherwise endup referencing a node that has yet
+ // to be created in the backend
+ QNodePrivate::get(node)->_q_ensureBackendNodeCreated();
+
Q_Q(QNode);
m_changeArbiter->addDirtyFrontEndNode(q, node, property, change);
}
diff --git a/src/doc/src/qmlextramaterials.qdoc b/src/doc/src/qmlextramaterials.qdoc
index e0a2e9edf..338bada09 100644
--- a/src/doc/src/qmlextramaterials.qdoc
+++ b/src/doc/src/qmlextramaterials.qdoc
@@ -544,6 +544,41 @@
The default value is 0.5.
*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::sourceRgbArg
+
+ Holds the blend equation source RGB blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::destinationRgbArg
+
+ Holds the blend equation destination RGB blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::sourceAlphaArg
+
+ Holds the blend equation source alpha blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquationArguments::Blending PhongAlphaMaterial::destinationAlphaArg
+
+ Holds the blend equation destination alpha blending argument.
+
+ \sa Qt3DRender::QBlendEquationArguments::Blending
+*/
+/*!
+ \qmlproperty BlendEquation::BlendFunction PhongAlphaMaterial::blendFunctionArg
+
+ Holds the blend equation function argument.
+
+ \sa Qt3DRender::QBlendEquation::BlendFunction
+*/
/*!
\qmltype PhongMaterial
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp
index 55e972406..0fbde1191 100644
--- a/src/quick3d/imports/scene3d/scene3ditem.cpp
+++ b/src/quick3d/imports/scene3d/scene3ditem.cpp
@@ -581,25 +581,45 @@ bool Scene3DItem::isHoverEnabled() const
void Scene3DItem::setCameraAspectModeHelper()
{
- switch (m_cameraAspectRatioMode) {
- case AutomaticAspectRatio:
- connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- // Update the aspect ratio the first time the surface is set
- updateCameraAspectRatio();
- break;
- case UserAspectRatio:
- disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
- disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
- break;
+ if (m_compositingMode == FBO) {
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(this, &Scene3DItem::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(this, &Scene3DItem::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
+ } else {
+ // In Underlay mode, we rely on the window for aspect ratio and not the size of the Scene3DItem
+ switch (m_cameraAspectRatioMode) {
+ case AutomaticAspectRatio:
+ connect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ connect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ // Update the aspect ratio the first time the surface is set
+ updateCameraAspectRatio();
+ break;
+ case UserAspectRatio:
+ disconnect(window(), &QWindow::widthChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ disconnect(window(), &QWindow::heightChanged, this, &Scene3DItem::updateCameraAspectRatio);
+ break;
+ }
}
}
void Scene3DItem::updateCameraAspectRatio()
{
if (m_camera) {
- m_camera->setAspectRatio(static_cast<float>(width()) /
- static_cast<float>(height()));
+ if (m_compositingMode == FBO)
+ m_camera->setAspectRatio(static_cast<float>(width()) /
+ static_cast<float>(height()));
+ else
+ m_camera->setAspectRatio(static_cast<float>(window()->width()) /
+ static_cast<float>(window()->height()));
}
}
diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp
index 9d298b435..f38d135f0 100644
--- a/src/quick3d/imports/scene3d/scene3dview.cpp
+++ b/src/quick3d/imports/scene3d/scene3dview.cpp
@@ -278,6 +278,8 @@ QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode
if (m_dirtyFlags & DirtyTexture) {
fboNode->setTexture(m_texture);
m_dirtyFlags.setFlag(DirtyTexture, false);
+ // Show FBO Node at this point
+ fboNode->show();
}
if (m_dirtyFlags & DirtyNode) {
fboNode->markDirty(QSGNode::DirtyMaterial);
diff --git a/src/render/framegraph/qbuffercapture.cpp b/src/render/framegraph/qbuffercapture.cpp
index 0c12a3aff..c71c0adb7 100644
--- a/src/render/framegraph/qbuffercapture.cpp
+++ b/src/render/framegraph/qbuffercapture.cpp
@@ -62,6 +62,14 @@ QBufferCapturePrivate::QBufferCapturePrivate()
\inmodule Qt3DRender
\brief Exchanges buffer data between GPU and CPU.
*/
+
+/*!
+ \qmltype BufferCapture
+ \inqmlmodule Qt3D.Render
+ \instantiates Qt3DRender::QBufferCapture
+ \brief Exchanges buffer data between GPU and CPU.
+*/
+
QBufferCapture::QBufferCapture(Qt3DCore::QNode *parent)
: QFrameGraphNode(*new QBufferCapturePrivate, parent)
{
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 0d634c911..6db3bab44 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -137,20 +137,31 @@ void Buffer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
m_manager->addDirtyBuffer(peerId());
}
{
- QVariant v = node->property("QT3D_updateData");
- if (v.isValid()) {
+ const QVariant v = node->property("QT3D_updateData");
+
+ // Make sure we record data if it's the first time we are called
+ // or if we have no partial updates
+ if (firstTime || !v.isValid()){
+ const QByteArray newData = node->data();
+ const bool dirty = m_data != newData;
+ m_bufferDirty |= dirty;
+ m_data = newData;
+
+ // Since frontend applies partial updates to its m_data
+ // if we enter this code block, there's no problem in actually
+ // ignoring the partial updates
+ if (v.isValid())
+ const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
+
+ if (dirty && !m_data.isEmpty())
+ forceDataUpload();
+ } else if (v.isValid()) {
+ // Apply partial updates and record them to allow partial upload to the GPU
Qt3DRender::QBufferUpdate updateData = v.value<Qt3DRender::QBufferUpdate>();
m_data.replace(updateData.offset, updateData.data.size(), updateData.data);
m_bufferUpdates.push_back(updateData);
m_bufferDirty = true;
const_cast<QBuffer *>(node)->setProperty("QT3D_updateData", {});
- } else {
- QByteArray newData = node->data();
- bool dirty = m_data != newData;
- m_bufferDirty |= dirty;
- m_data = newData;
- if (dirty && !m_data.isEmpty())
- forceDataUpload();
}
}
markDirty(AbstractRenderer::BuffersDirty);
diff --git a/src/render/geometry/geometryrenderer.cpp b/src/render/geometry/geometryrenderer.cpp
index 3b460f48c..881c0f66b 100644
--- a/src/render/geometry/geometryrenderer.cpp
+++ b/src/render/geometry/geometryrenderer.cpp
@@ -139,8 +139,16 @@ void GeometryRenderer::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
if (functorDirty) {
m_dirty = true;
m_geometryFactory = newFunctor;
- if (m_geometryFactory && m_manager != nullptr)
+ if (m_geometryFactory && m_manager != nullptr) {
m_manager->addDirtyGeometryRenderer(peerId());
+
+ const bool isQMeshFunctor = m_geometryFactory->id() == Qt3DRender::functorTypeId<MeshLoaderFunctor>();
+ if (isQMeshFunctor) {
+ const QMesh *meshNode = static_cast<const QMesh *>(node);
+ QMeshPrivate *dmeshNode = QMeshPrivate::get(const_cast<QMesh *>(meshNode));
+ dmeshNode->setStatus(QMesh::Loading);
+ }
+ }
}
markDirty(AbstractRenderer::GeometryDirty);
diff --git a/src/render/jobs/filterentitybycomponentjob_p.h b/src/render/jobs/filterentitybycomponentjob_p.h
index dd64e50a7..75e487d7f 100644
--- a/src/render/jobs/filterentitybycomponentjob_p.h
+++ b/src/render/jobs/filterentitybycomponentjob_p.h
@@ -97,10 +97,6 @@ private:
QVector<Entity *> m_filteredEntities;
};
-template<typename T, typename ... Ts>
-using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
-
-
} // Render
} // Qt3DRender
diff --git a/src/render/jobs/lightgatherer.cpp b/src/render/jobs/lightgatherer.cpp
index b76cd4d73..f4c8dfba8 100644
--- a/src/render/jobs/lightgatherer.cpp
+++ b/src/render/jobs/lightgatherer.cpp
@@ -58,6 +58,9 @@ LightGatherer::LightGatherer()
void LightGatherer::run()
{
+ m_lights.clear();
+ m_environmentLight = nullptr;
+
const QVector<HEntity> handles = m_manager->activeHandles();
int envLightCount = 0;
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
index 725f83b62..9f45a8005 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h
@@ -68,14 +68,14 @@ public:
inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
inline void setEntities(const QVector<Entity *> &entities) { m_entities = entities; }
- inline QVector<EntityRenderCommandData> &commandData() { return m_commandData; }
+ inline EntityRenderCommandData &commandData() { return m_commandData; }
void run() final;
private:
RenderView *m_renderView;
QVector<Entity *> m_entities;
- QVector<EntityRenderCommandData> m_commandData;
+ EntityRenderCommandData m_commandData;
};
typedef QSharedPointer<RenderViewCommandBuilderJob> RenderViewCommandBuilderJobPtr;
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
index d58b288e6..af1d545ed 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp
@@ -70,11 +70,7 @@ void RenderViewCommandUpdaterJob::run()
// Copy commands out of cached -> ensures we can submit them for rendering
// while cache is rebuilt or modified for next frame
- QVector<RenderCommand> commands;
- commands.reserve(m_renderables.size());
- for (const EntityRenderCommandData *data : m_renderables)
- commands.push_back(data->command);
- m_commands = commands;
+ m_commands = m_renderables.commands;
}
}
diff --git a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
index 3fff5f1a0..72caef6cf 100644
--- a/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
+++ b/src/render/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h
@@ -71,7 +71,7 @@ public:
inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; }
inline void setRenderer(Renderer *renderer) Q_DECL_NOTHROW { m_renderer = renderer; }
- inline void setRenderables(const QVector<EntityRenderCommandData *> &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
+ inline void setRenderables(const EntityRenderCommandData &renderables) Q_DECL_NOTHROW { m_renderables = renderables; }
QVector<RenderCommand> &commands() Q_DECL_NOTHROW { return m_commands; }
@@ -80,7 +80,7 @@ public:
private:
RenderView *m_renderView;
Renderer *m_renderer;
- QVector<EntityRenderCommandData *> m_renderables;
+ EntityRenderCommandData m_renderables;
QVector<RenderCommand> m_commands;
};
diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h
index 58ab0cadd..0180d6996 100644
--- a/src/render/renderers/opengl/renderer/rendercommand_p.h
+++ b/src/render/renderers/opengl/renderer/rendercommand_p.h
@@ -131,11 +131,58 @@ inline bool operator!=(const RenderCommand &lhs, const RenderCommand &rhs) noexc
struct EntityRenderCommandData
{
- Entity *entity;
- RenderCommand command;
- RenderPassParameterData passData;
+ QVector<Entity *> entities;
+ QVector<RenderCommand> commands;
+ QVector<RenderPassParameterData> passesData;
+
+ void reserve(int size)
+ {
+ entities.reserve(size);
+ commands.reserve(size);
+ passesData.reserve(size);
+ }
+
+ inline int size() const { return entities.size(); }
+
+ inline void push_back(Entity *e, const RenderCommand &c, const RenderPassParameterData &p)
+ {
+ entities.push_back(e);
+ commands.push_back(c);
+ passesData.push_back(p);
+ }
+
+ inline void push_back(Entity *e, RenderCommand &&c, RenderPassParameterData &&p)
+ {
+ entities.push_back(e);
+ commands.push_back(std::move(c));
+ passesData.push_back(std::move(p));
+ }
+
+ EntityRenderCommandData &operator+=(const EntityRenderCommandData &t)
+ {
+ entities += t.entities;
+ commands += t.commands;
+ passesData += t.passesData;
+ return *this;
+ }
+
+ EntityRenderCommandData &operator+=(EntityRenderCommandData &&t)
+ {
+ entities += std::move(t.entities);
+ commands += std::move(t.commands);
+ passesData += std::move(t.passesData);
+ return *this;
+ }
+
+ EntityRenderCommandData mid(int idx, int len) const
+ {
+ return { entities.mid(idx, len), commands.mid(idx, len), passesData.mid(idx, len) };
+ }
+
+
};
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 9220a719a..a530c26b0 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -93,6 +93,7 @@
#include <Qt3DRender/private/subtreeenabler_p.h>
#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
#include <Qt3DRender/private/qshaderprogram_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -138,6 +139,82 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
+
+namespace {
+
+class SyncLightsGatherer
+{
+public:
+ explicit SyncLightsGatherer(LightGathererPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->gatheredLights = m_gatherJob->lights();
+ m_cache->environmentLight = m_gatherJob->takeEnvironmentLight();
+ }
+
+private:
+ LightGathererPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncRenderableEntities
+{
+public:
+ explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->renderableEntities = selectedEntities;
+ }
+
+private:
+ RenderableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+class SyncComputableEntities
+{
+public:
+ explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
+ RendererCache *cache)
+ : m_gatherJob(gatherJob)
+ , m_cache(cache)
+ {
+ }
+
+ void operator()()
+ {
+ QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
+ std::sort(selectedEntities.begin(), selectedEntities.end());
+
+ QMutexLocker lock(m_cache->mutex());
+ m_cache->computeEntities = selectedEntities;
+ }
+
+private:
+ ComputableEntityFilterPtr m_gatherJob;
+ RendererCache *m_cache;
+};
+
+} // anonymous
+
+
/*!
\internal
@@ -193,6 +270,9 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create())
, m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create())
, m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create())
+ , m_lightGathererJob(Render::LightGathererPtr::create())
+ , m_renderableEntityFilterJob(Render::RenderableEntityFilterPtr::create())
+ , m_computableEntityFilterJob(Render::ComputableEntityFilterPtr::create())
, m_bufferGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering))
, m_vaoGathererJob(SynchronizerJobPtr::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
, m_textureGathererJob(SynchronizerJobPtr::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
@@ -207,6 +287,12 @@ Renderer::Renderer(QRenderAspect::RenderType type)
[this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); },
JobTypes::DirtyShaderGathering))
, m_syncLoadingJobs(SynchronizerJobPtr::create([] {}, JobTypes::SyncLoadingJobs))
+ , m_cacheRenderableEntitiesJob(SynchronizerJobPtr::create(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheComputableEntitiesJob(SynchronizerJobPtr::create(SyncComputableEntities(m_computableEntityFilterJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
+ , m_cacheLightsJob(SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, &m_cache),
+ JobTypes::EntityComponentTypeFiltering))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
, m_shouldSwapBuffers(true)
@@ -240,6 +326,10 @@ Renderer::Renderer(QRenderAspect::RenderType type)
m_introspectShaderJob->addDependency(m_filterCompatibleTechniqueJob);
+ m_cacheLightsJob->addDependency(m_lightGathererJob);
+ m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
+ m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
+
m_filterCompatibleTechniqueJob->setRenderer(this);
m_defaultRenderStateSet = new RenderStateSet;
@@ -309,6 +399,9 @@ void Renderer::setNodeManagers(NodeManagers *managers)
m_updateEntityLayersJob->setManager(m_nodesManager);
m_updateTreeEnabledJob->setManagers(m_nodesManager);
m_sendBufferCaptureJob->setManagers(m_nodesManager);
+ m_lightGathererJob->setManager(m_nodesManager->renderNodesManager());
+ m_renderableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
+ m_computableEntityFilterJob->setManager(m_nodesManager->renderNodesManager());
}
void Renderer::setServices(QServiceLocator *services)
@@ -1862,6 +1955,21 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
if (layersDirty)
renderBinJobs.push_back(m_updateEntityLayersJob);
+ if (renderableDirty) {
+ renderBinJobs.push_back(m_renderableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheRenderableEntitiesJob);
+ }
+
+ if (computeableDirty) {
+ renderBinJobs.push_back(m_computableEntityFilterJob);
+ renderBinJobs.push_back(m_cacheComputableEntitiesJob);
+ }
+
+ if (lightsDirty) {
+ renderBinJobs.push_back(m_lightGathererJob);
+ renderBinJobs.push_back(m_cacheLightsJob);
+ }
+
QMutexLocker lock(m_renderQueue->mutex());
if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
// Traverse the current framegraph. For each leaf node create a
@@ -1892,11 +2000,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
// If we have a new RV (wasn't in the cache before, then it contains no cached data)
const bool isNewRV = !m_cache.leafNodeCache.contains(leaf);
builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt || isNewRV);
- builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty || isNewRV);
- builder.setComputableCacheNeedsToBeRebuilt(computeableDirty || isNewRV);
- builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty || isNewRV);
builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt || isNewRV);
- builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty || isNewRV);
builder.setRenderCommandCacheNeedsToBeRebuilt(renderCommandsDirty || isNewRV);
builder.prepareJobs();
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index f007ab05c..b2889bb0e 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -82,6 +82,7 @@
#include <Qt3DRender/private/texture_p.h>
#include <Qt3DRender/private/glfence_p.h>
#include <Qt3DRender/private/shaderbuilder_p.h>
+#include <Qt3DRender/private/lightgatherer_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -158,6 +159,13 @@ typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>;
+template<typename T, typename ... Ts>
+class FilterEntityByComponentJob;
+template<typename T, typename ... Ts>
+using FilterEntityByComponentJobPtr = QSharedPointer<FilterEntityByComponentJob<T, Ts...>>;
+using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
+using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
+
class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
public:
@@ -227,6 +235,12 @@ public:
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
inline Qt3DCore::QAspectJobPtr sendTextureChangesToFrontendJob() const { return m_sendTextureChangesToFrontendJob; }
inline UpdateEntityLayersJobPtr updateEntityLayersJob() const { return m_updateEntityLayersJob; }
+ inline LightGathererPtr lightGathererJob() const { return m_lightGathererJob; }
+ inline RenderableEntityFilterPtr renderableEntityFilterJob() const { return m_renderableEntityFilterJob; }
+ inline ComputableEntityFilterPtr computableEntityFilterJob() const { return m_computableEntityFilterJob; }
+ inline SynchronizerJobPtr cacheLightJob() const { return m_cacheLightsJob; }
+ inline SynchronizerJobPtr cacheRenderableEntitiesJob() const { return m_cacheRenderableEntitiesJob; }
+ inline SynchronizerJobPtr cacheComputableEntitiesJob() const { return m_cacheComputableEntitiesJob; }
Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override;
@@ -369,6 +383,9 @@ private:
UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob;
FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob;
UpdateEntityLayersJobPtr m_updateEntityLayersJob;
+ LightGathererPtr m_lightGathererJob;
+ RenderableEntityFilterPtr m_renderableEntityFilterJob;
+ ComputableEntityFilterPtr m_computableEntityFilterJob;
QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests;
@@ -386,6 +403,9 @@ private:
SynchronizerPostFramePtr m_sendDisablesToFrontendJob;
SynchronizerPostFramePtr m_introspectShaderJob;
SynchronizerJobPtr m_syncLoadingJobs;
+ SynchronizerJobPtr m_cacheRenderableEntitiesJob;
+ SynchronizerJobPtr m_cacheComputableEntitiesJob;
+ SynchronizerJobPtr m_cacheLightsJob;
void lookForAbandonedVaos();
void lookForDirtyBuffers();
diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h
index a1298f491..02fe4ff41 100644
--- a/src/render/renderers/opengl/renderer/renderercache_p.h
+++ b/src/render/renderers/opengl/renderer/renderercache_p.h
@@ -70,13 +70,16 @@ struct RendererCache
{
QVector<Entity *> filterEntitiesByLayer;
MaterialParameterGathererData materialParameterGatherer;
- QVector<LightSource> gatheredLights;
- QVector<Entity *> renderableEntities;
- QVector<Entity *> computeEntities;
- EnvironmentLight* environmentLight;
- QVector<EntityRenderCommandData> renderCommandData;
+ EntityRenderCommandData renderCommandData;
};
+ // Shared amongst all RV cache
+ QVector<Entity *> renderableEntities;
+ QVector<Entity *> computeEntities;
+ QVector<LightSource> gatheredLights;
+ EnvironmentLight* environmentLight;
+
+ // Per RV cache
QHash<FrameGraphNode *, LeafNodeData> leafNodeCache;
QMutex *mutex() { return &m_mutex; }
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 7fb1c5fb9..97d494370 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -621,11 +621,11 @@ void RenderView::addClearBuffers(const ClearBuffers *cb) {
}
// If we are there, we know that entity had a GeometryRenderer + Material
-QVector<EntityRenderCommandData> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const
{
- QVector<EntityRenderCommandData> commands;
- commands.reserve(entities.size());
+ EntityRenderCommandData commands;
+ commands.reserve(entities.size());
for (Entity *entity : entities) {
GeometryRenderer *geometryRenderer = nullptr;
@@ -662,8 +662,9 @@ QVector<EntityRenderCommandData> RenderView::buildDrawRenderCommands(const QVect
}
command.m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(pass->shaderProgram());
- const EntityRenderCommandData commandData = { entity, command, passData };
- commands.append(commandData);
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
}
}
}
@@ -671,15 +672,17 @@ QVector<EntityRenderCommandData> RenderView::buildDrawRenderCommands(const QVect
return commands;
}
-QVector<EntityRenderCommandData> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
+EntityRenderCommandData RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const
{
// If the RenderView contains only a ComputeDispatch then it cares about
// A ComputeDispatch is also implicitely a NoDraw operation
// enabled flag
// layer component
// material/effect/technique/parameters/filters/
- QVector<EntityRenderCommandData> commands;
+ EntityRenderCommandData commands;
+
commands.reserve(entities.size());
+
for (Entity *entity : entities) {
ComputeCommand *computeJob = nullptr;
HComputeCommand computeCommandHandle = entity->componentHandle<ComputeCommand>();
@@ -712,8 +715,9 @@ QVector<EntityRenderCommandData> RenderView::buildComputeRenderCommands(const QV
command.m_workGroups[1] = std::max(m_workGroups[1], computeJob->y());
command.m_workGroups[2] = std::max(m_workGroups[2], computeJob->z());
- const EntityRenderCommandData commandData = { entity, command, passData };
- commands.append(commandData);
+ commands.push_back(entity,
+ std::move(command),
+ std::move(passData));
}
}
}
@@ -721,7 +725,7 @@ QVector<EntityRenderCommandData> RenderView::buildComputeRenderCommands(const QV
return commands;
}
-void RenderView::updateRenderCommand(QVector<EntityRenderCommandData *> &renderCommandData)
+void RenderView::updateRenderCommand(EntityRenderCommandData &renderCommandData)
{
// Note: since many threads can be building render commands
// we need to ensure that the UniformBlockValueBuilder they are using
@@ -731,10 +735,10 @@ void RenderView::updateRenderCommand(QVector<EntityRenderCommandData *> &renderC
builder->textureManager = m_manager->textureManager();
m_localData.setLocalData(builder);
- for (EntityRenderCommandData *commandData : renderCommandData) {
- Entity *entity = commandData->entity;
- RenderPassParameterData passData = commandData->passData;
- RenderCommand &command = commandData->command;
+ for (int i = 0, m = renderCommandData.size(); i < m; ++i) {
+ Entity *entity = renderCommandData.entities.at(i);
+ const RenderPassParameterData passData = renderCommandData.passesData.at(i);
+ RenderCommand &command = renderCommandData.commands[i];
// Pick which lights to take in to account.
// For now decide based on the distance by taking the MAX_LIGHTS closest lights.
@@ -1010,7 +1014,8 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
if (lightIdx == MAX_LIGHTS)
break;
Entity *lightEntity = lightSource.entity;
- const Vector3D worldPos = lightEntity->worldBoundingVolume()->center();
+ const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform());
+ const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f);
for (Light *light : lightSource.lights) {
if (!light->isEnabled())
continue;
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index 7d148118d..1221e7a59 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -227,11 +227,11 @@ public:
RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true);
- QVector<EntityRenderCommandData> buildDrawRenderCommands(const QVector<Entity *> &entities) const;
- QVector<EntityRenderCommandData> buildComputeRenderCommands(const QVector<Entity *> &entities) const;
+ EntityRenderCommandData buildDrawRenderCommands(const QVector<Entity *> &entities) const;
+ EntityRenderCommandData buildComputeRenderCommands(const QVector<Entity *> &entities) const;
- void updateRenderCommand(QVector<EntityRenderCommandData *> &renderCommandData);
+ void updateRenderCommand(EntityRenderCommandData &renderCommandData);
void setCommands(const QVector<RenderCommand> &commands) Q_DECL_NOTHROW { m_commands = commands; }
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
index 3c6521263..40179fbd6 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -73,9 +73,10 @@ public:
// Split commands to build among jobs
QMutexLocker lock(m_renderer->cache()->mutex());
// Rebuild RenderCommands for all entities in RV (ignoring filtering)
- const RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+ RendererCache *cache = m_renderer->cache();
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
RenderView *rv = m_renderViewInitializer->renderView();
- const auto entities = !rv->isCompute() ? dataCacheForLeaf.renderableEntities : dataCacheForLeaf.computeEntities;
+ const auto entities = !rv->isCompute() ? cache->renderableEntities : cache->computeEntities;
rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
@@ -256,21 +257,18 @@ public:
if (!rv->noDraw()) {
///////// CACHE LOCKED ////////////
// Retrieve Data from Cache
- QMutexLocker lock(m_renderer->cache()->mutex());
- Q_ASSERT(m_renderer->cache()->leafNodeCache.contains(m_leafNode));
+ RendererCache *cache = m_renderer->cache();
+ QMutexLocker lock(cache->mutex());
+ Q_ASSERT(cache->leafNodeCache.contains(m_leafNode));
const bool isDraw = !rv->isCompute();
- const RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+ const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode];
// Rebuild RenderCommands if required
// This should happen fairly infrequently (FrameGraph Change, Geometry/Material change)
// and allow to skip that step most of the time
if (m_fullRebuild) {
- // Clear previous cache
- RendererCache::LeafNodeData &writableCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- writableCacheForLeaf.renderCommandData.clear();
-
- QVector<EntityRenderCommandData> commandData;
+ EntityRenderCommandData commandData;
// Reduction
{
int totalCommandCount = 0;
@@ -280,17 +278,19 @@ public:
for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
commandData += std::move(renderViewCommandBuilder->commandData());
}
- // Store in cache
+
+ // Store new cache
+ RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode];
writableCacheForLeaf.renderCommandData = std::move(commandData);
}
- const QVector<EntityRenderCommandData> commandData = dataCacheForLeaf.renderCommandData;
+ const EntityRenderCommandData commandData = dataCacheForLeaf.renderCommandData;
- QVector<Entity *> renderableEntities = isDraw ? dataCacheForLeaf.renderableEntities : dataCacheForLeaf.computeEntities;
const QVector<Entity *> filteredEntities = dataCacheForLeaf.filterEntitiesByLayer;
- QVector<LightSource> lightSources = dataCacheForLeaf.gatheredLights;
+ QVector<Entity *> renderableEntities = isDraw ? cache->renderableEntities : cache->computeEntities;
+ QVector<LightSource> lightSources = cache->gatheredLights;
rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer);
- rv->setEnvironmentLight(dataCacheForLeaf.environmentLight);
+ rv->setEnvironmentLight(cache->environmentLight);
lock.unlock();
///////// END OF CACHE LOCKED ////////////
@@ -315,26 +315,28 @@ public:
// Filter out Render commands for which the Entity wasn't selected because
// of frustum, proximity or layer filtering
- QVector<EntityRenderCommandData *> filteredCommandData;
+ EntityRenderCommandData filteredCommandData;
filteredCommandData.reserve(renderableEntities.size());
// Because dataCacheForLeaf.renderableEntities or computeEntities are sorted
// What we get out of EntityRenderCommandData is also sorted by Entity
auto eIt = std::cbegin(renderableEntities);
- auto cIt = std::cbegin(commandData);
const auto eEnd = std::cend(renderableEntities);
- const auto cEnd = std::cend(commandData);
+ int cIt = 0;
+ const int cEnd = commandData.size();
while (eIt != eEnd) {
const Entity *targetEntity = *eIt;
// Advance until we have commands whose Entity has a lower address
// than the selected filtered entity
- while (cIt->entity < targetEntity && cIt != cEnd)
+ while (cIt != cEnd && commandData.entities.at(cIt) < targetEntity)
++cIt;
// Push pointers to command data for all commands that match the
// entity
- while (cIt->entity == targetEntity && cIt != cEnd) {
- filteredCommandData.push_back(const_cast<EntityRenderCommandData *>(&(*cIt)));
+ while (cIt != cEnd && commandData.entities.at(cIt) == targetEntity) {
+ filteredCommandData.push_back(commandData.entities.at(cIt),
+ commandData.commands.at(cIt),
+ commandData.passesData.at(cIt));
++cIt;
}
++eIt;
@@ -441,88 +443,6 @@ private:
FrameGraphNode *m_leafNode;
};
-class SyncLightsGatherer
-{
-public:
- explicit SyncLightsGatherer(LightGathererPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.gatheredLights = m_gatherJob->lights();
- dataCacheForLeaf.environmentLight = m_gatherJob->takeEnvironmentLight();
- }
-
-private:
- LightGathererPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncRenderableEntities
-{
-public:
- explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
- std::sort(selectedEntities.begin(), selectedEntities.end());
-
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.renderableEntities = selectedEntities;
- }
-
-private:
- RenderableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncComputableEntities
-{
-public:
- explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_gatherJob(gatherJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities();
- std::sort(selectedEntities.begin(), selectedEntities.end());
-
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.computeEntities = selectedEntities;
- }
-
-private:
- ComputableEntityFilterPtr m_gatherJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
} // anonymous
RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer)
@@ -531,9 +451,6 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende
, m_renderer(renderer)
, m_layerCacheNeedsToBeRebuilt(false)
, m_materialGathererCacheNeedsToBeRebuilt(false)
- , m_lightsCacheNeedsToBeRebuilt(false)
- , m_renderableCacheNeedsToBeRebuilt(false)
- , m_computableCacheNeedsToBeRebuilt(false)
, m_renderCommandCacheNeedsToBeRebuilt(false)
, m_renderViewJob(RenderViewInitializerJobPtr::create())
, m_filterEntityByLayerJob()
@@ -555,21 +472,6 @@ FilterLayerEntityJobPtr RenderViewBuilder::filterEntityByLayerJob() const
return m_filterEntityByLayerJob;
}
-LightGathererPtr RenderViewBuilder::lightGathererJob() const
-{
- return m_lightGathererJob;
-}
-
-RenderableEntityFilterPtr RenderViewBuilder::renderableEntityFilterJob() const
-{
- return m_renderableEntityFilterJob;
-}
-
-ComputableEntityFilterPtr RenderViewBuilder::computableEntityFilterJob() const
-{
- return m_computableEntityFilterJob;
-}
-
FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const
{
return m_frustumCullingJob;
@@ -638,39 +540,9 @@ FilterProximityDistanceJobPtr RenderViewBuilder::filterProximityJob() const
void RenderViewBuilder::prepareJobs()
{
// Init what we can here
- EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager();
m_filterProximityJob->setManager(m_renderer->nodeManagers());
m_frustumCullingJob->setRoot(m_renderer->sceneRoot());
- if (m_lightsCacheNeedsToBeRebuilt) {
- m_lightGathererJob = Render::LightGathererPtr::create();
- m_lightGathererJob->setManager(entityManager);
-
- m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheLightsJob->addDependency(m_lightGathererJob);
- }
-
- if (m_renderableCacheNeedsToBeRebuilt) {
- m_renderableEntityFilterJob = RenderableEntityFilterPtr::create();
- m_renderableEntityFilterJob->setManager(entityManager);
-
- m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create(
- SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob);
- }
-
- if (m_computableCacheNeedsToBeRebuilt) {
- m_computableEntityFilterJob = ComputableEntityFilterPtr::create();
- m_computableEntityFilterJob->setManager(entityManager);
-
- m_cacheComputableEntitiesJob = SynchronizerJobPtr::create(
- SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode),
- JobTypes::EntityComponentTypeFiltering);
- m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob);
- }
-
if (m_renderCommandCacheNeedsToBeRebuilt) {
m_renderViewCommandBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
@@ -789,6 +661,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->introspectShadersJob());
m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->bufferGathererJob());
m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->textureGathererJob());
+ m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->cacheLightJob());
for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs)) {
renderViewCommandUpdater->addDependency(m_syncRenderViewPreCommandUpdateJob);
@@ -801,28 +674,11 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
// Add jobs
jobs.push_back(m_renderViewJob); // Step 1
- if (m_lightsCacheNeedsToBeRebuilt) {
- jobs.push_back(m_lightGathererJob); // Step 1
- jobs.push_back(m_cacheLightsJob);
- m_syncRenderViewPreCommandUpdateJob->addDependency(m_cacheLightsJob);
- }
-
- if (m_renderableCacheNeedsToBeRebuilt) {
- jobs.push_back(m_renderableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheRenderableEntitiesJob);
- }
-
- if (m_computableCacheNeedsToBeRebuilt) {
- // Note: do it only if OpenGL 4.3+ available
- jobs.push_back(m_computableEntityFilterJob); // Step 1
- jobs.push_back(m_cacheComputableEntitiesJob);
- }
-
jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2
if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3
- m_syncRenderViewPreCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob);
- m_syncRenderViewPreCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob);
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheComputableEntitiesJob());
+ m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheRenderableEntitiesJob());
m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob);
if (m_materialGathererCacheNeedsToBeRebuilt)
@@ -907,36 +763,6 @@ bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const
return m_materialGathererCacheNeedsToBeRebuilt;
}
-void RenderViewBuilder::setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_renderableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::renderableCacheNeedsToBeRebuilt() const
-{
- return m_renderableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_computableCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::computableCacheNeedsToBeRebuilt() const
-{
- return m_computableCacheNeedsToBeRebuilt;
-}
-
-void RenderViewBuilder::setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
-{
- m_lightsCacheNeedsToBeRebuilt = needsToBeRebuilt;
-}
-
-bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const
-{
- return m_lightsCacheNeedsToBeRebuilt;
-}
-
void RenderViewBuilder::setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
{
m_renderCommandCacheNeedsToBeRebuilt = needsToBeRebuilt;
diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
index 66344da11..a2ab80e7e 100644
--- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
+++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h
@@ -53,7 +53,6 @@
#include <functional>
#include <Qt3DCore/qaspectjob.h>
-#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
#include <Qt3DRender/private/filterlayerentityjob_p.h>
#include <Qt3DRender/private/genericlambdajob_p.h>
#include <Qt3DRender/private/materialparametergathererjob_p.h>
@@ -62,7 +61,6 @@
#include <Qt3DRender/private/renderviewcommandupdaterjob_p.h>
#include <Qt3DRender/private/renderview_p.h>
#include <Qt3DRender/private/frustumcullingjob_p.h>
-#include <Qt3DRender/private/lightgatherer_p.h>
#include <Qt3DRender/private/filterproximitydistancejob_p.h>
QT_BEGIN_NAMESPACE
@@ -74,8 +72,6 @@ namespace Render {
class Renderer;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>;
-using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>;
class Q_AUTOTEST_EXPORT RenderViewBuilder
{
@@ -84,9 +80,6 @@ public:
RenderViewInitializerJobPtr renderViewJob() const;
FilterLayerEntityJobPtr filterEntityByLayerJob() const;
- LightGathererPtr lightGathererJob() const;
- RenderableEntityFilterPtr renderableEntityFilterJob() const;
- ComputableEntityFilterPtr computableEntityFilterJob() const;
FrustumCullingJobPtr frustumCullingJob() const;
QVector<RenderViewCommandBuilderJobPtr> renderViewCommandBuilderJobs() const;
QVector<RenderViewCommandUpdaterJobPtr> renderViewCommandUpdaterJobs() const;
@@ -111,16 +104,6 @@ public:
bool layerCacheNeedsToBeRebuilt() const;
void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
bool materialGathererCacheNeedsToBeRebuilt() const;
-
- void setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool renderableCacheNeedsToBeRebuilt() const;
-
- void setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool computableCacheNeedsToBeRebuilt() const;
-
- void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
- bool lightGathererCacheNeedsToBeRebuilt() const;
-
void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
bool renderCommandCacheNeedsToBeRebuilt() const;
@@ -133,16 +116,10 @@ private:
Renderer *m_renderer;
bool m_layerCacheNeedsToBeRebuilt;
bool m_materialGathererCacheNeedsToBeRebuilt;
- bool m_lightsCacheNeedsToBeRebuilt;
- bool m_renderableCacheNeedsToBeRebuilt;
- bool m_computableCacheNeedsToBeRebuilt;
bool m_renderCommandCacheNeedsToBeRebuilt;
RenderViewInitializerJobPtr m_renderViewJob;
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
- LightGathererPtr m_lightGathererJob;
- RenderableEntityFilterPtr m_renderableEntityFilterJob;
- ComputableEntityFilterPtr m_computableEntityFilterJob;
FrustumCullingJobPtr m_frustumCullingJob;
QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
@@ -158,10 +135,6 @@ private:
SynchronizerJobPtr m_syncMaterialGathererJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
- SynchronizerJobPtr m_cacheRenderableEntitiesJob;
- SynchronizerJobPtr m_cacheComputableEntitiesJob;
- SynchronizerJobPtr m_cacheLightsJob;
-
static const int m_optimalParallelJobCount;
};
diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp
index 1b5a972ec..20e6007a0 100644
--- a/src/render/renderers/opengl/textures/gltexture.cpp
+++ b/src/render/renderers/opengl/textures/gltexture.cpp
@@ -232,11 +232,9 @@ void GLTexture::loadTextureDataFromImages()
GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
{
TextureUpdateInfo textureInfo;
- m_properties.status = QAbstractTexture::Error;
m_wasTextureRecreated = false;
const bool hasSharedTextureId = m_sharedTextureId > 0;
-
// Only load texture data if we are not using a sharedTextureId
// Check if dataFunctor or images have changed
if (!hasSharedTextureId) {
@@ -269,17 +267,17 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
// Reset image flag
setDirtyFlag(TextureImageData, false);
}
- }
- // Don't try to create the texture if the target or format was still not set
- // Format should either be set by user or if Automatic
- // by either the dataGenerator of the texture or the first Image
- // Target should explicitly be set by the user or the dataGenerator
- if (m_properties.target == QAbstractTexture::TargetAutomatic ||
- m_properties.format == QAbstractTexture::Automatic ||
- m_properties.format == QAbstractTexture::NoFormat) {
- textureInfo.properties.status = QAbstractTexture::Error;
- return textureInfo;
+ // Don't try to create the texture if the target or format was still not set
+ // Format should either be set by user or if Automatic
+ // by either the dataGenerator of the texture or the first Image
+ // Target should explicitly be set by the user or the dataGenerator
+ if (m_properties.target == QAbstractTexture::TargetAutomatic ||
+ m_properties.format == QAbstractTexture::Automatic ||
+ m_properties.format == QAbstractTexture::NoFormat) {
+ textureInfo.properties.status = QAbstractTexture::Error;
+ return textureInfo;
+ }
}
// If the properties changed or texture has become a shared texture from a
diff --git a/src/render/services/vsyncframeadvanceservice.cpp b/src/render/services/vsyncframeadvanceservice.cpp
index b49870e68..d7398e2ce 100644
--- a/src/render/services/vsyncframeadvanceservice.cpp
+++ b/src/render/services/vsyncframeadvanceservice.cpp
@@ -62,7 +62,7 @@ public:
QSemaphore m_semaphore;
QElapsedTimer m_elapsed;
- quint64 m_elapsedTimeSincePreviousFrame;
+ qint64 m_elapsedTimeSincePreviousFrame;
bool m_drivenByRenderThread;
};
@@ -75,14 +75,19 @@ VSyncFrameAdvanceService::~VSyncFrameAdvanceService()
{
}
-// Aspect Thread
+// Main Thread
qint64 VSyncFrameAdvanceService::waitForNextFrame()
{
Q_D(VSyncFrameAdvanceService);
+#ifdef Q_OS_MACOS
+ if (!d->m_semaphore.tryAcquire(std::max(d->m_semaphore.available(), 1), 4))
+ return -1;
+#else
d->m_semaphore.acquire(std::max(d->m_semaphore.available(), 1));
+#endif
- const quint64 currentTime = d->m_elapsed.nsecsElapsed();
+ const qint64 currentTime = d->m_elapsed.nsecsElapsed();
qCDebug(VSyncAdvanceService) << "Elapsed nsecs since last call " << currentTime - d->m_elapsedTimeSincePreviousFrame;
d->m_elapsedTimeSincePreviousFrame = currentTime;
return currentTime;
diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp
index bca66e630..84a228428 100644
--- a/src/render/texture/qtexture.cpp
+++ b/src/render/texture/qtexture.cpp
@@ -1125,7 +1125,7 @@ TextureDownloadRequest::TextureDownloadRequest(const QTextureFromSourceGenerator
}
-// Executed in aspect thread
+// Executed in main thread
void TextureDownloadRequest::onCompleted()
{
if (cancelled() || !succeeded())
@@ -1142,16 +1142,11 @@ void TextureDownloadRequest::onCompleted()
QTextureFromSourceGeneratorPtr oldGenerator = qSharedPointerCast<QTextureFromSourceGenerator>(texture->dataGenerator());
- // We create a new functor
- // Which is a copy of the old one + the downloaded sourceData
- auto newGenerator = QTextureFromSourceGeneratorPtr::create(*oldGenerator);
-
// Set raw data on functor so that it can really load something
- newGenerator->m_sourceData = m_data;
+ oldGenerator->m_sourceData = m_data;
- // Set new generator on texture
- // it implictely marks the texture as dirty so that the functor runs again with the downloaded data
- texture->setDataGenerator(newGenerator);
+ // Mark the texture as dirty so that the functor runs again with the downloaded data
+ texture->addDirtyFlag(Render::Texture::DirtyDataGenerator);
}
/*!
@@ -1520,7 +1515,10 @@ QTextureLoader::QTextureLoader(QNode *parent)
// Regenerate the texture functor when properties we support overriding
// from QAbstractTexture get changed.
Q_D(QTextureLoader);
- auto regenerate = [=] () { d->updateGenerator(); };
+ auto regenerate = [=] () {
+ if (!notificationsBlocked()) // check the change doesn't come from the backend
+ d->updateGenerator();
+ };
connect(this, &QAbstractTexture::formatChanged, regenerate);
}
diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp
index 5ebde56b0..1414cd337 100644
--- a/src/render/texture/texture.cpp
+++ b/src/render/texture/texture.cpp
@@ -149,6 +149,8 @@ void Texture::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
auto newGenerator = node->dataGenerator();
if (newGenerator != m_dataFunctor) {
setDataGenerator(newGenerator);
+ QAbstractTexturePrivate *dTexture = static_cast<QAbstractTexturePrivate *>(QNodePrivate::get(const_cast<QNode *>(frontEnd)));
+ dTexture->setStatus(QAbstractTexture::Loading);
}
QAbstractTexturePrivate *dnode = dynamic_cast<QAbstractTexturePrivate *>(QAbstractTexturePrivate::get(const_cast<QAbstractTexture *>(node)));
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 25565d470..b5291cab7 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -41,6 +41,7 @@
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
#include <Qt3DCore/private/qscenechange_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
#include <private/qabstractaspect_p.h>
#include <private/qpostman_p.h>
@@ -93,6 +94,7 @@ private slots:
void checkConstructionWithNonRootParent(); // QTBUG-73986
void checkConstructionAsListElement();
void checkSceneIsSetOnConstructionWithParent(); // QTBUG-69352
+ void checkSubNodePostConstructIsCalledWhenReferincingNodeProperty(); // QTBUG-79350
void appendingComponentToEntity();
void appendingParentlessComponentToEntityWithoutScene();
@@ -291,22 +293,15 @@ public slots:
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded);
}
}
void removeAttribute(MyQNode *attribute)
{
Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
+
m_attributes.removeOne(attribute);
// Remove bookkeeping connection
d->unregisterDestructionHelper(attribute);
@@ -385,11 +380,7 @@ public:
if (!attribute->parent())
attribute->setParent(this);
- if (d->m_changeArbiter != nullptr) {
- const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute);
- change->setPropertyName("attribute");
- d->notifyObservers(change);
- }
+ d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved);
}
}
@@ -436,6 +427,29 @@ public:
}
};
+class MyFakeMaterial : public Qt3DCore::QComponent
+{
+ Q_OBJECT
+public:
+ explicit MyFakeMaterial(Qt3DCore::QNode *parent = nullptr)
+ : QComponent(parent)
+ , m_effect(new MyQNode(this))
+ , m_technique(new MyQNode(m_effect))
+ , m_renderPass(new MyQNode(m_technique))
+ {
+ }
+
+ void setArbiter(Qt3DCore::QAbstractArbiter *arbiter)
+ {
+ Q_ASSERT(arbiter);
+ Qt3DCore::QComponentPrivate::get(this)->setArbiter(arbiter);
+ }
+
+ MyQNode *m_effect;
+ MyQNode *m_technique;
+ MyQNode *m_renderPass;
+};
+
class TestAspectPrivate;
class TestAspect : public Qt3DCore::QAbstractAspect
{
@@ -1545,20 +1559,8 @@ void tst_Nodes::checkConstructionAsListElement()
QCoreApplication::processEvents();
QCOMPARE(root->children().count(), 1);
- QCOMPARE(spy.events.size(), 2); // 1 child added change, 1 property change
-
- const auto newChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!newChildEvent.isNull());
- QCOMPARE(newChildEvent->subjectId(), root->id());
- QCOMPARE(newChildEvent->propertyName(), "children");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
-
- // Ensure second and last event is property set change
- const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
- QVERIFY(!propertyEvent.isNull());
- QCOMPARE(propertyEvent->subjectId(), root->id());
- QCOMPARE(propertyEvent->propertyName(), "attribute");
- QCOMPARE(newChildEvent->addedNodeId(), node->id());
+ QCOMPARE(spy.dirtyNodes.size(), 1); // 1 property change
+ QCOMPARE(spy.dirtySubNodes.size(), 1); // 1 child added change
}
void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
@@ -1607,6 +1609,52 @@ void tst_Nodes::checkSceneIsSetOnConstructionWithParent()
QCOMPARE(spy.dirtySubNodes.size(), 5); // 5 entities changed
}
+void tst_Nodes::checkSubNodePostConstructIsCalledWhenReferincingNodeProperty()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QAspectEngine engine;
+ Qt3DCore::QScene scene(&engine);
+ QScopedPointer<MyQNode> root(new MyQNode());
+
+ // WHEN
+ root->setArbiterAndScene(&spy, &scene);
+ root->setSimulateBackendCreated(true);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
+
+ // WHEN
+ Qt3DCore::QEntity *subTreeRoot = new Qt3DCore::QEntity(root.data());
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(subTreeRoot)->m_hasBackendNode);
+
+ // WHEN
+ MyFakeMaterial *material = new MyFakeMaterial(subTreeRoot);
+ subTreeRoot->addComponent(material);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(material)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_effect)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_technique)->m_hasBackendNode);
+ QVERIFY(Qt3DCore::QNodePrivate::get(material->m_renderPass)->m_hasBackendNode);
+
+ // WHEN
+ MyQNode *fakeRenderState = new MyQNode(material);
+ Qt3DCore::QNodePrivate *dPtr = Qt3DCore::QNodePrivate::get(fakeRenderState);
+
+ // THEN
+ QVERIFY(!dPtr->m_hasBackendNode);
+
+ // WHEN
+ material->m_renderPass->addAttribute(fakeRenderState);
+
+ // THEN
+ QVERIFY(dPtr->m_hasBackendNode);
+}
+
void tst_Nodes::appendingParentlessComponentToEntityWithoutScene()
{
// GIVEN
diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp
index 1b53efd33..fa1491914 100644
--- a/tests/auto/render/buffer/tst_buffer.cpp
+++ b/tests/auto/render/buffer/tst_buffer.cpp
@@ -157,6 +157,61 @@ private Q_SLOTS:
QVERIFY(backendBuffer.pendingBufferUpdates().empty());
}
+
+ void checkForceFullUploadOnFirstTime()
+ {
+ // GIVEN
+ Qt3DRender::Render::Buffer backendBuffer;
+ Qt3DRender::Render::BufferManager bufferManager;
+ TestRenderer renderer;
+ Qt3DRender::QBuffer frontendBuffer;
+
+ QByteArray data("111456789\0");
+
+ frontendBuffer.setData(data);
+ frontendBuffer.updateData(1, QByteArray("23\0"));
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("123456789\0"));
+
+ // WHEN
+ backendBuffer.setManager(&bufferManager);
+ backendBuffer.setRenderer(&renderer);
+ simulateInitializationSync(&frontendBuffer, &backendBuffer);
+
+ // THEN
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ Qt3DRender::QBufferUpdate fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ backendBuffer.pendingBufferUpdates().clear();
+
+ // WHEN
+ frontendBuffer.updateData(1, QByteArray("00\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, false);
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("100456789\0"));
+ QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1);
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, 1);
+ QCOMPARE(fullUpdate.data, QByteArray("00\0"));
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+
+ // WHEN
+ frontendBuffer.updateData(1, QByteArray("22\0"));
+ backendBuffer.syncFromFrontEnd(&frontendBuffer, true);
+
+ // THEN
+ QCOMPARE(frontendBuffer.data(), QByteArray("122456789\0"));
+ fullUpdate = backendBuffer.pendingBufferUpdates().first();
+ QCOMPARE(fullUpdate.offset, -1);
+ QVERIFY(fullUpdate.data.isEmpty());
+ QCOMPARE(frontendBuffer.data(), backendBuffer.data());
+ }
+
void checkPropertyChanges()
{
// GIVEN
diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp
index 0940348bd..a343d6e57 100644
--- a/tests/auto/render/renderer/tst_renderer.cpp
+++ b/tests/auto/render/renderer/tst_renderer.cpp
@@ -223,12 +223,6 @@ private Q_SLOTS:
1 + // updateSkinningPaletteJob
1 + // SyncLoadingJobs
1 + // sendDisablesToFrontend
- 1 + // LightGathererJob
- 1 + // CacheLightJob
- 1 + // RenderableEntityFilterJob
- 1 + // CacheRenderableEntitiesJob
- 1 + // ComputableEntityFilterJob
- 1 + // CacheComputableEntitiesJob
singleRenderViewJobCount +
singleRenderViewCommandRebuildJobCount +
renderViewBuilderMaterialCacheJobCount +
diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
index 0fb1f5e24..6024084bd 100644
--- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
+++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
@@ -52,6 +52,7 @@
#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DRender/private/nodemanagers_p.h>
#include <Qt3DRender/private/managers_p.h>
+#include <Qt3DRender/private/filterentitybycomponentjob_p.h>
QT_BEGIN_NAMESPACE
@@ -280,39 +281,6 @@ private Q_SLOTS:
// mark jobs dirty and recheck
QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
}
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.lightGathererCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.renderableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
-
- {
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
-
- // THEN
- QCOMPARE(renderViewBuilder.computableCacheNeedsToBeRebuilt(), true);
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- }
}
void checkCheckJobDependencies()
@@ -365,13 +333,14 @@ private Q_SLOTS:
QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
- QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6);
+ QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7);
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob()));
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob()));
// Step 5
for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) {
@@ -487,21 +456,18 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.lightGathererJob()->run();
+ renderer->lightGathererJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.lightGathererJob()->lights().size(), 2);
- QVERIFY(renderViewBuilder.lightGathererJob()->takeEnvironmentLight() != nullptr);
+ QCOMPARE(renderer->lightGathererJob()->lights().size(), 2);
+ QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr);
}
void checkRenderableEntitiesFilteringExecution()
@@ -510,20 +476,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.renderableEntityFilterJob()->run();
+ renderer->renderableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkComputableEntitiesFilteringExecution()
@@ -532,20 +495,17 @@ private Q_SLOTS:
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport();
Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport);
Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
// WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true);
- renderViewBuilder.prepareJobs();
- renderViewBuilder.buildJobHierachy();
- renderViewBuilder.computableEntityFilterJob()->run();
+ renderer->computableEntityFilterJob()->run();
// THEN
- QCOMPARE(renderViewBuilder.computableEntityFilterJob()->filteredEntities().size(), 1);
+ QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1);
}
void checkSyncRenderViewInitializationExecution()
@@ -662,24 +622,28 @@ private Q_SLOTS:
Qt3DRender::QLayer *layer = new Qt3DRender::QLayer();
layerFilter->addLayer(layer);
Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer));
+ Qt3DRender::Render::Renderer *renderer = testAspect.renderer();
// THEN
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id());
QVERIFY(leafNode != nullptr);
// WHEN
+ renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr);
+
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
- renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true);
renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
+ renderer->renderableEntityFilterJob()->run();
+ renderer->cacheRenderableEntitiesJob()->run();
+
renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.renderableEntityFilterJob()->run();
renderViewBuilder.syncRenderViewPostInitializationJob()->run();
renderViewBuilder.filterEntityByLayerJob()->run();
- QVector<Qt3DRender::Render::Entity *> renderableEntity = renderViewBuilder.renderableEntityFilterJob()->filteredEntities();
+ QVector<Qt3DRender::Render::Entity *> renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities();
QVector<Qt3DRender::Render::Entity *> filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities();
// THEN
diff --git a/tests/manual/sharedtexture/main.cpp b/tests/manual/sharedtexture/main.cpp
index a85f90ee6..6f2ef42f2 100644
--- a/tests/manual/sharedtexture/main.cpp
+++ b/tests/manual/sharedtexture/main.cpp
@@ -137,8 +137,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();
diff --git a/tests/manual/sharedtexture/videoplayer.cpp b/tests/manual/sharedtexture/videoplayer.cpp
index f970116b5..2e52b85e0 100644
--- a/tests/manual/sharedtexture/videoplayer.cpp
+++ b/tests/manual/sharedtexture/videoplayer.cpp
@@ -57,8 +57,6 @@ TextureWidget::TextureWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_texture(QOpenGLTexture::Target2D)
{
- // Lock mutex so that we never process a frame until we have been initialized
- m_mutex.lock();
}
// Main thread
@@ -104,14 +102,11 @@ void TextureWidget::initializeGL()
qDebug() << Q_FUNC_INFO << context()->shareContext();
m_vao.create();
- // Allow rendering/frame acquisition to go on
- m_mutex.unlock();
}
// Main thread
void TextureWidget::paintGL()
{
- QMutexLocker lock(&m_mutex);
glViewport(0, 0, width(), height());
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -131,12 +126,8 @@ void TextureWidget::paintGL()
m_shader.release();
}
-// Video Player thread
void TextureWidget::setVideoFrame(const QVideoFrame &frame)
{
- // Ensure we won't be rendering while we are processing the frame
- QMutexLocker lock(&m_mutex);
-
QVideoFrame f = frame;
// Map frame
@@ -194,16 +185,14 @@ bool GLVideoSurface::present(const QVideoFrame &frame)
return true;
}
-VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
- : QThread(textureWidget)
+VideoPlayer::VideoPlayer(TextureWidget *textureWidget)
+ : QObject(textureWidget)
, m_player(new QMediaPlayer(nullptr, QMediaPlayer::VideoSurface))
, m_surface(new GLVideoSurface())
{
- m_player->moveToThread(this);
- m_player->setMedia(QUrl("https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4"));
+ m_player->setMedia(QUrl("https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"));
// Tell player to render on GLVideoSurface
- m_surface->moveToThread(this);
m_player->setVideoOutput(m_surface.get());
// Display errors
@@ -218,16 +207,13 @@ VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget)
m_player->play();
});
- // Start playing when thread starts
- QObject::connect(this, &QThread::started, this, [this] { m_player->play(); });
-
- // Direct connection between 2 objects living in different threads
QObject::connect(m_surface.get(), &GLVideoSurface::onNewFrame,
textureWidget, &TextureWidget::setVideoFrame, Qt::DirectConnection);
+
+ // Start playing
+ m_player->play();
}
-VideoPlayerThread::~VideoPlayerThread()
+VideoPlayer::~VideoPlayer()
{
- exit(0);
- wait();
}
diff --git a/tests/manual/sharedtexture/videoplayer.h b/tests/manual/sharedtexture/videoplayer.h
index 377ea57fe..a96cb16b1 100644
--- a/tests/manual/sharedtexture/videoplayer.h
+++ b/tests/manual/sharedtexture/videoplayer.h
@@ -48,9 +48,6 @@
**
****************************************************************************/
-#include <QThread>
-#include <QMutex>
-
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
@@ -90,7 +87,6 @@ private:
QOpenGLVertexArrayObject m_vao;
QOpenGLShaderProgram m_shader;
QOpenGLTexture m_texture;
- QMutex m_mutex;
};
@@ -108,12 +104,12 @@ Q_SIGNALS:
};
-class VideoPlayerThread : public QThread
+class VideoPlayer : public QObject
{
Q_OBJECT
public:
- VideoPlayerThread(TextureWidget *textureWidget);
- ~VideoPlayerThread();
+ VideoPlayer(TextureWidget *textureWidget);
+ ~VideoPlayer();
private:
TextureWidget *m_textureWidget;
diff --git a/tests/manual/sharedtextureqml/main.cpp b/tests/manual/sharedtextureqml/main.cpp
index 5c7ae9cff..c0a79e6f8 100644
--- a/tests/manual/sharedtextureqml/main.cpp
+++ b/tests/manual/sharedtextureqml/main.cpp
@@ -108,8 +108,7 @@ int main(int argc, char* argv[])
// Multimedia player
TextureWidget textureWidget;
- VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget);
- videoPlayer->start();
+ VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget);
textureWidget.resize(800, 600);
textureWidget.show();