diff options
Diffstat (limited to 'src/render/renderers/opengl')
5 files changed, 215 insertions, 40 deletions
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 746ca514f..e7fa4615c 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -200,6 +200,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading)) + , m_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create()) , m_ownedContext(false) , m_offscreenHelper(nullptr) #if QT_CONFIG(qt3d_profile_jobs) @@ -212,6 +213,9 @@ Renderer::Renderer(QRenderAspect::RenderType type) if (m_renderThread) m_renderThread->waitForStart(); + m_worldTransformJob->addDependency(m_updateEntityHierarchyJob); + m_updateEntityLayersJob->addDependency(m_updateEntityHierarchyJob); + // 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); @@ -301,6 +305,7 @@ void Renderer::setNodeManagers(NodeManagers *managers) m_updateMeshTriangleListJob->setManagers(m_nodesManager); m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); m_updateEntityLayersJob->setManager(m_nodesManager); + m_updateEntityHierarchyJob->setManager(m_nodesManager); } void Renderer::setServices(QServiceLocator *services) @@ -1783,14 +1788,17 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Add jobs const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - if (entitiesEnabledDirty) { + const bool entityHierarchyNeedsToBeRebuilt = dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty; + if (entitiesEnabledDirty || entityHierarchyNeedsToBeRebuilt) { 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); + m_calculateBoundingVolumeJob->addDependency(m_updateEntityHierarchyJob); } - if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { + if (dirtyBitsForFrame & AbstractRenderer::TransformDirty || + dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty) { renderBinJobs.push_back(m_worldTransformJob); renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); renderBinJobs.push_back(m_updateShaderDataTransformJob); @@ -1803,6 +1811,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() } if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || + dirtyBitsForFrame & AbstractRenderer::EntityHierarchyDirty || dirtyBitsForFrame & AbstractRenderer::TransformDirty) { renderBinJobs.push_back(m_expandBoundingVolumeJob); } @@ -1829,10 +1838,17 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // Layer cache is dependent on layers, layer filters (hence FG structure // changes) and the enabled flag on entities const bool frameGraphDirty = dirtyBitsForFrame & AbstractRenderer::FrameGraphDirty; - const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; + const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty || entityHierarchyNeedsToBeRebuilt; const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty || frameGraphDirty; const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; const bool materialCacheNeedsToBeRebuilt = materialDirty || frameGraphDirty; + const bool lightsDirty = dirtyBitsForFrame & AbstractRenderer::LightsDirty; + const bool computeableDirty = dirtyBitsForFrame & AbstractRenderer::ComputeDirty; + const bool renderableDirty = dirtyBitsForFrame & AbstractRenderer::GeometryDirty; + + // Rebuild Entity Hierarchy if dirty + if (entityHierarchyNeedsToBeRebuilt) + renderBinJobs.push_back(m_updateEntityHierarchyJob); // Rebuild Entity Layers list if layers are dirty if (layersDirty) @@ -1860,6 +1876,10 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() RenderViewBuilder builder(fgLeaves.at(i), i, this); builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt); + builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty); + builder.setComputableCacheNeedsToBeRebuilt(computeableDirty); + builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty); + builder.prepareJobs(); renderBinJobs.append(builder.buildJobHierachy()); } diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index 97bd4f73e..5b5f5c4f4 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -78,6 +78,7 @@ #include <Qt3DRender/private/filtercompatibletechniquejob_p.h> #include <Qt3DRender/private/updateskinningpalettejob_p.h> #include <Qt3DRender/private/updateentitylayersjob_p.h> +#include <Qt3DRender/private/updateentityhierarchyjob_p.h> #include <Qt3DRender/private/renderercache_p.h> #include <Qt3DRender/private/texture_p.h> #include <Qt3DRender/private/glfence_p.h> @@ -367,6 +368,7 @@ private: UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob; FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; UpdateEntityLayersJobPtr m_updateEntityLayersJob; + UpdateEntityHierarchyJobPtr m_updateEntityHierarchyJob; QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests; diff --git a/src/render/renderers/opengl/renderer/renderercache_p.h b/src/render/renderers/opengl/renderer/renderercache_p.h index 2aa50d131..0e9c5d3cd 100644 --- a/src/render/renderers/opengl/renderer/renderercache_p.h +++ b/src/render/renderers/opengl/renderer/renderercache_p.h @@ -55,6 +55,7 @@ #include <Qt3DRender/private/entity_p.h> #include <Qt3DRender/private/renderviewjobutils_p.h> +#include <Qt3DRender/private/lightsource_p.h> QT_BEGIN_NAMESPACE @@ -68,6 +69,10 @@ struct RendererCache { QVector<Entity *> filterEntitiesByLayer; MaterialParameterGathererData materialParameterGatherer; + QVector<LightSource> gatheredLights; + QVector<Entity *> renderableEntities; + QVector<Entity *> computeEntities; + EnvironmentLight* environmentLight; }; QHash<FrameGraphNode *, LeafNodeData> leafNodeCache; diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp index d3d2d2dc4..83fab301a 100644 --- a/src/render/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/render/renderers/opengl/renderer/renderviewbuilder.cpp @@ -177,9 +177,6 @@ public: explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob, const FrustumCullingJobPtr &frustumCullingJob, const FilterProximityDistanceJobPtr &filterProximityJob, - const LightGathererPtr &lightGathererJob, - const RenderableEntityFilterPtr &renderableEntityFilterJob, - const ComputableEntityFilterPtr &computableEntityFilterJob, const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs, const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs, Renderer *renderer, @@ -187,9 +184,6 @@ public: : m_renderViewJob(renderViewJob) , m_frustumCullingJob(frustumCullingJob) , m_filterProximityJob(filterProximityJob) - , m_lightGathererJob(lightGathererJob) - , m_renderableEntityFilterJob(renderableEntityFilterJob) - , m_computableEntityFilterJob(computableEntityFilterJob) , m_materialGathererJobs(materialGathererJobs) , m_renderViewBuilderJobs(renderViewBuilderJobs) , m_renderer(renderer) @@ -203,28 +197,27 @@ public: RenderView *rv = m_renderViewJob->renderView(); if (!rv->noDraw()) { - rv->setEnvironmentLight(m_lightGathererJob->takeEnvironmentLight()); - - // We sort the vector so that the removal can then be performed linearly - QVector<Entity *> renderableEntities; const bool isDraw = !rv->isCompute(); + QMutexLocker lock(m_renderer->cache()->mutex()); + const auto& cacheData = m_renderer->cache()->leafNodeCache.value(m_leafNode); + if (isDraw) - renderableEntities = std::move(m_renderableEntityFilterJob->filteredEntities()); + renderableEntities = cacheData.renderableEntities; else - renderableEntities = std::move(m_computableEntityFilterJob->filteredEntities()); + renderableEntities = cacheData.computeEntities; - // Filter out entities that weren't selected by the layer filters - std::sort(renderableEntities.begin(), renderableEntities.end()); + const QVector<Entity *> filteredEntities = cacheData.filterEntitiesByLayer; + QVector<LightSource> lightSources = cacheData.gatheredLights; + rv->setEnvironmentLight(cacheData.environmentLight); - QMutexLocker lock(m_renderer->cache()->mutex()); - const QVector<Entity *> filteredEntities = m_renderer->cache()->leafNodeCache.value(m_leafNode).filterEntitiesByLayer; lock.unlock(); + + // Filter out entities that weren't selected by the layer filters // Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, filteredEntities); // Set the light sources, with layer filters applied. - QVector<LightSource> lightSources = m_lightGathererJob->lights(); for (int i = 0; i < lightSources.count(); ++i) { if (!filteredEntities.contains(lightSources[i].entity)) lightSources.removeAt(i--); @@ -260,9 +253,6 @@ private: RenderViewInitializerJobPtr m_renderViewJob; FrustumCullingJobPtr m_frustumCullingJob; FilterProximityDistanceJobPtr m_filterProximityJob; - LightGathererPtr m_lightGathererJob; - RenderableEntityFilterPtr m_renderableEntityFilterJob; - ComputableEntityFilterPtr m_computableEntityFilterJob; QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; Renderer *m_renderer; @@ -345,6 +335,84 @@ private: FrameGraphNode *m_leafNode; }; +class SyncLightsGatherer +{ +public: + explicit SyncLightsGatherer(LightGathererPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.gatheredLights = m_gatherJob->lights(); + dataCacheForLeaf.environmentLight = m_gatherJob->takeEnvironmentLight(); + } + +private: + LightGathererPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + +class SyncRenderableEntities +{ +public: + explicit SyncRenderableEntities(RenderableEntityFilterPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.renderableEntities = m_gatherJob->filteredEntities(); + std::sort(dataCacheForLeaf.renderableEntities.begin(), dataCacheForLeaf.renderableEntities.end()); + } + +private: + RenderableEntityFilterPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + +class SyncComputableEntities +{ +public: + explicit SyncComputableEntities(ComputableEntityFilterPtr gatherJob, + Renderer *renderer, + FrameGraphNode *leafNode) + : m_gatherJob(gatherJob) + , m_renderer(renderer) + , m_leafNode(leafNode) + { + } + + void operator()() + { + QMutexLocker lock(m_renderer->cache()->mutex()); + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; + dataCacheForLeaf.computeEntities = m_gatherJob->filteredEntities(); + std::sort(dataCacheForLeaf.computeEntities.begin(), dataCacheForLeaf.computeEntities.end()); + } + +private: + ComputableEntityFilterPtr m_gatherJob; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; +}; + } // anonymous RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer) @@ -353,11 +421,11 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende , m_renderer(renderer) , m_layerCacheNeedsToBeRebuilt(false) , m_materialGathererCacheNeedsToBeRebuilt(false) + , m_lightsCacheNeedsToBeRebuilt(false) + , m_renderableCacheNeedsToBeRebuilt(false) + , m_computableCacheNeedsToBeRebuilt(false) , m_renderViewJob(RenderViewInitializerJobPtr::create()) , m_filterEntityByLayerJob() - , m_lightGathererJob(Render::LightGathererPtr::create()) - , m_renderableEntityFilterJob(RenderableEntityFilterPtr::create()) - , m_computableEntityFilterJob(ComputableEntityFilterPtr::create()) , m_frustumCullingJob(new Render::FrustumCullingJob()) , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling)) , m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex)) @@ -451,10 +519,37 @@ void RenderViewBuilder::prepareJobs() // Init what we can here EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager(); m_filterProximityJob->setManager(m_renderer->nodeManagers()); - m_renderableEntityFilterJob->setManager(entityManager); - m_computableEntityFilterJob->setManager(entityManager); m_frustumCullingJob->setRoot(m_renderer->sceneRoot()); - m_lightGathererJob->setManager(entityManager); + + if (m_lightsCacheNeedsToBeRebuilt) { + m_lightGathererJob = Render::LightGathererPtr::create(); + m_lightGathererJob->setManager(entityManager); + + m_cacheLightsJob = SynchronizerJobPtr::create(SyncLightsGatherer(m_lightGathererJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheLightsJob->addDependency(m_lightGathererJob); + } + + if (m_renderableCacheNeedsToBeRebuilt) { + m_renderableEntityFilterJob = RenderableEntityFilterPtr::create(); + m_renderableEntityFilterJob->setManager(entityManager); + + m_cacheRenderableEntitiesJob = SynchronizerJobPtr::create( + SyncRenderableEntities(m_renderableEntityFilterJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheRenderableEntitiesJob->addDependency(m_renderableEntityFilterJob); + } + + if (m_computableCacheNeedsToBeRebuilt) { + m_computableEntityFilterJob = ComputableEntityFilterPtr::create(); + m_computableEntityFilterJob->setManager(entityManager); + + m_cacheComputableEntitiesJob = SynchronizerJobPtr::create( + SyncComputableEntities(m_computableEntityFilterJob, m_renderer, m_leafNode), + JobTypes::EntityComponentTypeFiltering); + m_cacheComputableEntitiesJob->addDependency(m_computableEntityFilterJob); + } + m_renderViewJob->setRenderer(m_renderer); m_renderViewJob->setFrameGraphLeafNode(m_leafNode); m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex); @@ -502,9 +597,6 @@ void RenderViewBuilder::prepareJobs() m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob, m_frustumCullingJob, m_filterProximityJob, - m_lightGathererJob, - m_renderableEntityFilterJob, - m_computableEntityFilterJob, m_materialGathererJobs, m_renderViewBuilderJobs, m_renderer, @@ -523,7 +615,6 @@ void RenderViewBuilder::prepareJobs() m_materialGathererJobs, m_renderViewBuilderJobs), JobTypes::SyncRenderViewInitialization); - } QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const @@ -553,10 +644,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob); m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob); - m_syncRenderCommandBuildingJob->addDependency(m_renderableEntityFilterJob); - m_syncRenderCommandBuildingJob->addDependency(m_computableEntityFilterJob); m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob); - m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob); m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob); // Ensure the RenderThread won't be able to process dirtyResources @@ -575,11 +663,25 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const // Add jobs jobs.push_back(m_renderViewJob); // Step 1 - jobs.push_back(m_renderableEntityFilterJob); // Step 1 - jobs.push_back(m_lightGathererJob); // Step 1 - // Note: do it only if OpenGL 4.3+ available - jobs.push_back(m_computableEntityFilterJob); // Step 1 + if (m_lightsCacheNeedsToBeRebuilt) { + jobs.push_back(m_lightGathererJob); // Step 1 + jobs.push_back(m_cacheLightsJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheLightsJob); + } + + if (m_renderableCacheNeedsToBeRebuilt) { + jobs.push_back(m_renderableEntityFilterJob); // Step 1 + jobs.push_back(m_cacheRenderableEntitiesJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheRenderableEntitiesJob); + } + + if (m_computableCacheNeedsToBeRebuilt) { + // Note: do it only if OpenGL 4.3+ available + jobs.push_back(m_computableEntityFilterJob); // Step 1 + jobs.push_back(m_cacheComputableEntitiesJob); + m_syncRenderCommandBuildingJob->addDependency(m_cacheComputableEntitiesJob); + } jobs.push_back(m_syncRenderViewInitializationJob); // Step 2 @@ -652,6 +754,36 @@ bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const return m_materialGathererCacheNeedsToBeRebuilt; } +void RenderViewBuilder::setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_renderableCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::renderableCacheNeedsToBeRebuilt() const +{ + return m_renderableCacheNeedsToBeRebuilt; +} + +void RenderViewBuilder::setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_computableCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::computableCacheNeedsToBeRebuilt() const +{ + return m_computableCacheNeedsToBeRebuilt; +} + +void RenderViewBuilder::setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_lightsCacheNeedsToBeRebuilt = needsToBeRebuilt; +} + +bool RenderViewBuilder::lightGathererCacheNeedsToBeRebuilt() const +{ + return m_lightsCacheNeedsToBeRebuilt; +} + int RenderViewBuilder::optimalJobCount() { return RenderViewBuilder::m_optimalParallelJobCount; diff --git a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h index 818313500..e223a5f1e 100644 --- a/src/render/renderers/opengl/renderer/renderviewbuilder_p.h +++ b/src/render/renderers/opengl/renderer/renderviewbuilder_p.h @@ -109,6 +109,15 @@ public: void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt); bool materialGathererCacheNeedsToBeRebuilt() const; + void setRenderableCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool renderableCacheNeedsToBeRebuilt() const; + + void setComputableCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool computableCacheNeedsToBeRebuilt() const; + + void setLightGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool lightGathererCacheNeedsToBeRebuilt() const; + static int optimalJobCount(); static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset); @@ -118,6 +127,9 @@ private: Renderer *m_renderer; bool m_layerCacheNeedsToBeRebuilt; bool m_materialGathererCacheNeedsToBeRebuilt; + bool m_lightsCacheNeedsToBeRebuilt; + bool m_renderableCacheNeedsToBeRebuilt; + bool m_computableCacheNeedsToBeRebuilt; RenderViewInitializerJobPtr m_renderViewJob; FilterLayerEntityJobPtr m_filterEntityByLayerJob; @@ -137,6 +149,10 @@ private: SynchronizerJobPtr m_syncMaterialGathererJob; FilterProximityDistanceJobPtr m_filterProximityJob; + SynchronizerJobPtr m_cacheRenderableEntitiesJob; + SynchronizerJobPtr m_cacheComputableEntitiesJob; + SynchronizerJobPtr m_cacheLightsJob; + static const int m_optimalParallelJobCount; }; |