Browse Source

Add more parameters for binding images to shaders.

rdb 11 years ago
parent
commit
cd79de19b2

+ 48 - 28
panda/src/glstuff/glShaderContext_src.cxx

@@ -1153,9 +1153,14 @@ disable_shader_texture_bindings() {
 
     if (gl_enable_memory_barriers) {
       for (int i = 0; i < num_image_units; ++i) {
-        // We don't distinguish between read-only and read-write/write-only
-        // image access, so we have to assume that the shader wrote to it.
-        _glsl_img_textures[i]->mark_incoherent();
+        const InternalName *name = _glsl_img_inputs[i];
+        const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name);
+
+        if ((input->_access & ShaderInput::A_write) != 0) {
+          _glsl_img_textures[i]->mark_incoherent(true);
+        } else {
+          _glsl_img_textures[i]->mark_incoherent(false);
+        }
         _glsl_img_textures[i] = NULL;
       }
     }
@@ -1193,21 +1198,18 @@ update_shader_texture_bindings(ShaderContext *prev) {
   int num_image_units = min(_glsl_img_inputs.size(), (size_t)_glgsg->_max_image_units);
 
   if (num_image_units > 0) {
-    GLuint *multi_img = NULL;
-    // If we support multi-bind, prepare an array.
-    if (_glgsg->_supports_multi_bind) {
-      multi_img = new GLuint[num_image_units];
-    }
-
     for (int i = 0; i < num_image_units; ++i) {
       const InternalName *name = _glsl_img_inputs[i];
-      Texture *tex = _glgsg->_target_shader->get_shader_input_texture(name);
+      const ShaderInput *input = _glgsg->_target_shader->get_shader_input(name);
+      Texture *tex = input->get_texture();
 
       GLuint gl_tex = 0;
+      CLP(TextureContext) *gtc;
+
       if (tex != NULL) {
         int view = _glgsg->get_current_tex_view_offset();
 
-        CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg));
+        gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg));
         if (gtc != (TextureContext*)NULL) {
           _glsl_img_textures[i] = gtc;
 
@@ -1220,27 +1222,45 @@ update_shader_texture_bindings(ShaderContext *prev) {
         }
       }
 
-      if (multi_img != NULL) {
-        // Put in array so we can multi-bind later.
-        multi_img[i] = gl_tex;
-
+      if (gl_tex == 0) {
+        _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
       } else {
-        // We don't support multi-bind, so bind now in the same way that multi-bind would have done it.
-        if (gl_tex == 0) {
-          _glgsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
+        //TODO: automatically convert to sized type instead of plain GL_RGBA
+        // If a base type is used, it will crash.
+        if (gtc->_internal_format == GL_RGBA || gtc->_internal_format == GL_RGB) {
+          GLCAT.error()
+            << "Texture " << tex->get_name() << " has an unsized format.  Textures bound "
+            << "to a shader as an image need a sized format.\n";
+
+          // This may not actually be right, but may still prevent a crash.
+          if (gtc->_internal_format == GL_RGBA) {
+            gtc->_internal_format = GL_RGBA8;
+          } else {
+            gtc->_internal_format = GL_RGB8;
+          }
+        }
+
+        GLenum access = GL_READ_ONLY;
+        GLboolean layered = (input->_access & ShaderInput::A_layered) != 0;
+
+        if ((input->_access & ShaderInput::A_read) != 0 &&
+            (input->_access & ShaderInput::A_write) != 0) {
+          access = GL_READ_WRITE;
+
+        } else if ((input->_access & ShaderInput::A_read) != 0) {
+          access = GL_READ_ONLY;
+
+        } else if ((input->_access & ShaderInput::A_write) != 0) {
+          access = GL_WRITE_ONLY;
+
         } else {
-          //TODO: automatically convert to sized type instead of plain GL_RGBA
-          // If a base type is used, it will crash.
-          GLint internal_format = _glgsg->get_internal_image_format(tex);
-          _glgsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format);
+          access = GL_READ_ONLY;
+          gl_tex = 0;
         }
+        _glgsg->_glBindImageTexture(i, gl_tex, input->_bind_level, layered,
+                                    input->_bind_layer, access, gtc->_internal_format);
       }
     }
-
-    if (multi_img != NULL) {
-      _glgsg->_glBindImageTextures(0, num_image_units, multi_img);
-      delete[] multi_img;
-    }
   }
 #endif
 
@@ -1332,7 +1352,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
 
 #ifndef OPENGLES
   if (barriers != 0) {
-    // Issue a memory barrier.
+    // Issue a memory barrier prior to this shader's execution.
     _glgsg->issue_memory_barrier(barriers);
   }
 #endif

+ 0 - 1
panda/src/glstuff/glTextureContext_src.I

@@ -28,7 +28,6 @@ CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg,
   glGenTextures(1, &_index);
 
   _handle = 0;
-  _needs_barrier = false;
   _has_storage = false;
   _immutable = false;
   _uses_mipmaps = false;

+ 13 - 4
panda/src/glstuff/glTextureContext_src.cxx

@@ -87,7 +87,6 @@ reset_data() {
 
   _handle = 0;
   _handle_resident = false;
-  _needs_barrier = false;
   _has_storage = false;
   _immutable = false;
 
@@ -169,15 +168,25 @@ needs_barrier(GLbitfield barrier) {
 //     Function: GLTextureContext::mark_incoherent
 //       Access: Public
 //  Description: Mark a texture as needing a memory barrier, since
-//               a non-coherent write just happened to it.
+//               a non-coherent read or write just happened to it.
+//               If 'wrote' is true, it was written to.
 ////////////////////////////////////////////////////////////////////
 void CLP(TextureContext)::
-mark_incoherent() {
+mark_incoherent(bool wrote) {
   if (!gl_enable_memory_barriers) {
     return;
   }
 
-  _glgsg->_textures_needing_fetch_barrier.insert(this);
+  // If we only read from it, the next read operation won't need
+  // another barrier, since it'll be reading the same data.
+  if (wrote) {
+    _glgsg->_textures_needing_fetch_barrier.insert(this);
+  }
+
+  // We could still write to it before we read from it, so we have
+  // to always insert these barriers.  This could be slightly
+  // optimized so that we don't issue a barrier between consecutive
+  // image reads, but that may not be worth the trouble.
   _glgsg->_textures_needing_image_access_barrier.insert(this);
   _glgsg->_textures_needing_update_barrier.insert(this);
   _glgsg->_textures_needing_framebuffer_barrier.insert(this);

+ 1 - 6
panda/src/glstuff/glTextureContext_src.h

@@ -40,7 +40,7 @@ public:
   CONSTEXPR bool needs_barrier(GLbitfield barrier) { return false; };
 #else
   bool needs_barrier(GLbitfield barrier);
-  void mark_incoherent();
+  void mark_incoherent(bool wrote);
 #endif
 
   // This is the GL "name" of the texture object.
@@ -50,11 +50,6 @@ public:
   GLuint64 _handle;
   bool _handle_resident;
 
-  // This is true if the texture was recently written to in a
-  // non-coherent way, and Panda may have to call glMemoryBarrier
-  // for the results of this write to become visible.
-  bool _needs_barrier;
-
   // These are the parameters that we specified with the last
   // glTexImage2D() or glTexStorage2D() call.  If none of these have
   // changed, we can reload the texture image with a glTexSubImage2D().

+ 9 - 251
panda/src/pgraph/nodePath.cxx

@@ -4001,250 +4001,28 @@ set_shader_input(const InternalName *id, Texture *tex, int priority) {
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void NodePath::
-set_shader_input(const InternalName *id, const NodePath &np, int priority) {
-  set_shader_input(new ShaderInput(id,np,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-void NodePath::
-set_shader_input(const InternalName *id, int n1, int n2, int n3, int n4, int priority) {
-  set_shader_input(new ShaderInput(id, LVecBase4i(n1, n2, n3, n4), priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const InternalName *id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) {
-  set_shader_input(new ShaderInput(id, LVecBase4(n1, n2, n3, n4), priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_float &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_double &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_int &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase4 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase3 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase2 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase4 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase3 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase4i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase3i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LVecBase2i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase4i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase3i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase2i &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LVecBase2 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LMatrix4 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const PTA_LMatrix3 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LMatrix4 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
+set_shader_input(const InternalName *id, Texture *tex, bool read, bool write, int z, int n, int priority) {
+  set_shader_input(new ShaderInput(id,tex,read,write,z,n,priority));
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, const LMatrix3 &v, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),v,priority));
-}
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_shader_input
 //       Access: Published
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void NodePath::
-set_shader_input(const string &id, Texture *tex, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),tex,priority));
+set_shader_input(const InternalName *id, const NodePath &np, int priority) {
+  set_shader_input(new ShaderInput(id,np,priority));
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePath::set_shader_input
 //       Access: Published
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 void NodePath::
-set_shader_input(const string &id, const NodePath &np, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id),np,priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::set_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath:: 
-set_shader_input(const string &id, int n1, int n2, int n3, int n4, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id), LVecBase4i(n1, n2, n3, n4), priority));
+set_shader_input(const InternalName *id, int n1, int n2, int n3, int n4, int priority) {
+  set_shader_input(new ShaderInput(id, LVecBase4i(n1, n2, n3, n4), priority));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -4253,28 +4031,8 @@ set_shader_input(const string &id, int n1, int n2, int n3, int n4, int priority)
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 void NodePath:: 
-set_shader_input(const string &id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) {
-  set_shader_input(new ShaderInput(InternalName::make(id), LVecBase4(n1, n2, n3, n4), priority));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::get_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-const ShaderInput *NodePath::
-get_shader_input(const string &id) const {
-  return get_shader_input(InternalName::make(id));
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodePath::clear_shader_input
-//       Access: Published
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void NodePath::
-clear_shader_input(const string &id) {
-  clear_shader_input(InternalName::make(id));
+set_shader_input(const InternalName *id, PN_stdfloat n1, PN_stdfloat n2, PN_stdfloat n3, PN_stdfloat n4, int priority) {
+  set_shader_input(new ShaderInput(id, LVecBase4(n1, n2, n3, n4), priority));
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 29
panda/src/pgraph/nodePath.h

@@ -615,6 +615,7 @@ PUBLISHED:
 
   void set_shader_input(const ShaderInput *inp);
   void set_shader_input(const InternalName *id, Texture *tex, int priority=0);
+  void set_shader_input(const InternalName *id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0);
   void set_shader_input(const InternalName *id, const NodePath &np, int priority=0);
   void set_shader_input(const InternalName *id, const PTA_float &v, int priority=0);
   void set_shader_input(const InternalName *id, const PTA_double &v, int priority=0);
@@ -640,41 +641,13 @@ PUBLISHED:
   void set_shader_input(const InternalName *id, PN_stdfloat n1, PN_stdfloat n2=0,
                         PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
 
-  void set_shader_input(const string &id, Texture *tex, int priority=0);
-  void set_shader_input(const string &id, const NodePath &np, int priority=0);
-  void set_shader_input(const string &id, const PTA_float &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_double &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_int &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase4 &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase3 &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase2 &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LMatrix4 &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LMatrix3 &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase4 &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase3 &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase2 &v, int priority=0);
-  void set_shader_input(const string &id, const LMatrix4 &v, int priority=0);
-  void set_shader_input(const string &id, const LMatrix3 &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase4i &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase3i &v, int priority=0);
-  void set_shader_input(const string &id, const PTA_LVecBase2i &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase4i &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase3i &v, int priority=0);
-  void set_shader_input(const string &id, const LVecBase2i &v, int priority=0);
-  void set_shader_input(const string &id, int n1, int n2=0, int n3=0,
-                                          int n4=0, int priority=0);
-  void set_shader_input(const string &id, PN_stdfloat n1, PN_stdfloat n2=0,
-                        PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
-
   void clear_shader_input(const InternalName *id);
-  void clear_shader_input(const string &id);
   void set_instance_count(int instance_count);
 
   const Shader *get_shader() const;
   const ShaderInput *get_shader_input(const InternalName *id) const;
-  const ShaderInput *get_shader_input(const string &id) const;
   const int get_instance_count() const;
-  
+
   void set_tex_transform(TextureStage *stage, const TransformState *transform);
   void clear_tex_transform();
   void clear_tex_transform(TextureStage *stage);

+ 157 - 32
panda/src/pgraph/shaderInput.I

@@ -31,7 +31,10 @@ INLINE ShaderInput::
 ShaderInput(const InternalName *name, int priority) :
   _name(name),
   _type(M_invalid),
-  _priority(priority)
+  _priority(priority),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -45,8 +48,40 @@ ShaderInput(const InternalName *name, Texture *tex, int priority) :
   _name(name),
   _type(M_texture),
   _priority(priority),
-  _stored_texture(tex)
+  _stored_texture(tex),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read | A_write | A_layered)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ShaderInput::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE ShaderInput::
+ShaderInput(const InternalName *name, Texture *tex, bool read, bool write, int z, int n, int priority) :
+  _name(name),
+  _type(M_texture),
+  _priority(priority),
+  _stored_texture(tex),
+  _bind_layer(z),
+  _bind_level(n),
+  _access(0)
 {
+  if (read) {
+    _access |= A_read;
+  }
+  if (write) {
+    _access |= A_write;
+  }
+  if (z >= 0) {
+    _bind_layer = z;
+  } else {
+    _bind_layer = 0;
+    _access |= A_layered;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -59,7 +94,10 @@ ShaderInput(const InternalName *name, const NodePath &np, int priority) :
   _name(name),
   _type(M_nodepath),
   _priority(priority),
-  _stored_nodepath(np)
+  _stored_nodepath(np),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -73,7 +111,10 @@ ShaderInput(const InternalName *name, const PTA_float &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -87,7 +128,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase4f &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -101,7 +145,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase3f &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -115,7 +162,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase2f &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -130,7 +180,10 @@ ShaderInput(const InternalName *name, const LVecBase4f &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(LCAST(PN_stdfloat, vec))
+  _stored_vector(LCAST(PN_stdfloat, vec)),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -145,7 +198,10 @@ ShaderInput(const InternalName *name, const LVecBase3f &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0)
+  _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -160,7 +216,10 @@ ShaderInput(const InternalName *name, const LVecBase2f &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0)
+  _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -174,7 +233,10 @@ ShaderInput(const InternalName *name, const PTA_LMatrix4f &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -188,7 +250,10 @@ ShaderInput(const InternalName *name, const PTA_LMatrix3f &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -202,7 +267,10 @@ ShaderInput(const InternalName *name, const LMatrix4f &mat, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(mat)
+  _stored_ptr(mat),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -216,7 +284,10 @@ ShaderInput(const InternalName *name, const LMatrix3f &mat, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(mat)
+  _stored_ptr(mat),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -230,7 +301,10 @@ ShaderInput(const InternalName *name, const PTA_double &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -244,7 +318,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase4d &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -258,7 +335,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase3d &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -272,7 +352,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase2d &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -287,7 +370,10 @@ ShaderInput(const InternalName *name, const LVecBase4d &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(LCAST(PN_stdfloat, vec))
+  _stored_vector(LCAST(PN_stdfloat, vec)),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -302,7 +388,10 @@ ShaderInput(const InternalName *name, const LVecBase3d &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0)
+  _stored_vector(vec.get_x(), vec.get_y(), vec.get_z(), 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -317,7 +406,10 @@ ShaderInput(const InternalName *name, const LVecBase2d &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0)
+  _stored_vector(vec.get_x(), vec.get_y(), 0.0, 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -331,7 +423,10 @@ ShaderInput(const InternalName *name, const PTA_LMatrix4d &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -345,7 +440,10 @@ ShaderInput(const InternalName *name, const PTA_LMatrix3d &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -359,7 +457,10 @@ ShaderInput(const InternalName *name, const LMatrix4d &mat, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(mat)
+  _stored_ptr(mat),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -373,7 +474,10 @@ ShaderInput(const InternalName *name, const LMatrix3d &mat, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(mat)
+  _stored_ptr(mat),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -387,7 +491,10 @@ ShaderInput(const InternalName *name, const PTA_int &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -401,7 +508,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase4i &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -415,7 +525,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase3i &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -429,7 +542,10 @@ ShaderInput(const InternalName *name, const PTA_LVecBase2i &ptr, int priority) :
   _name(name),
   _type(M_numeric),
   _priority(priority),
-  _stored_ptr(ptr)
+  _stored_ptr(ptr),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -444,7 +560,10 @@ ShaderInput(const InternalName *name, const LVecBase4i &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), (int)vec.get_w())
+  _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), (int)vec.get_w()),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -459,7 +578,10 @@ ShaderInput(const InternalName *name, const LVecBase3i &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), 0.0)
+  _stored_vector((int)vec.get_x(), (int)vec.get_y(), (int)vec.get_z(), 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 
@@ -474,7 +596,10 @@ ShaderInput(const InternalName *name, const LVecBase2i &vec, int priority) :
   _type(M_numeric),
   _priority(priority),
   _stored_ptr(vec),
-  _stored_vector((int)vec.get_x(), (int)vec.get_y(), 0.0, 0.0)
+  _stored_vector((int)vec.get_x(), (int)vec.get_y(), 0.0, 0.0),
+  _bind_layer(0),
+  _bind_level(0),
+  _access(A_read)
 {
 }
 

+ 15 - 2
panda/src/pgraph/shaderInput.h

@@ -43,10 +43,18 @@ public:
   INLINE ~ShaderInput();
 
 PUBLISHED:
+  // Used when binding texture images.
+  enum AccessFlags {
+    A_read    = 0x01,
+    A_write   = 0x02,
+    A_layered = 0x04,
+  };
+
   static const ShaderInput *get_blank();
   INLINE ShaderInput(const InternalName *id, int priority=0);
   INLINE ShaderInput(const InternalName *id, const NodePath &np, int priority=0);
   INLINE ShaderInput(const InternalName *id, Texture *tex, int priority=0);
+  INLINE ShaderInput(const InternalName *id, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0);
   INLINE ShaderInput(const InternalName *id, const PTA_float &ptr, int priority=0);
   INLINE ShaderInput(const InternalName *id, const PTA_LVecBase4f &ptr, int priority=0);
   INLINE ShaderInput(const InternalName *id, const PTA_LVecBase3f &ptr, int priority=0);
@@ -85,9 +93,9 @@ PUBLISHED:
     M_nodepath,
     M_numeric
   };
-  
+
   INLINE const InternalName *get_name() const;
-  
+
   INLINE int get_value_type() const;
   INLINE int get_priority() const;
   INLINE Texture *get_texture() const;
@@ -107,6 +115,11 @@ private:
   NodePath _stored_nodepath;
   LVecBase4 _stored_vector;
 
+public:
+  int _bind_layer;
+  int _bind_level;
+  int _access;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;