Browse Source

shaderpipeline: Refactoring, more powerful SPIR-V manipulation, etc.

Now has the ability to create push constant blocks and UBOs from existing inputs (necessary for Vulkan), and the InstructionWriter will be useful for defining further transforms or generators down the line.

Add scalar sampled type field to ShaderType::Image.

No longer assigns locations to builtin uniforms.

Struct varying inputs/outputs need more work.
rdb 5 years ago
parent
commit
0bb5b4f96c

+ 9 - 9
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -191,7 +191,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
       } else {
       } else {
         loc = cgGetParameterResourceIndex(p);
         loc = cgGetParameterResourceIndex(p);
 
 
-        if (loc != 0 && bind._id._name == "vtx_position") {
+        if (loc != 0 && bind._id._name->get_basename() == "vtx_position") {
           // We really have to bind the vertex position to attribute 0, since
           // We really have to bind the vertex position to attribute 0, since
           // OpenGL will hide the model if attribute 0 is not enabled, and we
           // OpenGL will hide the model if attribute 0 is not enabled, and we
           // can only ever be sure that vtx_position is bound.
           // can only ever be sure that vtx_position is bound.
@@ -228,7 +228,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
       }
       }
       loc = _glgsg->_glGetAttribLocation(_glsl_program, attribname);
       loc = _glgsg->_glGetAttribLocation(_glsl_program, attribname);
 
 
-      if (bind._id._name == "vtx_color") {
+      if (bind._id._name->get_basename() == "vtx_color") {
         _color_attrib_index = loc;
         _color_attrib_index = loc;
       }
       }
 
 
@@ -246,7 +246,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
           GLCAT.debug(false) << " (" << resource << ") in the compiled GLSL program.\n";
           GLCAT.debug(false) << " (" << resource << ") in the compiled GLSL program.\n";
         }
         }
 
 
-      } else if (loc != 0 && bind._id._name == "vtx_position") {
+      } else if (loc != 0 && bind._id._name->get_basename() == "vtx_position") {
         // We really have to bind the vertex position to attribute 0, since
         // We really have to bind the vertex position to attribute 0, since
         // OpenGL will hide the model if attribute 0 is not enabled, and we
         // OpenGL will hide the model if attribute 0 is not enabled, and we
         // can only ever be sure that vtx_position is bound.
         // can only ever be sure that vtx_position is bound.
@@ -554,12 +554,12 @@ issue_parameters(int altered) {
         release_resources();
         release_resources();
         return;
         return;
       }
       }
-      CGparameter p = _cg_parameter_map[spec._id._seqno];
+      CGparameter p = _cg_parameter_map[spec._id._location];
       void *data = ptr_data->_ptr;
       void *data = ptr_data->_ptr;
 
 
       switch (ptr_data->_type) {
       switch (ptr_data->_type) {
       case ShaderType::ST_float:
       case ShaderType::ST_float:
-        if (spec._info._type->as_array() != nullptr) {
+        if (spec._id._type->as_array() != nullptr) {
           switch (spec._dim[1]) {
           switch (spec._dim[1]) {
           case 1: cgGLSetParameterArray1f(p, 0, spec._dim[0], (float *)data); continue;
           case 1: cgGLSetParameterArray1f(p, 0, spec._dim[0], (float *)data); continue;
           case 2: cgGLSetParameterArray2f(p, 0, spec._dim[0], (float *)data); continue;
           case 2: cgGLSetParameterArray2f(p, 0, spec._dim[0], (float *)data); continue;
@@ -583,7 +583,7 @@ issue_parameters(int altered) {
         break;
         break;
 
 
       case ShaderType::ST_double:
       case ShaderType::ST_double:
-        if (spec._info._type->as_array() != nullptr) {
+        if (spec._id._type->as_array() != nullptr) {
           switch (spec._dim[1]) {
           switch (spec._dim[1]) {
           case 1: cgGLSetParameterArray1d(p, 0, spec._dim[0], (double *)data); continue;
           case 1: cgGLSetParameterArray1d(p, 0, spec._dim[0], (double *)data); continue;
           case 2: cgGLSetParameterArray2d(p, 0, spec._dim[0], (double *)data); continue;
           case 2: cgGLSetParameterArray2d(p, 0, spec._dim[0], (double *)data); continue;
@@ -637,7 +637,7 @@ issue_parameters(int altered) {
       if (!val) continue;
       if (!val) continue;
       const PN_stdfloat *data = val->get_data();
       const PN_stdfloat *data = val->get_data();
 
 
-      CGparameter p = _cg_parameter_map[spec._id._seqno];
+      CGparameter p = _cg_parameter_map[spec._id._location];
       switch (spec._piece) {
       switch (spec._piece) {
       case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue;
       case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue;
       case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue;
       case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue;
@@ -991,7 +991,7 @@ disable_shader_texture_bindings() {
   }
   }
 
 
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
-    CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
+    CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._location];
     if (p == 0) continue;
     if (p == 0) continue;
 
 
     int texunit = cgGetParameterResourceIndex(p);
     int texunit = cgGetParameterResourceIndex(p);
@@ -1039,7 +1039,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
   for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) {
     Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
     Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
 
 
-    CGparameter p = _cg_parameter_map[spec._id._seqno];
+    CGparameter p = _cg_parameter_map[spec._id._location];
     if (p == 0) {
     if (p == 0) {
       continue;
       continue;
     }
     }

+ 78 - 52
panda/src/glstuff/glShaderContext_src.cxx

@@ -58,7 +58,7 @@ TypeHandle CLP(ShaderContext)::_type_handle;
  * pushed onto _mat_spec.
  * pushed onto _mat_spec.
  */
  */
 bool CLP(ShaderContext)::
 bool CLP(ShaderContext)::
-parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_type, GLint param_size, Shader *objShader) {
+parse_and_set_short_hand_shader_vars(Shader::Parameter &arg_id, GLenum param_type, GLint param_size, Shader *objShader) {
   /*Shader::ShaderArgInfo p;
   /*Shader::ShaderArgInfo p;
   p._id = arg_id;
   p._id = arg_id;
 
 
@@ -243,7 +243,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t
           param_size = 4;
           param_size = 4;
         }
         }
         for (int i = 1; i < param_size; ++i) {
         for (int i = 1; i < param_size; ++i) {
-          bind._id._seqno += 1;
+          bind._id._location += 1;
           bind._piece = (Shader::ShaderMatPiece)((int)bind._piece + 1);
           bind._piece = (Shader::ShaderMatPiece)((int)bind._piece + 1);
           objShader->cp_add_mat_spec(bind);
           objShader->cp_add_mat_spec(bind);
         }
         }
@@ -296,9 +296,9 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
     size_t num_textures = s->_tex_spec.size();
     size_t num_textures = s->_tex_spec.size();
     for (size_t i = 0; i < num_textures;) {
     for (size_t i = 0; i < num_textures;) {
       Shader::ShaderTexSpec &spec = s->_tex_spec[i];
       Shader::ShaderTexSpec &spec = s->_tex_spec[i];
-      nassertd(spec._id._seqno >= 0) continue;
+      nassertd(spec._id._location >= 0) continue;
 
 
-      GLint location = get_uniform_location(spec._id._seqno);
+      GLint location = get_uniform_location(spec._id._location);
       if (location < 0) {
       if (location < 0) {
         // Not used.  Optimize it out.
         // Not used.  Optimize it out.
         s->_tex_spec.erase(s->_tex_spec.begin() + i);
         s->_tex_spec.erase(s->_tex_spec.begin() + i);
@@ -313,14 +313,14 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
     size_t num_images = min(s->_img_spec.size(), (size_t)glgsg->_max_image_units);
     size_t num_images = min(s->_img_spec.size(), (size_t)glgsg->_max_image_units);
     for (size_t i = 0; i < num_images;) {
     for (size_t i = 0; i < num_images;) {
       Shader::ShaderImgSpec &spec = s->_img_spec[i];
       Shader::ShaderImgSpec &spec = s->_img_spec[i];
-      nassertd(spec._id._seqno >= 0) continue;
+      nassertd(spec._id._location >= 0) continue;
 
 
       if (GLCAT.is_debug()) {
       if (GLCAT.is_debug()) {
         GLCAT.debug()
         GLCAT.debug()
-          << "Active uniform " << spec._id._name << " is bound to location " << spec._id._seqno << " (image binding " << i << ")\n";
+          << "Active uniform " << spec._id._name << " is bound to location " << spec._id._location << " (image binding " << i << ")\n";
       }
       }
 
 
-      GLint location = get_uniform_location(spec._id._seqno);
+      GLint location = get_uniform_location(spec._id._location);
       if (location < 0) {
       if (location < 0) {
         // Not used.  Optimize it out.
         // Not used.  Optimize it out.
         s->_img_spec.erase(s->_img_spec.begin() + i);
         s->_img_spec.erase(s->_img_spec.begin() + i);
@@ -338,7 +338,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
     if (_remap_uniform_locations) {
     if (_remap_uniform_locations) {
       for (auto it = s->_mat_spec.begin(); it != s->_mat_spec.end();) {
       for (auto it = s->_mat_spec.begin(); it != s->_mat_spec.end();) {
         const Shader::ShaderMatSpec &spec = *it;
         const Shader::ShaderMatSpec &spec = *it;
-        if (get_uniform_location(spec._id._seqno) < 0) {
+        if (get_uniform_location(spec._id._location) < 0) {
           // Not used.  Optimize it out.
           // Not used.  Optimize it out.
           it = s->_mat_spec.erase(it);
           it = s->_mat_spec.erase(it);
           continue;
           continue;
@@ -348,7 +348,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
 
 
       for (auto it = s->_ptr_spec.begin(); it != s->_ptr_spec.end();) {
       for (auto it = s->_ptr_spec.begin(); it != s->_ptr_spec.end();) {
         const Shader::ShaderPtrSpec &spec = *it;
         const Shader::ShaderPtrSpec &spec = *it;
-        if (get_uniform_location(spec._id._seqno) < 0) {
+        if (get_uniform_location(spec._id._location) < 0) {
           // Not used.  Optimize it out.
           // Not used.  Optimize it out.
           it = s->_ptr_spec.erase(it);
           it = s->_ptr_spec.erase(it);
           continue;
           continue;
@@ -365,7 +365,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
     for (auto it = s->_var_spec.begin(); it != s->_var_spec.end(); ++it) {
     for (auto it = s->_var_spec.begin(); it != s->_var_spec.end(); ++it) {
       Shader::ShaderVarSpec &spec = *it;
       Shader::ShaderVarSpec &spec = *it;
       if (spec._name == InternalName::get_color()) {
       if (spec._name == InternalName::get_color()) {
-        _color_attrib_index = spec._id._seqno;
+        _color_attrib_index = spec._id._location;
         break;
         break;
       }
       }
     }
     }
@@ -823,9 +823,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
 
 
   string param_name(name_buffer);
   string param_name(name_buffer);
 
 
-  Shader::ShaderArgId arg_id;
+  Shader::Parameter arg_id;
   arg_id._name = param_name;
   arg_id._name = param_name;
-  arg_id._seqno = p;
+  arg_id._location = p;
 
 
   // Check if it has a p3d_ prefix - if so, assign special meaning.
   // Check if it has a p3d_ prefix - if so, assign special meaning.
   if (strncmp(name_buffer, "p3d_", 4) == 0) {
   if (strncmp(name_buffer, "p3d_", 4) == 0) {
@@ -957,9 +957,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
           // hard to fix on the 1.10 branch.  We'll have a proper fix on the
           // hard to fix on the 1.10 branch.  We'll have a proper fix on the
           // master branch.
           // master branch.
 #ifdef __APPLE__
 #ifdef __APPLE__
-          bind._id._seqno = p + bind._index * 4;
+          bind._id._location = p + bind._index * 4;
 #else
 #else
-          bind._id._seqno = p + bind._index;
+          bind._id._location = p + bind._index;
 #endif
 #endif
           _shader->cp_add_mat_spec(bind);
           _shader->cp_add_mat_spec(bind);
         }
         }
@@ -1180,7 +1180,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
       for (int i = 0; i < param_size; ++i) {
       for (int i = 0; i < param_size; ++i) {
         Shader::ShaderMatSpec bind;
         Shader::ShaderMatSpec bind;
         bind._id = arg_id;
         bind._id = arg_id;
-        bind._id._seqno = p + i;
+        bind._id._location = p + i;
         bind._piece = Shader::SMP_row3;
         bind._piece = Shader::SMP_row3;
         bind._func = Shader::SMF_first;
         bind._func = Shader::SMF_first;
         bind._index = i;
         bind._index = i;
@@ -1655,8 +1655,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
           break;
           break;
         }
         }
         bind._arg = InternalName::make(param_name);
         bind._arg = InternalName::make(param_name);
-        bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
-        bind._dep[1] = Shader::SSD_NONE;
         _shader->_ptr_spec.push_back(bind);
         _shader->_ptr_spec.push_back(bind);
         return;
         return;
       }
       }
@@ -1784,8 +1782,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
         break;
         break;
       }
       }
       bind._arg = InternalName::make(param_name);
       bind._arg = InternalName::make(param_name);
-      bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame;
-      bind._dep[1] = Shader::SSD_NONE;
       _shader->_ptr_spec.push_back(bind);
       _shader->_ptr_spec.push_back(bind);
       return;
       return;
     }
     }
@@ -1918,52 +1914,84 @@ get_param_type(GLenum param_type) {
 #endif
 #endif
 
 
 #ifndef OPENGLES
 #ifndef OPENGLES
-  case GL_INT_SAMPLER_1D:
-  case GL_UNSIGNED_INT_SAMPLER_1D:
   case GL_SAMPLER_1D:
   case GL_SAMPLER_1D:
   case GL_SAMPLER_1D_SHADOW:
   case GL_SAMPLER_1D_SHADOW:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture, ShaderType::ST_float));
+
+  case GL_INT_SAMPLER_1D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture, ShaderType::ST_int));
+
+  case GL_UNSIGNED_INT_SAMPLER_1D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture, ShaderType::ST_uint));
+
+  case GL_SAMPLER_1D_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture_array, ShaderType::ST_float));
 
 
   case GL_INT_SAMPLER_1D_ARRAY:
   case GL_INT_SAMPLER_1D_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture_array, ShaderType::ST_int));
+
   case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
   case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
-  case GL_SAMPLER_1D_ARRAY:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture_array));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture_array, ShaderType::ST_uint));
 #endif
 #endif
 
 
-  case GL_INT_SAMPLER_2D:
-  case GL_UNSIGNED_INT_SAMPLER_2D:
   case GL_SAMPLER_2D:
   case GL_SAMPLER_2D:
   case GL_SAMPLER_2D_SHADOW:
   case GL_SAMPLER_2D_SHADOW:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture, ShaderType::ST_float));
+
+  case GL_INT_SAMPLER_2D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture, ShaderType::ST_int));
+
+  case GL_UNSIGNED_INT_SAMPLER_2D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture, ShaderType::ST_uint));
+
+  case GL_SAMPLER_3D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_3d_texture, ShaderType::ST_float));
 
 
   case GL_INT_SAMPLER_3D:
   case GL_INT_SAMPLER_3D:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_3d_texture, ShaderType::ST_int));
+
   case GL_UNSIGNED_INT_SAMPLER_3D:
   case GL_UNSIGNED_INT_SAMPLER_3D:
-  case GL_SAMPLER_3D:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_3d_texture));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_3d_texture, ShaderType::ST_uint));
 
 
-  case GL_INT_SAMPLER_CUBE:
-  case GL_UNSIGNED_INT_SAMPLER_CUBE:
   case GL_SAMPLER_CUBE:
   case GL_SAMPLER_CUBE:
   case GL_SAMPLER_CUBE_SHADOW:
   case GL_SAMPLER_CUBE_SHADOW:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map, ShaderType::ST_float));
+
+  case GL_INT_SAMPLER_CUBE:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map, ShaderType::ST_int));
+
+  case GL_UNSIGNED_INT_SAMPLER_CUBE:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map, ShaderType::ST_uint));
 
 
-  case GL_INT_SAMPLER_2D_ARRAY:
-  case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
   case GL_SAMPLER_2D_ARRAY:
   case GL_SAMPLER_2D_ARRAY:
   case GL_SAMPLER_2D_ARRAY_SHADOW:
   case GL_SAMPLER_2D_ARRAY_SHADOW:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture_array));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture_array, ShaderType::ST_float));
+
+  case GL_INT_SAMPLER_2D_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture_array, ShaderType::ST_int));
+
+  case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_2d_texture_array, ShaderType::ST_uint));
 
 
 #ifndef OPENGLES
 #ifndef OPENGLES
-  case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
-  case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
   case GL_SAMPLER_CUBE_MAP_ARRAY:
   case GL_SAMPLER_CUBE_MAP_ARRAY:
   case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
   case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map_array));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map_array, ShaderType::ST_float));
+
+  case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map_array, ShaderType::ST_int));
+
+  case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_cube_map_array, ShaderType::ST_uint));
+
+  case GL_SAMPLER_BUFFER:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_buffer_texture, ShaderType::ST_float));
 
 
   case GL_INT_SAMPLER_BUFFER:
   case GL_INT_SAMPLER_BUFFER:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_buffer_texture, ShaderType::ST_int));
+
   case GL_UNSIGNED_INT_SAMPLER_BUFFER:
   case GL_UNSIGNED_INT_SAMPLER_BUFFER:
-  case GL_SAMPLER_BUFFER:
-    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_buffer_texture));
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_buffer_texture, ShaderType::ST_uint));
 #endif  // !OPENGLES
 #endif  // !OPENGLES
   }
   }
 
 
@@ -2315,7 +2343,7 @@ issue_parameters(int altered) {
       nassertd(spec._dim[1] > 0) continue;
       nassertd(spec._dim[1] > 0) continue;
 
 
       uint32_t dim = spec._dim[1] * spec._dim[2];
       uint32_t dim = spec._dim[1] * spec._dim[2];
-      GLint p = get_uniform_location(spec._id._seqno);
+      GLint p = get_uniform_location(spec._id._location);
       if (p < 0) {
       if (p < 0) {
         continue;
         continue;
       }
       }
@@ -2380,8 +2408,7 @@ issue_parameters(int altered) {
 
 
           // Deactivate it to make sure the user doesn't get flooded with this
           // Deactivate it to make sure the user doesn't get flooded with this
           // error.
           // error.
-          spec._dep[0] = 0;
-          spec._dep[1] = 0;
+          set_uniform_location(spec._id._location, -1);
 
 
         } else {
         } else {
           switch (spec._dim[1] * spec._dim[2]) {
           switch (spec._dim[1] * spec._dim[2]) {
@@ -2402,8 +2429,7 @@ issue_parameters(int altered) {
 
 
           // Deactivate it to make sure the user doesn't get flooded with this
           // Deactivate it to make sure the user doesn't get flooded with this
           // error.
           // error.
-          spec._dep[0] = 0;
-          spec._dep[1] = 0;
+          set_uniform_location(spec._id._location, -1);
 
 
         } else {
         } else {
           switch (spec._dim[1] * spec._dim[2]) {
           switch (spec._dim[1] * spec._dim[2]) {
@@ -2421,8 +2447,8 @@ issue_parameters(int altered) {
 
 
         // Deactivate it to make sure the user doesn't get flooded with this
         // Deactivate it to make sure the user doesn't get flooded with this
         // error.
         // error.
-        spec._dep[0] = 0;
-        spec._dep[1] = 0;
+        set_uniform_location(spec._id._location, -1);
+        break;
 
 
       default:
       default:
         continue;
         continue;
@@ -2449,7 +2475,7 @@ issue_parameters(int altered) {
       const PN_float32 *data = valf.get_data();
       const PN_float32 *data = valf.get_data();
 #endif
 #endif
 
 
-      GLint p = get_uniform_location(spec._id._seqno);
+      GLint p = get_uniform_location(spec._id._location);
       if (p < 0) {
       if (p < 0) {
         continue;
         continue;
       }
       }
@@ -2561,7 +2587,7 @@ disable_shader_vertex_arrays() {
 
 
   for (size_t i = 0; i < _shader->_var_spec.size(); ++i) {
   for (size_t i = 0; i < _shader->_var_spec.size(); ++i) {
     const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
     const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
-    GLint p = bind._id._seqno;
+    GLint p = bind._id._location;
 
 
     for (int i = 0; i < bind._elements; ++i) {
     for (int i = 0; i < bind._elements; ++i) {
       _glgsg->disable_vertex_attrib_array(p + i);
       _glgsg->disable_vertex_attrib_array(p + i);
@@ -2667,7 +2693,7 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
         }
         }
       }
       }
 
 
-      GLint p = bind._id._seqno;
+      GLint p = bind._id._location;
       max_p = max(max_p, p + bind._elements);
       max_p = max(max_p, p + bind._elements);
 
 
       // Don't apply vertex colors if they are disabled with a ColorAttrib.
       // Don't apply vertex colors if they are disabled with a ColorAttrib.
@@ -2764,7 +2790,7 @@ disable_shader_texture_bindings() {
 #ifndef OPENGLES
 #ifndef OPENGLES
     // Check if bindless was used, if so, there's nothing to unbind.
     // Check if bindless was used, if so, there's nothing to unbind.
     if (_glgsg->_supports_bindless_texture) {
     if (_glgsg->_supports_bindless_texture) {
-      GLint p = _shader->_tex_spec[i]._id._seqno;
+      GLint p = _shader->_tex_spec[i]._id._location;
 
 
       if (_glsl_uniform_handles.count(p) > 0) {
       if (_glsl_uniform_handles.count(p) > 0) {
         continue;
         continue;
@@ -3037,7 +3063,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
     }
     }
 
 
 #ifndef OPENGLES
 #ifndef OPENGLES
-    GLint p = spec._id._seqno;
+    GLint p = spec._id._location;
 
 
     // If it was recently written to, we will have to issue a memory barrier
     // If it was recently written to, we will have to issue a memory barrier
     // soon.
     // soon.

+ 1 - 1
panda/src/glstuff/glShaderContext_src.h

@@ -140,7 +140,7 @@ private:
   void report_program_errors(GLuint program, bool fatal);
   void report_program_errors(GLuint program, bool fatal);
   bool attach_shader(const ShaderModule *module);
   bool attach_shader(const ShaderModule *module);
   bool compile_and_link();
   bool compile_and_link();
-  bool parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_type, GLint param_size, Shader *s);
+  bool parse_and_set_short_hand_shader_vars(Shader::Parameter &arg_id, GLenum param_type, GLint param_size, Shader *s);
   void release_resources();
   void release_resources();
 
 
 public:
 public:

+ 115 - 97
panda/src/gobj/shader.cxx

@@ -675,7 +675,7 @@ cg_parameter_type(CGparameter p) {
       default:
       default:
         return nullptr;
         return nullptr;
       }
       }
-      return ::ShaderType::register_type(::ShaderType::SampledImage(texture_type));
+      return ::ShaderType::register_type(::ShaderType::SampledImage(texture_type, ::ShaderType::ST_float));
     }
     }
 
 
   default:
   default:
@@ -1003,7 +1003,10 @@ cg_analyze_entry_point(CGprogram prog, ShaderType type) {
           success &= bind_vertex_input(name, arg_type, -1);
           success &= bind_vertex_input(name, arg_type, -1);
         }
         }
         else if (vbl == CG_UNIFORM) {
         else if (vbl == CG_UNIFORM) {
-          success &= bind_parameter(name, arg_type, -1);
+          Parameter param;
+          param._name = name;
+          param._type = arg_type;
+          success &= bind_parameter(param);
         }
         }
       }
       }
     } else if (shader_cat.is_debug()) {
     } else if (shader_cat.is_debug()) {
@@ -1091,22 +1094,21 @@ cg_analyze_shader(const ShaderCaps &caps) {
     }
     }
   }
   }
 
 
-  // Assign sequence numbers to all parameters.  GLCgShaderContext relies on
-  // the fact that the varyings start at seqno 0.
-  int seqno = 0;
+  // Assign locations to all parameters.  GLCgShaderContext relies on the fact
+  // that the varyings start at location 0.
+  int location = 0;
   for (size_t i = 0; i < _var_spec.size(); ++i) {
   for (size_t i = 0; i < _var_spec.size(); ++i) {
-    _var_spec[i]._id._seqno = seqno++;
+    _var_spec[i]._id._location = location++;
   }
   }
   for (size_t i = 0; i < _mat_spec.size(); ++i) {
   for (size_t i = 0; i < _mat_spec.size(); ++i) {
-    _mat_spec[i]._id._seqno = seqno++;
+    _mat_spec[i]._id._location = location++;
   }
   }
   for (size_t i = 0; i < _tex_spec.size(); ++i) {
   for (size_t i = 0; i < _tex_spec.size(); ++i) {
-    _tex_spec[i]._id._seqno = seqno++;
+    _tex_spec[i]._id._location = location++;
   }
   }
 
 
   for (size_t i = 0; i < _ptr_spec.size(); ++i) {
   for (size_t i = 0; i < _ptr_spec.size(); ++i) {
-    _ptr_spec[i]._id._seqno = seqno++;
-    _ptr_spec[i]._info._id = _ptr_spec[i]._id;
+    _ptr_spec[i]._id._location = location++;
   }
   }
 
 
   /*
   /*
@@ -1264,12 +1266,12 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
     programs_by_type[cgGetProgramDomain(program)] = program;
     programs_by_type[cgGetProgramDomain(program)] = program;
   }
   }
 
 
-  for (size_t i = 0; i < n_mat; ++i) {
-    const ShaderArgId &id = _mat_spec[i]._id;
-    map[id._seqno] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
+  /*for (size_t i = 0; i < n_mat; ++i) {
+    const Parameter &id = _mat_spec[i]._id;
+    map[id._location] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
 
 
     if (shader_cat.is_debug()) {
     if (shader_cat.is_debug()) {
-      const char *resource = cgGetParameterResourceName(map[id._seqno]);
+      const char *resource = cgGetParameterResourceName(map[id._location]);
       if (resource != nullptr) {
       if (resource != nullptr) {
         shader_cat.debug() << "Uniform parameter " << id._name
         shader_cat.debug() << "Uniform parameter " << id._name
                            << " is bound to resource " << resource << "\n";
                            << " is bound to resource " << resource << "\n";
@@ -1278,7 +1280,7 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
   }
   }
 
 
   for (size_t i = 0; i < n_tex; ++i) {
   for (size_t i = 0; i < n_tex; ++i) {
-    const ShaderArgId &id = _tex_spec[i]._id;
+    const Parameter &id = _tex_spec[i]._id;
     CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
     CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
 
 
     if (shader_cat.is_debug()) {
     if (shader_cat.is_debug()) {
@@ -1288,11 +1290,11 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
                           << " is bound to resource " << resource << "\n";
                           << " is bound to resource " << resource << "\n";
       }
       }
     }
     }
-    map[id._seqno] = p;
+    map[id._location] = p;
   }
   }
 
 
   for (size_t i = 0; i < n_var; ++i) {
   for (size_t i = 0; i < n_var; ++i) {
-    const ShaderArgId &id = _var_spec[i]._id;
+    const Parameter &id = _var_spec[i]._id;
     CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
     CGparameter p = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
 
 
     const char *resource = cgGetParameterResourceName(p);
     const char *resource = cgGetParameterResourceName(p);
@@ -1309,21 +1311,21 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
       }
       }
     }
     }
 
 
-    map[id._seqno] = p;
+    map[id._location] = p;
   }
   }
 
 
   for (size_t i = 0; i < n_ptr; ++i) {
   for (size_t i = 0; i < n_ptr; ++i) {
-    const ShaderArgId &id = _ptr_spec[i]._id;
-    map[id._seqno] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
+    const Parameter &id = _ptr_spec[i]._id;
+    map[id._location] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str());
 
 
     if (shader_cat.is_debug()) {
     if (shader_cat.is_debug()) {
-      const char *resource = cgGetParameterResourceName(map[id._seqno]);
+      const char *resource = cgGetParameterResourceName(map[id._location]);
       if (resource != nullptr) {
       if (resource != nullptr) {
         shader_cat.debug() << "Uniform ptr parameter " << id._name
         shader_cat.debug() << "Uniform ptr parameter " << id._name
                            << " is bound to resource " << resource << "\n";
                            << " is bound to resource " << resource << "\n";
       }
       }
     }
     }
-  }
+  }*/
 
 
   // Transfer ownership of the compiled shader.
   // Transfer ownership of the compiled shader.
   if (_cg_vprogram != 0) {
   if (_cg_vprogram != 0) {
@@ -1722,8 +1724,8 @@ do_load_source(ShaderModule::Stage stage, const std::string &source, BamCacheRec
 bool Shader::
 bool Shader::
 link() {
 link() {
   // Go through all the modules to fetch the parameters.
   // Go through all the modules to fetch the parameters.
-  pmap<CPT_InternalName, const ShaderModule::Variable *> parameters_by_name;
-  pvector<const ShaderModule::Variable *> parameters;
+  pmap<CPT_InternalName, Parameter> parameters_by_name;
+  pvector<Parameter *> parameters;
   BitArray used_locations;
   BitArray used_locations;
 
 
   for (COWPT(ShaderModule) &cow_module : _modules) {
   for (COWPT(ShaderModule) &cow_module : _modules) {
@@ -1731,14 +1733,20 @@ link() {
     pmap<int, int> remap;
     pmap<int, int> remap;
 
 
     for (const ShaderModule::Variable &var : module->_parameters) {
     for (const ShaderModule::Variable &var : module->_parameters) {
-      const auto result = parameters_by_name.insert({var.name, &var});
-      const auto &it = result.first;
+      Parameter param;
+      param._name = var.name;
+      param._type = var.type;
+      param._location = var._location;
+      param._stage_mask = (1 << (int)module->get_stage());
+
+      auto result = parameters_by_name.insert({var.name, param});
+      auto &it = result.first;
 
 
       if (!result.second) {
       if (!result.second) {
         // A variable by this name was already added by another stage.  Check
         // A variable by this name was already added by another stage.  Check
         // that it has the same type and location.
         // that it has the same type and location.
-        const ShaderModule::Variable &other = *(it->second);
-        if (other.type != var.type) {
+        Parameter &other = it->second;
+        if (other._type != var.type) {
           shader_cat.error()
           shader_cat.error()
             << "Parameter " << *var.name << " in module " << *module
             << "Parameter " << *var.name << " in module " << *module
             << " is declared in another stage with a mismatching type!\n";
             << " is declared in another stage with a mismatching type!\n";
@@ -1748,10 +1756,11 @@ link() {
         // Aggregate types don't seem to work properly when sharing uniforms
         // Aggregate types don't seem to work properly when sharing uniforms
         // between shader stages.  Needs revisiting.
         // between shader stages.  Needs revisiting.
         if (!var.type->is_aggregate_type()) {
         if (!var.type->is_aggregate_type()) {
-          if (it->second->get_location() != var.get_location()) {
+          if (other._location != param._location) {
             // Different location; need to remap this.
             // Different location; need to remap this.
-            remap[var.get_location()] = it->second->get_location();
+            remap[param._location] = other._location;
           }
           }
+          other._stage_mask |= param._stage_mask;
           continue;
           continue;
         }
         }
       }
       }
@@ -1772,11 +1781,12 @@ link() {
           }
           }
           used_locations.set_range(location, num_locations);
           used_locations.set_range(location, num_locations);
           remap[var.get_location()] = location;
           remap[var.get_location()] = location;
+          it->second._location = location;
         } else {
         } else {
           used_locations.set_range(var.get_location(), num_locations);
           used_locations.set_range(var.get_location(), num_locations);
         }
         }
       }
       }
-      parameters.push_back(&var);
+      parameters.push_back(&(it->second));
     }
     }
 
 
     if (!remap.empty()) {
     if (!remap.empty()) {
@@ -1799,8 +1809,8 @@ link() {
 
 
   // Now bind all of the parameters.
   // Now bind all of the parameters.
   bool success = true;
   bool success = true;
-  for (const ShaderModule::Variable *var : parameters) {
-    if (!bind_parameter(var->name, var->type, var->get_location())) {
+  for (const Parameter *param : parameters) {
+    if (!bind_parameter(*param)) {
       success = false;
       success = false;
     }
     }
   }
   }
@@ -1817,7 +1827,8 @@ bind_vertex_input(const InternalName *name, const ::ShaderType *type, int locati
 
 
   Shader::ShaderVarSpec bind;
   Shader::ShaderVarSpec bind;
   bind._id._name = name_str;
   bind._id._name = name_str;
-  bind._id._seqno = location;
+  bind._id._type = type;
+  bind._id._location = location;
   bind._name = nullptr;
   bind._name = nullptr;
   bind._append_uv = -1;
   bind._append_uv = -1;
 
 
@@ -1906,7 +1917,9 @@ bind_vertex_input(const InternalName *name, const ::ShaderType *type, int locati
  * Binds a uniform parameter with the given type.
  * Binds a uniform parameter with the given type.
  */
  */
 bool Shader::
 bool Shader::
-bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
+bind_parameter(const Parameter &param) {
+  const InternalName *name = param._name;
+  const ::ShaderType *type = param._type;
   std::string name_str = name->get_name();
   std::string name_str = name->get_name();
 
 
   // If this is an empty struct, we bind the individual members.
   // If this is an empty struct, we bind the individual members.
@@ -1918,7 +1931,11 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
       const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
       const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
 
 
       // Recurse.
       // Recurse.
-      if (!bind_parameter(InternalName::make(member.name), member.type, location + i)) {
+      Parameter member_param(param);
+      member_param._name = member.name;
+      member_param._type = member.type;
+      member_param._location += i;
+      if (!bind_parameter(member_param)) {
         success = false;
         success = false;
       }
       }
     }
     }
@@ -1929,13 +1946,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   if (shader_cat.is_debug()) {
   if (shader_cat.is_debug()) {
     shader_cat.debug()
     shader_cat.debug()
       << "Binding parameter " << name_str << " with type " << *type
       << "Binding parameter " << name_str << " with type " << *type
-      << " (location=" << location << ")\n";
+      << " (location=" << param._location << ")\n";
   }
   }
 
 
-  ShaderArgId arg_id;
-  arg_id._name = name_str;
-  arg_id._seqno = location;
-
   // Split it at the underscores.
   // Split it at the underscores.
   vector_string pieces;
   vector_string pieces;
   tokenize(name_str, pieces, "_");
   tokenize(name_str, pieces, "_");
@@ -1966,7 +1979,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         matrix_name.compare(matrix_name.size() - 6, 6, "Matrix") == 0) {
         matrix_name.compare(matrix_name.size() - 6, 6, "Matrix") == 0) {
 
 
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_compose;
       bind._func = SMF_compose;
       bind._arg[0] = nullptr;
       bind._arg[0] = nullptr;
       bind._arg[1] = nullptr;
       bind._arg[1] = nullptr;
@@ -2061,9 +2074,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
 //          // hard to fix on the 1.10 branch.  We'll have a proper fix on the
 //          // hard to fix on the 1.10 branch.  We'll have a proper fix on the
 //          // master branch.
 //          // master branch.
 //#ifdef __APPLE__
 //#ifdef __APPLE__
-//          bind._id._seqno = p + bind._index * 4;
+//          bind._id._location = p + bind._index * 4;
 //#else
 //#else
-//          bind._id._seqno = p + bind._index;
+//          bind._id._location = p + bind._index;
 //#endif
 //#endif
 //          cp_add_mat_spec(bind);
 //          cp_add_mat_spec(bind);
 //        }
 //        }
@@ -2078,7 +2091,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     }
     if (pieces[1].compare(0, 7, "Texture") == 0) {
     if (pieces[1].compare(0, 7, "Texture") == 0) {
       ShaderTexSpec bind;
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._part = STO_stage_i;
       bind._part = STO_stage_i;
       bind._name = 0;
       bind._name = 0;
       bind._desired_type = Texture::TT_2d_texture;
       bind._desired_type = Texture::TT_2d_texture;
@@ -2095,7 +2108,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     }
     if (pieces[1] == "Material") {
     if (pieces[1] == "Material") {
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_attr_material;
       bind._part[0] = SMO_attr_material;
       bind._arg[0] = nullptr;
       bind._arg[0] = nullptr;
@@ -2111,9 +2124,10 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
       for (size_t i = 0; i < struct_type->get_num_members(); ++i) {
       for (size_t i = 0; i < struct_type->get_num_members(); ++i) {
         const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
         const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
 
 
-        CPT(InternalName) fqname = ((InternalName *)name.p())->append(member.name);
-        bind._id._seqno = arg_id._seqno + i;
+        CPT(InternalName) fqname = ((InternalName *)name)->append(member.name);
+        bind._id._location = param._location + i;
         bind._id._name = fqname->get_name();
         bind._id._name = fqname->get_name();
+        bind._id._type = member.type;
 
 
         if (member.name == "baseColor") {
         if (member.name == "baseColor") {
           if (expect_float_vector(fqname, member.type, 4, 4)) {
           if (expect_float_vector(fqname, member.type, 4, 4)) {
@@ -2194,7 +2208,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_attr_colorscale;
       bind._part[0] = SMO_attr_colorscale;
       bind._arg[0] = nullptr;
       bind._arg[0] = nullptr;
@@ -2206,7 +2220,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     }
     if (pieces[1] == "TexAlphaOnly") {
     if (pieces[1] == "TexAlphaOnly") {
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._index = 0;
       bind._index = 0;
       bind._part[0] = SMO_tex_is_alpha_i;
       bind._part[0] = SMO_tex_is_alpha_i;
@@ -2229,13 +2243,13 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
           return report_parameter_error(name, type, "expected 'ambient' member");
           return report_parameter_error(name, type, "expected 'ambient' member");
         }
         }
 
 
-        CPT(InternalName) fqname = ((InternalName *)name.p())->append(member.name);
+        CPT(InternalName) fqname = ((InternalName *)name)->append(member.name);
         if (!expect_float_vector(fqname, member.type, 3, 4)) {
         if (!expect_float_vector(fqname, member.type, 3, 4)) {
           return false;
           return false;
         }
         }
 
 
         ShaderMatSpec bind;
         ShaderMatSpec bind;
-        bind._id = arg_id;
+        bind._id = param;
         bind._func = SMF_first;
         bind._func = SMF_first;
         bind._part[0] = SMO_light_ambient;
         bind._part[0] = SMO_light_ambient;
         bind._arg[0] = nullptr;
         bind._arg[0] = nullptr;
@@ -2263,29 +2277,33 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return report_parameter_error(name, type, "expected array of structs");
         return report_parameter_error(name, type, "expected array of structs");
       }
       }
 
 
+      int location = param._location;
+
       size_t num_members = struct_type->get_num_members();
       size_t num_members = struct_type->get_num_members();
       for (size_t i = 0; i < num_members; ++i) {
       for (size_t i = 0; i < num_members; ++i) {
         const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
         const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
 
 
-        CPT(InternalName) fqname = ((InternalName *)name.p())->append(member.name);
+        CPT(InternalName) fqname = ((InternalName *)name)->append(member.name);
 
 
         if (member.name == "shadowMap") {
         if (member.name == "shadowMap") {
           if (member.type->as_sampled_image() == nullptr) {
           if (member.type->as_sampled_image() == nullptr) {
             return report_parameter_error(name, type, "expected sampler2D");
             return report_parameter_error(name, type, "expected sampler2D");
           }
           }
           ShaderTexSpec bind;
           ShaderTexSpec bind;
-          bind._id = arg_id;
-          bind._id._name = fqname->get_name();
+          bind._id = param;
+          bind._id._name = fqname;
+          bind._id._location = location++;
           bind._part = STO_light_i_shadow_map;
           bind._part = STO_light_i_shadow_map;
           bind._desired_type = Texture::TT_2d_texture;
           bind._desired_type = Texture::TT_2d_texture;
           for (bind._stage = 0; bind._stage < (int)array->get_num_elements(); ++bind._stage) {
           for (bind._stage = 0; bind._stage < (int)array->get_num_elements(); ++bind._stage) {
             _tex_spec.push_back(bind);
             _tex_spec.push_back(bind);
-            bind._id._seqno += num_members;
+            bind._id._location += num_members;
           }
           }
         } else {
         } else {
           ShaderMatSpec bind;
           ShaderMatSpec bind;
-          bind._id = arg_id;
-          bind._id._name = fqname->get_name();
+          bind._id = param;
+          bind._id._name = fqname;
+          bind._id._location = location++;
           bind._func = SMF_first;
           bind._func = SMF_first;
           bind._part[0] = SMO_light_source_i_attrib;
           bind._part[0] = SMO_light_source_i_attrib;
           bind._arg[0] = InternalName::make(member.name);
           bind._arg[0] = InternalName::make(member.name);
@@ -2344,11 +2362,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
           }
           }
           for (bind._index = 0; bind._index < (int)array->get_num_elements(); ++bind._index) {
           for (bind._index = 0; bind._index < (int)array->get_num_elements(); ++bind._index) {
             cp_add_mat_spec(bind);
             cp_add_mat_spec(bind);
-            bind._id._seqno += num_members;
+            bind._id._location += num_members;
           }
           }
         }
         }
-
-        arg_id._seqno += 1;
       }
       }
 
 
       return true;
       return true;
@@ -2364,7 +2380,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     // These inputs are supported by OpenSceneGraph.  We can support them as
     // These inputs are supported by OpenSceneGraph.  We can support them as
     // well, to increase compatibility.
     // well, to increase compatibility.
     ShaderMatSpec bind;
     ShaderMatSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._arg[0] = nullptr;
     bind._arg[0] = nullptr;
     bind._arg[1] = nullptr;
     bind._arg[1] = nullptr;
 
 
@@ -2394,7 +2410,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     }
     else if (pieces[1] == "FrameNumber") {
     else if (pieces[1] == "FrameNumber") {
       if (type == ::ShaderType::int_type) {
       if (type == ::ShaderType::int_type) {
-        _frame_number_loc = location;
+        _frame_number_loc = param._location;
         return true;
         return true;
       } else {
       } else {
         return report_parameter_error(name, type, "expected int");
         return report_parameter_error(name, type, "expected int");
@@ -2457,7 +2473,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._piece = SMP_whole;
       bind._func = SMF_compose;
       bind._func = SMF_compose;
       bind._part[1] = SMO_light_source_i_attrib;
       bind._part[1] = SMO_light_source_i_attrib;
@@ -2501,7 +2517,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
       pieces[0] == "col3") {
       pieces[0] == "col3") {
 
 
     ShaderMatSpec bind;
     ShaderMatSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._func = SMF_compose;
     bind._func = SMF_compose;
 
 
     if (pieces[0] == "trans" || pieces[0] == "tpose") {
     if (pieces[0] == "trans" || pieces[0] == "tpose") {
@@ -2596,7 +2612,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       if (pieces[1] == "material") {
       if (pieces[1] == "material") {
         if (!expect_float_matrix(name, type, 4, 4)) {
         if (!expect_float_matrix(name, type, 4, 4)) {
           return false;
           return false;
@@ -2702,7 +2718,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_alight_x;
       bind._part[0] = SMO_alight_x;
@@ -2720,7 +2736,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_satten_x;
       bind._part[0] = SMO_satten_x;
@@ -2737,7 +2753,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_transpose;
       bind._piece = SMP_transpose;
       int next = 1;
       int next = 1;
       pieces.push_back("");
       pieces.push_back("");
@@ -2778,7 +2794,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._piece = SMP_whole;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_texmat_i;
       bind._part[0] = SMO_texmat_i;
@@ -2797,7 +2813,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_texscale_i;
       bind._part[0] = SMO_texscale_i;
@@ -2816,7 +2832,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_texcolor_i;
       bind._part[0] = SMO_texcolor_i;
@@ -2835,7 +2851,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_plane_x;
       bind._part[0] = SMO_plane_x;
@@ -2853,7 +2869,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_clipplane_x;
       bind._part[0] = SMO_clipplane_x;
@@ -2871,7 +2887,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[1] = SMO_identity;
       bind._part[1] = SMO_identity;
@@ -2913,7 +2929,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return report_parameter_error(name, type, "unrecognized parameter name");
         return report_parameter_error(name, type, "unrecognized parameter name");
       }
       }
       ShaderTexSpec bind;
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._name = nullptr;
       bind._name = nullptr;
       bind._stage = atoi(pieces[1].c_str());
       bind._stage = atoi(pieces[1].c_str());
       bind._part = STO_stage_i;
       bind._part = STO_stage_i;
@@ -2938,7 +2954,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return report_parameter_error(name, type, "unrecognized parameter name");
         return report_parameter_error(name, type, "unrecognized parameter name");
       }
       }
       ShaderTexSpec bind;
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._name = nullptr;
       bind._name = nullptr;
       bind._stage = atoi(pieces[1].c_str());
       bind._stage = atoi(pieces[1].c_str());
       bind._part = STO_light_i_shadow_map;
       bind._part = STO_light_i_shadow_map;
@@ -2961,7 +2977,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_texpad_x;
       bind._part[0] = SMO_texpad_x;
@@ -2978,7 +2994,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
         return false;
       }
       }
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_texpix_x;
       bind._part[0] = SMO_texpix_x;
@@ -3007,7 +3023,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   // user-defined input.
   // user-defined input.
   if (const ::ShaderType::SampledImage *sampler = type->as_sampled_image()) {
   if (const ::ShaderType::SampledImage *sampler = type->as_sampled_image()) {
     ShaderTexSpec bind;
     ShaderTexSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._part = STO_named_input;
     bind._part = STO_named_input;
     bind._name = name;
     bind._name = name;
     bind._desired_type = sampler->get_texture_type();
     bind._desired_type = sampler->get_texture_type();
@@ -3017,7 +3033,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   }
   }
   else if (const ::ShaderType::Image *image = type->as_image()) {
   else if (const ::ShaderType::Image *image = type->as_image()) {
     ShaderImgSpec bind;
     ShaderImgSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._name = name;
     bind._name = name;
     bind._desired_type = image->get_texture_type();
     bind._desired_type = image->get_texture_type();
     bind._writable = image->is_writable();
     bind._writable = image->is_writable();
@@ -3027,7 +3043,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   else if (const ::ShaderType::Matrix *matrix = type->as_matrix()) {
   else if (const ::ShaderType::Matrix *matrix = type->as_matrix()) {
     if (matrix->get_num_columns() == 3 && matrix->get_num_rows() == 3) {
     if (matrix->get_num_columns() == 3 && matrix->get_num_rows() == 3) {
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_upper3x3;
       bind._piece = SMP_upper3x3;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_mat_constant_x;
       bind._part[0] = SMO_mat_constant_x;
@@ -3039,7 +3055,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     }
     else if (matrix->get_num_columns() == 4 && matrix->get_num_rows() == 4) {
     else if (matrix->get_num_columns() == 4 && matrix->get_num_rows() == 4) {
       ShaderMatSpec bind;
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._piece = SMP_whole;
       bind._func = SMF_first;
       bind._func = SMF_first;
       bind._part[0] = SMO_mat_constant_x;
       bind._part[0] = SMO_mat_constant_x;
@@ -3057,7 +3073,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     for (size_t i = 0; i < struct_type->get_num_members(); ++i) {
     for (size_t i = 0; i < struct_type->get_num_members(); ++i) {
       const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
       const ::ShaderType::Struct::Member &member = struct_type->get_member(i);
 
 
-      PT(InternalName) fqname = ((InternalName *)name.p())->append(member.name);
+      PT(InternalName) fqname = ((InternalName *)name)->append(member.name);
 
 
       // Numeric struct members under GLSL may need a special treatment.
       // Numeric struct members under GLSL may need a special treatment.
       ScalarType scalar_type;
       ScalarType scalar_type;
@@ -3070,8 +3086,8 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         // light parameter.  It might also just be a custom struct parameter.
         // light parameter.  It might also just be a custom struct parameter.
         // We can't know yet, so we always have to handle it specially.
         // We can't know yet, so we always have to handle it specially.
         ShaderMatSpec bind;
         ShaderMatSpec bind;
-        bind._id = arg_id;
-        bind._id._seqno += i;
+        bind._id = param;
+        bind._id._location += i;
         if (member.name == "shadowMatrix" && dim[1] == 4 && dim[2] == 4) {
         if (member.name == "shadowMatrix" && dim[1] == 4 && dim[2] == 4) {
           // Special exception for shadowMatrix, which is deprecated because it
           // Special exception for shadowMatrix, which is deprecated because it
           // includes the model transformation.  It is far more efficient to do
           // includes the model transformation.  It is far more efficient to do
@@ -3089,7 +3105,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
           bind._part[0] = SMO_model_to_apiview;
           bind._part[0] = SMO_model_to_apiview;
           bind._arg[0] = nullptr;
           bind._arg[0] = nullptr;
           bind._part[1] = SMO_mat_constant_x_attrib;
           bind._part[1] = SMO_mat_constant_x_attrib;
-          bind._arg[1] = ((InternalName *)name.p())->append("shadowViewMatrix");
+          bind._arg[1] = ((InternalName *)name)->append("shadowViewMatrix");
         }
         }
         else {
         else {
           bind._func = SMF_first;
           bind._func = SMF_first;
@@ -3125,7 +3141,11 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
       }
       }
 
 
       // Otherwise, recurse.
       // Otherwise, recurse.
-      if (!bind_parameter(fqname, member.type, location + i)) {
+      Parameter member_param(param);
+      member_param._name = fqname;
+      member_param._type = member.type;
+      member_param._location += i;
+      if (!bind_parameter(member_param)) {
         success = false;
         success = false;
       }
       }
     }
     }
@@ -3134,6 +3154,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   }
   }
   else if (const ::ShaderType::Array *array_type = type->as_array()) {
   else if (const ::ShaderType::Array *array_type = type->as_array()) {
     // Check if this is an array of structs.
     // Check if this is an array of structs.
+    int location = param._location;
     if (const ::ShaderType::Struct *struct_type = array_type->get_element_type()->as_struct()) {
     if (const ::ShaderType::Struct *struct_type = array_type->get_element_type()->as_struct()) {
       bool success = true;
       bool success = true;
 
 
@@ -3152,8 +3173,11 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
           const ::ShaderType::Struct::Member &member = struct_type->get_member(mi);
           const ::ShaderType::Struct::Member &member = struct_type->get_member(mi);
 
 
           // Recurse.
           // Recurse.
-          PT(InternalName) fqname = elemname->append(member.name);
-          if (!bind_parameter(fqname, member.type, location++)) {
+          Parameter member_param(param);
+          member_param._name = elemname->append(member.name);
+          member_param._type = member.type;
+          member_param._location = location++;
+          if (!bind_parameter(member_param)) {
             success = false;
             success = false;
           }
           }
         }
         }
@@ -3164,15 +3188,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
 
 
   ShaderPtrSpec bind;
   ShaderPtrSpec bind;
   if (type->as_scalar_type(bind._type, bind._dim[0], bind._dim[1], bind._dim[2])) {
   if (type->as_scalar_type(bind._type, bind._dim[0], bind._dim[1], bind._dim[2])) {
-    bind._id = arg_id;
+    bind._id = param;
     bind._arg = std::move(name);
     bind._arg = std::move(name);
 
 
-    // We specify SSD_frame because a PTA may be modified by the app from
-    // frame to frame, and we have no way to know.  So, we must respecify a
-    // PTA at least once every frame.
-    bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
-    bind._dep[1] = SSD_NONE;
-
     //if (k_prefix) {
     //if (k_prefix) {
     //  // Backward compatibility, disables certain checks.
     //  // Backward compatibility, disables certain checks.
     //  bind._dim[0] = -1;
     //  bind._dim[0] = -1;

+ 12 - 18
panda/src/gobj/shader.h

@@ -293,10 +293,11 @@ public:
     SMF_first,
     SMF_first,
   };
   };
 
 
-  struct ShaderArgId {
-    std::string     _name;
-    ShaderType _type;
-    int        _seqno;
+  struct Parameter {
+    CPT_InternalName _name;
+    const ::ShaderType *_type = nullptr;
+    int _location = -1;
+    int _stage_mask = 0;
   };
   };
 
 
   enum ShaderPtrType {
   enum ShaderPtrType {
@@ -307,11 +308,6 @@ public:
     SPT_unknown = ScalarType::ST_unknown,
     SPT_unknown = ScalarType::ST_unknown,
   };
   };
 
 
-  struct ShaderArgInfo {
-    ShaderArgId _id;
-    const ::ShaderType *_type;
-  };
-
   // Container structure for data of parameters ShaderPtrSpec.
   // Container structure for data of parameters ShaderPtrSpec.
   struct ShaderPtrData {
   struct ShaderPtrData {
   private:
   private:
@@ -378,7 +374,7 @@ public:
    */
    */
   struct ShaderMatSpec {
   struct ShaderMatSpec {
     size_t _cache_offset[2];
     size_t _cache_offset[2];
-    ShaderArgId       _id;
+    Parameter         _id;
     ShaderMatFunc     _func;
     ShaderMatFunc     _func;
     ShaderMatInput    _part[2];
     ShaderMatInput    _part[2];
     CPT(InternalName) _arg[2];
     CPT(InternalName) _arg[2];
@@ -389,7 +385,7 @@ public:
   };
   };
 
 
   struct ShaderTexSpec {
   struct ShaderTexSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     CPT(InternalName) _name;
     CPT(InternalName) _name;
     ShaderTexInput    _part;
     ShaderTexInput    _part;
     int               _stage;
     int               _stage;
@@ -398,14 +394,14 @@ public:
   };
   };
 
 
   struct ShaderImgSpec {
   struct ShaderImgSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     CPT(InternalName) _name;
     CPT(InternalName) _name;
     int               _desired_type;
     int               _desired_type;
     bool              _writable;
     bool              _writable;
   };
   };
 
 
   struct ShaderVarSpec {
   struct ShaderVarSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     PT(InternalName)  _name;
     PT(InternalName)  _name;
     int               _append_uv;
     int               _append_uv;
     int               _elements;
     int               _elements;
@@ -413,11 +409,9 @@ public:
   };
   };
 
 
   struct ShaderPtrSpec {
   struct ShaderPtrSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     uint32_t          _dim[3]; //n_elements,rows,cols
     uint32_t          _dim[3]; //n_elements,rows,cols
-    int               _dep[2];
     CPT(InternalName) _arg;
     CPT(InternalName) _arg;
-    ShaderArgInfo     _info;
     ScalarType        _type;
     ScalarType        _type;
   };
   };
 
 
@@ -482,7 +476,7 @@ public:
   void cp_add_mat_spec(ShaderMatSpec &spec);
   void cp_add_mat_spec(ShaderMatSpec &spec);
   size_t cp_get_mat_cache_size() const;
   size_t cp_get_mat_cache_size() const;
 
 
-  bool compile_parameter(ShaderArgId &p);
+  bool compile_parameter(Parameter &p);
 
 
   void clear_parameters();
   void clear_parameters();
 
 
@@ -589,7 +583,7 @@ private:
 public:
 public:
   bool link();
   bool link();
   bool bind_vertex_input(const InternalName *name, const ::ShaderType *type, int location);
   bool bind_vertex_input(const InternalName *name, const ::ShaderType *type, int location);
-  bool bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location);
+  bool bind_parameter(const Parameter &parameter);
 
 
   bool check_modified() const;
   bool check_modified() const;
   ShaderCompiler *get_compiler(ShaderLanguage lang) const;
   ShaderCompiler *get_compiler(ShaderLanguage lang) const;

+ 38 - 3
panda/src/gobj/shaderType.I

@@ -142,9 +142,26 @@ add_member(const ShaderType *type, std::string name) {
   Member member;
   Member member;
   member.type = type;
   member.type = type;
   member.name = std::move(name);
   member.name = std::move(name);
+  member.offset = _members.empty() ? 0 : _members.back().offset + _members.back().type->get_size_bytes();
   _members.push_back(std::move(member));
   _members.push_back(std::move(member));
 }
 }
 
 
+/**
+ * Adds a member to this struct with a given offset.
+ */
+INLINE void ShaderType::Struct::
+add_member(const ShaderType *type, std::string name, uint32_t offset) {
+  pvector<Member>::iterator it = _members.begin();
+  while (it != _members.end() && it->offset < offset) {
+    ++it;
+  }
+  Member member;
+  member.type = type;
+  member.name = std::move(name);
+  member.offset = offset;
+  _members.insert(it, std::move(member));
+}
+
 /**
 /**
  * Constructs an array type from a base type and number of elements.
  * Constructs an array type from a base type and number of elements.
  */
  */
@@ -174,8 +191,9 @@ get_num_elements() const {
  * Constructs an image type.
  * Constructs an image type.
  */
  */
 INLINE ShaderType::Image::
 INLINE ShaderType::Image::
-Image(Texture::TextureType type, Access access) :
+Image(Texture::TextureType type, ScalarType sampled_type, Access access) :
   _texture_type(type),
   _texture_type(type),
+  _sampled_type(sampled_type),
   _access(access) {
   _access(access) {
 }
 }
 
 
@@ -187,6 +205,14 @@ get_texture_type() const {
   return _texture_type;
   return _texture_type;
 }
 }
 
 
+/**
+ * Returns the type of scalar that sampling this image produces.
+ */
+INLINE ShaderType::ScalarType ShaderType::Image::
+get_sampled_type() const {
+  return _sampled_type;
+}
+
 /**
 /**
  * Returns the way this image is accessed.
  * Returns the way this image is accessed.
  */
  */
@@ -207,8 +233,9 @@ is_writable() const {
  * Constructs a sampled image type.
  * Constructs a sampled image type.
  */
  */
 INLINE ShaderType::SampledImage::
 INLINE ShaderType::SampledImage::
-SampledImage(Texture::TextureType type) :
-  _texture_type(type) {
+SampledImage(Texture::TextureType type, ScalarType sampled_type) :
+  _texture_type(type),
+  _sampled_type(sampled_type) {
 }
 }
 
 
 /**
 /**
@@ -218,3 +245,11 @@ INLINE Texture::TextureType ShaderType::SampledImage::
 get_texture_type() const {
 get_texture_type() const {
   return _texture_type;
   return _texture_type;
 }
 }
+
+/**
+ * Returns the type of scalar that sampling this image produces.
+ */
+INLINE ShaderType::ScalarType ShaderType::SampledImage::
+get_sampled_type() const {
+  return _sampled_type;
+}

+ 94 - 4
panda/src/gobj/shaderType.cxx

@@ -81,6 +81,25 @@ std::ostream &operator << (std::ostream &out, ShaderType::ScalarType scalar_type
 }
 }
 
 
 #ifndef CPPPARSER
 #ifndef CPPPARSER
+/**
+ * Returns the size in bytes of this type in memory, if applicable.  Opaque
+ * types will return -1.
+ */
+int ShaderType::
+get_size_bytes() const {
+  ScalarType type;
+  uint32_t dim[3];
+  if (as_scalar_type(type, dim[0], dim[1], dim[2]) && type != ST_bool) {
+    if (type == ST_double) {
+      return 8 * dim[0] * dim[1] * dim[2];
+    } else {
+      return 4 * dim[0] * dim[1] * dim[2];
+    }
+  } else {
+    return -1;
+  }
+}
+
 /**
 /**
  * Returns true if this type contains the given scalar type.
  * Returns true if this type contains the given scalar type.
  */
  */
@@ -213,6 +232,15 @@ compare_to_impl(const ShaderType &other) const {
        - (_num_columns < other_matrix._num_columns);
        - (_num_columns < other_matrix._num_columns);
 }
 }
 
 
+/**
+ * Returns the number of in/out locations taken up by in/out variables having
+ * this type.
+ */
+int ShaderType::Matrix::
+get_num_interface_locations() const {
+  return _num_rows;
+}
+
 /**
 /**
  * Returns true if this type contains the given scalar type.
  * Returns true if this type contains the given scalar type.
  */
  */
@@ -267,6 +295,28 @@ compare_to_impl(const ShaderType &other) const {
   return 0;
   return 0;
 }
 }
 
 
+/**
+ * Returns the size in bytes of this type in memory, if applicable.  Opaque
+ * types will return -1.
+ */
+int ShaderType::Struct::
+get_size_bytes() const {
+  return _members.empty() ? 0 : _members.back().offset + _members.back().type->get_size_bytes();
+}
+
+/**
+ * Returns the number of in/out locations taken up by in/out variables having
+ * this type.
+ */
+int ShaderType::Struct::
+get_num_interface_locations() const {
+  int total = 0;
+  for (const Member &member : _members) {
+    total += member.type->get_num_interface_locations();
+  }
+  return total;
+}
+
 /**
 /**
  * Returns the number of uniform locations taken up by uniform variables having
  * Returns the number of uniform locations taken up by uniform variables having
  * this type.
  * this type.
@@ -326,6 +376,24 @@ compare_to_impl(const ShaderType &other) const {
        - (_num_elements < other_array._num_elements);
        - (_num_elements < other_array._num_elements);
 }
 }
 
 
+/**
+ * Returns the size in bytes of this type in memory, if applicable.  Opaque
+ * types will return -1.
+ */
+int ShaderType::Array::
+get_size_bytes() const {
+  return _element_type->get_size_bytes() * _num_elements;
+}
+
+/**
+ * Returns the number of in/out locations taken up by in/out variables having
+ * this type.
+ */
+int ShaderType::Array::
+get_num_interface_locations() const {
+  return _element_type->get_num_interface_locations() * _num_elements;
+}
+
 /**
 /**
  * Returns the number of uniform locations taken up by uniform variables having
  * Returns the number of uniform locations taken up by uniform variables having
  * this type.
  * this type.
@@ -340,6 +408,11 @@ get_num_parameter_locations() const {
  */
  */
 void ShaderType::Image::
 void ShaderType::Image::
 output(std::ostream &out) const {
 output(std::ostream &out) const {
+  if (_sampled_type == ST_int) {
+    out << 'i';
+  } else if (_sampled_type == ST_uint) {
+    out << 'u';
+  }
   out << "image" << texture_type_suffixes[_texture_type];
   out << "image" << texture_type_suffixes[_texture_type];
 }
 }
 
 
@@ -350,8 +423,16 @@ output(std::ostream &out) const {
 int ShaderType::Image::
 int ShaderType::Image::
 compare_to_impl(const ShaderType &other) const {
 compare_to_impl(const ShaderType &other) const {
   const Image &other_image = (const Image &)other;
   const Image &other_image = (const Image &)other;
-  return (_texture_type > other_image._texture_type)
-       - (_texture_type < other_image._texture_type);
+  if (_texture_type != other_image._texture_type) {
+    return (_texture_type > other_image._texture_type)
+         - (_texture_type < other_image._texture_type);
+  }
+  if (_sampled_type != other_image._sampled_type) {
+    return (_sampled_type > other_image._sampled_type)
+         - (_sampled_type < other_image._sampled_type);
+  }
+  return (_access > other_image._access)
+       - (_access < other_image._access);
 }
 }
 
 
 /**
 /**
@@ -377,6 +458,11 @@ compare_to_impl(const ShaderType &other) const {
  */
  */
 void ShaderType::SampledImage::
 void ShaderType::SampledImage::
 output(std::ostream &out) const {
 output(std::ostream &out) const {
+  if (_sampled_type == ST_int) {
+    out << 'i';
+  } else if (_sampled_type == ST_uint) {
+    out << 'u';
+  }
   out << "sampler" << texture_type_suffixes[_texture_type];
   out << "sampler" << texture_type_suffixes[_texture_type];
 }
 }
 
 
@@ -387,7 +473,11 @@ output(std::ostream &out) const {
 int ShaderType::SampledImage::
 int ShaderType::SampledImage::
 compare_to_impl(const ShaderType &other) const {
 compare_to_impl(const ShaderType &other) const {
   const SampledImage &other_sampled_image = (const SampledImage &)other;
   const SampledImage &other_sampled_image = (const SampledImage &)other;
-  return (_texture_type > other_sampled_image._texture_type)
-       - (_texture_type < other_sampled_image._texture_type);
+  if (_texture_type != other_sampled_image._texture_type) {
+    return (_texture_type > other_sampled_image._texture_type)
+         - (_texture_type < other_sampled_image._texture_type);
+  }
+  return (_sampled_type > other_sampled_image._sampled_type)
+       - (_sampled_type < other_sampled_image._sampled_type);
 }
 }
 #endif  // CPPPARSER
 #endif  // CPPPARSER

+ 17 - 2
panda/src/gobj/shaderType.h

@@ -34,6 +34,8 @@ public:
 
 
   virtual void output(std::ostream &out) const=0;
   virtual void output(std::ostream &out) const=0;
 
 
+  virtual int get_size_bytes() const;
+  virtual int get_num_interface_locations() const { return 1; }
   virtual int get_num_parameter_locations() const { return 1; }
   virtual int get_num_parameter_locations() const { return 1; }
 
 
   enum ScalarType {
   enum ScalarType {
@@ -197,6 +199,8 @@ public:
   virtual bool as_scalar_type(ScalarType &type, uint32_t &num_elements,
   virtual bool as_scalar_type(ScalarType &type, uint32_t &num_elements,
                               uint32_t &num_rows, uint32_t &num_columns) const override;
                               uint32_t &num_rows, uint32_t &num_columns) const override;
 
 
+  virtual int get_num_interface_locations() const override;
+
   const Matrix *as_matrix() const override { return this; }
   const Matrix *as_matrix() const override { return this; }
 
 
   virtual void output(std::ostream &out) const override;
   virtual void output(std::ostream &out) const override;
@@ -232,10 +236,13 @@ public:
   INLINE size_t get_num_members() const;
   INLINE size_t get_num_members() const;
   INLINE const Member &get_member(size_t i) const;
   INLINE const Member &get_member(size_t i) const;
   INLINE void add_member(const ShaderType *type, std::string name);
   INLINE void add_member(const ShaderType *type, std::string name);
+  INLINE void add_member(const ShaderType *type, std::string name, uint32_t offset);
 
 
   virtual void output(std::ostream &out) const override;
   virtual void output(std::ostream &out) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
 
 
+  virtual int get_size_bytes() const override;
+  virtual int get_num_interface_locations() const override;
   virtual int get_num_parameter_locations() const override;
   virtual int get_num_parameter_locations() const override;
 
 
   bool is_aggregate_type() const override { return true; }
   bool is_aggregate_type() const override { return true; }
@@ -248,6 +255,7 @@ PUBLISHED:
   struct Member {
   struct Member {
     const ShaderType *type;
     const ShaderType *type;
     std::string name;
     std::string name;
+    uint32_t offset;
   };
   };
 
 
 private:
 private:
@@ -284,6 +292,8 @@ public:
   virtual void output(std::ostream &out) const override;
   virtual void output(std::ostream &out) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
 
 
+  virtual int get_size_bytes() const override;
+  virtual int get_num_interface_locations() const override;
   virtual int get_num_parameter_locations() const override;
   virtual int get_num_parameter_locations() const override;
 
 
   bool is_aggregate_type() const override { return true; }
   bool is_aggregate_type() const override { return true; }
@@ -324,9 +334,10 @@ PUBLISHED:
   };
   };
 
 
 public:
 public:
-  INLINE Image(Texture::TextureType texture_type, Access access);
+  INLINE Image(Texture::TextureType texture_type, ScalarType sampled_type, Access access);
 
 
   INLINE Texture::TextureType get_texture_type() const;
   INLINE Texture::TextureType get_texture_type() const;
+  INLINE ScalarType get_sampled_type() const;
   INLINE Access get_access() const;
   INLINE Access get_access() const;
   INLINE bool is_writable() const;
   INLINE bool is_writable() const;
 
 
@@ -337,11 +348,13 @@ public:
 
 
 PUBLISHED:
 PUBLISHED:
   MAKE_PROPERTY(texture_type, get_texture_type);
   MAKE_PROPERTY(texture_type, get_texture_type);
+  MAKE_PROPERTY(sampled_type, get_sampled_type);
   MAKE_PROPERTY(access, get_access);
   MAKE_PROPERTY(access, get_access);
   MAKE_PROPERTY(writable, is_writable);
   MAKE_PROPERTY(writable, is_writable);
 
 
 private:
 private:
   Texture::TextureType _texture_type;
   Texture::TextureType _texture_type;
+  ScalarType _sampled_type;
   Access _access;
   Access _access;
 
 
 public:
 public:
@@ -390,9 +403,10 @@ private:
  */
  */
 class EXPCL_PANDA_GOBJ ShaderType::SampledImage final : public ShaderType {
 class EXPCL_PANDA_GOBJ ShaderType::SampledImage final : public ShaderType {
 public:
 public:
-  INLINE SampledImage(Texture::TextureType texture_type);
+  INLINE SampledImage(Texture::TextureType texture_type, ScalarType sampled_type);
 
 
   INLINE Texture::TextureType get_texture_type() const;
   INLINE Texture::TextureType get_texture_type() const;
+  INLINE ScalarType get_sampled_type() const;
 
 
   virtual void output(std::ostream &out) const override;
   virtual void output(std::ostream &out) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
@@ -401,6 +415,7 @@ public:
 
 
 private:
 private:
   Texture::TextureType _texture_type;
   Texture::TextureType _texture_type;
+  ScalarType _sampled_type;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 95 - 6
panda/src/shaderpipeline/shaderModuleSpirV.I

@@ -14,7 +14,7 @@
 /**
 /**
  * Returns a pointer to the raw words.
  * Returns a pointer to the raw words.
  */
  */
-const uint32_t *ShaderModuleSpirV::
+INLINE const uint32_t *ShaderModuleSpirV::
 get_data() const {
 get_data() const {
   return _instructions.get_data();
   return _instructions.get_data();
 }
 }
@@ -22,11 +22,41 @@ get_data() const {
 /**
 /**
  * Returns the number of words in the module.
  * Returns the number of words in the module.
  */
  */
-size_t ShaderModuleSpirV::
+INLINE size_t ShaderModuleSpirV::
 get_data_size() const {
 get_data_size() const {
   return _instructions.get_data_size();
   return _instructions.get_data_size();
 }
 }
 
 
+/**
+ * Returns true if this is a debug instruction.
+ */
+INLINE bool ShaderModuleSpirV::Instruction::
+is_debug() const {
+  return
+    opcode == spv::OpSourceContinued ||
+    opcode == spv::OpSource ||
+    opcode == spv::OpSourceExtension ||
+    opcode == spv::OpName ||
+    opcode == spv::OpMemberName ||
+    opcode == spv::OpString ||
+    opcode == spv::OpLine ||
+    opcode == spv::OpNoLine ||
+    opcode == spv::OpModuleProcessed;
+}
+
+/**
+ * Returns true if this is an annotation instruction.
+ */
+INLINE bool ShaderModuleSpirV::Instruction::
+is_annotation() const {
+  return
+    opcode == spv::OpDecorate ||
+    opcode == spv::OpMemberDecorate ||
+    opcode == spv::OpGroupDecorate ||
+    opcode == spv::OpGroupMemberDecorate ||
+    opcode == spv::OpDecorationGroup;
+}
+
 /**
 /**
  * Iterator dereference operator.
  * Iterator dereference operator.
  */
  */
@@ -133,6 +163,35 @@ begin_annotations() {
   return it;
   return it;
 }
 }
 
 
+/**
+ * Returns an iterator to the end of the annotations block.
+ */
+INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
+end_annotations() {
+  iterator it;
+  for (it = begin_annotations(); it != end(); ++it) {
+    if (!(*it).is_annotation()) {
+      break;
+    }
+  }
+  return it;
+}
+
+/**
+ * Returns an iterator to the beginning of the functions block.
+ */
+INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
+begin_functions() {
+  iterator it;
+  for (it = begin(); it != end(); ++it) {
+    spv::Op opcode = (*it).opcode;
+    if (opcode == spv::OpFunction) {
+      break;
+    }
+  }
+  return it;
+}
+
 /**
 /**
  * Returns an iterator past the end of the instruction stream.
  * Returns an iterator past the end of the instruction stream.
  */
  */
@@ -147,7 +206,7 @@ end() {
  * instruction.
  * instruction.
  */
  */
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
-insert(iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args) {
+insert(const iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args) {
   return insert(it, opcode, args.begin(), args.size());
   return insert(it, opcode, args.begin(), args.size());
 }
 }
 
 
@@ -157,7 +216,7 @@ insert(iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args) {
  * instruction.
  * instruction.
  */
  */
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
-insert(iterator &it, spv::Op opcode, const uint32_t *args, uint16_t nargs) {
+insert(const iterator &it, spv::Op opcode, const uint32_t *args, uint16_t nargs) {
   ptrdiff_t offset = it._words - &_words[0];
   ptrdiff_t offset = it._words - &_words[0];
 
 
   // If this triggers, you used an invalid iterator.
   // If this triggers, you used an invalid iterator.
@@ -169,12 +228,42 @@ insert(iterator &it, spv::Op opcode, const uint32_t *args, uint16_t nargs) {
   return iterator(&_words[offset]);
   return iterator(&_words[offset]);
 }
 }
 
 
+/**
+ * Inserts a new instruction before the given other one.  Invalidates existing
+ * iterators, but returns a new one pointing to the location of the inserted
+ * instruction.
+ */
+INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
+insert(const iterator &it, const Instruction &op) {
+  return insert(it, op.opcode, op.args, op.nargs);
+}
+
+/**
+ * Inserts the given argument of the given instruction.
+ */
+INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
+insert_arg(const iterator &it, uint16_t arg_index, uint32_t arg) {
+  ptrdiff_t offset = it._words - &_words[0];
+
+  // If this triggers, you used an invalid iterator.
+  assert(offset >= 0 && (size_t)offset <= _words.size());
+
+  uint16_t wcount = _words[offset] >> spv::WordCountShift;
+  nassertr(arg_index < wcount - 1, it);
+
+  spv::Op op = (spv::Op)(_words[offset] & spv::OpCodeMask);
+  _words[offset] = op | ((wcount + 1) << spv::WordCountShift);
+  _words.insert(_words.begin() + offset + 1 + arg_index, arg);
+
+  return iterator(&_words[offset]);
+}
+
 /**
 /**
  * Erases the given instruction.  Invalidates iterators at or after the
  * Erases the given instruction.  Invalidates iterators at or after the
  * insertion point, but returns a new iterator pointing to the next element.
  * insertion point, but returns a new iterator pointing to the next element.
  */
  */
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
-erase(iterator &it) {
+erase(const iterator &it) {
   ptrdiff_t offset = it._words - &_words[0];
   ptrdiff_t offset = it._words - &_words[0];
 
 
   // If this triggers, you used an invalid iterator.
   // If this triggers, you used an invalid iterator.
@@ -190,7 +279,7 @@ erase(iterator &it) {
  * Erases the given argument of the given instruction.
  * Erases the given argument of the given instruction.
  */
  */
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
-erase_arg(iterator &it, uint16_t arg) {
+erase_arg(const iterator &it, uint16_t arg) {
   ptrdiff_t offset = it._words - &_words[0];
   ptrdiff_t offset = it._words - &_words[0];
 
 
   // If this triggers, you used an invalid iterator.
   // If this triggers, you used an invalid iterator.

File diff suppressed because it is too large
+ 1141 - 598
panda/src/shaderpipeline/shaderModuleSpirV.cxx


+ 82 - 25
panda/src/shaderpipeline/shaderModuleSpirV.h

@@ -41,12 +41,21 @@ public:
 
 
   class InstructionStream;
   class InstructionStream;
 
 
+  /**
+   * A single instruction as returned by the InstructionIterator.
+   */
   struct Instruction {
   struct Instruction {
     const spv::Op opcode;
     const spv::Op opcode;
     const uint32_t nargs;
     const uint32_t nargs;
     uint32_t *args;
     uint32_t *args;
+
+    INLINE bool is_debug() const;
+    INLINE bool is_annotation() const;
   };
   };
 
 
+  /**
+   * Provided by InstructionStream to iterate over the instructions.
+   */
   class InstructionIterator {
   class InstructionIterator {
   public:
   public:
     constexpr InstructionIterator() = default;
     constexpr InstructionIterator() = default;
@@ -79,15 +88,17 @@ public:
 
 
     INLINE operator std::vector<uint32_t> & ();
     INLINE operator std::vector<uint32_t> & ();
 
 
-    InstructionStream strip() const;
-
     INLINE iterator begin();
     INLINE iterator begin();
     INLINE iterator begin_annotations();
     INLINE iterator begin_annotations();
+    INLINE iterator end_annotations();
+    INLINE iterator begin_functions();
     INLINE iterator end();
     INLINE iterator end();
-    INLINE iterator insert(iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args);
-    INLINE iterator insert(iterator &it, spv::Op opcode, const uint32_t *args, uint16_t nargs);
-    INLINE iterator erase(iterator &it);
-    INLINE iterator erase_arg(iterator &it, uint16_t arg);
+    INLINE iterator insert(const iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args);
+    INLINE iterator insert(const iterator &it, spv::Op opcode, const uint32_t *args, uint16_t nargs);
+    INLINE iterator insert(const iterator &it, const Instruction &op);
+    INLINE iterator insert_arg(const iterator &it, uint16_t arg_index, uint32_t arg);
+    INLINE iterator erase(const iterator &it);
+    INLINE iterator erase_arg(const iterator &it, uint16_t arg);
 
 
     INLINE const uint32_t *get_data() const;
     INLINE const uint32_t *get_data() const;
     INLINE size_t get_data_size() const;
     INLINE size_t get_data_size() const;
@@ -103,7 +114,6 @@ public:
 
 
   InstructionStream _instructions;
   InstructionStream _instructions;
 
 
-protected:
   enum DefinitionType {
   enum DefinitionType {
     DT_none,
     DT_none,
     DT_type,
     DT_type,
@@ -113,6 +123,18 @@ protected:
     DT_ext_inst,
     DT_ext_inst,
   };
   };
 
 
+  /**
+   * Used by below Definition struct to hold member info.
+   */
+  struct MemberDefinition {
+    std::string _name;
+    uint32_t _type_id = 0;
+    int _location = -1;
+    int _offset = -1;
+    spv::BuiltIn _builtin = spv::BuiltInMax;
+  };
+  typedef pvector<MemberDefinition> MemberDefinitions;
+
   /**
   /**
    * Temporary structure to hold a single definition, which could be a variable,
    * Temporary structure to hold a single definition, which could be a variable,
    * type or type pointer in the SPIR-V file.
    * type or type pointer in the SPIR-V file.
@@ -124,38 +146,73 @@ protected:
     int _location = -1;
     int _location = -1;
     spv::BuiltIn _builtin = spv::BuiltInMax;
     spv::BuiltIn _builtin = spv::BuiltInMax;
     uint32_t _constant = 0;
     uint32_t _constant = 0;
-    vector_string _member_names;
+    uint32_t _type_id = 0;
+    MemberDefinitions _members;
     bool _used = false;
     bool _used = false;
 
 
     // Only defined for DT_variable.
     // Only defined for DT_variable.
     spv::StorageClass _storage_class;
     spv::StorageClass _storage_class;
 
 
-    void set_name(const char *name);
-    void set_member_name(uint32_t i, const char *name);
+    bool has_builtin() const;
+    const MemberDefinition &get_member(uint32_t i) const;
+    MemberDefinition &modify_member(uint32_t i);
+    void clear();
+  };
+  typedef pvector<Definition> Definitions;
+
+  /**
+   * An InstructionWriter can be used for more advanced transformations on a
+   * SPIR-V instruction stream.  It sets up temporary support structures that
+   * help make changes more efficiently.  Only one writer to a given stream may
+   * exist at any given time, and the stream may not be modified by other means
+   * in the meantime.
+   */
+  class InstructionWriter {
+  public:
+    InstructionWriter(InstructionStream &stream);
 
 
-    void set_type(const ShaderType *type);
-    void set_type_pointer(spv::StorageClass storage_class, const ShaderType *type);
-    void set_variable(const ShaderType *type, spv::StorageClass storage_class);
-    void set_constant(const ShaderType *type, const uint32_t *words, uint32_t nwords);
-    void set_ext_inst(const char *name);
+    uint32_t find_definition(const std::string &name) const;
+    const Definition &get_definition(uint32_t id) const;
+    Definition &modify_definition(uint32_t id);
 
 
-    void mark_used();
+    void assign_locations(Stage stage);
 
 
-    void clear();
+    void flatten_struct(uint32_t type_id);
+    uint32_t make_block(const ShaderType::Struct *block_type, const pvector<int> &locations,
+                        spv::StorageClass storage_class, uint32_t binding=0, uint32_t set=0);
+
+    uint32_t define_variable(const ShaderType *type, spv::StorageClass storage_class);
+    uint32_t define_type_pointer(const ShaderType *type, spv::StorageClass storage_class);
+    uint32_t define_type(const ShaderType *type);
+    uint32_t define_constant(const ShaderType *type, uint32_t constant);
+
+  private:
+    uint32_t r_define_variable(InstructionIterator &it, const ShaderType *type, spv::StorageClass storage_class);
+    uint32_t r_define_type_pointer(InstructionIterator &it, const ShaderType *type, spv::StorageClass storage_class);
+    uint32_t r_define_type(InstructionIterator &it, const ShaderType *type);
+    uint32_t r_define_constant(InstructionIterator &it, const ShaderType *type, uint32_t constant);
+    void r_annotate_struct_layout(InstructionIterator &it, uint32_t type_id);
+
+    void parse_instruction(const Instruction &op);
+    void record_type(uint32_t id, const ShaderType *type);
+    void record_type_pointer(uint32_t id, spv::StorageClass storage_class, uint32_t type_id);
+    void record_variable(uint32_t id, uint32_t type_pointer_id, spv::StorageClass storage_class);
+    void record_constant(uint32_t id, uint32_t type_id, const uint32_t *words, uint32_t nwords);
+    void record_ext_inst_import(uint32_t id, const char *import);
+
+    InstructionStream &_instructions;
+    Definitions _defs;
+
+    // Reverse mapping from type to ID.  Excludes types with BuiltIn decoration.
+    typedef pmap<const ShaderType *, uint32_t> TypeMap;
+    TypeMap _type_map;
   };
   };
-  typedef pvector<Definition> Definitions;
 
 
 private:
 private:
-  bool parse(Definitions &defs);
-  bool parse_instruction(Definitions &defs, spv::Op opcode,
-                         const uint32_t *args, size_t nargs);
-
-  void assign_locations(Definitions &defs);
   void remap_locations(spv::StorageClass storage_class, const pmap<int, int> &locations);
   void remap_locations(spv::StorageClass storage_class, const pmap<int, int> &locations);
-
-  void flatten_struct(Definitions &defs, uint32_t type_id);
   void strip();
   void strip();
 
 
+private:
   int _index;
   int _index;
 
 
 public:
 public:

Some files were not shown because too many files changed in this diff