Support named postprocessor slots in pipeline templates
authorMikko Rasa <tdb@tdb.fi>
Tue, 23 Jul 2019 07:07:40 +0000 (10:07 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 23 Jul 2019 07:07:40 +0000 (10:07 +0300)
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
source/pipelinebuilder.h
source/pipelinetemplate.cpp
source/pipelinetemplate.h

index 705932994479c4f06b5cdc24b83bc5ae4b0cddd0..286d6cb62f747a4d97abb366389ca01695e60ea1 100644 (file)
@@ -17,6 +17,10 @@ PipelineBuilder::PipelineBuilder(const PipelineTemplate &t):
        const vector<PipelineTemplate::Pass> &passes = tmpl.get_passes();
        for(vector<PipelineTemplate::Pass>::const_iterator i=passes.begin(); i!=passes.end(); ++i)
                renderables[i->renderable_name] = 0;
+       const vector<PipelineTemplate::PostProcessor> &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);
        }
 }
 
index 6a40dbe77de61343f61c4d27fd8861059b8a7339..ab0dc4b9428c603fb4b555e83ee1091b9d2ef254 100644 (file)
@@ -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<std::string, Renderable *> renderables;
+       std::map<std::string, PostProcessor *> 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;
index 8c6dbe501203e0ee9bbcfb7a22fc27e3d869b7d8..14f6e2c024eed34fc123112161b15465e3f60cb5 100644 (file)
@@ -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<PipelineTemplate>(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<Pass>(p, 0)
index d98633539e06dff0dac89b3ef71d5f1478243676..a18eead4836401020a7a0e87d7abcaa2fbeee7cb 100644 (file)
@@ -17,30 +17,48 @@ class Lighting;
 
 class PipelineTemplate
 {
-public:
-       class Loader: public DataFile::CollectionObjectLoader<PipelineTemplate>
+private:
+       class PostProcLoader: virtual public DataFile::Loader
        {
        private:
                template<typename T>
                struct AddPostProc
                {
-                       static void add(Loader &ldr, const std::string &kw) { ldr.add(kw, &Loader::postprocessor<T>); }
+                       static void add(PostProcLoader &ldr, const std::string &kw) { ldr.add(kw, &PostProcLoader::postprocessor<T>); }
                };
 
+       protected:
+               RefPtr<PostProcessor::Template> postproc;
+
+       public:
+               PostProcLoader();
+
+               PostProcessor::Template *get_postprocessor_template() { return postproc.release(); }
+
+       protected:
+               virtual void postprocessor_loaded() { }
+
+       private:
+               template<typename T>
+               void postprocessor();
+
+               friend class PipelineTemplate;
+       };
+
+public:
+       class Loader: public DataFile::CollectionObjectLoader<PipelineTemplate>, 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<typename T>
-               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<Pass> PassArray;
-       typedef std::vector<PostProcessor::Template *> PostProcessorArray;
+       typedef std::vector<PostProcessor> PostProcessorArray;
 
 private:
-       typedef DataFile::LoadableTypeRegistry<Loader, Loader::AddPostProc> PostProcessorRegistry;
+       typedef DataFile::LoadableTypeRegistry<PostProcLoader, PostProcLoader::AddPostProc> PostProcessorRegistry;
 
        bool hdr;
        unsigned required_multisample;
@@ -108,11 +134,15 @@ void PipelineTemplate::register_postprocessor(const std::string &kw)
 }
 
 template<typename T>
-void PipelineTemplate::Loader::postprocessor()
+void PipelineTemplate::PostProcLoader::postprocessor()
 {
-       RefPtr<typename T::Template> 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<typename T::Template> pp = new typename T::Template;
+       load_sub(*pp);
+       postproc = pp;
+       pp = 0;
+       postprocessor_loaded();
 }
 
 } // namespace GL