diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2020-04-30 11:28:16 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2020-05-28 09:58:09 +0200 |
commit | 628e3a54126425fe4d1093641fe4f6efbb35b623 (patch) | |
tree | afb49ee0ff6ecbd8967517eda5d6481fa410161b /src | |
parent | 9d9305184ea0b19809baac844ae32bf9323d19d2 (diff) |
RenderViewBuilder improvements
- Only lock the cache when needed. It lots of cases job dependencies
ensure we don't have data races
- Use flags to know what needs to be rebuilt instead of booleans.
Makes it easier to transmit that information around.
- Cache filtered renderables and filered light sources.
LayerFilter or Light changes are fairly infrequent, no point in computing
that for every RV for every frame.
Change-Id: I9b768c62825b7e946369f91e7445ebf3f2a888a8
Reviewed-by: Mike Krus <mike.krus@kdab.com>
(cherry picked from commit f5b4bd3cb32d21cf034f13b999e819701da5d4e1)
Diffstat (limited to 'src')
6 files changed, 134 insertions, 61 deletions
diff --git a/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h b/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h index bb1975c82..9c7e84edd 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h +++ b/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob_p.h @@ -82,17 +82,16 @@ public: } EntityRenderCommandDataPtr renderables() const { return m_renderables; } - QVector<RenderCommand> &commands() Q_DECL_NOTHROW { return m_commands; } - + inline void setRebuildFlags(RebuildFlagSet rebuildFlags) { m_rebuildFlags = rebuildFlags; } void run() final; private: int m_offset; int m_count; + RebuildFlagSet m_rebuildFlags; RenderView *m_renderView; Renderer *m_renderer; EntityRenderCommandDataPtr m_renderables; - QVector<RenderCommand> m_commands; Q_DECLARE_PRIVATE(RenderViewCommandUpdaterJob) }; diff --git a/src/plugins/renderers/opengl/renderer/rendercommand_p.h b/src/plugins/renderers/opengl/renderer/rendercommand_p.h index 123ff232b..ce81e041d 100644 --- a/src/plugins/renderers/opengl/renderer/rendercommand_p.h +++ b/src/plugins/renderers/opengl/renderer/rendercommand_p.h @@ -73,6 +73,15 @@ namespace Render { class RenderStateSet; using RenderStateSetPtr = QSharedPointer<RenderStateSet>; +enum RebuildFlag { + FullCommandRebuild = 1 << 0, + LayerCacheRebuild = 1 << 1, + MaterialCacheRebuild = 1 << 2, + LightCacheRebuild = 1 << 3 +}; +Q_DECLARE_FLAGS(RebuildFlagSet, RebuildFlag) +Q_DECLARE_OPERATORS_FOR_FLAGS(RebuildFlagSet) + namespace OpenGL { class GLShader; diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp index 33baab665..d38b12384 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.cpp +++ b/src/plugins/renderers/opengl/renderer/renderer.cpp @@ -150,7 +150,6 @@ public: { LightGatherer::run(); - QMutexLocker lock(m_cache->mutex()); m_cache->gatheredLights = lights(); m_cache->environmentLight = environmentLight(); } @@ -175,7 +174,6 @@ public: QVector<Entity *> selectedEntities = filteredEntities(); std::sort(selectedEntities.begin(), selectedEntities.end()); - QMutexLocker lock(m_cache->mutex()); m_cache->renderableEntities = selectedEntities; } @@ -199,7 +197,6 @@ public: QVector<Entity *> selectedEntities = filteredEntities(); std::sort(selectedEntities.begin(), selectedEntities.end()); - QMutexLocker lock(m_cache->mutex()); m_cache->computeEntities = selectedEntities; } @@ -1943,6 +1940,12 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt || isNewRV); builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt || isNewRV); builder.setRenderCommandCacheNeedsToBeRebuilt(renderCommandsDirty || isNewRV); + builder.setLightCacheNeedsToBeRebuilt(lightsDirty); + + // Insert leaf into cache + if (isNewRV) { + m_cache.leafNodeCache[leaf] = {}; + } builder.prepareJobs(); renderBinJobs.append(builder.buildJobHierachy()); diff --git a/src/plugins/renderers/opengl/renderer/renderercache_p.h b/src/plugins/renderers/opengl/renderer/renderercache_p.h index 6b3946002..5e02df623 100644 --- a/src/plugins/renderers/opengl/renderer/renderercache_p.h +++ b/src/plugins/renderers/opengl/renderer/renderercache_p.h @@ -70,18 +70,36 @@ struct RendererCache { struct LeafNodeData { + // Set by the FilterLayerJob + // Contains all Entities that satisfy the layer filtering for the RV QVector<Entity *> filterEntitiesByLayer; + + // Set by the MaterialParameterGatherJob MaterialParameterGathererData materialParameterGatherer; + + // Set by the SyncRenderViewPreCommandUpdateJob + // Contains all Entities that are renderables (either compute or draw + // depending on the RV) and that satisfy the layer filtering. + QVector<Entity *> layeredFilteredRenderables; + QVector<LightSource> layeredFilteredLightSources; EntityRenderCommandData renderCommandData; }; - // Shared amongst all RV cache + // Variabled below are shared amongst all RV + + // Set by CachingRenderableEntityFilterJob QVector<Entity *> renderableEntities; + + // Set by CachingComputableEntityFilterJob QVector<Entity *> computeEntities; + + // Set by CachingLightGathererJob QVector<LightSource> gatheredLights; + EnvironmentLight* environmentLight; // Per RV cache + // Leaves inserted by SyncRenderViewPostInitialization QHash<FrameGraphNode *, LeafNodeData> leafNodeCache; QMutex *mutex() { return &m_mutex; } diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp index 823937f37..613148d50 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp @@ -76,26 +76,28 @@ public: void operator()() { // Split commands to build among jobs - QMutexLocker lock(m_renderer->cache()->mutex()); + // Rebuild RenderCommands for all entities in RV (ignoring filtering) RendererCache *cache = m_renderer->cache(); + + Q_ASSERT(cache->leafNodeCache.contains(m_leafNode)); + // The cache leaf should already have been created so we don't need to protect the access const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode]; RenderView *rv = m_renderViewInitializer->renderView(); const auto entities = !rv->isCompute() ? cache->renderableEntities : cache->computeEntities; rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer); - lock.unlock(); - // Split among the ideal number of command builders const int jobCount = m_renderViewCommandBuilderJobs.size(); - const int idealPacketSize = std::min(std::max(10, entities.size() / jobCount), entities.size()); + const int entityCount = entities.size(); + const int idealPacketSize = std::min(std::max(10, entityCount / jobCount), entityCount); // Try to split work into an ideal number of workers - const int m = findIdealNumberOfWorkers(entities.size(), idealPacketSize, jobCount); + const int m = findIdealNumberOfWorkers(entityCount, idealPacketSize, jobCount); for (int i = 0; i < m; ++i) { const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i); - const int count = (i == m - 1) ? entities.size() - (i * idealPacketSize) : idealPacketSize; + const int count = (i == m - 1) ? entityCount - (i * idealPacketSize) : idealPacketSize; renderViewCommandBuilder->setEntities(entities, i * idealPacketSize, count); } } @@ -134,6 +136,10 @@ public: rv->sort(); } + // TO DO: Record the commandData information with the idea of being to + // reuse it next frame without having to allocate everything again and + // minimizing the uniform updates we need to make + // Enqueue our fully populated RenderView with the RenderThread m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex()); } @@ -223,6 +229,8 @@ private: QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; QVector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs; QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs; + Renderer *m_renderer; + FrameGraphNode *m_leafNode; }; class SyncRenderViewPreCommandUpdate @@ -236,7 +244,7 @@ public: const QVector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs, Renderer *renderer, FrameGraphNode *leafNode, - bool fullCommandRebuild) + RebuildFlagSet rebuildFlags) : m_renderViewJob(renderViewJob) , m_frustumCullingJob(frustumCullingJob) , m_filterProximityJob(filterProximityJob) @@ -245,7 +253,7 @@ public: , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs) , m_renderer(renderer) , m_leafNode(leafNode) - , m_fullRebuild(fullCommandRebuild) + , m_rebuildFlags(rebuildFlags) {} void operator()() @@ -258,16 +266,25 @@ public: ///////// CACHE LOCKED //////////// // Retrieve Data from Cache RendererCache *cache = m_renderer->cache(); - QMutexLocker lock(cache->mutex()); Q_ASSERT(cache->leafNodeCache.contains(m_leafNode)); + // We don't need to protect the cache access as + // 1) The cache leaf is created + // 2) We are only reading conccurently the cache values that are shared across all RV + // 3) Each instance of this job is reading and writing in its own cache leaf so there's + // no conflict + const bool isDraw = !rv->isCompute(); const RendererCache::LeafNodeData &dataCacheForLeaf = cache->leafNodeCache[m_leafNode]; + const bool fullRebuild = m_rebuildFlags.testFlag(RebuildFlag::FullCommandRebuild); + const bool layerFilteringRebuild = m_rebuildFlags.testFlag(RebuildFlag::LayerCacheRebuild); + const bool lightsCacheRebuild = m_rebuildFlags.testFlag(RebuildFlag::LightCacheRebuild); + // Rebuild RenderCommands if required // This should happen fairly infrequently (FrameGraph Change, Geometry/Material change) // and allow to skip that step most of the time - if (m_fullRebuild) { + if (fullRebuild) { EntityRenderCommandData commandData; // Reduction { @@ -279,31 +296,41 @@ public: commandData += std::move(renderViewCommandBuilder->commandData()); } - // Store new cache RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode]; writableCacheForLeaf.renderCommandData = std::move(commandData); } const EntityRenderCommandData commandData = dataCacheForLeaf.renderCommandData; - const QVector<Entity *> filteredEntities = dataCacheForLeaf.filterEntitiesByLayer; - QVector<Entity *> renderableEntities = isDraw ? cache->renderableEntities : cache->computeEntities; - QVector<LightSource> lightSources = cache->gatheredLights; + // Should be fairly infrequent + if (layerFilteringRebuild || fullRebuild) { + RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode]; + + // Filter out renderable entities that weren't selected by the layer filters and store that in cache + writableCacheForLeaf.layeredFilteredRenderables = RenderViewBuilder::entitiesInSubset( + isDraw ? cache->renderableEntities : cache->computeEntities, + dataCacheForLeaf.filterEntitiesByLayer); + } + + if (lightsCacheRebuild) { + // Filter out renderable entities that weren't selected by the + // layer filters and store that in cache + const QVector<Entity *> &layeredFilteredEntities = dataCacheForLeaf.filterEntitiesByLayer; + QVector<LightSource> filteredLightSources = cache->gatheredLights; + for (int i = 0; i < filteredLightSources.count(); ++i) { + if (!layeredFilteredEntities.contains(filteredLightSources[i].entity)) + filteredLightSources.removeAt(i--); + } + RendererCache::LeafNodeData &writableCacheForLeaf = cache->leafNodeCache[m_leafNode]; + writableCacheForLeaf.layeredFilteredLightSources = filteredLightSources; + } + + QVector<Entity *> renderableEntities = dataCacheForLeaf.layeredFilteredRenderables; rv->setMaterialParameterTable(dataCacheForLeaf.materialParameterGatherer); rv->setEnvironmentLight(cache->environmentLight); - lock.unlock(); - ///////// END OF CACHE LOCKED //////////// - - // 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. - for (int i = 0; i < lightSources.count(); ++i) { - if (!filteredEntities.contains(lightSources[i].entity)) - lightSources.removeAt(i--); - } - rv->setLightSources(lightSources); + rv->setLightSources(dataCacheForLeaf.layeredFilteredLightSources); if (isDraw) { // Filter out frustum culled entity for drawable entities @@ -347,15 +374,15 @@ public: ++eIt; } - // Split among the number of command builders + // Split among the number of command updaters const int jobCount = m_renderViewCommandUpdaterJobs.size(); const int idealPacketSize = std::min(std::max(10, filteredCommandData->size() / jobCount), filteredCommandData->size()); const int m = findIdealNumberOfWorkers(filteredCommandData->size(), idealPacketSize, jobCount); for (int i = 0; i < m; ++i) { - const RenderViewCommandUpdaterJobPtr renderViewCommandBuilder = m_renderViewCommandUpdaterJobs.at(i); + const RenderViewCommandUpdaterJobPtr &renderViewCommandUpdater = m_renderViewCommandUpdaterJobs.at(i); const int count = (i == m - 1) ? filteredCommandData->size() - (i * idealPacketSize) : idealPacketSize; - renderViewCommandBuilder->setRenderables(filteredCommandData, i * idealPacketSize, count); + renderViewCommandUpdater->setRenderables(filteredCommandData, i * idealPacketSize, count); } } } @@ -369,7 +396,7 @@ private: QVector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs; Renderer *m_renderer; FrameGraphNode *m_leafNode; - bool m_fullRebuild; + RebuildFlagSet m_rebuildFlags; }; class SetClearDrawBufferIndex @@ -407,11 +434,11 @@ public: void operator()() { - QMutexLocker lock(m_renderer->cache()->mutex()); - // Save the filtered by layer subset into the cache - const QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities(); + Q_ASSERT(m_renderer->cache()->leafNodeCache.contains(m_leafNode)); + // The cache leaf should already have been created so we don't need to protect the access RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; - dataCacheForLeaf.filterEntitiesByLayer = filteredEntities; + // Save the filtered by layer subset into the cache + dataCacheForLeaf.filterEntitiesByLayer = std::move(m_filterEntityByLayerJob->filteredEntities()); } private: @@ -434,7 +461,9 @@ public: void operator()() { - QMutexLocker lock(m_renderer->cache()->mutex()); + // The cache leaf was created by SyncRenderViewPostInitialization on which we depend + // so we don't need to protect the access + RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; dataCacheForLeaf.materialParameterGatherer.clear(); @@ -454,9 +483,6 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende : m_leafNode(leafNode) , m_renderViewIndex(renderViewIndex) , m_renderer(renderer) - , m_layerCacheNeedsToBeRebuilt(false) - , m_materialGathererCacheNeedsToBeRebuilt(false) - , m_renderCommandCacheNeedsToBeRebuilt(false) , m_renderViewJob(RenderViewInitializerJobPtr::create()) , m_filterEntityByLayerJob() , m_frustumCullingJob(new Render::FrustumCullingJob()) @@ -552,7 +578,8 @@ void RenderViewBuilder::prepareJobs() m_filterProximityJob->setManager(m_renderer->nodeManagers()); m_frustumCullingJob->setRoot(m_renderer->sceneRoot()); - if (m_renderCommandCacheNeedsToBeRebuilt) { + const bool commandsNeedRebuild = m_rebuildFlags.testFlag(RebuildFlag::FullCommandRebuild); + if (commandsNeedRebuild) { m_renderViewCommandBuilderJobs.reserve(m_optimalParallelJobCount); for (auto i = 0; i < m_optimalParallelJobCount; ++i) { auto renderViewCommandBuilder = Render::OpenGL::RenderViewCommandBuilderJobPtr::create(); @@ -575,10 +602,12 @@ void RenderViewBuilder::prepareJobs() for (auto i = 0; i < m_optimalParallelJobCount; ++i) { auto renderViewCommandUpdater = Render::OpenGL::RenderViewCommandUpdaterJobPtr::create(); renderViewCommandUpdater->setRenderer(m_renderer); + renderViewCommandUpdater->setRebuildFlags(m_rebuildFlags); m_renderViewCommandUpdaterJobs.push_back(renderViewCommandUpdater); } - if (m_materialGathererCacheNeedsToBeRebuilt) { + const bool materialCacheNeedsRebuild = m_rebuildFlags.testFlag(RebuildFlag::MaterialCacheRebuild); + if (materialCacheNeedsRebuild) { // Since Material gathering is an heavy task, we split it const QVector<HMaterial> materialHandles = m_renderer->nodeManagers()->materialManager()->activeHandles(); if (materialHandles.count()) { @@ -600,7 +629,8 @@ void RenderViewBuilder::prepareJobs() JobTypes::SyncMaterialGatherer); } - if (m_layerCacheNeedsToBeRebuilt) { + const bool layerCacheNeedsRebuild = m_rebuildFlags.testFlag(RebuildFlag::LayerCacheRebuild); + if (layerCacheNeedsRebuild) { m_filterEntityByLayerJob = Render::FilterLayerEntityJobPtr::create(); m_filterEntityByLayerJob->setManager(m_renderer->nodeManagers()); m_syncFilterEntityByLayerJob = CreateSynchronizerJobPtr(SyncFilterEntityByLayer(m_filterEntityByLayerJob, @@ -617,7 +647,7 @@ void RenderViewBuilder::prepareJobs() m_renderViewCommandBuilderJobs, m_renderer, m_leafNode, - m_renderCommandCacheNeedsToBeRebuilt), + m_rebuildFlags), JobTypes::SyncRenderViewPreCommandUpdate); m_syncRenderViewPostCommandUpdateJob = CreateSynchronizerJobPtr(SyncRenderViewPostCommandUpdate(m_renderViewJob, @@ -691,12 +721,16 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const jobs.push_back(m_syncRenderViewPostInitializationJob); // Step 2 - if (m_renderCommandCacheNeedsToBeRebuilt) { // Step 3 + const bool commandsNeedRebuild = m_rebuildFlags.testFlag(RebuildFlag::FullCommandRebuild); + const bool materialCacheNeedsRebuild = m_rebuildFlags.testFlag(RebuildFlag::MaterialCacheRebuild); + const bool layerCacheNeedsRebuild = m_rebuildFlags.testFlag(RebuildFlag::LayerCacheRebuild); + + if (commandsNeedRebuild) { // Step 3 m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->computableEntityFilterJob()); m_syncRenderViewPreCommandBuildingJob->addDependency(m_renderer->renderableEntityFilterJob()); m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncRenderViewPostInitializationJob); - if (m_materialGathererCacheNeedsToBeRebuilt) + if (materialCacheNeedsRebuild) m_syncRenderViewPreCommandBuildingJob->addDependency(m_syncMaterialGathererJob); jobs.push_back(m_syncRenderViewPreCommandBuildingJob); @@ -708,7 +742,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const } } - if (m_layerCacheNeedsToBeRebuilt) { + if (layerCacheNeedsRebuild) { m_filterEntityByLayerJob->addDependency(updateEntityLayersJob); m_filterEntityByLayerJob->addDependency(m_syncRenderViewPostInitializationJob); m_filterEntityByLayerJob->addDependency(updateTreeEnabledJob); @@ -723,7 +757,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const jobs.push_back(m_filterProximityJob); // Step 3 jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3 - if (m_materialGathererCacheNeedsToBeRebuilt) { + if (materialCacheNeedsRebuild) { for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) { materialGatherer->addDependency(m_syncRenderViewPostInitializationJob); materialGatherer->addDependency(m_renderer->introspectShadersJob()); @@ -760,32 +794,42 @@ int RenderViewBuilder::renderViewIndex() const void RenderViewBuilder::setLayerCacheNeedsToBeRebuilt(bool needsToBeRebuilt) { - m_layerCacheNeedsToBeRebuilt = needsToBeRebuilt; + m_rebuildFlags.setFlag(RebuildFlag::LayerCacheRebuild, needsToBeRebuilt); } bool RenderViewBuilder::layerCacheNeedsToBeRebuilt() const { - return m_layerCacheNeedsToBeRebuilt; + return m_rebuildFlags.testFlag(RebuildFlag::LayerCacheRebuild); } void RenderViewBuilder::setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt) { - m_materialGathererCacheNeedsToBeRebuilt = needsToBeRebuilt; + m_rebuildFlags.setFlag(RebuildFlag::MaterialCacheRebuild, needsToBeRebuilt); } bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const { - return m_materialGathererCacheNeedsToBeRebuilt; + return m_rebuildFlags.testFlag(RebuildFlag::MaterialCacheRebuild); } void RenderViewBuilder::setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt) { - m_renderCommandCacheNeedsToBeRebuilt = needsToBeRebuilt; + m_rebuildFlags.setFlag(RebuildFlag::FullCommandRebuild, needsToBeRebuilt); } bool RenderViewBuilder::renderCommandCacheNeedsToBeRebuilt() const { - return m_renderCommandCacheNeedsToBeRebuilt; + return m_rebuildFlags.testFlag(RebuildFlag::FullCommandRebuild); +} + +void RenderViewBuilder::setLightCacheNeedsToBeRebuilt(bool needsToBeRebuilt) +{ + m_rebuildFlags.setFlag(RebuildFlag::LightCacheRebuild, needsToBeRebuilt); +} + +bool RenderViewBuilder::lightCacheNeedsToBeRebuilt() const +{ + return m_rebuildFlags.testFlag(RebuildFlag::LightCacheRebuild); } int RenderViewBuilder::defaultJobCount() diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h index 17e5fa744..98ac126f7 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h @@ -110,6 +110,8 @@ public: bool materialGathererCacheNeedsToBeRebuilt() const; void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt); bool renderCommandCacheNeedsToBeRebuilt() const; + void setLightCacheNeedsToBeRebuilt(bool needsToBeRebuilt); + bool lightCacheNeedsToBeRebuilt() const; static int defaultJobCount(); int optimalJobCount() const; @@ -121,9 +123,7 @@ private: Render::FrameGraphNode *m_leafNode; const int m_renderViewIndex; Renderer *m_renderer; - bool m_layerCacheNeedsToBeRebuilt; - bool m_materialGathererCacheNeedsToBeRebuilt; - bool m_renderCommandCacheNeedsToBeRebuilt; + RebuildFlagSet m_rebuildFlags; RenderViewInitializerJobPtr m_renderViewJob; FilterLayerEntityJobPtr m_filterEntityByLayerJob; |