diff options
author | Paul Lemire <paul.lemire350@gmail.com> | 2016-05-18 21:35:41 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-07-03 08:54:42 +0000 |
commit | 29b20eabafa6103132a82243e8b07d14fa3f4726 (patch) | |
tree | 5f8f618eafdf96577ff842dbd339b4a92fb3568d /src/render/framegraph/framegraphvisitor.cpp | |
parent | b42505ce7961aa03aeaedf30f9ad1043b8e95b9b (diff) |
Split RenderCommand building into more jobs
Leads a 200% gain on bigscene with 12 threads.
Change-Id: If6ba7b875fb7a8fa2b81e89fb8ad8d08a11ee683
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/framegraph/framegraphvisitor.cpp')
-rw-r--r-- | src/render/framegraph/framegraphvisitor.cpp | 73 |
1 files changed, 65 insertions, 8 deletions
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp index 5d357c7f6..e102fbed8 100644 --- a/src/render/framegraph/framegraphvisitor.cpp +++ b/src/render/framegraph/framegraphvisitor.cpp @@ -144,14 +144,24 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) computeEntityFilterer->setManager(entityManager); frustumCulling->setRoot(m_renderer->sceneRoot()); lightGatherer->setManager(entityManager); - renderViewCommandBuilder->setIndex(currentRenderViewIndex); - renderViewCommandBuilder->setRenderer(m_renderer); + + // RenderCommand building is the most consuming task -> split it + QVector<Render::RenderViewBuilderJobPtr> renderViewCommandBuilders; + const int commandBuilderCount = std::max(entityManager->count() / 32, 1); + // Estimate the number of jobs to create based on the number of entities + + for (auto i = 0; i < commandBuilderCount; ++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 materialGathererCount = std::max(materialHandles.size() / 8, 1); + const int materialGathererCount = materialHandles.size() / 8 + 1; materialGatherers.reserve(materialGathererCount); for (auto i = 0; i < materialGathererCount; ++i) { auto materialGatherer = Render::MaterialParameterGathererJobPtr::create(); @@ -178,6 +188,10 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) // Frustum culling frustumCulling->setViewProjection(rv->viewProjectionMatrix()); + + // Command builders + for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) + renderViewCommandBuilder->setRenderView(rv); }; // Copy shared ptr -> this is called after filtering / culling / parameter setting has been performed @@ -210,15 +224,31 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) renderableEntities.removeAt(i); } } + // Split among the number of command builders + const int packetSize = renderableEntities.size() / commandBuilderCount; + for (auto i = 0; i < commandBuilderCount; ++i) { + const RenderViewBuilderJobPtr renderViewCommandBuilder = renderViewCommandBuilders.at(i); + if (i == commandBuilderCount - 1) + renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % commandBuilderCount)); + else + renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize)); + } - rv->setRenderables(std::move(renderableEntities)); } else { QVector<Entity *> computableEntities = computeEntityFilterer->filteredEntities(); for (auto i = computableEntities.size() - 1; i >= 0; --i) { if (!filteredEntities.contains(computableEntities.at(i))) computableEntities.removeAt(i); } - rv->setComputables(std::move(computableEntities)); + // Split among the number of command builders + const int packetSize = computableEntities.size() / commandBuilderCount; + for (auto i = 0; i < commandBuilderCount; ++i) { + const RenderViewBuilderJobPtr renderViewCommandBuilder = renderViewCommandBuilders.at(i); + if (i == commandBuilderCount - 1) + renderViewCommandBuilder->setRenderables(computableEntities.mid(i * packetSize, packetSize + computableEntities.size() % commandBuilderCount)); + else + renderViewCommandBuilder->setRenderables(computableEntities.mid(i * packetSize, packetSize)); + } } // Reduction @@ -228,11 +258,30 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) // Set all required data on the RenderView for final processing rv->setMaterialParameterTable(std::move(params)); } - renderViewCommandBuilder->setRenderView(renderViewJob->renderView()); + }; + + Renderer *renderer = m_renderer; + // Called after each RenderViewBuilder has built its RenderCommands + auto syncRenderViewCommandBuilders = [=] () { + // Append all the commands and sort them + RenderView *rv = renderViewJob->renderView(); + + QVector<RenderCommand *> commands; + // 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 syncRenderViewCommandBuildingJob = GenericLambdaJobPtr<decltype(syncForRenderCommandBuilding)>::create(syncForRenderCommandBuilding); auto syncRenderViewInitializationJob = GenericLambdaJobPtr<decltype(syncRenderViewInitialization)>::create(syncRenderViewInitialization); + auto syncRenderViewCommandBuildersJob = GenericLambdaJobPtr<decltype(syncRenderViewCommandBuilders)>::create(syncRenderViewCommandBuilders); // Set dependencies syncRenderViewInitializationJob->addDependency(renderViewJob); @@ -250,7 +299,10 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) syncRenderViewCommandBuildingJob->addDependency(filterEntityByLayer); syncRenderViewCommandBuildingJob->addDependency(lightGatherer); - renderViewCommandBuilder->addDependency(syncRenderViewCommandBuildingJob); + for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) { + renderViewCommandBuilder->addDependency(syncRenderViewCommandBuildingJob); + syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder); + } // Add jobs m_jobs->push_back(renderViewJob); @@ -259,11 +311,16 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) m_jobs->push_back(computeEntityFilterer); m_jobs->push_back(syncRenderViewInitializationJob); m_jobs->push_back(syncRenderViewCommandBuildingJob); - m_jobs->push_back(renderViewCommandBuilder); m_jobs->push_back(frustumCulling); m_jobs->push_back(lightGatherer); + m_jobs->push_back(syncRenderViewCommandBuildersJob); + for (const auto materialGatherer : qAsConst(materialGatherers)) m_jobs->push_back(materialGatherer); + + for (const auto renderViewCommandBuilder : qAsConst(renderViewCommandBuilders)) + m_jobs->push_back(renderViewCommandBuilder); + } } |