]> git.tdb.fi Git - libs/gl.git/commitdiff
Support samplers as independent objects
authorMikko Rasa <tdb@tdb.fi>
Sat, 6 Feb 2021 13:27:53 +0000 (15:27 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 6 Feb 2021 17:46:18 +0000 (19:46 +0200)
source/sampler.cpp
source/sampler.h
source/texture.cpp
source/texture3d.cpp
source/texturing.cpp
source/texturing.h
source/texunit.cpp
source/texunit.h

index 9476ffe9fdca6ac930b37beeb4bf85cf42af713a..cc54901b683a5f635f73eb69252eb8a9b82fa59e 100644 (file)
@@ -14,6 +14,18 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
+Sampler::Sampler():
+       owner(0)
+{
+       init();
+
+       Require _req(ARB_sampler_objects);
+       if(ARB_direct_state_access)
+               glCreateSamplers(1, &id);
+       else
+               glGenSamplers(1, &id);
+}
+
 Sampler::Sampler(const Texture &tex):
        id(0),
        owner(&tex)
@@ -39,16 +51,25 @@ void Sampler::init()
 
 void Sampler::update_parameter(int mask) const
 {
-       if(!owner->get_id() || (!ARB_direct_state_access && TexUnit::current().get_texture()!=owner))
+       if(owner)
        {
-               TexUnit *unit = TexUnit::find_unit(owner);
-               if(!unit)
+               if(!owner->get_id())
                {
                        dirty_params |= mask;
                        return;
                }
 
-               unit->bind();
+               if(!ARB_direct_state_access && TexUnit::current().get_texture()!=owner)
+               {
+                       TexUnit *unit = TexUnit::find_unit(owner);
+                       if(!unit)
+                       {
+                               dirty_params |= mask;
+                               return;
+                       }
+
+                       unit->bind();
+               }
        }
 
        if(mask&MIN_FILTER)
@@ -73,7 +94,9 @@ void Sampler::update_parameter(int mask) const
 
 void Sampler::set_parameter_i(unsigned param, int value) const
 {
-       if(ARB_direct_state_access)
+       if(id)
+               glSamplerParameteri(id, param, value);
+       else if(ARB_direct_state_access)
                glTextureParameteri(owner->get_id(), param, value);
        else
                glTexParameteri(owner->get_target(), param, value);
@@ -81,7 +104,9 @@ void Sampler::set_parameter_i(unsigned param, int value) const
 
 void Sampler::set_parameter_f(unsigned param, float value) const
 {
-       if(ARB_direct_state_access)
+       if(id)
+               glSamplerParameterf(id, param, value);
+       else if(ARB_direct_state_access)
                glTextureParameterf(owner->get_id(), param, value);
        else
                glTexParameterf(owner->get_target(), param, value);
@@ -160,16 +185,36 @@ void Sampler::set_compare(Predicate f)
 void Sampler::bind_to(unsigned i) const
 {
        TexUnit &unit = TexUnit::get_unit(i);
-       if(owner!=unit.get_texture())
+       if(owner && owner!=unit.get_texture())
                throw invalid_operation("Sampler::bind_to");
 
-       if(dirty_params)
+       const Sampler *cur = unit.get_sampler();
+       if(unit.set_sampler(this))
        {
-               update_parameter(dirty_params);
-               dirty_params = 0;
+               if(!owner || (cur && cur->id))
+                       glBindSampler(i, id);
+
+               if(dirty_params)
+               {
+                       update_parameter(dirty_params);
+                       dirty_params = 0;
+               }
        }
 }
 
+const Sampler *Sampler::current(unsigned i)
+{
+       return TexUnit::get_unit(i).get_sampler();
+}
+
+void Sampler::unbind_from(unsigned i)
+{
+       TexUnit &unit = TexUnit::get_unit(i);
+       const Sampler *cur = unit.get_sampler();
+       if(unit.set_sampler(0) && cur->id)
+               glBindSampler(i, 0);
+}
+
 void Sampler::unload()
 {
        // TODO check which params actually need refreshing
index 255d1da4b7d8988eb1fb42c50c0fc1356bfa7c7b..e1e9bec5d60332e5331cd6e1e52e421c5256e8e9 100644 (file)
@@ -149,6 +149,10 @@ public:
        void bind() const { bind_to(0); }
        void bind_to(unsigned) const;
 
+       static const Sampler *current(unsigned = 0);
+       static void unbind() { unbind_from(0); }
+       static void unbind_from(unsigned);
+
        void unload();
 };
 
index ab5700482ce02484efb7b960df00a9b3a95a0908..381a0a59d6eaed1453fa965b6e9062ba7233dcec 100644 (file)
@@ -238,7 +238,8 @@ void Texture::bind_to(unsigned i) const
                        glBindTexture(target, id);
                }
 
-               default_sampler.bind_to(i);
+               if(!unit.get_sampler())
+                       default_sampler.bind_to(i);
        }
 }
 
@@ -260,6 +261,9 @@ void Texture::unbind_from(unsigned i)
                        unit.bind();
                        glBindTexture(cur->target, 0);
                }
+
+               if(unit.get_sampler()==&cur->default_sampler)
+                       Sampler::unbind_from(i);
        }
 }
 
index 667f8c31c1ede8dfe9c1896159eaa263385738be..1f62e050db9897ccc8dcff5511efbe94a0f6fb83 100644 (file)
@@ -142,22 +142,11 @@ void Texture3D::image(const Graphics::Image &img, unsigned lv)
 {
        unsigned w = img.get_width();
        unsigned h = img.get_height();
-       unsigned d = 1;
 
-       if(depth)
-       {
-               if(h%depth)
-                       throw incompatible_data("Texture3D::load_image");
-               h /= depth;
-               d = depth;
-       }
-       else
-       {
-               if(h%w)
-                       throw incompatible_data("Texture3D::load_image");
-               d = h/w;
-               h = w;
-       }
+       if(h%w)
+               throw incompatible_data("Texture3D::load_image");
+       unsigned d = h/w;
+       h = w;
 
        PixelFormat fmt = pixelformat_from_image(img);
        if(width==0)
index c30216f139ebbf91e4a7fdcb53021e1fa6cbc39f..ab5d39b4c42e2b38d51c9ba1dfea5258e851a23a 100644 (file)
@@ -21,7 +21,7 @@ int Texturing::find_free_unit(const string &name_hint) const
        max_unit -= min(max_unit/4, 8U);
        unsigned initial_unit = (name_hint.empty() ? 0 : hash32(name_hint)%max_unit);
        unsigned unit = initial_unit;
-       while(get_attached_texture(unit))
+       while(get_attached_texture(unit) || get_attached_sampler(unit))
        {
                unit = (unit+1)%max_unit;
                if(unit==initial_unit)
@@ -31,34 +31,40 @@ int Texturing::find_free_unit(const string &name_hint) const
        return unit;
 }
 
-void Texturing::attach(unsigned attch, const Texture &tex)
+void Texturing::attach(unsigned attch, const Texture &tex, const Sampler *samp)
 {
-       set_attachment(attch, &tex);
+       set_attachment(attch, &tex, samp);
+}
+
+void Texturing::attach(unsigned attch, const Sampler &samp)
+{
+       set_attachment(attch, 0, &samp);
 }
 
 void Texturing::detach(unsigned attch)
 {
-       set_attachment(attch, 0);
+       set_attachment(attch, 0, 0);
 }
 
-void Texturing::set_attachment(unsigned unit, const Texture *tex)
+void Texturing::set_attachment(unsigned unit, const Texture *tex, const Sampler *samp)
 {
        if(unit>=TexUnit::get_n_units())
                throw out_of_range("Texturing::set_attachment");
 
-       if(tex)
+       if(tex || samp)
        {
                vector<Attachment>::iterator i;
                for(i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
                        if(i->unit==unit)
                        {
                                i->texture = tex;
+                               i->sampler = samp;
                                if(current()==this)
-                                       tex->bind_to(unit);
+                                       bind_attachment(*i);
                                return;
                        }
 
-               attachments.insert(i, Attachment(unit, tex));
+               attachments.insert(i, Attachment(unit, tex, samp));
                if(current()==this)
                        tex->bind_to(unit);
        }
@@ -69,7 +75,7 @@ void Texturing::set_attachment(unsigned unit, const Texture *tex)
                        {
                                attachments.erase(i);
                                if(current()==this)
-                                       Texture::unbind_from(unit);
+                                       unbind_attachment(unit);
                                return;
                        }
        }
@@ -83,6 +89,14 @@ const Texture *Texturing::get_attached_texture(unsigned unit) const
        return 0;
 }
 
+const Sampler *Texturing::get_attached_sampler(unsigned unit) const
+{
+       for(vector<Attachment>::const_iterator i=attachments.begin(); (i!=attachments.end() && i->unit<=unit); ++i)
+               if(i->unit==unit)
+                       return i->sampler;
+       return 0;
+}
+
 void Texturing::bind() const
 {
        const Texturing *old = current();
@@ -96,14 +110,14 @@ void Texturing::bind() const
                        {
                                if(i!=attachments.end() && (j==old->attachments.end() || i->unit<=j->unit))
                                {
-                                       i->texture->bind_to(i->unit);
+                                       bind_attachment(*i);
                                        if(j!=old->attachments.end() && j->unit==i->unit)
                                                ++j;
                                        ++i;
                                }
                                else
                                {
-                                       Texture::unbind_from(j->unit);
+                                       unbind_attachment(j->unit);
                                        ++j;
                                }
                        }
@@ -111,25 +125,41 @@ void Texturing::bind() const
                else
                {
                        for(vector<Attachment>::const_iterator i=attachments.begin(); i!=attachments.end(); ++i)
-                               i->texture->bind_to(i->unit);
+                               bind_attachment(*i);
                }
        }
 }
 
+void Texturing::bind_attachment(const Attachment &attch) const
+{
+       if(attch.sampler)
+               attch.sampler->bind_to(attch.unit);
+       else
+               Sampler::unbind_from(attch.unit);
+       attch.texture->bind_to(attch.unit);
+}
+
 void Texturing::unbind()
 {
        const Texturing *old = current();
        if(set_current(0))
        {
                for(vector<Attachment>::const_iterator i=old->attachments.begin(); i!=old->attachments.end(); ++i)
-                       Texture::unbind_from(i->unit);
+                       unbind_attachment(i->unit);
        }
 }
 
+void Texturing::unbind_attachment(unsigned unit)
+{
+       Texture::unbind_from(unit);
+       Sampler::unbind_from(unit);
+}
+
 
-Texturing::Attachment::Attachment(unsigned u, const Texture *t):
+Texturing::Attachment::Attachment(unsigned u, const Texture *t, const Sampler *s):
        unit(u),
-       texture(t)
+       texture(t),
+       sampler(s)
 { }
 
 } // namespace GL
index cba77e3fb3e49a57e4ca98f7bb698f7ddf7f8489..0da3eae41794d167d5ee9421943cdac29c9cc74f 100644 (file)
@@ -16,8 +16,9 @@ private:
        {
                unsigned unit;
                const Texture *texture;
+               const Sampler *sampler;
 
-               Attachment(unsigned, const Texture *);
+               Attachment(unsigned, const Texture *, const Sampler *);
        };
 
        std::vector<Attachment> attachments;
@@ -26,16 +27,22 @@ public:
        ~Texturing();
 
        int find_free_unit(const std::string & = std::string()) const;
-       void attach(unsigned, const Texture &);
+       void attach(unsigned, const Texture &, const Sampler * = 0);
+       void attach(unsigned, const Sampler &);
        void detach(unsigned);
 private:
-       void set_attachment(unsigned, const Texture *);
+       void set_attachment(unsigned, const Texture *, const Sampler *);
 public:
        const Texture *get_attached_texture(unsigned) const;
+       const Sampler *get_attached_sampler(unsigned) const;
 
        void bind() const;
 
        static void unbind();
+
+private:
+       void bind_attachment(const Attachment &) const;
+       static void unbind_attachment(unsigned);
 };
 
 } // namespace GL
index 493a761133eaba7af8bafa85e45a9bf90c0827a2..0659d6154e80523ffaa0baf75f6bf00ff96a05f2 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/gl/extensions/arb_vertex_shader.h>
 #include "gl.h"
 #include "misc.h"
+#include "texture.h"
 #include "texunit.h"
 
 using namespace std;
@@ -14,7 +15,8 @@ vector<TexUnit> TexUnit::units;
 TexUnit *TexUnit::cur_unit = 0;
 
 TexUnit::TexUnit():
-       texture(0)
+       texture(0),
+       sampler(0)
 { }
 
 bool TexUnit::set_texture(const Texture *tex)
@@ -24,6 +26,13 @@ bool TexUnit::set_texture(const Texture *tex)
        return result;
 }
 
+bool TexUnit::set_sampler(const Sampler *samp)
+{
+       bool result = (samp!=sampler);
+       sampler = samp;
+       return result;
+}
+
 void TexUnit::bind()
 {
        if(cur_unit!=this && (cur_unit || index))
index 6bd2f82d43511e933c02e719251a9b7b20197a6b..6253d8d914f52c85f7f9eec6a4beae0fcd733722 100644 (file)
@@ -6,8 +6,7 @@
 namespace Msp {
 namespace GL {
 
-class TexEnv;
-class TexGen;
+class Sampler;
 class Texture;
 
 /**
@@ -18,6 +17,7 @@ class TexUnit
 private:
        unsigned index;
        const Texture *texture;
+       const Sampler *sampler;
 
        static std::vector<TexUnit> units;
        static TexUnit *cur_unit;
@@ -28,6 +28,8 @@ public:
        unsigned get_index() const { return index; }
        bool set_texture(const Texture *);
        const Texture *get_texture() const { return texture; }
+       bool set_sampler(const Sampler *);
+       const Sampler *get_sampler() const { return sampler; }
        void bind();
 
        static unsigned get_n_units();