summaryrefslogtreecommitdiffstats
path: root/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp')
-rw-r--r--src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp466
1 files changed, 1 insertions, 465 deletions
diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
index 26ad8f0ec..6ba85db9e 100644
--- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
+++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp
@@ -39,6 +39,7 @@
#include "renderviewbuilder_p.h"
#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DRender/private/rendersyncjobs_p.h>
#include <QThread>
@@ -49,398 +50,8 @@ namespace Qt3DRender {
namespace Render {
namespace OpenGL {
-using RendererCache = Render::RendererCache<RenderCommand>;
-
namespace {
-int findIdealNumberOfWorkers(int elementCount, int packetSize = 100, int maxJobCount = 1)
-{
- if (elementCount == 0 || packetSize == 0)
- return 0;
- return std::min(std::max(elementCount / packetSize, 1), maxJobCount);
-}
-
-
-class SyncPreCommandBuilding
-{
-public:
- explicit SyncPreCommandBuilding(RenderViewInitializerJobPtr renderViewInitializerJob,
- const std::vector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_renderViewInitializer(renderViewInitializerJob)
- , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- // Split commands to build among jobs
-
- // Rebuild RenderCommands for all entities in RV (ignoring filtering)
- RendererCache *cache = m_renderer->cache();
- QMutexLocker lock(cache->mutex());
-
- 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);
-
- // Split among the ideal number of command builders
- const int jobCount = m_renderViewCommandBuilderJobs.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(entityCount, idealPacketSize, jobCount);
-
- const Entity **entitiesPtr = const_cast<const Entity **>(entities.data());
- for (int i = 0; i < m; ++i) {
- const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i);
- const int count = (i == m - 1) ? entityCount - (i * idealPacketSize) : idealPacketSize;
- renderViewCommandBuilder->setEntities(entitiesPtr, i * idealPacketSize, count);
- }
- }
-
-private:
- RenderViewInitializerJobPtr m_renderViewInitializer;
- std::vector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncRenderViewPostCommandUpdate
-{
-public:
- explicit SyncRenderViewPostCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
- const std::vector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdateJobs,
- Renderer *renderer)
- : m_renderViewJob(renderViewJob)
- , m_renderViewCommandUpdaterJobs(renderViewCommandUpdateJobs)
- , m_renderer(renderer)
- {
- }
-
- void operator()()
- {
- // Append all the commands and sort them
- RenderView *rv = m_renderViewJob->renderView();
-
- if (!rv->noDraw()) {
- // Sort command on RenderView
- rv->sort();
- }
- // Enqueue our fully populated RenderView with the RenderThread
- m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex());
- }
-
-private:
- RenderViewInitializerJobPtr m_renderViewJob;
- std::vector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
- Renderer *m_renderer;
-};
-
-class SyncPreFrustumCulling
-{
-public:
- explicit SyncPreFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCulling)
- : m_renderViewJob(renderViewJob)
- , m_frustumCullingJob(frustumCulling)
- {}
-
- void operator()()
- {
- RenderView *rv = m_renderViewJob->renderView();
-
- // Update matrices now that all transforms have been updated
- rv->updateMatrices();
-
- // Frustum culling
- m_frustumCullingJob->setViewProjection(rv->viewProjectionMatrix());
- }
-
-private:
- RenderViewInitializerJobPtr m_renderViewJob;
- FrustumCullingJobPtr m_frustumCullingJob;
-};
-
-class SyncRenderViewPostInitialization
-{
-public:
- explicit SyncRenderViewPostInitialization(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterLayerEntityJobPtr &filterEntityByLayerJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const std::vector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const std::vector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
- const std::vector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs)
- : m_renderViewJob(renderViewJob)
- , m_frustumCullingJob(frustumCullingJob)
- , m_filterEntityByLayerJob(filterEntityByLayerJob)
- , m_filterProximityJob(filterProximityJob)
- , m_materialGathererJobs(materialGathererJobs)
- , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
- , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
- {}
-
- void operator()()
- {
- RenderView *rv = m_renderViewJob->renderView();
-
- // Layer filtering
- if (!m_filterEntityByLayerJob.isNull())
- m_filterEntityByLayerJob->setLayerFilters(rv->layerFilters());
-
- // Proximity filtering
- m_filterProximityJob->setProximityFilterIds(rv->proximityFilterIds());
-
- // Material Parameter building
- for (const auto &materialGatherer : m_materialGathererJobs) {
- materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter()));
- materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter()));
- }
-
- // Command builders and updates
- for (const auto &renderViewCommandUpdater : m_renderViewCommandUpdaterJobs)
- renderViewCommandUpdater->setRenderView(rv);
- for (const auto &renderViewCommandBuilder : m_renderViewCommandBuilderJobs)
- renderViewCommandBuilder->setRenderView(rv);
-
- // Set whether frustum culling is enabled or not
- m_frustumCullingJob->setActive(rv->frustumCulling());
- }
-
-private:
- RenderViewInitializerJobPtr m_renderViewJob;
- FrustumCullingJobPtr m_frustumCullingJob;
- FilterLayerEntityJobPtr m_filterEntityByLayerJob;
- FilterProximityDistanceJobPtr m_filterProximityJob;
- std::vector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- std::vector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
- std::vector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
-};
-
-class SyncRenderViewPreCommandUpdate
-{
-public:
- explicit SyncRenderViewPreCommandUpdate(const RenderViewInitializerJobPtr &renderViewJob,
- const FrustumCullingJobPtr &frustumCullingJob,
- const FilterProximityDistanceJobPtr &filterProximityJob,
- const std::vector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const std::vector<RenderViewCommandUpdaterJobPtr> &renderViewCommandUpdaterJobs,
- const std::vector<RenderViewCommandBuilderJobPtr> &renderViewCommandBuilderJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode,
- RebuildFlagSet rebuildFlags)
- : m_renderViewJob(renderViewJob)
- , m_frustumCullingJob(frustumCullingJob)
- , m_filterProximityJob(filterProximityJob)
- , m_materialGathererJobs(materialGathererJobs)
- , m_renderViewCommandUpdaterJobs(renderViewCommandUpdaterJobs)
- , m_renderViewCommandBuilderJobs(renderViewCommandBuilderJobs)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- , m_rebuildFlags(rebuildFlags)
- {}
-
- void operator()()
- {
- // Set the result of previous job computations
- // for final RenderCommand building
- RenderView *rv = m_renderViewJob->renderView();
-
- if (!rv->noDraw()) {
- ///////// 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();
- RendererCache::LeafNodeData &cacheForLeaf = 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);
- const bool cameraDirty = cacheForLeaf.viewProjectionMatrix != rv->viewProjectionMatrix();
- const bool hasProximityFilter = !rv->proximityFilterIds().empty();
- const bool commandFilteringRequired =
- fullRebuild ||
- layerFilteringRebuild ||
- lightsCacheRebuild ||
- cameraDirty ||
- hasProximityFilter;
-
- // If we have no filteredRenderCommandDataViews then we should have fullRebuild set to true
- // otherwise something is wrong
- Q_ASSERT(fullRebuild || cacheForLeaf.filteredRenderCommandDataViews);
-
- // 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 (fullRebuild) {
- EntityRenderCommandData commandData;
- // Reduction
- {
- int totalCommandCount = 0;
- for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
- totalCommandCount += renderViewCommandBuilder->commandData().size();
- commandData.reserve(totalCommandCount);
- for (const RenderViewCommandBuilderJobPtr &renderViewCommandBuilder : qAsConst(m_renderViewCommandBuilderJobs))
- commandData += std::move(renderViewCommandBuilder->commandData());
- }
-
- // Store new cache
- EntityRenderCommandDataViewPtr dataView = EntityRenderCommandDataViewPtr::create();
- dataView->data = std::move(commandData);
- // Store the update dataView
- cacheForLeaf.filteredRenderCommandDataViews = dataView;
- }
-
-
- // Should be fairly infrequent
- if (layerFilteringRebuild || fullRebuild) {
- // Filter out renderable entities that weren't selected by the layer filters and store that in cache
- cacheForLeaf.layeredFilteredRenderables = RenderViewBuilder::entitiesInSubset(
- isDraw ? cache->renderableEntities : cache->computeEntities,
- cacheForLeaf.filterEntitiesByLayer);
- // Set default value for filteredAndCulledRenderables
- if (isDraw)
- cacheForLeaf.filteredAndCulledRenderables = cacheForLeaf.layeredFilteredRenderables;
- }
-
- // Should be fairly infrequent
- if (lightsCacheRebuild) {
- // Filter out light sources that weren't selected by the
- // layer filters and store that in cache
- const std::vector<Entity *> &layeredFilteredEntities = cacheForLeaf.filterEntitiesByLayer;
- std::vector<LightSource> filteredLightSources = cache->gatheredLights;
-
- auto it = filteredLightSources.begin();
-
- while (it != filteredLightSources.end()) {
- if (!std::binary_search(layeredFilteredEntities.begin(),
- layeredFilteredEntities.end(),
- it->entity))
- it = filteredLightSources.erase(it);
- else
- ++it;
- }
- cacheForLeaf.layeredFilteredLightSources = std::move(filteredLightSources);
- }
-
- // This is likely very frequent
- if (cameraDirty) {
- // Record the updated viewProjectionMatrix in the cache to allow check to be performed
- // next frame
- cacheForLeaf.viewProjectionMatrix = rv->viewProjectionMatrix();
- }
-
- // Filter out frustum culled entity for drawable entities and store in cache
- // We need to check this regardless of whether the camera has moved since
- // entities in the scene themselves could have moved
- if (isDraw && rv->frustumCulling()) {
- cacheForLeaf.filteredAndCulledRenderables = RenderViewBuilder::entitiesInSubset(
- cacheForLeaf.layeredFilteredRenderables,
- m_frustumCullingJob->visibleEntities());
- }
-
- rv->setMaterialParameterTable(cacheForLeaf.materialParameterGatherer);
- rv->setEnvironmentLight(cache->environmentLight);
-
- // Set the light sources, with layer filters applied.
- rv->setLightSources(cacheForLeaf.layeredFilteredLightSources);
-
- std::vector<Entity *> renderableEntities = isDraw ? cacheForLeaf.filteredAndCulledRenderables : cacheForLeaf.layeredFilteredRenderables;
-
- // TO DO: Find a way to do that only if proximity entities has changed
- if (isDraw) {
- // Filter out entities which didn't satisfy proximity filtering
- if (hasProximityFilter)
- renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities,
- m_filterProximityJob->filteredEntities());
- }
-
- EntityRenderCommandDataViewPtr filteredCommandData = cacheForLeaf.filteredRenderCommandDataViews;
-
- // Set RenderCommandDataView on RV (will be used later on to sort commands ...)
- rv->setRenderCommandDataView(filteredCommandData);
-
- // Filter out Render commands for which the Entity wasn't selected because
- // of frustum, proximity or layer filtering
- if (commandFilteringRequired) {
- const std::vector<const Entity *> &entities = filteredCommandData->data.entities;
- // Because cacheForLeaf.renderableEntities or computeEntities are sorted
- // What we get out of EntityRenderCommandData is also sorted by Entity
- auto eIt = renderableEntities.cbegin();
- const auto eEnd = renderableEntities.cend();
- size_t cIt = 0;
- const size_t cEnd = entities.size();
-
- std::vector<size_t> filteredCommandIndices;
- filteredCommandIndices.reserve(renderableEntities.size());
-
- while (eIt != eEnd) {
- const Entity *targetEntity = *eIt;
- // Advance until we have commands whose Entity has a lower address
- // than the selected filtered entity
- while (cIt != cEnd && entities[cIt] < targetEntity)
- ++cIt;
-
- // Push pointers to command data for all commands that match the
- // entity
- while (cIt != cEnd && entities[cIt] == targetEntity) {
- filteredCommandIndices.push_back(cIt);
- ++cIt;
- }
- ++eIt;
- }
-
- // Store result in cache
- cacheForLeaf.filteredRenderCommandDataViews->indices = std::move(filteredCommandIndices);
- }
-
- // Split among the number of command updaters
- const int jobCount = m_renderViewCommandUpdaterJobs.size();
- const int commandCount = filteredCommandData->size();
- const int idealPacketSize = std::min(std::max(10, commandCount), commandCount);
- const int m = findIdealNumberOfWorkers(commandCount, idealPacketSize, jobCount);
-
- for (int i = 0; i < m; ++i) {
- // TO DO: Based on whether we had to update the commands
- // we should be able to know what needs to be recomputed
- // -> lights/standard uniforms ... might no have to be set over and over again
- // if they are identical
- const RenderViewCommandUpdaterJobPtr &renderViewCommandUpdater = m_renderViewCommandUpdaterJobs.at(i);
- const size_t count = (i == m - 1) ? commandCount - (i * idealPacketSize) : idealPacketSize;
- renderViewCommandUpdater->setRenderablesSubView({filteredCommandData, size_t(i * idealPacketSize), count});
- }
- }
- }
-
-private:
- RenderViewInitializerJobPtr m_renderViewJob;
- FrustumCullingJobPtr m_frustumCullingJob;
- FilterProximityDistanceJobPtr m_filterProximityJob;
- std::vector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
- std::vector<RenderViewCommandUpdaterJobPtr> m_renderViewCommandUpdaterJobs;
- std::vector<RenderViewCommandBuilderJobPtr> m_renderViewCommandBuilderJobs;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
- RebuildFlagSet m_rebuildFlags;
-};
-
class SetClearDrawBufferIndex
{
public:
@@ -462,69 +73,6 @@ private:
RenderViewInitializerJobPtr m_renderViewJob;
};
-class SyncFilterEntityByLayer
-{
-public:
- explicit SyncFilterEntityByLayer(const FilterLayerEntityJobPtr &filterEntityByLayerJob,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_filterEntityByLayerJob(filterEntityByLayerJob)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- QMutexLocker lock(m_renderer->cache()->mutex());
- 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];
- // Save the filtered by layer subset into the cache
- dataCacheForLeaf.filterEntitiesByLayer = std::move(m_filterEntityByLayerJob->filteredEntities());
- }
-
-private:
- FilterLayerEntityJobPtr m_filterEntityByLayerJob;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
-class SyncMaterialParameterGatherer
-{
-public:
- explicit SyncMaterialParameterGatherer(const std::vector<MaterialParameterGathererJobPtr> &materialParameterGathererJobs,
- Renderer *renderer,
- FrameGraphNode *leafNode)
- : m_materialParameterGathererJobs(materialParameterGathererJobs)
- , m_renderer(renderer)
- , m_leafNode(leafNode)
- {
- }
-
- void operator()()
- {
- // The cache leaf was created by SyncRenderViewPostInitialization on which we depend
- // so we don't need to protect the access
- QMutexLocker lock(m_renderer->cache()->mutex());
- RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
- dataCacheForLeaf.materialParameterGatherer.clear();
-
- for (const auto &materialGatherer : m_materialParameterGathererJobs) {
- const MaterialParameterGathererData &source = materialGatherer->materialToPassAndParameter();
- for (auto it = std::begin(source); it != std::end(source); ++it) {
- Q_ASSERT(!dataCacheForLeaf.materialParameterGatherer.contains(it.key()));
- dataCacheForLeaf.materialParameterGatherer.insert(it.key(), it.value());
- }
- }
- }
-
-private:
- std::vector<MaterialParameterGathererJobPtr> m_materialParameterGathererJobs;
- Renderer *m_renderer;
- FrameGraphNode *m_leafNode;
-};
-
} // anonymous
RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer)
@@ -917,18 +465,6 @@ void RenderViewBuilder::setOptimalJobCount(int v)
m_optimalParallelJobCount = v;
}
-std::vector<Entity *> RenderViewBuilder::entitiesInSubset(const std::vector<Entity *> &entities,
- const std::vector<Entity *> &subset)
-{
- std::vector<Entity *> intersection;
- intersection.reserve(qMin(entities.size(), subset.size()));
- std::set_intersection(entities.begin(), entities.end(),
- subset.begin(), subset.end(),
- std::back_inserter(intersection));
-
- return intersection;
-}
-
} // OpenGL
} // Render