diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e2e4e8de1..d0fd406842 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -243,11 +243,8 @@ #include "webbrowser/WebBrowserSuggestionsEngine.h" #include - #include "AboutUtil.h" -#include - #if defined(Q_OS_WIN) #include @@ -2979,7 +2976,7 @@ void Application::initializeDisplayPlugins() { void Application::initializeRenderEngine() { // FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. DeadlockWatchdogThread::withPause([&] { - _graphicsEngine.initializeRender(DISABLE_DEFERRED); + _graphicsEngine.initializeRender(); DependencyManager::get()->registerKeyboardHighlighting(); }); } diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index da2874a3f4..704d7963e7 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -272,10 +272,10 @@ public: } }; -void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { +void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor) { const auto cachedArg = task.addJob("SecondaryCamera"); - task.addJob("RenderSecondView", cullFunctor, isDeferred, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); + task.addJob("RenderSecondView", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); task.addJob("EndSecondaryCamera", cachedArg); } \ No newline at end of file diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index 941ccc5f93..463034527a 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -65,7 +65,7 @@ public: using JobModel = render::Task::Model; SecondaryCameraRenderTask() {} void configure(const Config& config) {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor); }; #endif diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 267822baf2..4f8b86cc0c 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -65,15 +65,15 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { DependencyManager::get()->setGPUContext(_gpuContext); } -void GraphicsEngine::initializeRender(bool disableDeferred) { +void GraphicsEngine::initializeRender() { // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("UpdateScene"); #ifndef Q_OS_ANDROID - _renderEngine->addJob("SecondaryCameraJob", cullFunctor, !disableDeferred); + _renderEngine->addJob("SecondaryCameraJob", cullFunctor); #endif - _renderEngine->addJob("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0); + _renderEngine->addJob("RenderMainView", cullFunctor, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0); _renderEngine->load(); _renderEngine->registerScene(_renderScene); diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index f0b88d2459..dccb098d5e 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -44,7 +44,7 @@ public: ~GraphicsEngine(); void initializeGPU(GLWidget*); - void initializeRender(bool disableDeferred); + void initializeRender(); void startup(); void shutdown(); diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 7230635060..61823cf01c 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -15,7 +15,9 @@ #include "RenderDeferredTask.h" #include "RenderForwardTask.h" -void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) { +#include + +void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) { const auto items = task.addJob("FetchCullSort", cullFunctor, tagBits, tagMask); assert(items.canCast()); @@ -25,17 +27,19 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render: // Assemble the lighting stages current frames const auto lightingStageFramesAndZones = task.addJob("AssembleStages", items); - if (isDeferred) { + if (!DISABLE_DEFERRED) { // Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling // is performed, then casters not in the view frustum will be removed, which is not what we wish. const auto shadowTaskIn = RenderShadowTask::Input(lightingStageFramesAndZones.get().get0()[0], lightingModel).asVarying(); - const auto shadowTaskOut = task.addJob("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask); + const auto shadowTaskOut = task.addSwitchJob("RenderShadowTask", 0, shadowTaskIn, cullFunctor, tagBits, tagMask); - const auto renderInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying(); - task.addJob("RenderDeferredTask", renderInput); + const auto renderDeferredInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying(); + task.addSwitchJob("RenderDeferredTask", 0, renderDeferredInput); + + const auto renderForwardInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying(); + task.addSwitchJob("RenderForwardTask", 1, renderForwardInput); } else { const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying(); - task.addJob("Forward", renderInput); + task.addJob("RenderForwardTask", renderInput); } } - diff --git a/libraries/render-utils/src/RenderViewTask.h b/libraries/render-utils/src/RenderViewTask.h index 5da3d18474..b4d9326944 100644 --- a/libraries/render-utils/src/RenderViewTask.h +++ b/libraries/render-utils/src/RenderViewTask.h @@ -19,11 +19,12 @@ class RenderViewTask { public: using Input = RenderFetchCullSortTask::Output; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelIS; RenderViewTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); + void configure(const render::SwitchConfig& configuration) {} + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); }; diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index 5e8e4b246d..c836d06717 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -133,3 +133,11 @@ JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { return found; } } + +void SwitchConfig::setSwitchIndex(uint8_t index) { + if (_switchIndex != index) { + _switchIndex = index; + // We can re-use this signal here + emit dirtyEnabled(); + } +} \ No newline at end of file diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 486b28b6b9..d158e16eec 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -262,6 +262,18 @@ public slots: void refresh(); }; +class SwitchConfig : public TaskConfig { + Q_OBJECT + Q_PROPERTY(bool switchIndex READ getSwitchIndex WRITE setSwitchIndex NOTIFY dirtyEnabled) + +public: + uint8_t getSwitchIndex() const { return _switchIndex; } + void setSwitchIndex(uint8_t index); + +protected: + uint8_t _switchIndex { 0 }; +}; + } #endif // hifi_task_Config_h diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index b74986235e..e4f7e789f4 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -15,6 +15,8 @@ #include "Config.h" #include "Varying.h" +#include + namespace task { class JobConcept; @@ -244,25 +246,6 @@ public: const Varying getOutput() const override { return _output; } Varying& editInput() override { return _input; } - typename Jobs::iterator editJob(std::string name) { - typename Jobs::iterator jobIt; - for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { - if (jobIt->getName() == name) { - return jobIt; - } - } - return jobIt; - } - typename Jobs::const_iterator getJob(std::string name) const { - typename Jobs::const_iterator jobIt; - for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { - if (jobIt->getName() == name) { - return jobIt; - } - } - return jobIt; - } - TaskConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {} // Create a new job in the container's queue; returns the job's output @@ -331,7 +314,7 @@ public: return Concept::_config; } - void applyConfiguration() override { + virtual void applyConfiguration() override { TimeProfiler probe("configure::" + JobConcept::getName()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { @@ -339,7 +322,7 @@ public: } } - void run(const ContextPointer& jobContext) override { + virtual void run(const ContextPointer& jobContext) override { auto config = std::static_pointer_cast(Concept::_config); if (config->isEnabled()) { for (auto job : TaskConcept::_jobs) { @@ -357,6 +340,81 @@ public: template using ModelO = TaskModel; template using ModelIO = TaskModel; + template class SwitchTaskModel : public TaskModel { + public: + using Input = I; + + std::unordered_map _jobsSwitch; + + SwitchTaskModel(const std::string& name, const Varying& input, QConfigPointer config) : TaskModel(name, input, config) {} + + template + static std::shared_ptr create(const std::string& name, const Varying& input, A&&... args) { + auto model = std::make_shared(name, input, std::make_shared()); + + { + TimeProfiler probe("build::" + model->getName()); + model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); + } + // Recreate the Config to use the templated type + model->createConfiguration(); + model->applyConfiguration(); + + return model; + } + + template + static std::shared_ptr create(const std::string& name, A&&... args) { + const auto input = Varying(Input()); + return create(name, input, std::forward(args)...); + } + + void applyConfiguration() override { + TaskModel::applyConfiguration(); + + for (auto& jobs : _jobsSwitch) { + for (auto& job : jobs.second) { + job.applyConfiguration(); + } + } + } + + void run(const ContextPointer& jobContext) override { + auto config = std::static_pointer_cast(Concept::_config); + if (config->isEnabled()) { + // First we run all the setup jobs + TaskModel::run(jobContext); + + // Then we run the branching jobs + auto jobsIt = _jobsSwitch.find(config->getSwitchIndex()); + if (jobsIt != _jobsSwitch.end()) { + for (auto job : jobsIt->second) { + job.run(jobContext); + if (jobContext->taskFlow.doAbortTask()) { + jobContext->taskFlow.reset(); + return; + } + } + } + } + } + + template const Varying addSwitchJob(std::string name, uint8_t index, const Varying& input, NA&&... args) { + auto& jobs = _jobsSwitch[index]; + jobs.emplace_back((NT::JobModel::create(name, input, std::forward(args)...))); + + // Conect the child config to this task's config + std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(jobs.back().getConfiguration(), name); + + return jobs.back().getOutput(); + } + template const Varying addSwitchJob(std::string name, uint8_t index, NA&&... args) { + const auto input = Varying(typename NT::JobModel::Input()); + return addJob(name, index, input, std::forward(args)...); + } + }; + template using ModelIS = SwitchTaskModel; + // Create a new job in the Task's queue; returns the job's output template const Varying addJob(std::string name, const Varying& input, A&&... args) { return std::static_pointer_cast(JobType::_concept)->template addJob(name, input, std::forward(args)...); @@ -365,6 +423,13 @@ public: const auto input = Varying(typename T::JobModel::Input()); return std::static_pointer_cast(JobType::_concept)->template addJob(name, input, std::forward(args)...); } + template const Varying addSwitchJob(std::string name, uint8_t index, const Varying& input, A&&... args) { + return std::static_pointer_cast(JobType::_concept)->template addSwitchJob(name, index, input, std::forward(args)...); + } + template const Varying addSwitchJob(std::string name, uint8_t index, A&&... args) { + const auto input = Varying(typename T::JobModel::Input()); + return std::static_pointer_cast(JobType::_concept)->template addSwitchJob(name, index, input, std::forward(args)...); + } std::shared_ptr getConfiguration() { return std::static_pointer_cast(JobType::_concept->getConfiguration()); @@ -407,6 +472,7 @@ protected: #define Task_DeclareTypeAliases(ContextType, TimeProfiler) \ using JobConfig = task::JobConfig; \ using TaskConfig = task::TaskConfig; \ + using SwitchConfig = task::SwitchConfig; \ template using PersistentConfig = task::PersistentConfig; \ using Job = task::Job; \ using Task = task::Task; \