diff options
author | Mike Krus <mike.krus@kdab.com> | 2020-03-10 22:07:00 +0000 |
---|---|---|
committer | Mike Krus <mike.krus@kdab.com> | 2020-03-10 22:07:37 +0000 |
commit | 17f4f0f5f0407032c205c0efa0e08275470867da (patch) | |
tree | ebcc94d35919ea5421d2a35ff15aa0fb961cead8 | |
parent | 21cd6cb494c7a7b75081cc87ab14c8a6326eeb78 (diff) | |
parent | 707cfb5884b0a2dacde9b3a7ce47707a5c09744b (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Ida354e9c302ef968fbae78edd60a1ad1fabef477
32 files changed, 1039 insertions, 387 deletions
diff --git a/src/extras/defaults/qforwardrenderer.cpp b/src/extras/defaults/qforwardrenderer.cpp index 1268ab03d..71d99d84b 100644 --- a/src/extras/defaults/qforwardrenderer.cpp +++ b/src/extras/defaults/qforwardrenderer.cpp @@ -367,6 +367,24 @@ float QForwardRenderer::gamma() const return d->m_viewport->gamma(); } +/*! + \qmlproperty bool ForwardRenderer::showDebugOverlay + + If true, a debug overlay will be rendered over the scene. It will show + detailed information about the runtime rendering state, let the user + turn logging on and off, etc. + + \since 5.15 +*/ +/*! + \property QForwardRenderer::showDebugOverlay + + If true, a debug overlay will be rendered over the scene. It will show + detailed information about the runtime rendering state, let the user + turn logging on and off, etc. + + \since 5.15 +*/ bool QForwardRenderer::showDebugOverlay() const { Q_D(const QForwardRenderer); diff --git a/src/input/frontend/qmousedevice.cpp b/src/input/frontend/qmousedevice.cpp index d7cdf1ebc..49427c5a8 100644 --- a/src/input/frontend/qmousedevice.cpp +++ b/src/input/frontend/qmousedevice.cpp @@ -109,23 +109,23 @@ QMouseDevicePrivate::QMouseDevicePrivate() /*! \property Qt3DInput::QMouseDevice::updateAxesContinuously - If true, axes will be updated anytime they change regardless of whether + If \c true, axes will be updated anytime they change regardless of whether any mouse button is being pressed. Otherwise, axes are updated only when one of the mouse buttons is being pressed. + The default value is \c false. \since 5.15 - \default false */ /*! \qmlproperty bool MouseDevice::updateAxesContinuously - If true, axes will be updated anytime they change regardless of whether + If \c true, axes will be updated anytime they change regardless of whether any mouse button is being pressed. Otherwise, axes are updated only when one of the mouse buttons is being pressed. + The default value is \c false. \since 5.15 - \default false */ /*! diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp index e8e8eb84d..3ad9c2818 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.cpp +++ b/src/plugins/renderers/opengl/renderer/renderer.cpp @@ -67,7 +67,6 @@ #include <Qt3DRender/private/techniquefilternode_p.h> #include <Qt3DRender/private/viewportnode_p.h> #include <Qt3DRender/private/vsyncframeadvanceservice_p.h> -#include <Qt3DRender/private/pickeventfilter_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/buffermanager_p.h> #include <Qt3DRender/private/nodemanagers_p.h> @@ -81,13 +80,12 @@ #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/private/qrenderaspect_p.h> #ifndef Q_OS_INTEGRITY #include <imguirenderer_p.h> #endif #include <Qt3DRender/qcameralens.h> -#include <Qt3DCore/private/qeventfilterservice_p.h> #include <Qt3DCore/private/qabstractaspectjobmanager_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> #include <Qt3DCore/private/qsysteminformationservice_p.h> @@ -122,6 +120,8 @@ #include <QOffscreenSurface> #include <QWindow> #include <QThread> +#include <QKeyEvent> +#include <QMouseEvent> #include <QtGui/private/qopenglcontext_p.h> #include "frameprofiler_p.h" @@ -139,41 +139,41 @@ namespace OpenGL { namespace { -class SyncLightsGatherer -{ +class CachingLightGatherer : public LightGatherer { public: - explicit SyncLightsGatherer(LightGathererPtr gatherJob, - RendererCache *cache) - : m_gatherJob(gatherJob) + CachingLightGatherer(RendererCache *cache) + : LightGatherer() , m_cache(cache) { } - void operator()() + void run() override { + LightGatherer::run(); + QMutexLocker lock(m_cache->mutex()); - m_cache->gatheredLights = m_gatherJob->lights(); - m_cache->environmentLight = m_gatherJob->takeEnvironmentLight(); + m_cache->gatheredLights = lights(); + m_cache->environmentLight = environmentLight(); } private: - LightGathererPtr m_gatherJob; RendererCache *m_cache; }; -class SyncRenderableEntities -{ +class CachingRenderableEntityFilter : public RenderableEntityFilter { public: - explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob, - RendererCache *cache) - : m_gatherJob(gatherJob) + CachingRenderableEntityFilter(RendererCache *cache) + : RenderableEntityFilter() , m_cache(cache) { + } - void operator()() + void run() override { - QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities(); + RenderableEntityFilter::run(); + + QVector<Entity *> selectedEntities = filteredEntities(); std::sort(selectedEntities.begin(), selectedEntities.end()); QMutexLocker lock(m_cache->mutex()); @@ -181,23 +181,23 @@ public: } private: - RenderableEntityFilterPtr m_gatherJob; RendererCache *m_cache; }; -class SyncComputableEntities -{ +class CachingComputableEntityFilter : public ComputableEntityFilter { public: - explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob, - RendererCache *cache) - : m_gatherJob(gatherJob) + CachingComputableEntityFilter(RendererCache *cache) + : ComputableEntityFilter() , m_cache(cache) { + } - void operator()() + void run() override { - QVector<Entity *> selectedEntities = m_gatherJob->filteredEntities(); + ComputableEntityFilter::run(); + + QVector<Entity *> selectedEntities = filteredEntities(); std::sort(selectedEntities.begin(), selectedEntities.end()); QMutexLocker lock(m_cache->mutex()); @@ -205,7 +205,6 @@ public: } private: - ComputableEntityFilterPtr m_gatherJob; RendererCache *m_cache; }; @@ -233,6 +232,7 @@ private: Renderer::Renderer(QRenderAspect::RenderType type) : m_services(nullptr) + , m_aspect(nullptr) , m_nodesManager(nullptr) , m_renderSceneRoot(nullptr) , m_defaultRenderStateSet(nullptr) @@ -242,43 +242,25 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr)) , m_waitForInitializationToBeCompleted(0) , m_hasBeenInitializedMutex() - , m_pickEventFilter(new PickEventFilter()) , m_exposed(0) , m_lastFrameCorrect(0) , m_glContext(nullptr) , m_shareContext(nullptr) - , m_pickBoundingVolumeJob(PickBoundingVolumeJobPtr::create()) - , m_rayCastingJob(RayCastingJobPtr::create()) , m_time(0) , m_settings(nullptr) , m_updateShaderDataTransformJob(Render::UpdateShaderDataTransformJobPtr::create()) , m_cleanupJob(Render::FrameCleanupJobPtr::create()) - , m_worldTransformJob(Render::UpdateWorldTransformJobPtr::create()) - , m_expandBoundingVolumeJob(Render::ExpandBoundingVolumeJobPtr::create()) - , m_calculateBoundingVolumeJob(Render::CalculateBoundingVolumeJobPtr::create()) - , m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create()) - , m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create()) , m_sendBufferCaptureJob(Render::SendBufferCaptureJobPtr::create()) - , m_updateSkinningPaletteJob(Render::UpdateSkinningPaletteJobPtr::create()) - , m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create()) , m_filterCompatibleTechniqueJob(FilterCompatibleTechniqueJobPtr::create()) - , m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create()) - , m_lightGathererJob(Render::LightGathererPtr::create()) - , m_renderableEntityFilterJob(Render::RenderableEntityFilterPtr::create()) - , m_computableEntityFilterJob(Render::ComputableEntityFilterPtr::create()) + , m_lightGathererJob(new CachingLightGatherer(&m_cache)) + , m_renderableEntityFilterJob(new CachingRenderableEntityFilter(&m_cache)) + , m_computableEntityFilterJob(new CachingComputableEntityFilter(&m_cache)) , m_bufferGathererJob(CreateSynchronizerJobPtr([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) , m_vaoGathererJob(CreateSynchronizerJobPtr([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) , m_textureGathererJob(CreateSynchronizerJobPtr([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) , m_introspectShaderJob(CreateSynchronizerPostFramePtr([this] { reloadDirtyShaders(); }, [this] (Qt3DCore::QAspectManager *m) { sendShaderChangesToFrontend(m); }, JobTypes::DirtyShaderGathering)) - , m_syncLoadingJobs(CreateSynchronizerJobPtr([] {}, JobTypes::SyncLoadingJobs)) - , m_cacheRenderableEntitiesJob(CreateSynchronizerJobPtr(SyncRenderableEntities(m_renderableEntityFilterJob, &m_cache), - JobTypes::EntityComponentTypeFiltering)) - , m_cacheComputableEntitiesJob(CreateSynchronizerJobPtr(SyncComputableEntities(m_computableEntityFilterJob, &m_cache), - JobTypes::EntityComponentTypeFiltering)) - , m_cacheLightsJob(CreateSynchronizerJobPtr(SyncLightsGatherer(m_lightGathererJob, &m_cache), - JobTypes::EntityComponentTypeFiltering)) , m_ownedContext(false) , m_offscreenHelper(nullptr) , m_glResourceManagers(nullptr) @@ -293,26 +275,8 @@ Renderer::Renderer(QRenderAspect::RenderType type) if (m_renderThread) m_renderThread->waitForStart(); - // Create jobs to update transforms and bounding volumes - // We can only update bounding volumes once all world transforms are known - m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); - m_updateWorldBoundingVolumeJob->addDependency(m_calculateBoundingVolumeJob); - m_expandBoundingVolumeJob->addDependency(m_updateWorldBoundingVolumeJob); - m_updateShaderDataTransformJob->addDependency(m_worldTransformJob); - m_updateLevelOfDetailJob->addDependency(m_expandBoundingVolumeJob); - m_pickBoundingVolumeJob->addDependency(m_expandBoundingVolumeJob); - m_rayCastingJob->addDependency(m_expandBoundingVolumeJob); - // m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs - - // Ensures all skeletons are loaded before we try to update them - m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs); - 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; @@ -371,6 +335,12 @@ void Renderer::setJobsInLastFrame(int jobsInLastFrame) m_jobsInLastFrame = jobsInLastFrame; } +void Renderer::setAspect(QRenderAspect *aspect) +{ + m_aspect = aspect; + m_updateShaderDataTransformJob->addDependency(QRenderAspectPrivate::get(aspect)->m_worldTransformJob); +} + void Renderer::setNodeManagers(NodeManagers *managers) { m_nodesManager = managers; @@ -379,17 +349,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_updateShaderDataTransformJob->setManagers(m_nodesManager); m_cleanupJob->setManagers(m_nodesManager); - m_calculateBoundingVolumeJob->setManagers(m_nodesManager); - m_expandBoundingVolumeJob->setManagers(m_nodesManager); - m_worldTransformJob->setManagers(m_nodesManager); - m_pickBoundingVolumeJob->setManagers(m_nodesManager); - m_rayCastingJob->setManagers(m_nodesManager); - m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager()); - m_updateLevelOfDetailJob->setManagers(m_nodesManager); - m_updateSkinningPaletteJob->setManagers(m_nodesManager); m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); - 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()); @@ -403,6 +363,11 @@ void Renderer::setServices(QServiceLocator *services) m_nodesManager->sceneManager()->setDownloadService(m_services->downloadHelperService()); } +QRenderAspect *Renderer::aspect() const +{ + return m_aspect; +} + NodeManagers *Renderer::nodeManagers() const { return m_nodesManager; @@ -709,26 +674,12 @@ void Renderer::setSceneRoot(Entity *sgRoot) qCDebug(Backend) << Q_FUNC_INFO << "DUMPING SCENE"; // Set the scene root on the jobs - m_worldTransformJob->setRoot(m_renderSceneRoot); - m_expandBoundingVolumeJob->setRoot(m_renderSceneRoot); - m_calculateBoundingVolumeJob->setRoot(m_renderSceneRoot); m_cleanupJob->setRoot(m_renderSceneRoot); - m_pickBoundingVolumeJob->setRoot(m_renderSceneRoot); - m_rayCastingJob->setRoot(m_renderSceneRoot); - m_updateLevelOfDetailJob->setRoot(m_renderSceneRoot); - m_updateSkinningPaletteJob->setRoot(m_renderSceneRoot); - m_updateTreeEnabledJob->setRoot(m_renderSceneRoot); // Set all flags to dirty m_dirtyBits.marked |= AbstractRenderer::AllDirty; } -void Renderer::registerEventFilter(QEventFilterService *service) -{ - qCDebug(Backend) << Q_FUNC_INFO << QThread::currentThread(); - service->registerEventFilter(m_pickEventFilter.data(), 1024); -} - void Renderer::setSettings(RenderSettings *settings) { m_settings = settings; @@ -1870,35 +1821,21 @@ void Renderer::jobsDone(Qt3DCore::QAspectManager *manager) sendSetFenceHandlesToFrontend(manager); } +void Renderer::setPendingEvents(const QList<QPair<QObject *, QMouseEvent> > &mouseEvents, const QList<QKeyEvent> &keyEvents) +{ + QMutexLocker l(&m_frameEventsMutex); + m_frameMouseEvents = mouseEvents; + m_frameKeyEvents = keyEvents; +} + // Jobs we may have to run even if no rendering will happen QVector<QAspectJobPtr> Renderer::preRenderingJobs() { - { - QMutexLocker l(&m_frameEventsMutex); - m_frameMouseEvents = m_pickEventFilter->pendingMouseEvents(); - m_frameKeyEvents = m_pickEventFilter->pendingKeyEvents(); - } - - // Set values on picking jobs - RenderSettings *renderSetting = settings(); - if (renderSetting != nullptr) { - m_pickBoundingVolumeJob->setRenderSettings(renderSetting); - m_pickBoundingVolumeJob->setFrameGraphRoot(frameGraphRoot()); - m_pickBoundingVolumeJob->setMouseEvents(m_frameMouseEvents); - m_pickBoundingVolumeJob->setKeyEvents(m_frameKeyEvents); - - m_rayCastingJob->setRenderSettings(renderSetting); - m_rayCastingJob->setFrameGraphRoot(frameGraphRoot()); - } - QVector<QAspectJobPtr> jobs; if (m_sendBufferCaptureJob->hasRequests()) jobs.push_back(m_sendBufferCaptureJob); - jobs.append(pickBoundingVolumeJob()); - jobs.append(rayCastingJob()); - return jobs; } @@ -1911,46 +1848,18 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() QVector<QAspectJobPtr> renderBinJobs; // Remove previous dependencies - m_calculateBoundingVolumeJob->removeDependency(QWeakPointer<QAspectJob>()); m_cleanupJob->removeDependency(QWeakPointer<QAspectJob>()); - m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot()); - const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining; m_dirtyBits.marked = {}; m_dirtyBits.remaining = {}; BackendNodeDirtySet notCleared = {}; // Add jobs - const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - if (entitiesEnabledDirty) { - renderBinJobs.push_back(m_updateTreeEnabledJob); - // This dependency is added here because we clear all dependencies - // at the start of this function. - m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { - renderBinJobs.push_back(m_worldTransformJob); - renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); + if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) renderBinJobs.push_back(m_updateShaderDataTransformJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || - dirtyBitsForFrame & AbstractRenderer::BuffersDirty) { - renderBinJobs.push_back(m_calculateBoundingVolumeJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || - dirtyBitsForFrame & AbstractRenderer::TransformDirty) { - renderBinJobs.push_back(m_expandBoundingVolumeJob); - } // TO DO: Conditionally add if skeletons dirty - renderBinJobs.push_back(m_syncLoadingJobs); - m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints()); - renderBinJobs.push_back(m_updateSkinningPaletteJob); - renderBinJobs.push_back(m_updateLevelOfDetailJob); renderBinJobs.push_back(m_cleanupJob); // Jobs to prepare GL Resource upload @@ -1962,9 +1871,9 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty) renderBinJobs.push_back(m_textureGathererJob); - // Layer cache is dependent on layers, layer filters (hence FG structure // changes) and the enabled flag on entities + const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty; const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; @@ -1976,24 +1885,14 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() const bool materialCacheNeedsToBeRebuilt = shadersDirty || materialDirty || frameGraphDirty; const bool renderCommandsDirty = materialCacheNeedsToBeRebuilt || renderableDirty || computeableDirty; - // Rebuild Entity Layers list if layers are dirty - if (layersDirty) - renderBinJobs.push_back(m_updateEntityLayersJob); - - if (renderableDirty) { + if (renderableDirty) renderBinJobs.push_back(m_renderableEntityFilterJob); - renderBinJobs.push_back(m_cacheRenderableEntitiesJob); - } - if (computeableDirty) { + if (computeableDirty) renderBinJobs.push_back(m_computableEntityFilterJob); - renderBinJobs.push_back(m_cacheComputableEntitiesJob); - } - if (lightsDirty) { + 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) @@ -2038,8 +1937,8 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // FilterLayerEntityJob is part of the RenderViewBuilder jobs and must be run later // if none of those jobs are started this frame notCleared |= AbstractRenderer::EntityEnabledDirty; - notCleared |= AbstractRenderer::FrameGraphDirty; notCleared |= AbstractRenderer::LayersDirty; + notCleared |= AbstractRenderer::FrameGraphDirty; } if (isRunning() && m_submissionContext->isInitialized()) { @@ -2057,26 +1956,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() return renderBinJobs; } -QAspectJobPtr Renderer::pickBoundingVolumeJob() -{ - return m_pickBoundingVolumeJob; -} - -QAspectJobPtr Renderer::rayCastingJob() -{ - return m_rayCastingJob; -} - -QAspectJobPtr Renderer::syncLoadingJobs() -{ - return m_syncLoadingJobs; -} - -QAspectJobPtr Renderer::expandBoundingVolumeJob() -{ - return m_expandBoundingVolumeJob; -} - QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const { return static_cast<Qt3DCore::QAbstractFrameAdvanceService *>(m_vsyncFrameAdvanceService.data()); diff --git a/src/plugins/renderers/opengl/renderer/renderer_p.h b/src/plugins/renderers/opengl/renderer/renderer_p.h index e1bcce693..8cf610efb 100644 --- a/src/plugins/renderers/opengl/renderer/renderer_p.h +++ b/src/plugins/renderers/opengl/renderer/renderer_p.h @@ -58,24 +58,16 @@ #include <Qt3DRender/private/abstractrenderer_p.h> #include <Qt3DCore/qaspectjob.h> #include <Qt3DRender/private/qt3drender_global_p.h> -#include <Qt3DRender/private/pickboundingvolumejob_p.h> -#include <Qt3DRender/private/raycastingjob_p.h> #include <Qt3DRender/private/rendersettings_p.h> -#include <Qt3DRender/private/expandboundingvolumejob_p.h> -#include <Qt3DRender/private/updateworldtransformjob_p.h> -#include <Qt3DRender/private/calcboundingvolumejob_p.h> #include <Qt3DRender/private/updateshaderdatatransformjob_p.h> #include <Qt3DRender/private/framecleanupjob_p.h> -#include <Qt3DRender/private/updateworldboundingvolumejob_p.h> -#include <Qt3DRender/private/updatetreeenabledjob_p.h> #include <Qt3DRender/private/platformsurfacefilter_p.h> #include <Qt3DRender/private/sendbuffercapturejob_p.h> #include <Qt3DRender/private/genericlambdajob_p.h> -#include <Qt3DRender/private/updateskinningpalettejob_p.h> -#include <Qt3DRender/private/updateentitylayersjob_p.h> #include <Qt3DRender/private/shaderbuilder_p.h> #include <Qt3DRender/private/lightgatherer_p.h> #include <Qt3DRender/private/texture_p.h> +#include <Qt3DRender/private/filterentitybycomponentjob_p.h> #include <shaderparameterpack_p.h> #include <renderviewinitializerjob_p.h> #include <filtercompatibletechniquejob_p.h> @@ -147,19 +139,13 @@ class RenderPass; class RenderThread; class RenderStateSet; class VSyncFrameAdvanceService; -class PickEventFilter; class NodeManagers; class ResourceAccessor; -class UpdateLevelOfDetailJob; -typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; - -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>; +using ComputableEntityFilter = FilterEntityByComponentJob<Render::ComputeCommand, Render::Material>; +using ComputableEntityFilterPtr = QSharedPointer<ComputableEntityFilter>; +using RenderableEntityFilter = FilterEntityByComponentJob<Render::GeometryRenderer, Render::Material>; +using RenderableEntityFilterPtr = QSharedPointer<RenderableEntityFilter>; using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; using SynchronizerPostFramePtr = GenericLambdaJobAndPostFramePtr<std::function<void ()>, std::function<void (Qt3DCore::QAspectManager *)>>; @@ -193,10 +179,12 @@ public: void setTime(qint64 time) override; void setJobsInLastFrame(int jobsInLastFrame) override; + void setAspect(QRenderAspect *aspect) override; void setNodeManagers(NodeManagers *managers) override; void setServices(Qt3DCore::QServiceLocator *services) override; void setSurfaceExposed(bool exposed) override; + QRenderAspect *aspect() const override; NodeManagers *nodeManagers() const override; Qt3DCore::QServiceLocator *services() const override { return m_services; } @@ -226,38 +214,22 @@ public: void skipNextFrame() override; void jobsDone(Qt3DCore::QAspectManager *manager) override; + void setPendingEvents(const QList<QPair<QObject *, QMouseEvent>> &mouseEvents, const QList<QKeyEvent> &keyEvents) override; + QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override; QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override; - Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override; - Qt3DCore::QAspectJobPtr rayCastingJob() override; - Qt3DCore::QAspectJobPtr syncLoadingJobs() override; - Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override; - inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; } inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; } - inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; } - inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; } - inline UpdateWorldTransformJobPtr updateWorldTransformJob() const { return m_worldTransformJob; } - inline UpdateWorldBoundingVolumeJobPtr updateWorldBoundingVolumeJob() const { return m_updateWorldBoundingVolumeJob; } - inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; } inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; } - inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; } - inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; } inline SynchronizerPostFramePtr introspectShadersJob() const { return m_introspectShaderJob; } inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; } inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; } - 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; - void registerEventFilter(Qt3DCore::QEventFilterService *service) override; - void setSettings(RenderSettings *settings) override; RenderSettings *settings() const override; QOpenGLContext *shareContext() const override; @@ -326,7 +298,6 @@ public: RendererCache *cache() { return &m_cache; } void setScreen(QScreen *scr) override; QScreen *screen() const override; - NodeManagers *nodesManager() const { return m_nodesManager; } #ifdef QT3D_RENDER_UNIT_TESTS public: @@ -338,6 +309,7 @@ private: Profiling::FrameProfiler *activeProfiler() const; Qt3DCore::QServiceLocator *m_services; + QRenderAspect *m_aspect; NodeManagers *m_nodesManager; // Frame graph root @@ -363,8 +335,6 @@ private: QAtomicInt m_running; - QScopedPointer<PickEventFilter> m_pickEventFilter; - QVector<Attribute *> m_dirtyAttributes; QVector<Geometry *> m_dirtyGeometry; QAtomicInt m_exposed; @@ -379,8 +349,6 @@ private: QOpenGLContext *m_glContext; QOpenGLContext *m_shareContext; mutable QMutex m_shareContextMutex; - PickBoundingVolumeJobPtr m_pickBoundingVolumeJob; - RayCastingJobPtr m_rayCastingJob; qint64 m_time; @@ -388,16 +356,8 @@ private: UpdateShaderDataTransformJobPtr m_updateShaderDataTransformJob; FrameCleanupJobPtr m_cleanupJob; - UpdateWorldTransformJobPtr m_worldTransformJob; - ExpandBoundingVolumeJobPtr m_expandBoundingVolumeJob; - CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob; - UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob; - UpdateTreeEnabledJobPtr m_updateTreeEnabledJob; SendBufferCaptureJobPtr m_sendBufferCaptureJob; - UpdateSkinningPaletteJobPtr m_updateSkinningPaletteJob; - UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob; FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; - UpdateEntityLayersJobPtr m_updateEntityLayersJob; LightGathererPtr m_lightGathererJob; RenderableEntityFilterPtr m_renderableEntityFilterJob; ComputableEntityFilterPtr m_computableEntityFilterJob; @@ -414,10 +374,6 @@ private: SynchronizerJobPtr m_vaoGathererJob; SynchronizerJobPtr m_textureGathererJob; SynchronizerPostFramePtr m_introspectShaderJob; - SynchronizerJobPtr m_syncLoadingJobs; - SynchronizerJobPtr m_cacheRenderableEntitiesJob; - SynchronizerJobPtr m_cacheComputableEntitiesJob; - SynchronizerJobPtr m_cacheLightsJob; void lookForAbandonedVaos(); void lookForDirtyBuffers(); diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp index a9713d2b9..8ed32ff10 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "renderviewbuilder_p.h" +#include <Qt3DRender/private/qrenderaspect_p.h> #include <QThread> @@ -642,6 +643,12 @@ void RenderViewBuilder::prepareJobs() QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const { QVector<Qt3DCore::QAspectJobPtr> jobs; + auto daspect = QRenderAspectPrivate::get(m_renderer->aspect()); + auto expandBVJob = daspect->m_expandBoundingVolumeJob; + auto wordTransformJob = daspect->m_worldTransformJob; + auto updateTreeEnabledJob = daspect->m_updateTreeEnabledJob; + auto updateSkinningPaletteJob = daspect->m_updateSkinningPaletteJob; + auto updateEntityLayersJob = daspect->m_updateEntityLayersJob; jobs.reserve(m_materialGathererJobs.size() + m_renderViewCommandUpdaterJobs.size() + 11); @@ -649,20 +656,20 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const // Finish the skinning palette job before processing renderviews // TODO: Maybe only update skinning palettes for non-culled entities - m_renderViewJob->addDependency(m_renderer->updateSkinningPaletteJob()); + m_renderViewJob->addDependency(updateSkinningPaletteJob); - m_syncPreFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob()); + m_syncPreFrustumCullingJob->addDependency(wordTransformJob); m_syncPreFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob()); m_syncPreFrustumCullingJob->addDependency(m_syncRenderViewPostInitializationJob); - m_frustumCullingJob->addDependency(m_renderer->expandBoundingVolumeJob()); + m_frustumCullingJob->addDependency(expandBVJob); m_frustumCullingJob->addDependency(m_syncPreFrustumCullingJob); m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewPostInitializationJob); m_syncRenderViewPostInitializationJob->addDependency(m_renderViewJob); - m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob()); + m_filterProximityJob->addDependency(expandBVJob); m_filterProximityJob->addDependency(m_syncRenderViewPostInitializationJob); m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncRenderViewPostInitializationJob); @@ -674,7 +681,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()); + m_syncRenderViewPreCommandUpdateJob->addDependency(m_renderer->lightGathererJob()); for (const auto &renderViewCommandUpdater : qAsConst(m_renderViewCommandUpdaterJobs)) { renderViewCommandUpdater->addDependency(m_syncRenderViewPreCommandUpdateJob); @@ -690,8 +697,8 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2 if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3 - m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheComputableEntitiesJob()); - m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->cacheRenderableEntitiesJob()); + m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->computableEntityFilterJob()); + m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->renderableEntityFilterJob()); m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob); if (m_materialGathererCacheNeedsToBeRebuilt) @@ -707,9 +714,9 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const } if (m_layerCacheNeedsToBeRebuilt) { - m_filterEntityByLayerJob->addDependency(m_renderer->updateEntityLayersJob()); + m_filterEntityByLayerJob->addDependency(updateEntityLayersJob); m_filterEntityByLayerJob->addDependency(m_syncRenderViewPostInitializationJob); - m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob()); + m_filterEntityByLayerJob->addDependency(updateTreeEnabledJob); m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob); m_syncRenderViewPreCommandUpdateJob->addDependency(m_syncFilterEntityByLayerJob); diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index f824d2c4e..295217f98 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -303,8 +303,8 @@ void Scene3DItem::setHoverEnabled(bool enabled) Additionally when using this mode, the window clearBeforeRendering will be set to false automatically. + The default value is \c FBO. \since 5.14 - \default FBO */ void Scene3DItem::setCompositingMode(Scene3DItem::CompositingMode mode) { diff --git a/src/quick3d/quick3d/items/quick3dnodev9.cpp b/src/quick3d/quick3d/items/quick3dnodev9.cpp index 40edadbc4..5162c2f6d 100644 --- a/src/quick3d/quick3d/items/quick3dnodev9.cpp +++ b/src/quick3d/quick3d/items/quick3dnodev9.cpp @@ -52,7 +52,6 @@ Quick3DNodeV9::Quick3DNodeV9(QObject *parent) /*! \qmlproperty QJSValue Qt3DCore::Node::propertyTrackingOverrides - \default {} Assuming a Qt3DCore::Node needs to override the PropertyTrackingMode on two properties (enabled and displacement), the value should be set as shown @@ -65,6 +64,7 @@ Quick3DNodeV9::Quick3DNodeV9(QObject *parent) } \endcode + By default, there are no override values set. \since 2.9 */ diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index 4e25d627f..020aa6c9f 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -66,6 +66,8 @@ class QSurface; class QSize; class QScreen; class QOpenGLTexture; +class QMouseEvent; +class QKeyEvent; namespace Qt3DCore { class QAbstractFrameAdvanceService; @@ -130,10 +132,12 @@ public: virtual void setTime(qint64 time) = 0; virtual void setJobsInLastFrame(int jobsInLastFrame) = 0; + virtual void setAspect(QRenderAspect *aspect) = 0; virtual void setNodeManagers(NodeManagers *managers) = 0; virtual void setServices(Qt3DCore::QServiceLocator *services) = 0; virtual void setSurfaceExposed(bool exposed) = 0; + virtual QRenderAspect *aspect() const = 0; virtual NodeManagers *nodeManagers() const = 0; virtual Qt3DCore::QServiceLocator *services() const = 0; @@ -159,12 +163,10 @@ public: virtual void skipNextFrame() = 0; virtual void jobsDone(Qt3DCore::QAspectManager *manager) = 0; + virtual void setPendingEvents(const QList<QPair<QObject *, QMouseEvent>> &mouseEvents, const QList<QKeyEvent> &keyEvents) = 0; + virtual QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() = 0; virtual QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() = 0; - virtual Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() = 0; - virtual Qt3DCore::QAspectJobPtr rayCastingJob() = 0; - virtual Qt3DCore::QAspectJobPtr syncLoadingJobs() = 0; - virtual Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() = 0; virtual void setSceneRoot(Entity *root) = 0; @@ -172,7 +174,6 @@ public: virtual FrameGraphNode *frameGraphRoot() const = 0; virtual Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const = 0; - virtual void registerEventFilter(Qt3DCore::QEventFilterService *service) = 0; virtual void setSettings(RenderSettings *settings) = 0; virtual RenderSettings *settings() const = 0; diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp index 3e0e4626d..c635ddb61 100644 --- a/src/render/backend/cameralens.cpp +++ b/src/render/backend/cameralens.cpp @@ -48,6 +48,7 @@ #include <Qt3DRender/private/sphere_p.h> #include <Qt3DRender/private/computefilteredboundingvolumejob_p.h> #include <Qt3DRender/private/renderlogging_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qtransform.h> #include <Qt3DCore/private/qaspectmanager_p.h> @@ -167,7 +168,7 @@ void CameraLens::computeSceneBoundingVolume(QNodeId entityId, Entity *camNode = nodeManagers->renderNodesManager()->lookupResource(cameraId); ComputeFilteredBoundingVolumeJobPtr job(new GetBoundingVolumeWithoutCameraJob(this, requestId)); - job->addDependency(m_renderer->expandBoundingVolumeJob()); + job->addDependency(QRenderAspectPrivate::get(m_renderer->aspect())->m_expandBoundingVolumeJob); job->setRoot(root); job->setManagers(nodeManagers); job->ignoreSubTree(camNode); diff --git a/src/render/backend/transform.cpp b/src/render/backend/transform.cpp index 9e78bc96f..e9e40e34a 100644 --- a/src/render/backend/transform.cpp +++ b/src/render/backend/transform.cpp @@ -105,6 +105,9 @@ void Transform::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::TransformDirty); } + if (transform->isEnabled() != isEnabled()) + markDirty(AbstractRenderer::TransformDirty); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); } diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index f09dec67a..6015c1659 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -159,12 +159,14 @@ #include <Qt3DRender/private/waitfence_p.h> #include <Qt3DRender/private/shaderimage_p.h> #include <Qt3DRender/private/debugoverlay_p.h> +#include <Qt3DRender/private/qrendererpluginfactory_p.h> +#include <Qt3DRender/private/updatelevelofdetailjob_p.h> +#include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/pickeventfilter_p.h> #include <private/qrenderpluginfactory_p.h> #include <private/qrenderplugin_p.h> -#include <Qt3DRender/private/qrendererpluginfactory_p.h> - #include <Qt3DCore/qentity.h> #include <Qt3DCore/qtransform.h> #include <Qt3DCore/qattribute.h> @@ -176,6 +178,7 @@ #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/private/qentity_p.h> #include <Qt3DCore/private/qaspectmanager_p.h> +#include <Qt3DCore/private/qeventfilterservice_p.h> #include <QThread> #include <QOpenGLContext> @@ -186,6 +189,9 @@ using namespace Qt3DCore; namespace Qt3DRender { +#define CreateSynchronizerJobPtr(lambda, type) \ + Render::SynchronizerJobPtr::create(lambda, type, #type) + /*! * \class Qt3DRender::QRenderAspect * \inheaderfile Qt3DRender/QRenderAspect @@ -210,6 +216,18 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type) , m_renderAfterJobs(false) , m_renderType(type) , m_offscreenHelper(nullptr) + , m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create()) + , m_worldTransformJob(Render::UpdateWorldTransformJobPtr::create()) + , m_expandBoundingVolumeJob(Render::ExpandBoundingVolumeJobPtr::create()) + , m_calculateBoundingVolumeJob(Render::CalculateBoundingVolumeJobPtr::create()) + , m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create()) + , m_updateSkinningPaletteJob(Render::UpdateSkinningPaletteJobPtr::create()) + , m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create()) + , m_updateEntityLayersJob(Render::UpdateEntityLayersJobPtr::create()) + , m_syncLoadingJobs(CreateSynchronizerJobPtr([] {}, Render::JobTypes::SyncLoadingJobs)) + , m_pickBoundingVolumeJob(Render::PickBoundingVolumeJobPtr::create()) + , m_rayCastingJob(Render::RayCastingJobPtr::create()) + , m_pickEventFilter(new Render::PickEventFilter()) { m_instances.append(this); loadSceneParsers(); @@ -217,6 +235,11 @@ QRenderAspectPrivate::QRenderAspectPrivate(QRenderAspect::RenderType type) m_renderType = QRenderAspect::Synchronous; m_renderAfterJobs = true; } + + m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); + m_updateWorldBoundingVolumeJob->addDependency(m_calculateBoundingVolumeJob); + m_expandBoundingVolumeJob->addDependency(m_updateWorldBoundingVolumeJob); + m_updateLevelOfDetailJob->addDependency(m_expandBoundingVolumeJob); } /*! \internal */ @@ -243,6 +266,11 @@ QRenderAspectPrivate *QRenderAspectPrivate::findPrivate(Qt3DCore::QAspectEngine return nullptr; } +QRenderAspectPrivate *QRenderAspectPrivate::get(QRenderAspect *q) +{ + return q->d_func(); +} + void QRenderAspectPrivate::jobsDone() { m_renderer->jobsDone(m_aspectManager); @@ -255,6 +283,41 @@ void QRenderAspectPrivate::frameDone() m_renderer->doRender(true); } +void QRenderAspectPrivate::createNodeManagers() +{ + m_nodeManagers = new Render::NodeManagers(); + + m_updateTreeEnabledJob->setManagers(m_nodeManagers); + m_worldTransformJob->setManagers(m_nodeManagers); + m_expandBoundingVolumeJob->setManagers(m_nodeManagers); + m_calculateBoundingVolumeJob->setManagers(m_nodeManagers); + m_updateWorldBoundingVolumeJob->setManager(m_nodeManagers->renderNodesManager()); + m_updateSkinningPaletteJob->setManagers(m_nodeManagers); + m_updateLevelOfDetailJob->setManagers(m_nodeManagers); + m_updateEntityLayersJob->setManager(m_nodeManagers); + m_pickBoundingVolumeJob->setManagers(m_nodeManagers); + m_rayCastingJob->setManagers(m_nodeManagers); +} + +void QRenderAspectPrivate::onEngineStartup() +{ + Render::Entity *rootEntity = m_nodeManagers->lookupResource<Render::Entity, Render::EntityManager>(m_rootId); + Q_ASSERT(rootEntity); + m_renderer->setSceneRoot(rootEntity); + + m_worldTransformJob->setRoot(rootEntity); + m_expandBoundingVolumeJob->setRoot(rootEntity); + m_calculateBoundingVolumeJob->setRoot(rootEntity); + m_updateLevelOfDetailJob->setRoot(rootEntity); + m_updateSkinningPaletteJob->setRoot(rootEntity); + m_updateTreeEnabledJob->setRoot(rootEntity); + m_pickBoundingVolumeJob->setRoot(rootEntity); + m_rayCastingJob->setRoot(rootEntity); + + // Ensures all skeletons are loaded before we try to update them + m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs); +} + /*! \internal */ void QRenderAspectPrivate::registerBackendTypes() { @@ -483,6 +546,8 @@ void QRenderAspectPrivate::renderShutdown() QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) { + using namespace Render; + Q_D(QRenderAspect); d->m_renderer->setTime(time); @@ -506,10 +571,10 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // asked for jobs to execute (this function). If that is the case, the RenderSettings will // be null and we should not generate any jobs. if (d->m_renderer->isRunning() && d->m_renderer->settings()) { - - Render::NodeManagers *manager = d->m_renderer->nodeManagers(); - QAspectJobPtr loadingJobSync = d->m_renderer->syncLoadingJobs(); - loadingJobSync->removeDependency(QWeakPointer<QAspectJob>()); + NodeManagers *manager = d->m_nodeManagers; + d->m_syncLoadingJobs->removeDependency(QWeakPointer<QAspectJob>()); + d->m_calculateBoundingVolumeJob->removeDependency(QWeakPointer<QAspectJob>()); + d->m_updateLevelOfDetailJob->setFrameGraphRoot(d->m_renderer->frameGraphRoot()); // Launch skeleton loader jobs once all loading jobs have completed. const QVector<Render::HSkeleton> skeletonsToLoad = @@ -517,7 +582,7 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) for (const auto &skeletonHandle : skeletonsToLoad) { auto loadSkeletonJob = Render::LoadSkeletonJobPtr::create(skeletonHandle); loadSkeletonJob->setNodeManagers(manager); - loadingJobSync->addDependency(loadSkeletonJob); + d->m_syncLoadingJobs->addDependency(loadSkeletonJob); jobs.append(loadSkeletonJob); } @@ -534,9 +599,6 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) const QVector<QAspectJobPtr> geometryJobs = d->createGeometryRendererJobs(); jobs.append(geometryJobs); - const QVector<QAspectJobPtr> preRenderingJobs = d->m_renderer->preRenderingJobs(); - jobs.append(preRenderingJobs); - // Don't spawn any rendering jobs, if the renderer decides to skip this frame // Note: this only affects rendering jobs (jobs that load buffers, // perform picking,... must still be run) @@ -550,9 +612,51 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspect::jobsToExecute(qint64 time) // RenderBins with RenderCommands // All jobs needed to create the frame and their dependencies are set by // renderBinJobs() + + const AbstractRenderer::BackendNodeDirtySet dirtyBitsForFrame = d->m_renderer->dirtyBits(); + + // Create the jobs to build the frame + const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; + if (entitiesEnabledDirty) { + jobs.push_back(d->m_updateTreeEnabledJob); + // This dependency is added here because we clear all dependencies + // at the start of this function. + d->m_calculateBoundingVolumeJob->addDependency(d->m_updateTreeEnabledJob); + } + + if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { + jobs.push_back(d->m_worldTransformJob); + jobs.push_back(d->m_updateWorldBoundingVolumeJob); + } + + if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || + dirtyBitsForFrame & AbstractRenderer::BuffersDirty) { + jobs.push_back(d->m_calculateBoundingVolumeJob); + } + + if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || + dirtyBitsForFrame & AbstractRenderer::TransformDirty) { + jobs.push_back(d->m_expandBoundingVolumeJob); + } + + // TO DO: Conditionally add if skeletons dirty + jobs.push_back(d->m_syncLoadingJobs); + d->m_updateSkinningPaletteJob->setDirtyJoints(manager->jointManager()->dirtyJoints()); + jobs.push_back(d->m_updateSkinningPaletteJob); + jobs.push_back(d->m_updateLevelOfDetailJob); + + // Rebuild Entity Layers list if layers are dirty + const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; + if (layersDirty) + jobs.push_back(d->m_updateEntityLayersJob); + + const QVector<QAspectJobPtr> preRenderingJobs = d->createPreRendererJobs(); + jobs.append(preRenderingJobs); + const QVector<QAspectJobPtr> renderBinJobs = d->m_renderer->renderBinJobs(); jobs.append(renderBinJobs); } + return jobs; } @@ -582,10 +686,7 @@ void QRenderAspect::onEngineStartup() Q_D(QRenderAspect); if (d->m_renderAfterJobs) // synchronous rendering but using QWindow d->m_renderer->initialize(); - Render::NodeManagers *managers = d->m_renderer->nodeManagers(); - Render::Entity *rootEntity = managers->lookupResource<Render::Entity, Render::EntityManager>(rootEntityId()); - Q_ASSERT(rootEntity); - d->m_renderer->setSceneRoot(rootEntity); + d->onEngineStartup(); } void QRenderAspect::onRegistered() @@ -594,12 +695,13 @@ void QRenderAspect::onRegistered() // using a threaded renderer, this blocks until the render thread has been created // and started. Q_D(QRenderAspect); - d->m_nodeManagers = new Render::NodeManagers(); + d->createNodeManagers(); // Load proper Renderer class based on Qt configuration preferences d->m_renderer = d->loadRendererPlugin(); Q_ASSERT(d->m_renderer); d->m_renderer->setScreen(d->m_screen); + d->m_renderer->setAspect(this); d->m_renderer->setNodeManagers(d->m_nodeManagers); // Create a helper for deferring creation of an offscreen surface used during cleanup @@ -612,7 +714,6 @@ void QRenderAspect::onRegistered() d->registerBackendTypes(); if (!d->m_initialized) { - // Register the VSyncFrameAdvanceService to drive the aspect manager loop // depending on the vsync if (d->m_aspectManager) { @@ -628,7 +729,7 @@ void QRenderAspect::onRegistered() } if (d->m_aspectManager) - d->m_renderer->registerEventFilter(d->services()->eventFilterService()); + d->services()->eventFilterService()->registerEventFilter(d->m_pickEventFilter.data(), 1024); } void QRenderAspect::onUnregistered() @@ -658,14 +759,14 @@ void QRenderAspect::onUnregistered() d->m_offscreenHelper = nullptr; } -QVector<Qt3DCore::QAspectJobPtr> QRenderAspectPrivate::createGeometryRendererJobs() +QVector<Qt3DCore::QAspectJobPtr> QRenderAspectPrivate::createGeometryRendererJobs() const { Render::GeometryRendererManager *geomRendererManager = m_nodeManagers->geometryRendererManager(); const QVector<QNodeId> dirtyGeometryRenderers = geomRendererManager->dirtyGeometryRenderers(); QVector<QAspectJobPtr> dirtyGeometryRendererJobs; dirtyGeometryRendererJobs.reserve(dirtyGeometryRenderers.size()); - for (const QNodeId geoRendererId : dirtyGeometryRenderers) { + for (const QNodeId &geoRendererId : dirtyGeometryRenderers) { Render::HGeometryRenderer geometryRendererHandle = geomRendererManager->lookupHandle(geoRendererId); if (!geometryRendererHandle.isNull()) { auto job = Render::LoadGeometryJobPtr::create(geometryRendererHandle); @@ -677,6 +778,35 @@ QVector<Qt3DCore::QAspectJobPtr> QRenderAspectPrivate::createGeometryRendererJob return dirtyGeometryRendererJobs; } +QVector<QAspectJobPtr> QRenderAspectPrivate::createPreRendererJobs() const +{ + if (!m_renderer) + return {}; + + const auto frameMouseEvents = m_pickEventFilter->pendingMouseEvents(); + const auto frameKeyEvents = m_pickEventFilter->pendingKeyEvents(); + m_renderer->setPendingEvents(frameMouseEvents, m_pickEventFilter->pendingKeyEvents()); + + auto jobs = m_renderer->preRenderingJobs(); + + // Set values on picking jobs + Render::RenderSettings *renderSetting = m_renderer->settings(); + if (renderSetting != nullptr) { + m_pickBoundingVolumeJob->setRenderSettings(renderSetting); + m_pickBoundingVolumeJob->setFrameGraphRoot(m_renderer->frameGraphRoot()); + m_pickBoundingVolumeJob->setMouseEvents(frameMouseEvents); + m_pickBoundingVolumeJob->setKeyEvents(frameKeyEvents); + + m_rayCastingJob->setRenderSettings(renderSetting); + m_rayCastingJob->setFrameGraphRoot(m_renderer->frameGraphRoot()); + } + + jobs.append(m_pickBoundingVolumeJob); + jobs.append(m_rayCastingJob); + + return jobs; +} + void QRenderAspectPrivate::loadSceneParsers() { const QStringList keys = QSceneImportFactory::keys(); diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index f347f169e..d18ccfc24 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -54,6 +54,16 @@ #include <Qt3DRender/qrenderaspect.h> #include <Qt3DCore/private/qabstractaspect_p.h> #include <Qt3DRender/private/qt3drender_global_p.h> +#include <Qt3DRender/private/expandboundingvolumejob_p.h> +#include <Qt3DRender/private/updateworldtransformjob_p.h> +#include <Qt3DRender/private/updateworldboundingvolumejob_p.h> +#include <Qt3DRender/private/calcboundingvolumejob_p.h> +#include <Qt3DRender/private/updateskinningpalettejob_p.h> +#include <Qt3DRender/private/updateentitylayersjob_p.h> +#include <Qt3DRender/private/updatetreeenabledjob_p.h> +#include <Qt3DRender/private/genericlambdajob_p.h> +#include <Qt3DRender/private/pickboundingvolumejob_p.h> +#include <Qt3DRender/private/raycastingjob_p.h> #include <QtCore/qmutex.h> @@ -74,6 +84,12 @@ class QRenderPlugin; namespace Render { class OffscreenSurfaceHelper; +class PickEventFilter; + +using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; + +class UpdateLevelOfDetailJob; +typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; } class Q_3DRENDERSHARED_PRIVATE_EXPORT QRenderAspectPrivate : public Qt3DCore::QAbstractAspectPrivate @@ -85,10 +101,14 @@ public: Q_DECLARE_PUBLIC(QRenderAspect) static QRenderAspectPrivate* findPrivate(Qt3DCore::QAspectEngine *engine); + static QRenderAspectPrivate *get(QRenderAspect *q); void jobsDone() override; void frameDone() override; + void createNodeManagers(); + void onEngineStartup(); + void registerBackendTypes(); void unregisterBackendTypes(); void loadSceneParsers(); @@ -97,7 +117,9 @@ public: void renderSynchronous(bool swapBuffers = true); void renderShutdown(); void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor); - QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs(); + QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs() const; + QVector<Qt3DCore::QAspectJobPtr> createPreRendererJobs() const; + QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const; Render::AbstractRenderer *loadRendererPlugin(); Render::NodeManagers *m_nodeManagers; @@ -112,6 +134,20 @@ public: Render::OffscreenSurfaceHelper *m_offscreenHelper; QScreen *m_screen = nullptr; + Render::UpdateTreeEnabledJobPtr m_updateTreeEnabledJob; + Render::UpdateWorldTransformJobPtr m_worldTransformJob; + Render::ExpandBoundingVolumeJobPtr m_expandBoundingVolumeJob; + Render::CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob; + Render::UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob; + Render::UpdateSkinningPaletteJobPtr m_updateSkinningPaletteJob; + Render::UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob; + Render::UpdateEntityLayersJobPtr m_updateEntityLayersJob; + Render::SynchronizerJobPtr m_syncLoadingJobs; + Render::PickBoundingVolumeJobPtr m_pickBoundingVolumeJob; + Render::RayCastingJobPtr m_rayCastingJob; + + QScopedPointer<Render::PickEventFilter> m_pickEventFilter; + static QMutex m_pluginLock; static QVector<QString> m_pluginConfig; static QVector<QRenderAspectPrivate *> m_instances; diff --git a/src/render/frontend/qrendercapabilities.cpp b/src/render/frontend/qrendercapabilities.cpp index f614a528c..885c43bc2 100644 --- a/src/render/frontend/qrendercapabilities.cpp +++ b/src/render/frontend/qrendercapabilities.cpp @@ -107,7 +107,13 @@ namespace Qt3DRender { /*! \class Qt3DRender::QRenderCapabilities \brief The QRenderCapabilities class holds settings related to available rendering engines - */ + +QRenderCapabilities provides details of graphical features that are available at runtime. +It can be used to decide which code path to use for some algorithms, for example, depending +on whether compute shaders are available or not. + +\since 5.15 +*/ /*! \qmltype RenderCapabilities @@ -115,7 +121,13 @@ namespace Qt3DRender { \since 5.15 \inqmlmodule Qt3D.Render \instantiates Qt3DRender::QRenderCapabilities - */ + +RenderCapabilities provides details of graphical features that are available at runtime. +It can be used to decide which code path to use for some algorithms, for example, depending +on whether compute shaders are available or not. + +\since 5.15 +*/ /*! \internal */ @@ -240,186 +252,620 @@ QRenderCapabilities::~QRenderCapabilities() } +/*! +\qmlproperty bool RenderCapabilities::valid + +true if the data is valid, otherwise Qt 3D failed to query the available hardware. + +\readonly +*/ +/*! +\property QRenderCapabilities::valid + +true if the data is valid, otherwise Qt 3D failed to query the available hardware. + +\readonly +*/ bool QRenderCapabilities::isValid() const { Q_D(const QRenderCapabilities); return d->m_valid; } +/*! +\qmlproperty QRenderCapabilities::API RenderCapabilities::api + +Returns which API is currently in use. + +\readonly +*/ +/*! +\property QRenderCapabilities::api + +Returns which API is currently in use. + +\readonly +*/ QRenderCapabilities::API QRenderCapabilities::api() const { Q_D(const QRenderCapabilities); return d->m_api; } +/*! +\qmlproperty bool RenderCapabilities::profile + +Returns which profile (if applicable) is currently in use. + +\readonly +*/ +/*! +\property QRenderCapabilities::profile + +Returns which profile (if applicable) is currently in use. + +\readonly +*/ QRenderCapabilities::Profile QRenderCapabilities::profile() const { Q_D(const QRenderCapabilities); return d->m_profile; } +/*! +\qmlproperty int RenderCapabilities::majorVersion + +Returns the major version number currently in use. + +\readonly +*/ +/*! +\property QRenderCapabilities::majorVersion + +Returns the major version number currently in use. + +\readonly +*/ int QRenderCapabilities::majorVersion() const { Q_D(const QRenderCapabilities); return d->m_majorVersion; } +/*! +\qmlproperty int RenderCapabilities::minorVersion + +Returns the minor version number currently in use. + +\readonly +*/ +/*! +\property QRenderCapabilities::minorVersion + +Returns the minor version number currently in use. + +\readonly +*/ int QRenderCapabilities::minorVersion() const { Q_D(const QRenderCapabilities); return d->m_minorVersion; } +/*! +\qmlproperty QStringList RenderCapabilities::extensions + +Returns the list of extensions currently available. + +\readonly +*/ +/*! +\property QRenderCapabilities::extensions + +Returns the list of extensions currently available. + +\readonly +*/ QStringList QRenderCapabilities::extensions() const { Q_D(const QRenderCapabilities); return d->m_extensions; } +/*! +\qmlproperty QString RenderCapabilities::vendor + +Returns the vendor identification string. + +\readonly +*/ +/*! +\property QRenderCapabilities::vendor + +Returns the vendor identification string. + +\readonly +*/ QString QRenderCapabilities::vendor() const { Q_D(const QRenderCapabilities); return d->m_vendor; } +/*! +\qmlproperty QString RenderCapabilities::renderer + +Returns the device identification string. + +\readonly +*/ +/*! +\property QRenderCapabilities::renderer + +Returns the device identification string. + +\readonly +*/ QString QRenderCapabilities::renderer() const { Q_D(const QRenderCapabilities); return d->m_renderer; } +/*! +\qmlproperty QString RenderCapabilities::driverVersion + +Returns the driver version string. + +\readonly +*/ +/*! +\property QRenderCapabilities::driverVersion + +Returns the driver version string. + +\readonly +*/ QString QRenderCapabilities::driverVersion() const { Q_D(const QRenderCapabilities); return d->m_version; } +/*! +\qmlproperty QString RenderCapabilities::glslVersion + +Returns the GLSL version string. + +\readonly +*/ +/*! +\property QRenderCapabilities::glslVersion + +Returns the GLSL version string. + +\readonly +*/ QString QRenderCapabilities::glslVersion() const { Q_D(const QRenderCapabilities); return d->m_glslVersion; } +/*! +\qmlproperty int RenderCapabilities::maxSamples + +Returns the maximum number of samples available for MSAA. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxSamples + +Returns the maximum number of samples available for MSAA. + +\readonly +*/ int QRenderCapabilities::maxSamples() const { Q_D(const QRenderCapabilities); return d->m_maxSamples; } +/*! +\qmlproperty int RenderCapabilities::maxTextureSize + +Returns the maximum size of textures. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxTextureSize + +Returns the maximum size of textures. + +\readonly +*/ int QRenderCapabilities::maxTextureSize() const { Q_D(const QRenderCapabilities); return d->m_maxTextureSize; } +/*! +\qmlproperty int RenderCapabilities::maxTextureUnits + +Returns the number of available texture units. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxTextureUnits + +Returns the number of available texture units. + +\readonly +*/ int QRenderCapabilities::maxTextureUnits() const { Q_D(const QRenderCapabilities); return d->m_maxTextureUnits; } +/*! +\qmlproperty int RenderCapabilities::maxTextureLayers + +Returns the number of available texture layers. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxTextureLayers + +Returns the number of available texture layers. + +\readonly +*/ int QRenderCapabilities::maxTextureLayers() const { Q_D(const QRenderCapabilities); return d->m_maxTextureLayers; } +/*! +\qmlproperty bool RenderCapabilities::supportsUBO + +Returns true if UBOs are supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::supportsUBO + +Returns true if UBOs are supported. + +\readonly +*/ bool QRenderCapabilities::supportsUBO() const { Q_D(const QRenderCapabilities); return d->m_supportsUBO; } +/*! +\qmlproperty int RenderCapabilities::maxUBOSize + +Returns the maximum size of UBOs, if supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxUBOSize + +Returns the maximum size of UBOs, if supported. + +\readonly +*/ int QRenderCapabilities::maxUBOSize() const { Q_D(const QRenderCapabilities); return d->m_maxUBOSize; } +/*! +\qmlproperty int RenderCapabilities::maxUBOBindings + +Returns the maximum number of available UBO binding points, if supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxUBOBindings + +Returns the maximum number of available UBO binding points, if supported. + +\readonly +*/ int QRenderCapabilities::maxUBOBindings() const { Q_D(const QRenderCapabilities); return d->m_maxUBOBindings; } +/*! +\qmlproperty bool RenderCapabilities::supportsSSBO + +Returns true if SSBOs are supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::supportsSSBO + +Returns true if SSBOs are supported. + +\readonly +*/ bool QRenderCapabilities::supportsSSBO() const { Q_D(const QRenderCapabilities); return d->m_supportsSSBO; } +/*! +\qmlproperty int RenderCapabilities::maxSSBOSize + +Returns the maximum size of SSBOs, if available. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxSSBOSize + +Returns the maximum size of SSBOs, if available. + +\readonly +*/ int QRenderCapabilities::maxSSBOSize() const { Q_D(const QRenderCapabilities); return d->m_maxSSBOSize; } +/*! +\qmlproperty int RenderCapabilities::maxSSBOBindings + +Returns the maximum number of available SSBO binding points, if supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxSSBOBindings + +Returns the maximum number of available SSBO binding points, if supported. + +\readonly +*/ int QRenderCapabilities::maxSSBOBindings() const { Q_D(const QRenderCapabilities); return d->m_maxSSBOBindings; } +/*! +\qmlproperty bool RenderCapabilities::supportsImageStore + +Returns true if Image Store operations are supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::supportsImageStore + +Returns true if Image Store operations are supported. + +\readonly +*/ bool QRenderCapabilities::supportsImageStore() const { Q_D(const QRenderCapabilities); return d->m_supportsImageStore; } +/*! +\qmlproperty int RenderCapabilities::maxImageUnits + +Returns the maximum number of available image units. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxImageUnits + +Returns the maximum number of available image units. + +\readonly +*/ int QRenderCapabilities::maxImageUnits() const { Q_D(const QRenderCapabilities); return d->m_maxImageUnits; } +/*! +\qmlproperty bool RenderCapabilities::supportsCompute + +Returns true if Compute Shaders are supported. + +\readonly +*/ +/*! +\property QRenderCapabilities::supportsCompute + +Returns true if Compute Shaders are supported. + +\readonly +*/ bool QRenderCapabilities::supportsCompute() const { Q_D(const QRenderCapabilities); return d->m_supportCompute; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupCountX + +Returns the maximum number of available Compute Shader workgroups in the X axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupCountX + +Returns the maximum number of available Compute Shader workgroups in the X axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupCountX() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupCount[0]; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupCountY + +Returns the maximum number of available Compute Shader workgroups in the Y axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupCountY + +Returns the maximum number of available Compute Shader workgroups in the Y axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupCountY() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupCount[1]; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupCountZ + +Returns the maximum number of available Compute Shader workgroups in the Z axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupCountZ + +Returns the maximum number of available Compute Shader workgroups in the Z axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupCountZ() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupCount[2]; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupSizeX + +Returns the maximum size of Compute Shader local workgroups in the X axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupSizeX + +Returns the maximum size of Compute Shader local workgroups in the X axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupSizeX() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupSize[0]; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupSizeY + +Returns the maximum size of Compute Shader local workgroups in the Y axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupSizeY + +Returns the maximum size of Compute Shader local workgroups in the Y axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupSizeY() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupSize[1]; } +/*! +\qmlproperty int RenderCapabilities::maxWorkGroupSizeZ + +Returns the maximum size of Compute Shader local workgroups in the Z axis. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxWorkGroupSizeZ + +Returns the maximum size of Compute Shader local workgroups in the Z axis. + +\readonly +*/ int QRenderCapabilities::maxWorkGroupSizeZ() const { Q_D(const QRenderCapabilities); return d->m_maxWorkGroupSize[2]; } +/*! +\qmlproperty int RenderCapabilities::maxComputeInvocations + +Returns the maximum number of Compute Shaders available. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxComputeInvocations + +Returns the maximum number of Compute Shaders available. + +\readonly +*/ int QRenderCapabilities::maxComputeInvocations() const { Q_D(const QRenderCapabilities); return d->m_maxComputeInvocations; } +/*! +\qmlproperty int RenderCapabilities::maxComputeSharedMemorySize + +Returns the maximum amount of shared memory available for Compute Shaders. + +\readonly +*/ +/*! +\property QRenderCapabilities::maxComputeSharedMemorySize + +Returns the maximum amount of shared memory available for Compute Shaders. + +\readonly +*/ int QRenderCapabilities::maxComputeSharedMemorySize() const { Q_D(const QRenderCapabilities); diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp index 0796b74f0..19d919b39 100644 --- a/src/render/frontend/qrendersettings.cpp +++ b/src/render/frontend/qrendersettings.cpp @@ -148,6 +148,7 @@ QRenderSettings::~QRenderSettings() Holds the details of the supported rendering engine \readonly + \since 5.15 */ /*! \property QRenderSettings::renderCapabilities @@ -155,6 +156,7 @@ QRenderSettings::~QRenderSettings() Holds the details of the supported rendering engine \readonly + \since 5.15 */ QRenderCapabilities *QRenderSettings::renderCapabilities() { diff --git a/src/render/jobs/filterentitybycomponentjob_p.h b/src/render/jobs/filterentitybycomponentjob_p.h index cefcdd296..61b2e7ce4 100644 --- a/src/render/jobs/filterentitybycomponentjob_p.h +++ b/src/render/jobs/filterentitybycomponentjob_p.h @@ -80,7 +80,7 @@ public: inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; } inline QVector<Entity *> &filteredEntities() Q_DECL_NOTHROW { return m_filteredEntities; } - void run() final + void run() { m_filteredEntities.clear(); const QVector<HEntity> handles = m_manager->activeHandles(); @@ -97,6 +97,9 @@ 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_p.h b/src/render/jobs/lightgatherer_p.h index 59e64ad74..cc3948f12 100644 --- a/src/render/jobs/lightgatherer_p.h +++ b/src/render/jobs/lightgatherer_p.h @@ -71,14 +71,9 @@ public: inline void setManager(EntityManager *manager) Q_DECL_NOTHROW { m_manager = manager; } inline QVector<LightSource> &lights() { return m_lights; } - inline EnvironmentLight *takeEnvironmentLight() - { - auto envLight = m_environmentLight; - m_environmentLight = nullptr; - return envLight; - } - - void run() final; + inline EnvironmentLight *environmentLight() const { return m_environmentLight; } + + void run() override; private: EntityManager *m_manager; diff --git a/src/render/materialsystem/qshaderimage.cpp b/src/render/materialsystem/qshaderimage.cpp index 4b1f9bafc..d8bcb41ac 100644 --- a/src/render/materialsystem/qshaderimage.cpp +++ b/src/render/materialsystem/qshaderimage.cpp @@ -347,7 +347,7 @@ QShaderImagePrivate::~QShaderImagePrivate() Holds which mipLevel out of the referenced texture should be used for the ShaderImage. - \default 0 + The default value is 0. */ /*! @@ -365,7 +365,7 @@ QShaderImagePrivate::~QShaderImagePrivate() cubeMapFace = layer - (cubeMapLayer * 6) \endcode - Default value is 0. + The default value is 0. */ /*! @@ -377,7 +377,7 @@ QShaderImagePrivate::~QShaderImagePrivate() for all layers. If set to false, only the single layer specified by the \a layer property will be bound. - Default value is \c false. + The default value is \c false. */ /*! @@ -394,7 +394,7 @@ QShaderImagePrivate::~QShaderImagePrivate() \value ShaderImage.ReadWrite Read-write access. - Default value is ShaderImage.ReadWrite. + The default value is ShaderImage.ReadWrite. */ /*! @@ -414,7 +414,7 @@ QShaderImagePrivate::~QShaderImagePrivate() By default Qt3D will try to set the image format to match that of the referenced texture. - Default value is ShaderImage.Automatic. + The default value is ShaderImage.Automatic. */ /*! @@ -695,8 +695,8 @@ QShaderImagePrivate::~QShaderImagePrivate() Holds which mipLevel out of the referenced texture should be used for the QShaderImage. - \default 0 - */ + The default value is 0. +*/ /*! \property Qt3DRender::QShaderImage::layer @@ -713,7 +713,7 @@ QShaderImagePrivate::~QShaderImagePrivate() cubeMapFace = layer - (cubeMapLayer * 6) \endcode - \default 0 + The default value is 0. */ /*! @@ -725,7 +725,7 @@ QShaderImagePrivate::~QShaderImagePrivate() for all layers. If set to false, only the single layer specified by the \a layer property will be bound. - \default false + The default value is \c false. */ /*! @@ -735,7 +735,7 @@ QShaderImagePrivate::~QShaderImagePrivate() the image. If a shader tries to write or read from an image that has incompatible access, the behavior is undefined. - \default QShaderImage::ReadWrite + The default value is QShaderImage::ReadWrite. */ /*! @@ -755,7 +755,7 @@ QShaderImagePrivate::~QShaderImagePrivate() By default Qt3D will try to set the image format to match that of the referenced texture. - \default QShaderImage::Automatic + The default value is QShaderImage::Automatic. */ /*! diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp index 7d6fcede8..2f679ceb1 100644 --- a/src/render/picking/objectpicker.cpp +++ b/src/render/picking/objectpicker.cpp @@ -42,6 +42,7 @@ #include <Qt3DRender/qobjectpicker.h> #include <Qt3DRender/private/qobjectpicker_p.h> #include <Qt3DRender/private/pickboundingvolumejob_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> QT_BEGIN_NAMESPACE @@ -102,8 +103,8 @@ void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstT void ObjectPicker::notifyJob() { - if (m_renderer && m_renderer->pickBoundingVolumeJob()) - qSharedPointerCast<PickBoundingVolumeJob>(m_renderer->pickBoundingVolumeJob())->markPickersDirty(); + if (m_renderer && m_renderer->aspect()) + QRenderAspectPrivate::get(m_renderer->aspect())->m_pickBoundingVolumeJob->markPickersDirty(); } bool ObjectPicker::isPressed() const diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp index 8d3456595..b441a5099 100644 --- a/src/render/picking/raycaster.cpp +++ b/src/render/picking/raycaster.cpp @@ -44,6 +44,7 @@ #include <Qt3DRender/qlayer.h> #include <Qt3DRender/private/qabstractraycaster_p.h> #include <Qt3DRender/private/raycastingjob_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> QT_BEGIN_NAMESPACE @@ -178,8 +179,8 @@ void RayCaster::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime void RayCaster::notifyJob() { - if (m_renderer && m_renderer->rayCastingJob()) - qSharedPointerCast<RayCastingJob>(m_renderer->rayCastingJob())->markCastersDirty(); + if (m_renderer && m_renderer->aspect()) + QRenderAspectPrivate::get(m_renderer->aspect())->m_rayCastingJob->markCastersDirty(); } } // Render diff --git a/tests/auto/render/aspect/aspect.pro b/tests/auto/render/aspect/aspect.pro new file mode 100644 index 000000000..1e8a9c042 --- /dev/null +++ b/tests/auto/render/aspect/aspect.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_aspect + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_aspect.cpp + +CONFIG += useCommonTestAspect +include(../commons/commons.pri) diff --git a/tests/auto/render/aspect/tst_aspect.cpp b/tests/auto/render/aspect/tst_aspect.cpp new file mode 100644 index 000000000..9bd5df698 --- /dev/null +++ b/tests/auto/render/aspect/tst_aspect.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QMutex> +#include <QWaitCondition> +#include <QThread> +#include <Qt3DRender/qrenderaspect.h> +#include <Qt3DRender/private/offscreensurfacehelper_p.h> +#include <Qt3DRender/private/rendersettings_p.h> +#include <Qt3DRender/private/viewportnode_p.h> +#include <Qt3DRender/private/job_common_p.h> +#include <Qt3DRender/private/entity_p.h> + +#include "testaspect.h" +#include "testrenderer.h" + +class TestRendererAspect : public Qt3DRender::TestAspect { +public: + TestRendererAspect(Qt3DCore::QEntity *root) : Qt3DRender::TestAspect(root) { + auto d = Qt3DCore::QAbstractAspectPrivate::get(this); + d->m_rootId = root->id(); + } + + void replaceWithTestRenderer() { + auto daspect = Qt3DRender::QRenderAspectPrivate::get(this); + + auto sceneRoot = daspect->m_renderer->sceneRoot(); + daspect->m_renderer->shutdown(); + delete daspect->m_renderer; + daspect->m_renderer = new TestRenderer(); + daspect->m_renderer->setNodeManagers(daspect->m_nodeManagers); + daspect->m_renderer->setOffscreenSurfaceHelper(daspect->m_offscreenHelper); + sceneRoot->setRenderer(daspect->m_renderer); + daspect->m_renderer->setSceneRoot(sceneRoot); + + // Give it a setting instance + Qt3DRender::Render::RenderSettings settings; + // owned by FG manager + Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); + const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); + + daspect->m_nodeManagers->frameGraphManager()->appendNode(fgRootId, fgRoot); + settings.setActiveFrameGraphId(fgRootId); + + daspect->m_renderer->setSettings(&settings); + } +}; + +class tst_Aspect : public QObject +{ + Q_OBJECT +public : + tst_Aspect() = default; + ~tst_Aspect() = default; + +private Q_SLOTS: + + void checkJobs() + { + // GIVEN + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + QScopedPointer<TestRendererAspect> aspect(new TestRendererAspect(rootEntity)); + auto daspect = Qt3DRender::QRenderAspectPrivate::get(aspect.data()); + daspect->m_renderAfterJobs = true; + aspect->onEngineStartup(); + + // replace with empty renderer + aspect->replaceWithTestRenderer(); + + // WHEN + daspect->m_renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); + + auto jobs = daspect->jobsToExecute(1.); +// qDebug() << jobs.size(); +// for (auto job: jobs) +// qDebug() << Qt3DCore::QAspectJobPrivate::get(job.data())->m_jobName; + + // THEN -> AllDirty + QCOMPARE(jobs.size(), + 1 + // UpdateTreeEnabled + 1 + // UpdateTransform + 1 + // UpdateWorldBoundingVolume + 1 + // CalcBoundingVolume + 1 + // ExpandBoundingVolume + 1 + // SyncLoadingJobs + 1 + // UpdateSkinningPalette + 1 + // UpdateLevelOfDetail + 1 + // UpdateLayerEntity + 1 + // PickBoundingVolume + 1 + // RayCasting + 0 // No skeleton, no scene loading, no geometry, no buffers + ); + + // WHEN + daspect->m_renderer->clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + jobs = daspect->jobsToExecute(1.); + + // THEN -> Nothing dirty + QCOMPARE(jobs.size(), + 1 + // SyncLoadingJobs + 1 + // UpdateSkinningPalette + 1 + // UpdateLevelOfDetail + 1 + // PickBoundingVolume + 1 + // RayCasting + 0 // No skeleton, no scene loading, no geometry, no buffers + ); + + // WHEN + daspect->m_renderer->clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + daspect->m_renderer->markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); + jobs = daspect->jobsToExecute(1.); + + // THEN -> enabled dirty + QCOMPARE(jobs.size(), + 1 + // UpdateTreeEnabled + 1 + // SyncLoadingJobs + 1 + // UpdateSkinningPalette + 1 + // UpdateLevelOfDetail + 1 + // PickBoundingVolume + 1 + // RayCasting + 0 // No skeleton, no scene loading, no geometry, no buffers + ); + + // WHEN + daspect->m_renderer->clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + daspect->m_renderer->markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); + jobs = daspect->jobsToExecute(1.); + + // THEN -> transform dirty + QCOMPARE(jobs.size(), + 1 + // UpdateTransform + 1 + // UpdateWorldBoundingVolume + 1 + // ExpandBoundingVolume + 1 + // SyncLoadingJobs + 1 + // UpdateSkinningPalette + 1 + // UpdateLevelOfDetail + 1 + // PickBoundingVolume + 1 + // RayCasting + 0 // No skeleton, no scene loading, no geometry, no buffers + ); + + // WHEN + daspect->m_renderer->clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + daspect->m_renderer->markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); + jobs = daspect->jobsToExecute(1.); + + // THEN -> geometry dirty + QCOMPARE(jobs.size(), + 1 + // CalcBoundingVolume + 1 + // ExpandBoundingVolume + 1 + // SyncLoadingJobs + 1 + // UpdateSkinningPalette + 1 + // UpdateLevelOfDetail + 1 + // PickBoundingVolume + 1 + // RayCasting + 0 // No skeleton, no scene loading, no geometry, no buffers + ); + } +}; + +QTEST_MAIN(tst_Aspect) + +#include "tst_aspect.moc" diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 1746b81f8..33922a8bc 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -225,9 +225,6 @@ private Q_SLOTS: backendBuffer.unsetDirty(); QVERIFY(!backendBuffer.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::BuffersDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - // WHEN frontendBuffer.updateData(2, QByteArrayLiteral("LS5")); backendBuffer.syncFromFrontEnd(&frontendBuffer, false); diff --git a/tests/auto/render/commons/commons.pri b/tests/auto/render/commons/commons.pri index 6f4382a0b..1c6645f8d 100644 --- a/tests/auto/render/commons/commons.pri +++ b/tests/auto/render/commons/commons.pri @@ -6,7 +6,7 @@ HEADERS += \ useCommonTestAspect { SOURCES += $$PWD/testaspect.cpp - SOURCES += $$PWD/testaspect.h + HEADERS += $$PWD/testaspect.h } INCLUDEPATH += $$PWD diff --git a/tests/auto/render/commons/testaspect.cpp b/tests/auto/render/commons/testaspect.cpp index 87ffc56d7..086d79bb6 100644 --- a/tests/auto/render/commons/testaspect.cpp +++ b/tests/auto/render/commons/testaspect.cpp @@ -95,6 +95,11 @@ Render::NodeManagers *TestAspect::nodeManagers() const return d_func()->m_renderer->nodeManagers(); } +void TestAspect::onEngineStartup() +{ + QRenderAspect::onEngineStartup(); +} + void TestAspect::onRegistered() { QRenderAspect::onRegistered(); diff --git a/tests/auto/render/commons/testaspect.h b/tests/auto/render/commons/testaspect.h index a0da98721..dfbe78fbd 100644 --- a/tests/auto/render/commons/testaspect.h +++ b/tests/auto/render/commons/testaspect.h @@ -56,6 +56,7 @@ public: Qt3DRender::Render::NodeManagers *nodeManagers() const; + void onEngineStartup(); void onRegistered(); void onUnregistered(); diff --git a/tests/auto/render/commons/testrenderer.cpp b/tests/auto/render/commons/testrenderer.cpp index 6b6e2326e..a6687aac6 100644 --- a/tests/auto/render/commons/testrenderer.cpp +++ b/tests/auto/render/commons/testrenderer.cpp @@ -50,7 +50,7 @@ Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet TestRenderer::dirtyBit #if defined(QT_BUILD_INTERNAL) void TestRenderer::clearDirtyBits(Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet changes) { - m_changes &= changes; + m_changes &= ~changes; } #endif diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 7b3e0a387..8d5d87a98 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -43,15 +43,17 @@ public: void dumpInfo() const override {} API api() const override { return AbstractRenderer::OpenGL; } qint64 time() const override { return 0; } - void setTime(qint64 time) override { Q_UNUSED(time); } + void setTime(qint64 time) override { Q_UNUSED(time) } + void setAspect(Qt3DRender::QRenderAspect *aspect) override { m_aspect = aspect; } void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override { m_managers = m; m_resourceAccessor.reset(new Qt3DRender::Render::ResourceAccessor(this, m_managers)); } - void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services); } - void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed); } + void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services) } + void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed) } void setJobsInLastFrame(int jobsInLastFrame) override { Q_UNUSED(jobsInLastFrame) } + Qt3DRender::QRenderAspect *aspect() const override { return m_aspect; } Qt3DRender::Render::NodeManagers *nodeManagers() const override { return m_managers; } Qt3DCore::QServiceLocator *services() const override { return nullptr; } void initialize() override {} @@ -66,17 +68,13 @@ public: void jobsDone(Qt3DCore::QAspectManager *manager) override { Q_UNUSED(manager) } QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); } QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override { return QVector<Qt3DCore::QAspectJobPtr>(); } - Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } - Qt3DCore::QAspectJobPtr rayCastingJob() override { return Qt3DCore::QAspectJobPtr(); } - Qt3DCore::QAspectJobPtr syncLoadingJobs() override { return Qt3DCore::QAspectJobPtr(); } - Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root) } Qt3DRender::Render::Entity *sceneRoot() const override { return nullptr; } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const override { return nullptr; } Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override { return nullptr; } - void registerEventFilter(Qt3DCore::QEventFilterService *service) override { Q_UNUSED(service) } - void setSettings(Qt3DRender::Render::RenderSettings *settings) override { Q_UNUSED(settings) } - Qt3DRender::Render::RenderSettings *settings() const override { return nullptr; } + void setSettings(Qt3DRender::Render::RenderSettings *settings) override { m_settings = settings; } + Qt3DRender::Render::RenderSettings *settings() const override { return m_settings; } + void setPendingEvents(const QList<QPair<QObject *, QMouseEvent> > &, const QList<QKeyEvent> &) override { } void markDirty(Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet changes, Qt3DRender::Render::BackendNode *node) override; Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet dirtyBits() override; @@ -99,8 +97,10 @@ public: protected: Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes; + Qt3DRender::QRenderAspect *m_aspect = nullptr; Qt3DRender::Render::NodeManagers *m_managers = nullptr; QSharedPointer<Qt3DRender::Render::ResourceAccessor> m_resourceAccessor; + Qt3DRender::Render::RenderSettings *m_settings = nullptr; }; QT_END_NAMESPACE diff --git a/tests/auto/render/opengl/renderer/renderer.pro b/tests/auto/render/opengl/renderer/renderer.pro index d481c7b9e..a4a459655 100644 --- a/tests/auto/render/opengl/renderer/renderer.pro +++ b/tests/auto/render/opengl/renderer/renderer.pro @@ -10,3 +10,6 @@ SOURCES += tst_renderer.cpp # Link Against OpenGL Renderer Plugin include(../opengl_render_plugin.pri) + +CONFIG += useCommonTestAspect +include(../../commons/commons.pri) diff --git a/tests/auto/render/opengl/renderer/tst_renderer.cpp b/tests/auto/render/opengl/renderer/tst_renderer.cpp index d0f1d5c17..85582d178 100644 --- a/tests/auto/render/opengl/renderer/tst_renderer.cpp +++ b/tests/auto/render/opengl/renderer/tst_renderer.cpp @@ -30,12 +30,15 @@ #include <QMutex> #include <QWaitCondition> #include <QThread> -#include <Qt3DRender/private/viewportnode_p.h> #include <renderer_p.h> #include <renderview_p.h> #include <renderviewbuilder_p.h> -#include <Qt3DRender/private/offscreensurfacehelper_p.h> #include <renderqueue_p.h> +#include <Qt3DRender/private/viewportnode_p.h> +#include <Qt3DRender/private/offscreensurfacehelper_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> + +#include "testaspect.h" class tst_Renderer : public QObject { @@ -72,19 +75,14 @@ private Q_SLOTS: QVector<Qt3DCore::QAspectJobPtr> jobs = renderer.preRenderingJobs(); // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1); // RayCastingJob + QCOMPARE(jobs.size(), 0); // WHEN renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); jobs = renderer.preRenderingJobs(); // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob - 1); // SendBufferCaptureJob + QCOMPARE(jobs.size(), 1); // SendBufferCaptureJob // Note: pending render buffer captures are only cleared when the job is run // WHEN @@ -93,8 +91,6 @@ private Q_SLOTS: // THEN QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob 1); // SendBufferCaptureJob´ // Note: pending set fence handles are only cleared when the job is run @@ -105,8 +101,12 @@ private Q_SLOTS: void checkRenderBinJobs() { // GIVEN + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); + QScopedPointer<Qt3DRender::TestAspect> aspect(new Qt3DRender::TestAspect(rootEntity)); + auto daspect = Qt3DRender::QRenderAspectPrivate::get(aspect.data()); + Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + auto &renderer = *(static_cast<Qt3DRender::Render::OpenGL::Renderer *>(daspect->m_renderer)); Qt3DRender::Render::OpenGL::RenderQueue *renderQueue = renderer.renderQueue(); Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); Qt3DRender::Render::RenderSettings settings; @@ -155,26 +155,14 @@ private Q_SLOTS: // (Renderer is not initialized so FilterCompatibleTechniqueJob // and ShaderGathererJob are not added here) QCOMPARE(jobs.size(), - 1 + // EntityEnabledDirty - 1 + // WorldTransformJob - 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform - 1 + // ExpandBoundingVolumeJob - 1 + // CalculateBoundingVolumeJob - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // BufferGathererJob 1 + // TexturesGathererJob - 1 + // UpdateEntityLayersJob 1 + // LightGathererJob - 1 + // CacheLightJob 1 + // RenderableEntityFilterJob - 1 + // CacheRenderableEntitiesJob 1 + // ComputableEntityFilterJob - 1 + // CacheComputableEntitiesJob singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + layerCacheJobCount + @@ -189,11 +177,8 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + @@ -209,11 +194,8 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + @@ -228,12 +210,8 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // EntityEnabledDirty singleRenderViewJobCount + layerCacheJobCount); @@ -246,15 +224,9 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // WorldTransformJob - 1 + // UpdateWorldBoundingVolume 1 + // UpdateShaderDataTransform - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // ExpandBoundingVolumeJob singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -266,11 +238,8 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount); @@ -284,15 +253,9 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // CalculateBoundingVolumeJob - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // ExpandBoundingVolumeJob 1 + // RenderableEntityFilterPtr - 1 + // SyncRenderableEntities singleRenderViewCommandRebuildJobCount + singleRenderViewJobCount); @@ -305,12 +268,8 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // CalculateBoundingVolumeJob 1 + // BufferGathererJob singleRenderViewJobCount); @@ -323,12 +282,9 @@ private Q_SLOTS: // THEN (level QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer 1 + // TexturesGathererJob - 1 + // updateSkinningPaletteJob - 1 + // SyncTexturesGathererJob singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); diff --git a/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp index fe534e243..19ab51c8c 100644 --- a/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp @@ -53,6 +53,7 @@ #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/managers_p.h> #include <Qt3DRender/private/filterentitybycomponentjob_p.h> +#include <Qt3DRender/private/qrenderaspect_p.h> QT_BEGIN_NAMESPACE @@ -290,6 +291,11 @@ private Q_SLOTS: Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + auto expandBVJob = Qt3DRender::QRenderAspectPrivate::get(&testAspect)->m_expandBoundingVolumeJob; + auto wordTransformJob = Qt3DRender::QRenderAspectPrivate::get(&testAspect)->m_worldTransformJob; + auto updateTreeEnabledJob = Qt3DRender::QRenderAspectPrivate::get(&testAspect)->m_updateTreeEnabledJob; + auto updateEntityLayerJob = Qt3DRender::QRenderAspectPrivate::get(&testAspect)->m_updateEntityLayersJob; + // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); @@ -304,7 +310,6 @@ private Q_SLOTS: // Step 1 QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update - // Step 2 QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), @@ -316,7 +321,7 @@ private Q_SLOTS: QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(expandBVJob)); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), @@ -324,14 +329,13 @@ private Q_SLOTS: QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(wordTransformJob)); QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); // Step 4 QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(expandBVJob)); QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); @@ -340,7 +344,7 @@ private Q_SLOTS: 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())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->lightGathererJob())); // Step 5 for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { @@ -374,16 +378,16 @@ private Q_SLOTS: // Step 3 QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(updateEntityLayerJob)); QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(updateTreeEnabledJob)); QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(expandBVJob)); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), @@ -391,7 +395,7 @@ private Q_SLOTS: QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(wordTransformJob)); QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { @@ -404,7 +408,7 @@ private Q_SLOTS: // Step 4 QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(expandBVJob)); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); @@ -467,7 +471,7 @@ private Q_SLOTS: // THEN QCOMPARE(renderer->lightGathererJob()->lights().size(), 2); - QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr); + QVERIFY(renderer->lightGathererJob()->environmentLight() != nullptr); } void checkRenderableEntitiesFilteringExecution() @@ -638,7 +642,6 @@ private Q_SLOTS: renderViewBuilder.buildJobHierachy(); renderer->renderableEntityFilterJob()->run(); - renderer->cacheRenderableEntitiesJob()->run(); renderViewBuilder.renderViewJob()->run(); renderViewBuilder.syncRenderViewPostInitializationJob()->run(); diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 9592b9f6c..c03f93d6c 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -2,6 +2,7 @@ TEMPLATE = subdirs qtConfig(private_tests) { SUBDIRS += \ + aspect \ entity \ renderpass \ shader \ diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp index 09192bbf9..268b8b2ca 100644 --- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp +++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp @@ -88,20 +88,26 @@ namespace Qt3DRender { QVector<Qt3DCore::QAspectJobPtr> worldTransformJob() { - static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_worldTransformJob->setRoot(d_func()->m_renderer->sceneRoot()); - return QVector<Qt3DCore::QAspectJobPtr>() << static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_worldTransformJob; + auto renderer = static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer); + auto daspect = Qt3DRender::QRenderAspectPrivate::get(renderer->aspect()); + daspect->m_worldTransformJob->setRoot(d_func()->m_renderer->sceneRoot()); + return QVector<Qt3DCore::QAspectJobPtr>() << daspect->m_worldTransformJob; } QVector<Qt3DCore::QAspectJobPtr> updateBoundingJob() { - static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob->setManager(d_func()->m_renderer->nodeManagers()->renderNodesManager()); - return QVector<Qt3DCore::QAspectJobPtr>() << static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob; + auto renderer = static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer); + auto daspect = Qt3DRender::QRenderAspectPrivate::get(renderer->aspect()); + daspect->m_updateWorldBoundingVolumeJob->setManager(d_func()->m_renderer->nodeManagers()->renderNodesManager()); + return QVector<Qt3DCore::QAspectJobPtr>() << daspect->m_updateWorldBoundingVolumeJob; } QVector<Qt3DCore::QAspectJobPtr> calculateBoundingVolumeJob() { - static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_calculateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); - return QVector<Qt3DCore::QAspectJobPtr>() << static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer)->m_calculateBoundingVolumeJob; + auto renderer = static_cast<Render::OpenGL::Renderer *>(d_func()->m_renderer); + auto daspect = Qt3DRender::QRenderAspectPrivate::get(renderer->aspect()); + daspect->m_calculateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); + return QVector<Qt3DCore::QAspectJobPtr>() << daspect->m_calculateBoundingVolumeJob; } QVector<Qt3DCore::QAspectJobPtr> framePreparationJob() |