diff options
author | Paul Lemire <paul.lemire350@gmail.com> | 2016-05-16 13:44:43 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-07-03 08:54:20 +0000 |
commit | b246d17fb3e45848ddbfd581d7cb87b9575f7e86 (patch) | |
tree | a644489ff9ca0dfba9edac1af302c1d0d1dff1ad /src/render/framegraph/framegraphvisitor.cpp | |
parent | 4d94fa74e3422766f8e84e2192d731310b87bd95 (diff) |
Split RenderViewJobs
Change-Id: I6c4f8970b14e39085480c029b8acdfcdbfc6fa8d
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/framegraph/framegraphvisitor.cpp')
-rw-r--r-- | src/render/framegraph/framegraphvisitor.cpp | 142 |
1 files changed, 140 insertions, 2 deletions
diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp index 78f6272d8..c43a32e3f 100644 --- a/src/render/framegraph/framegraphvisitor.cpp +++ b/src/render/framegraph/framegraphvisitor.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2016 Paul Lemire ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -42,6 +43,14 @@ #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> QT_BEGIN_NAMESPACE @@ -95,8 +104,137 @@ void FrameGraphVisitor::visit(Render::FrameGraphNode *node) // TODO: Pass in only framegraph config that has changed from previous // index RenderViewJob. if (fgChildIds.empty()) { - QAspectJobPtr job = m_renderer->createRenderViewInitializerJob(node, m_renderviewIndex++); - m_jobs->append(job); + // 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) -> One 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) One 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++; + RenderViewInitializerJobPtr renderViewJob = m_renderer->createRenderViewInitializerJob(node, currentRenderViewIndex); + auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create(); + auto filterEntityByLayer = Render::FilterLayerEntityJobPtr::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 materialGatherer = Render::MaterialParameterGathererJobPtr::create(); + auto frustumCulling = Render::FrustumCullingJobPtr::create(); + + // Init what we can here + EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager(); + filterEntityByLayer->setManager(entityManager); + renderableEntityFilterer->setManager(entityManager); + computeEntityFilterer->setManager(entityManager); + materialGatherer->setNodeManagers(m_renderer->nodeManagers()); + materialGatherer->setRenderer(m_renderer); + frustumCulling->setRoot(m_renderer->sceneRoot()); + renderViewCommandBuilder->setIndex(currentRenderViewIndex); + renderViewCommandBuilder->setRenderer(m_renderer); + + // 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 + materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter())); + materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter())); + + // 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()) { + // Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector + const QVector<Entity *> filteredEntities = filterEntityByLayer->filteredEntities(); + + // Note: this could further be improved if needed + // Set the renderable and computable entities + if (!rv->isCompute()) { + QVector<Entity *> renderableEntities = renderableEntityFilterer->filteredEntities(); + + for (auto i = renderableEntities.size() - 1; i >= 0; --i) { + if (!filteredEntities.contains(renderableEntities.at(i))) + renderableEntities.removeAt(i); + } + + if (rv->frustumCulling()) { + const QVector<Entity *> visibleEntities = frustumCulling->visibleEntities(); + for (auto i = renderableEntities.size() - 1; i >= 0; --i) { + if (!visibleEntities.contains(renderableEntities.at(i))) + renderableEntities.removeAt(i); + } + } + + 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)); + } + + // Set all required data on the RenderView for final processing + rv->setMaterialParameterTable(std::move(materialGatherer->materialToPassAndParameter())); + } + renderViewCommandBuilder->setRenderView(renderViewJob->renderView()); + }; + + auto syncRenderViewCommandBuildingJob = GenericLambdaJobPtr<decltype(syncForRenderCommandBuilding)>::create(syncForRenderCommandBuilding); + auto syncRenderViewInitializationJob = GenericLambdaJobPtr<decltype(syncRenderViewInitialization)>::create(syncRenderViewInitialization); + + // Set dependencies + syncRenderViewInitializationJob->addDependency(renderViewJob); + + filterEntityByLayer->addDependency(syncRenderViewInitializationJob); + materialGatherer->addDependency(syncRenderViewInitializationJob); + frustumCulling->addDependency(syncRenderViewInitializationJob); + + syncRenderViewCommandBuildingJob->addDependency(syncRenderViewInitializationJob); + syncRenderViewCommandBuildingJob->addDependency(materialGatherer); + syncRenderViewCommandBuildingJob->addDependency(renderableEntityFilterer); + syncRenderViewCommandBuildingJob->addDependency(computeEntityFilterer); + syncRenderViewCommandBuildingJob->addDependency(filterEntityByLayer); + + renderViewCommandBuilder->addDependency(syncRenderViewCommandBuildingJob); + + // 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(renderViewCommandBuilder); + m_jobs->push_back(materialGatherer); + m_jobs->push_back(frustumCulling); } } |