From e85d8669d6c389ded738c7b536f83ea54176662f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 23 Jul 2019 10:07:40 +0300 Subject: [PATCH] Support named postprocessor slots in pipeline templates This can be useful if a postprocessor in the middle of the chain needs to be created at runtime due to data dependencies. --- source/pipelinebuilder.cpp | 18 ++++++++++-- source/pipelinebuilder.h | 3 ++ source/pipelinetemplate.cpp | 29 +++++++++++++++++-- source/pipelinetemplate.h | 58 ++++++++++++++++++++++++++++--------- 4 files changed, 90 insertions(+), 18 deletions(-) diff --git a/source/pipelinebuilder.cpp b/source/pipelinebuilder.cpp index 70593299..286d6cb6 100644 --- a/source/pipelinebuilder.cpp +++ b/source/pipelinebuilder.cpp @@ -17,6 +17,10 @@ PipelineBuilder::PipelineBuilder(const PipelineTemplate &t): const vector &passes = tmpl.get_passes(); for(vector::const_iterator i=passes.begin(); i!=passes.end(); ++i) renderables[i->renderable_name] = 0; + const vector &postprocs = tmpl.get_postprocessors(); + for(PipelineTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i) + if(!i->slot_name.empty()) + postprocessors[i->slot_name] = 0; } void PipelineBuilder::set_renderable(const string &name, Renderable &rend) @@ -24,6 +28,11 @@ void PipelineBuilder::set_renderable(const string &name, Renderable &rend) get_item(renderables, name) = &rend; } +void PipelineBuilder::set_postprocessor(const string &name, PostProcessor &pproc) +{ + get_item(postprocessors, name) = &pproc; +} + void PipelineBuilder::build(Pipeline &pipeline) const { pipeline.set_hdr(tmpl.get_hdr()); @@ -49,8 +58,13 @@ void PipelineBuilder::build(Pipeline &pipeline) const const PipelineTemplate::PostProcessorArray &postprocs = tmpl.get_postprocessors(); for(PipelineTemplate::PostProcessorArray::const_iterator i=postprocs.begin(); i!=postprocs.end(); ++i) { - PostProcessor *proc = (*i)->create(pipeline.get_width(), pipeline.get_height()); - pipeline.add_postprocessor_owned(proc); + PostProcessor *proc = 0; + if(!i->slot_name.empty()) + proc = get_item(postprocessors, i->slot_name); + if(!proc && i->postprocessor_template) + proc = i->postprocessor_template->create(pipeline.get_width(), pipeline.get_height()); + if(proc) + pipeline.add_postprocessor_owned(proc); } } diff --git a/source/pipelinebuilder.h b/source/pipelinebuilder.h index 6a40dbe7..ab0dc4b9 100644 --- a/source/pipelinebuilder.h +++ b/source/pipelinebuilder.h @@ -10,6 +10,7 @@ namespace GL { class Framebuffer; class Pipeline; class PipelineTemplate; +class PostProcessor; class Renderable; class View; @@ -18,11 +19,13 @@ class PipelineBuilder private: const PipelineTemplate &tmpl; std::map renderables; + std::map postprocessors; public: PipelineBuilder(const PipelineTemplate &); void set_renderable(const std::string &, Renderable &); + void set_postprocessor(const std::string &, PostProcessor &); void build(Pipeline &) const; Pipeline *build(unsigned, unsigned) const; diff --git a/source/pipelinetemplate.cpp b/source/pipelinetemplate.cpp index 8c6dbe50..14f6e2c0 100644 --- a/source/pipelinetemplate.cpp +++ b/source/pipelinetemplate.cpp @@ -22,7 +22,7 @@ PipelineTemplate::PipelineTemplate(): PipelineTemplate::~PipelineTemplate() { for(PostProcessorArray::iterator i=postprocessors.begin(); i!=postprocessors.end(); ++i) - delete *i; + delete i->postprocessor_template; } @@ -45,6 +45,17 @@ PipelineTemplate::Pass::~Pass() { } +PipelineTemplate::PostProcessor::PostProcessor(GL::PostProcessor::Template *ppt): + postprocessor_template(ppt) +{ } + + +PipelineTemplate::PostProcLoader::PostProcLoader() +{ + get_postprocessor_registry().add_all(*this); +} + + PipelineTemplate::Loader::Loader(PipelineTemplate &t): DataFile::CollectionObjectLoader(t, 0) { @@ -63,8 +74,12 @@ void PipelineTemplate::Loader::init() add("multisample", &Loader::multisample); add("multisample", &Loader::multisample_range); add("pass", &Loader::pass); + add("postprocessor", &Loader::postprocessor); +} - get_postprocessor_registry().add_all(*this); +void PipelineTemplate::Loader::postprocessor_loaded() +{ + obj.postprocessors.push_back(get_postprocessor_template()); } void PipelineTemplate::Loader::multisample(unsigned samples) @@ -92,6 +107,16 @@ void PipelineTemplate::Loader::pass(const string &tag, const string &rend) obj.passes.push_back(pss); } +void PipelineTemplate::Loader::postprocessor(const std::string &slot) +{ + PostProcLoader ldr; + load_sub_with(ldr); + PostProcessor pp; + pp.postprocessor_template = ldr.get_postprocessor_template(); + pp.slot_name = slot; + obj.postprocessors.push_back(pp); +} + PipelineTemplate::Pass::Loader::Loader(Pass &p): DataFile::CollectionObjectLoader(p, 0) diff --git a/source/pipelinetemplate.h b/source/pipelinetemplate.h index d9863353..a18eead4 100644 --- a/source/pipelinetemplate.h +++ b/source/pipelinetemplate.h @@ -17,30 +17,48 @@ class Lighting; class PipelineTemplate { -public: - class Loader: public DataFile::CollectionObjectLoader +private: + class PostProcLoader: virtual public DataFile::Loader { private: template struct AddPostProc { - static void add(Loader &ldr, const std::string &kw) { ldr.add(kw, &Loader::postprocessor); } + static void add(PostProcLoader &ldr, const std::string &kw) { ldr.add(kw, &PostProcLoader::postprocessor); } }; + protected: + RefPtr postproc; + + public: + PostProcLoader(); + + PostProcessor::Template *get_postprocessor_template() { return postproc.release(); } + + protected: + virtual void postprocessor_loaded() { } + + private: + template + void postprocessor(); + + friend class PipelineTemplate; + }; + +public: + class Loader: public DataFile::CollectionObjectLoader, public PostProcLoader + { public: Loader(PipelineTemplate &); Loader(PipelineTemplate &, Collection &); private: void init(); + virtual void postprocessor_loaded(); void multisample(unsigned); void multisample_range(unsigned, unsigned); void pass(const std::string &, const std::string &); - - template - void postprocessor(); - - friend class PipelineTemplate; + void postprocessor(const std::string &); }; struct Pass @@ -73,11 +91,19 @@ public: ~Pass(); }; + struct PostProcessor + { + GL::PostProcessor::Template *postprocessor_template; + std::string slot_name; + + PostProcessor(GL::PostProcessor::Template * = 0); + }; + typedef std::vector PassArray; - typedef std::vector PostProcessorArray; + typedef std::vector PostProcessorArray; private: - typedef DataFile::LoadableTypeRegistry PostProcessorRegistry; + typedef DataFile::LoadableTypeRegistry PostProcessorRegistry; bool hdr; unsigned required_multisample; @@ -108,11 +134,15 @@ void PipelineTemplate::register_postprocessor(const std::string &kw) } template -void PipelineTemplate::Loader::postprocessor() +void PipelineTemplate::PostProcLoader::postprocessor() { - RefPtr postproc = new typename T::Template; - load_sub(*postproc); - obj.postprocessors.push_back(postproc.release()); + if(postproc) + throw std::logic_error("Only one postprocessor allowed per slot"); + RefPtr pp = new typename T::Template; + load_sub(*pp); + postproc = pp; + pp = 0; + postprocessor_loaded(); } } // namespace GL -- 2.45.2