diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2016-09-06 16:36:08 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2016-11-25 16:29:10 +0000 |
commit | d07496129a108a54345174b7651d1989cb9f157f (patch) | |
tree | 92bf79735135913abf256285d5f3b621965e5dd6 /src/render/framegraph/framegraphvisitor.cpp | |
parent | ca3303ecb77b2d09729dbc70502c97503a6673ea (diff) |
FrameGraphVisitor: use RenderViewBuilder
Change-Id: Iff44ed6c22af1cd2b1f9cc3e4aabf3ebeb149f4d
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/framegraph/framegraphvisitor.cpp')
-rw-r--r-- | src/render/framegraph/framegraphvisitor.cpp | 288 |
1 files changed, 3 insertions, 285 deletions
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp index 97f3194b2..d31e9cddd 100644 --- a/src/render/framegraph/framegraphvisitor.cpp +++ b/src/render/framegraph/framegraphvisitor.cpp @@ -43,15 +43,7 @@ #include "framegraphnode_p.h" #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/managers_p.h> -#include <Qt3DRender/private/filterentitybycomponentjob_p.h> -#include <Qt3DRender/private/filterlayerentityjob_p.h> -#include <Qt3DRender/private/genericlambdajob_p.h> -#include <Qt3DRender/private/materialparametergathererjob_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DRender/private/renderviewbuilderjob_p.h> -#include <Qt3DRender/private/renderview_p.h> -#include <Qt3DRender/private/frustumcullingjob_p.h> -#include <Qt3DRender/private/lightgatherer_p.h> +#include <Qt3DRender/private/renderviewbuilder_p.h> #include <QThreadPool> QT_BEGIN_NAMESPACE @@ -106,282 +98,8 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) // TODO: Pass in only framegraph config that has changed from previous // index RenderViewJob. if (fgChildIds.empty()) { - // 1) Prepare parameter pack for all possible Pass Filter / Technique Filter - // At most 1 of each per RenderView -> not very frequent -> doesn't need to be in a job - - // 1) Update all the ShaderData - - // 1) RenderView initialization from - // 2) One job to filter out the Entities in a layers (no dependency) - // 2) -> One job to filter out only the Entities with a QDispatchCompute - // 2) -> One job to filter out only the Entities with a GeometryRenderer - // 2) -> n job to create all ParameterInfoList for each Material - // 2) -> One job to perform frustrum culling of layered filtered entities - - // -> 3) Merge Parameter pack 1 / 2 + Material - // -> 4) n job to prepare the commands - // -> One job to sort the RenderCommands - // -> One job to set the active uniforms / build the ParameterPack - - // GenericLambdaJob will be used to sync data between jobs and their dependencies - // Prefer linear iteration over tree traversal - - const int currentRenderViewIndex = m_renderviewIndex++; - const int optimalParallelJobCount = std::max(QThread::idealThreadCount(), 2); - auto renderViewJob = RenderViewInitializerJobPtr::create(); - auto filterEntityByLayer = Render::FilterLayerEntityJobPtr::create(); - auto lightGatherer = Render::LightGathererPtr::create(); - auto renderableEntityFilterer = Render::FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>::create(); - - // Note: do it only if OpenGL 4.3+ available - auto computeEntityFilterer = Render::FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>::create(); - - auto frustumCulling = Render::FrustumCullingJobPtr::create(); - - // Copy for lambda capture - Renderer *renderer = m_renderer; - - // Init what we can here - EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager(); - filterEntityByLayer->setManager(m_renderer->nodeManagers()); - renderableEntityFilterer->setManager(entityManager); - computeEntityFilterer->setManager(entityManager); - frustumCulling->setRoot(m_renderer->sceneRoot()); - lightGatherer->setManager(entityManager); - renderViewJob->setRenderer(m_renderer); - renderViewJob->setFrameGraphLeafNode(node); - renderViewJob->setSubmitOrderIndex(currentRenderViewIndex); - - // RenderCommand building is the most consuming task -> split it - QVector<Render::RenderViewBuilderJobPtr> renderViewCommandBuilders; - // Estimate the number of jobs to create based on the number of entities - renderViewCommandBuilders.reserve(optimalParallelJobCount); - for (auto i = 0; i < optimalParallelJobCount; ++i) { - auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create(); - renderViewCommandBuilder->setIndex(currentRenderViewIndex); - renderViewCommandBuilder->setRenderer(m_renderer); - renderViewCommandBuilders.push_back(renderViewCommandBuilder); - } - - // Since Material gathering is an heavy task, we split it - QVector<Render::MaterialParameterGathererJobPtr> materialGatherers; - { // Scoped to avoid copy in lambdas - const QVector<HMaterial> materialHandles = m_renderer->nodeManagers()->materialManager()->activeHandles(); - const int elementsPerJob = materialHandles.size() / optimalParallelJobCount; - const int lastRemaingElements = materialHandles.size() % optimalParallelJobCount; - materialGatherers.reserve(optimalParallelJobCount); - for (auto i = 0; i < optimalParallelJobCount; ++i) { - auto materialGatherer = Render::MaterialParameterGathererJobPtr::create(); - materialGatherer->setNodeManagers(m_renderer->nodeManagers()); - materialGatherer->setRenderer(m_renderer); - if (i == optimalParallelJobCount - 1) - materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob + lastRemaingElements)); - else - materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob)); - materialGatherers.push_back(materialGatherer); - } - } - - // Copy shared ptr -> this is called once the FrameGraphBranch was used to fill initial data in the RenderView - auto syncRenderViewInitialization = [=] () { - RenderView *rv = renderViewJob->renderView(); - - // Layer filtering - filterEntityByLayer->setHasLayerFilter(rv->hasLayerFilter()); - filterEntityByLayer->setLayers(rv->layerFilter()); - - // Material Parameter building - for (const auto materialGatherer : qAsConst(materialGatherers)) { - materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter())); - materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter())); - } - - // Command builders - for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) - renderViewCommandBuilder->setRenderView(rv); - - // Set whether frustum culling is enabled or not - frustumCulling->setActive(rv->frustumCulling()); - }; - - // Copy shared ptr -> this is called once the FrameGraphBranch was used to fill initial data in the RenderView - auto syncFrustumCulling = [=] () { - RenderView *rv = renderViewJob->renderView(); - - // Update matrices now that all transforms have been updated - rv->updateMatrices(); - - // Frustum culling - frustumCulling->setViewProjection(rv->viewProjectionMatrix()); - }; - - // Copy shared ptr -> this is called after filtering / culling / parameter setting has been performed - auto syncForRenderCommandBuilding = [=] () { - // Set the result of previous job computations - // for final RenderCommand building - RenderView *rv = renderViewJob->renderView(); - - if (!rv->noDraw()) { - // Set the light sources - rv->setLightSources(std::move(lightGatherer->lights())); - - // Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector - QVector<Entity *> filteredEntities = filterEntityByLayer->filteredEntities(); - - // We sort the vector so that the removal can then be performed linearly - if (!rv->isCompute()) { - QVector<Entity *> renderableEntities = std::move(renderableEntityFilterer->filteredEntities()); - std::sort(renderableEntities.begin(), renderableEntities.end()); - std::sort(filteredEntities.begin(), filteredEntities.end()); - - for (auto i = renderableEntities.size() - 1, j = filteredEntities.size() - 1; i >= 0; --i) { - while (j >= 0 && filteredEntities.at(j) > renderableEntities.at(i)) - --j; - if (j < 0 || renderableEntities.at(i) != filteredEntities.at(j)) - renderableEntities.removeAt(i); - } - - if (rv->frustumCulling()) { - QVector<Entity *> visibleEntities = frustumCulling->visibleEntities(); - std::sort(visibleEntities.begin(), visibleEntities.end()); - - for (auto i = renderableEntities.size() - 1, j = visibleEntities.size() - 1; i >= 0; --i) { - while (j >= 0 && visibleEntities.at(j) > renderableEntities.at(i)) - --j; - if (j < 0 || renderableEntities.at(i) != visibleEntities.at(j)) - renderableEntities.removeAt(i); - } - } - // Split among the number of command builders - const int packetSize = renderableEntities.size() / optimalParallelJobCount; - for (auto i = 0; i < optimalParallelJobCount; ++i) { - const RenderViewBuilderJobPtr renderViewCommandBuilder = renderViewCommandBuilders.at(i); - if (i == optimalParallelJobCount - 1) - renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % optimalParallelJobCount)); - else - renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize)); - } - - } else { - QVector<Entity *> computableEntities = std::move(computeEntityFilterer->filteredEntities()); - std::sort(computableEntities.begin(), computableEntities.end()); - - for (auto i = computableEntities.size() - 1, j = filteredEntities.size() - 1; i >= 0; --i) { - while (j >= 0 && filteredEntities.at(j) > computableEntities.at(i)) - --j; - if (j < 0 || computableEntities.at(i) != filteredEntities.at(j)) - computableEntities.removeAt(i); - } - - // Split among the number of command builders - const int packetSize = computableEntities.size() / optimalParallelJobCount; - for (auto i = 0; i < optimalParallelJobCount; ++i) { - const RenderViewBuilderJobPtr renderViewCommandBuilder = renderViewCommandBuilders.at(i); - if (i == optimalParallelJobCount - 1) - renderViewCommandBuilder->setRenderables(computableEntities.mid(i * packetSize, packetSize + computableEntities.size() % optimalParallelJobCount)); - else - renderViewCommandBuilder->setRenderables(computableEntities.mid(i * packetSize, packetSize)); - } - } - - // Reduction - QHash<Qt3DCore::QNodeId, QVector<RenderPassParameterData>> params; - for (const auto materialGatherer : qAsConst(materialGatherers)) - params.unite(materialGatherer->materialToPassAndParameter()); - // Set all required data on the RenderView for final processing - rv->setMaterialParameterTable(std::move(params)); - } - }; - - // Called after each RenderViewBuilder has built its RenderCommands - auto syncRenderViewCommandBuilders = [=] () { - // Append all the commands and sort them - RenderView *rv = renderViewJob->renderView(); - - int totalCommandCount = 0; - for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) - totalCommandCount += renderViewCommandBuilder->commands().size(); - - QVector<RenderCommand *> commands; - commands.reserve(totalCommandCount); - - // Reduction - for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) - commands += std::move(renderViewCommandBuilder->commands()); - rv->setCommands(commands); - - // Sort the commands - rv->sort(); - - // Enqueue our fully populated RenderView with the RenderThread - renderer->enqueueRenderView(rv, currentRenderViewIndex); - }; - - auto setClearBufferDrawIndex = [=] () { - RenderView *rv = renderViewJob->renderView(); - QVector<ClearBufferInfo> &clearBuffersInfo = rv->specificClearColorBufferInfo(); - const AttachmentPack &attachmentPack = rv->attachmentPack(); - for (ClearBufferInfo &clearBufferInfo : clearBuffersInfo) - clearBufferInfo.drawBufferIndex = attachmentPack.getDrawBufferIndex(clearBufferInfo.attchmentPoint); - }; - - auto syncRenderViewCommandBuildingJob = GenericLambdaJobPtr<decltype(syncForRenderCommandBuilding)>::create(syncForRenderCommandBuilding, JobTypes::SyncRenderViewCommandBuilding); - auto syncRenderViewInitializationJob = GenericLambdaJobPtr<decltype(syncRenderViewInitialization)>::create(syncRenderViewInitialization, JobTypes::SyncRenderViewInitialization); - auto syncRenderViewCommandBuildersJob = GenericLambdaJobPtr<decltype(syncRenderViewCommandBuilders)>::create(syncRenderViewCommandBuilders, JobTypes::SyncRenderViewCommandBuilder); - auto syncFrustumCullingJob = GenericLambdaJobPtr<decltype(syncFrustumCulling)>::create(syncFrustumCulling, JobTypes::SyncFrustumCulling); - auto setClearBufferDrawIndexJob = GenericLambdaJobPtr<decltype(setClearBufferDrawIndex)>::create(setClearBufferDrawIndex, JobTypes::ClearBufferDrawIndex); - - // Set dependencies - syncFrustumCullingJob->addDependency(renderer->updateWorldTransformJob()); - syncFrustumCullingJob->addDependency(renderer->updateShaderDataTransformJob()); - syncFrustumCullingJob->addDependency(syncRenderViewInitializationJob); - - frustumCulling->addDependency(renderer->expandBoundingVolumeJob()); - frustumCulling->addDependency(syncFrustumCullingJob); - - setClearBufferDrawIndexJob->addDependency(syncRenderViewInitializationJob); - - syncRenderViewInitializationJob->addDependency(renderViewJob); - - filterEntityByLayer->addDependency(syncRenderViewInitializationJob); - - syncRenderViewCommandBuildingJob->addDependency(syncRenderViewInitializationJob); - for (const auto materialGatherer : qAsConst(materialGatherers)) { - materialGatherer->addDependency(syncRenderViewInitializationJob); - syncRenderViewCommandBuildingJob->addDependency(materialGatherer); - } - syncRenderViewCommandBuildingJob->addDependency(renderableEntityFilterer); - syncRenderViewCommandBuildingJob->addDependency(computeEntityFilterer); - syncRenderViewCommandBuildingJob->addDependency(filterEntityByLayer); - syncRenderViewCommandBuildingJob->addDependency(lightGatherer); - syncRenderViewCommandBuildingJob->addDependency(frustumCulling); - - for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) { - renderViewCommandBuilder->addDependency(syncRenderViewCommandBuildingJob); - syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder); - } - renderer->frameCleanupJob()->addDependency(syncRenderViewCommandBuildersJob); - renderer->frameCleanupJob()->addDependency(setClearBufferDrawIndexJob); - - // Add jobs - m_jobs->push_back(renderViewJob); - m_jobs->push_back(filterEntityByLayer); - m_jobs->push_back(renderableEntityFilterer); - m_jobs->push_back(computeEntityFilterer); - m_jobs->push_back(syncRenderViewInitializationJob); - m_jobs->push_back(syncRenderViewCommandBuildingJob); - m_jobs->push_back(frustumCulling); - m_jobs->push_back(lightGatherer); - m_jobs->push_back(syncRenderViewCommandBuildersJob); - m_jobs->push_back(syncFrustumCullingJob); - m_jobs->push_back(setClearBufferDrawIndexJob); - - for (const auto materialGatherer : qAsConst(materialGatherers)) - m_jobs->push_back(materialGatherer); - - for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) - m_jobs->push_back(renderViewCommandBuilder); - + RenderViewBuilder builder(node, m_renderviewIndex++, m_renderer); + m_jobs->append(builder.buildJobHierachy()); } } |