mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-07 06:32:57 +02:00
runtime switch for deferred/forward rendering
This commit is contained in:
parent
164984b15d
commit
ca5c7e3904
10 changed files with 129 additions and 41 deletions
|
@ -243,11 +243,8 @@
|
|||
#include "webbrowser/WebBrowserSuggestionsEngine.h"
|
||||
#include <DesktopPreviewProvider.h>
|
||||
|
||||
|
||||
#include "AboutUtil.h"
|
||||
|
||||
#include <DisableDeferred.h>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
|
@ -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<Keyboard>()->registerKeyboardHighlighting();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<SecondaryCameraJob>("SecondaryCamera");
|
||||
|
||||
task.addJob<RenderViewTask>("RenderSecondView", cullFunctor, isDeferred, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
task.addJob<RenderViewTask>("RenderSecondView", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
|
||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||
}
|
|
@ -65,7 +65,7 @@ public:
|
|||
using JobModel = render::Task::Model<SecondaryCameraRenderTask, Config>;
|
||||
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
|
||||
|
|
|
@ -65,15 +65,15 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) {
|
|||
DependencyManager::get<TextureCache>()->setGPUContext(_gpuContext);
|
||||
}
|
||||
|
||||
void GraphicsEngine::initializeRender(bool disableDeferred) {
|
||||
void GraphicsEngine::initializeRender() {
|
||||
|
||||
// Set up the render engine
|
||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||
_renderEngine->addJob<UpdateSceneTask>("UpdateScene");
|
||||
#ifndef Q_OS_ANDROID
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor, !disableDeferred);
|
||||
_renderEngine->addJob<SecondaryCameraRenderTask>("SecondaryCameraJob", cullFunctor);
|
||||
#endif
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->addJob<RenderViewTask>("RenderMainView", cullFunctor, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0);
|
||||
_renderEngine->load();
|
||||
_renderEngine->registerScene(_renderScene);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
~GraphicsEngine();
|
||||
|
||||
void initializeGPU(GLWidget*);
|
||||
void initializeRender(bool disableDeferred);
|
||||
void initializeRender();
|
||||
void startup();
|
||||
void shutdown();
|
||||
|
||||
|
|
|
@ -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 <DisableDeferred.h>
|
||||
|
||||
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<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, tagBits, tagMask);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
|
||||
|
@ -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<AssembleLightingStageTask>("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<AssembleLightingStageTask::Output>().get0()[0], lightingModel).asVarying();
|
||||
const auto shadowTaskOut = task.addJob<RenderShadowTask>("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask);
|
||||
const auto shadowTaskOut = task.addSwitchJob<RenderShadowTask>("RenderShadowTask", 0, shadowTaskIn, cullFunctor, tagBits, tagMask);
|
||||
|
||||
const auto renderInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderInput);
|
||||
const auto renderDeferredInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying();
|
||||
task.addSwitchJob<RenderDeferredTask>("RenderDeferredTask", 0, renderDeferredInput);
|
||||
|
||||
const auto renderForwardInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
|
||||
task.addSwitchJob<RenderForwardTask>("RenderForwardTask", 1, renderForwardInput);
|
||||
} else {
|
||||
const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
|
||||
task.addJob<RenderForwardTask>("Forward", renderInput);
|
||||
task.addJob<RenderForwardTask>("RenderForwardTask", renderInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
class RenderViewTask {
|
||||
public:
|
||||
using Input = RenderFetchCullSortTask::Output;
|
||||
using JobModel = render::Task::ModelI<RenderViewTask, Input>;
|
||||
using JobModel = render::Task::ModelIS<RenderViewTask, Input>;
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "Config.h"
|
||||
#include "Varying.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
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<C>(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<C>(Concept::_config);
|
||||
if (config->isEnabled()) {
|
||||
for (auto job : TaskConcept::_jobs) {
|
||||
|
@ -357,6 +340,81 @@ public:
|
|||
template <class T, class O, class C = Config> using ModelO = TaskModel<T, C, None, O>;
|
||||
template <class T, class I, class O, class C = Config> using ModelIO = TaskModel<T, C, I, O>;
|
||||
|
||||
template <class T, class C = SwitchConfig, class I = None, class O = None> class SwitchTaskModel : public TaskModel<T, C, I, O> {
|
||||
public:
|
||||
using Input = I;
|
||||
|
||||
std::unordered_map<uint8_t, Jobs> _jobsSwitch;
|
||||
|
||||
SwitchTaskModel(const std::string& name, const Varying& input, QConfigPointer config) : TaskModel<T, C, I, O>(name, input, config) {}
|
||||
|
||||
template <class... A>
|
||||
static std::shared_ptr<SwitchTaskModel> create(const std::string& name, const Varying& input, A&&... args) {
|
||||
auto model = std::make_shared<SwitchTaskModel>(name, input, std::make_shared<C>());
|
||||
|
||||
{
|
||||
TimeProfiler probe("build::" + model->getName());
|
||||
model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
|
||||
}
|
||||
// Recreate the Config to use the templated type
|
||||
model->createConfiguration();
|
||||
model->applyConfiguration();
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
template <class... A>
|
||||
static std::shared_ptr<SwitchTaskModel> create(const std::string& name, A&&... args) {
|
||||
const auto input = Varying(Input());
|
||||
return create(name, input, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
void applyConfiguration() override {
|
||||
TaskModel<T, C, I, O>::applyConfiguration();
|
||||
|
||||
for (auto& jobs : _jobsSwitch) {
|
||||
for (auto& job : jobs.second) {
|
||||
job.applyConfiguration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run(const ContextPointer& jobContext) override {
|
||||
auto config = std::static_pointer_cast<C>(Concept::_config);
|
||||
if (config->isEnabled()) {
|
||||
// First we run all the setup jobs
|
||||
TaskModel<T, C, I, O>::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 <class NT, class... NA> 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<NA>(args)...)));
|
||||
|
||||
// Conect the child config to this task's config
|
||||
std::static_pointer_cast<TaskConfig>(Concept::getConfiguration())->connectChildConfig(jobs.back().getConfiguration(), name);
|
||||
|
||||
return jobs.back().getOutput();
|
||||
}
|
||||
template <class NT, class... NA> const Varying addSwitchJob(std::string name, uint8_t index, NA&&... args) {
|
||||
const auto input = Varying(typename NT::JobModel::Input());
|
||||
return addJob<NT>(name, index, input, std::forward<NA>(args)...);
|
||||
}
|
||||
};
|
||||
template <class T, class I, class C = SwitchConfig> using ModelIS = SwitchTaskModel<T, C, I, None>;
|
||||
|
||||
// Create a new job in the Task's queue; returns the job's output
|
||||
template <class T, class... A> const Varying addJob(std::string name, const Varying& input, A&&... args) {
|
||||
return std::static_pointer_cast<TaskConcept>(JobType::_concept)->template addJob<T>(name, input, std::forward<A>(args)...);
|
||||
|
@ -365,6 +423,13 @@ public:
|
|||
const auto input = Varying(typename T::JobModel::Input());
|
||||
return std::static_pointer_cast<TaskConcept>(JobType::_concept)->template addJob<T>(name, input, std::forward<A>(args)...);
|
||||
}
|
||||
template <class T, class... A> const Varying addSwitchJob(std::string name, uint8_t index, const Varying& input, A&&... args) {
|
||||
return std::static_pointer_cast<SwitchTaskModel>(JobType::_concept)->template addSwitchJob<T>(name, index, input, std::forward<A>(args)...);
|
||||
}
|
||||
template <class T, class... A> const Varying addSwitchJob(std::string name, uint8_t index, A&&... args) {
|
||||
const auto input = Varying(typename T::JobModel::Input());
|
||||
return std::static_pointer_cast<SwitchTaskModel>(JobType::_concept)->template addSwitchJob<T>(name, index, input, std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
std::shared_ptr<Config> getConfiguration() {
|
||||
return std::static_pointer_cast<Config>(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 <class T> using PersistentConfig = task::PersistentConfig<T>; \
|
||||
using Job = task::Job<ContextType, TimeProfiler>; \
|
||||
using Task = task::Task<ContextType, TimeProfiler>; \
|
||||
|
|
Loading…
Reference in a new issue