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 {
         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
           // OpenGL will hide the model if attribute 0 is not enabled, and we
           // 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);
 
-      if (bind._id._name == "vtx_color") {
+      if (bind._id._name->get_basename() == "vtx_color") {
         _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";
         }
 
-      } 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
         // OpenGL will hide the model if attribute 0 is not enabled, and we
         // can only ever be sure that vtx_position is bound.
@@ -554,12 +554,12 @@ issue_parameters(int altered) {
         release_resources();
         return;
       }
-      CGparameter p = _cg_parameter_map[spec._id._seqno];
+      CGparameter p = _cg_parameter_map[spec._id._location];
       void *data = ptr_data->_ptr;
 
       switch (ptr_data->_type) {
       case ShaderType::ST_float:
-        if (spec._info._type->as_array() != nullptr) {
+        if (spec._id._type->as_array() != nullptr) {
           switch (spec._dim[1]) {
           case 1: cgGLSetParameterArray1f(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;
 
       case ShaderType::ST_double:
-        if (spec._info._type->as_array() != nullptr) {
+        if (spec._id._type->as_array() != nullptr) {
           switch (spec._dim[1]) {
           case 1: cgGLSetParameterArray1d(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;
       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) {
       case Shader::SMP_whole: GLfc(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) {
-    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;
 
     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) {
     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) {
       continue;
     }

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

@@ -58,7 +58,7 @@ TypeHandle CLP(ShaderContext)::_type_handle;
  * pushed onto _mat_spec.
  */
 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;
   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;
         }
         for (int i = 1; i < param_size; ++i) {
-          bind._id._seqno += 1;
+          bind._id._location += 1;
           bind._piece = (Shader::ShaderMatPiece)((int)bind._piece + 1);
           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();
     for (size_t i = 0; i < num_textures;) {
       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) {
         // Not used.  Optimize it out.
         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);
     for (size_t i = 0; i < num_images;) {
       Shader::ShaderImgSpec &spec = s->_img_spec[i];
-      nassertd(spec._id._seqno >= 0) continue;
+      nassertd(spec._id._location >= 0) continue;
 
       if (GLCAT.is_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) {
         // Not used.  Optimize it out.
         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) {
       for (auto it = s->_mat_spec.begin(); it != s->_mat_spec.end();) {
         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.
           it = s->_mat_spec.erase(it);
           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();) {
         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.
           it = s->_ptr_spec.erase(it);
           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) {
       Shader::ShaderVarSpec &spec = *it;
       if (spec._name == InternalName::get_color()) {
-        _color_attrib_index = spec._id._seqno;
+        _color_attrib_index = spec._id._location;
         break;
       }
     }
@@ -823,9 +823,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
 
   string param_name(name_buffer);
 
-  Shader::ShaderArgId arg_id;
+  Shader::Parameter arg_id;
   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.
   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
           // master branch.
 #ifdef __APPLE__
-          bind._id._seqno = p + bind._index * 4;
+          bind._id._location = p + bind._index * 4;
 #else
-          bind._id._seqno = p + bind._index;
+          bind._id._location = p + bind._index;
 #endif
           _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) {
         Shader::ShaderMatSpec bind;
         bind._id = arg_id;
-        bind._id._seqno = p + i;
+        bind._id._location = p + i;
         bind._piece = Shader::SMP_row3;
         bind._func = Shader::SMF_first;
         bind._index = i;
@@ -1655,8 +1655,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
           break;
         }
         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);
         return;
       }
@@ -1784,8 +1782,6 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
         break;
       }
       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);
       return;
     }
@@ -1918,52 +1914,84 @@ get_param_type(GLenum param_type) {
 #endif
 
 #ifndef OPENGLES
-  case GL_INT_SAMPLER_1D:
-  case GL_UNSIGNED_INT_SAMPLER_1D:
   case GL_SAMPLER_1D:
   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:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_1d_texture_array, ShaderType::ST_int));
+
   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
 
-  case GL_INT_SAMPLER_2D:
-  case GL_UNSIGNED_INT_SAMPLER_2D:
   case GL_SAMPLER_2D:
   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:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_3d_texture, ShaderType::ST_int));
+
   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_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_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
-  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_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:
+    return ShaderType::register_type(ShaderType::SampledImage(Texture::TT_buffer_texture, ShaderType::ST_int));
+
   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
   }
 
@@ -2315,7 +2343,7 @@ issue_parameters(int altered) {
       nassertd(spec._dim[1] > 0) continue;
 
       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) {
         continue;
       }
@@ -2380,8 +2408,7 @@ issue_parameters(int altered) {
 
           // Deactivate it to make sure the user doesn't get flooded with this
           // error.
-          spec._dep[0] = 0;
-          spec._dep[1] = 0;
+          set_uniform_location(spec._id._location, -1);
 
         } else {
           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
           // error.
-          spec._dep[0] = 0;
-          spec._dep[1] = 0;
+          set_uniform_location(spec._id._location, -1);
 
         } else {
           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
         // error.
-        spec._dep[0] = 0;
-        spec._dep[1] = 0;
+        set_uniform_location(spec._id._location, -1);
+        break;
 
       default:
         continue;
@@ -2449,7 +2475,7 @@ issue_parameters(int altered) {
       const PN_float32 *data = valf.get_data();
 #endif
 
-      GLint p = get_uniform_location(spec._id._seqno);
+      GLint p = get_uniform_location(spec._id._location);
       if (p < 0) {
         continue;
       }
@@ -2561,7 +2587,7 @@ disable_shader_vertex_arrays() {
 
   for (size_t i = 0; i < _shader->_var_spec.size(); ++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) {
       _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);
 
       // Don't apply vertex colors if they are disabled with a ColorAttrib.
@@ -2764,7 +2790,7 @@ disable_shader_texture_bindings() {
 #ifndef OPENGLES
     // Check if bindless was used, if so, there's nothing to unbind.
     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) {
         continue;
@@ -3037,7 +3063,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
     }
 
 #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
     // soon.

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

@@ -140,7 +140,7 @@ private:
   void report_program_errors(GLuint program, bool fatal);
   bool attach_shader(const ShaderModule *module);
   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();
 
 public:

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

@@ -675,7 +675,7 @@ cg_parameter_type(CGparameter p) {
       default:
         return nullptr;
       }
-      return ::ShaderType::register_type(::ShaderType::SampledImage(texture_type));
+      return ::ShaderType::register_type(::ShaderType::SampledImage(texture_type, ::ShaderType::ST_float));
     }
 
   default:
@@ -1003,7 +1003,10 @@ cg_analyze_entry_point(CGprogram prog, ShaderType type) {
           success &= bind_vertex_input(name, arg_type, -1);
         }
         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()) {
@@ -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) {
-    _var_spec[i]._id._seqno = seqno++;
+    _var_spec[i]._id._location = location++;
   }
   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) {
-    _tex_spec[i]._id._seqno = seqno++;
+    _tex_spec[i]._id._location = location++;
   }
 
   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;
   }
 
-  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()) {
-      const char *resource = cgGetParameterResourceName(map[id._seqno]);
+      const char *resource = cgGetParameterResourceName(map[id._location]);
       if (resource != nullptr) {
         shader_cat.debug() << "Uniform parameter " << id._name
                            << " 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) {
-    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());
 
     if (shader_cat.is_debug()) {
@@ -1288,11 +1290,11 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
                           << " is bound to resource " << resource << "\n";
       }
     }
-    map[id._seqno] = p;
+    map[id._location] = p;
   }
 
   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());
 
     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) {
-    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()) {
-      const char *resource = cgGetParameterResourceName(map[id._seqno]);
+      const char *resource = cgGetParameterResourceName(map[id._location]);
       if (resource != nullptr) {
         shader_cat.debug() << "Uniform ptr parameter " << id._name
                            << " is bound to resource " << resource << "\n";
       }
     }
-  }
+  }*/
 
   // Transfer ownership of the compiled shader.
   if (_cg_vprogram != 0) {
@@ -1722,8 +1724,8 @@ do_load_source(ShaderModule::Stage stage, const std::string &source, BamCacheRec
 bool Shader::
 link() {
   // 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;
 
   for (COWPT(ShaderModule) &cow_module : _modules) {
@@ -1731,14 +1733,20 @@ link() {
     pmap<int, int> remap;
 
     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) {
         // A variable by this name was already added by another stage.  Check
         // 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()
             << "Parameter " << *var.name << " in module " << *module
             << " 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
         // between shader stages.  Needs revisiting.
         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.
-            remap[var.get_location()] = it->second->get_location();
+            remap[param._location] = other._location;
           }
+          other._stage_mask |= param._stage_mask;
           continue;
         }
       }
@@ -1772,11 +1781,12 @@ link() {
           }
           used_locations.set_range(location, num_locations);
           remap[var.get_location()] = location;
+          it->second._location = location;
         } else {
           used_locations.set_range(var.get_location(), num_locations);
         }
       }
-      parameters.push_back(&var);
+      parameters.push_back(&(it->second));
     }
 
     if (!remap.empty()) {
@@ -1799,8 +1809,8 @@ link() {
 
   // Now bind all of the parameters.
   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;
     }
   }
@@ -1817,7 +1827,8 @@ bind_vertex_input(const InternalName *name, const ::ShaderType *type, int locati
 
   Shader::ShaderVarSpec bind;
   bind._id._name = name_str;
-  bind._id._seqno = location;
+  bind._id._type = type;
+  bind._id._location = location;
   bind._name = nullptr;
   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.
  */
 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();
 
   // 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);
 
       // 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;
       }
     }
@@ -1929,13 +1946,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   if (shader_cat.is_debug()) {
     shader_cat.debug()
       << "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.
   vector_string 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) {
 
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_compose;
       bind._arg[0] = 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
 //          // master branch.
 //#ifdef __APPLE__
-//          bind._id._seqno = p + bind._index * 4;
+//          bind._id._location = p + bind._index * 4;
 //#else
-//          bind._id._seqno = p + bind._index;
+//          bind._id._location = p + bind._index;
 //#endif
 //          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) {
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._part = STO_stage_i;
       bind._name = 0;
       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") {
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._part[0] = SMO_attr_material;
       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) {
         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._type = member.type;
 
         if (member.name == "baseColor") {
           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;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._part[0] = SMO_attr_colorscale;
       bind._arg[0] = nullptr;
@@ -2206,7 +2220,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     if (pieces[1] == "TexAlphaOnly") {
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._func = SMF_first;
       bind._index = 0;
       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");
         }
 
-        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)) {
           return false;
         }
 
         ShaderMatSpec bind;
-        bind._id = arg_id;
+        bind._id = param;
         bind._func = SMF_first;
         bind._part[0] = SMO_light_ambient;
         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");
       }
 
+      int location = param._location;
+
       size_t num_members = struct_type->get_num_members();
       for (size_t i = 0; i < num_members; ++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.type->as_sampled_image() == nullptr) {
             return report_parameter_error(name, type, "expected sampler2D");
           }
           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._desired_type = Texture::TT_2d_texture;
           for (bind._stage = 0; bind._stage < (int)array->get_num_elements(); ++bind._stage) {
             _tex_spec.push_back(bind);
-            bind._id._seqno += num_members;
+            bind._id._location += num_members;
           }
         } else {
           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._part[0] = SMO_light_source_i_attrib;
           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) {
             cp_add_mat_spec(bind);
-            bind._id._seqno += num_members;
+            bind._id._location += num_members;
           }
         }
-
-        arg_id._seqno += 1;
       }
 
       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
     // well, to increase compatibility.
     ShaderMatSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._arg[0] = nullptr;
     bind._arg[1] = nullptr;
 
@@ -2394,7 +2410,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
     }
     else if (pieces[1] == "FrameNumber") {
       if (type == ::ShaderType::int_type) {
-        _frame_number_loc = location;
+        _frame_number_loc = param._location;
         return true;
       } else {
         return report_parameter_error(name, type, "expected int");
@@ -2457,7 +2473,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._func = SMF_compose;
       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") {
 
     ShaderMatSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._func = SMF_compose;
 
     if (pieces[0] == "trans" || pieces[0] == "tpose") {
@@ -2596,7 +2612,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       if (pieces[1] == "material") {
         if (!expect_float_matrix(name, type, 4, 4)) {
           return false;
@@ -2702,7 +2718,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_alight_x;
@@ -2720,7 +2736,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_satten_x;
@@ -2737,7 +2753,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_transpose;
       int next = 1;
       pieces.push_back("");
@@ -2778,7 +2794,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._func = SMF_first;
       bind._part[0] = SMO_texmat_i;
@@ -2797,7 +2813,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_texscale_i;
@@ -2816,7 +2832,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_texcolor_i;
@@ -2835,7 +2851,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_plane_x;
@@ -2853,7 +2869,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_clipplane_x;
@@ -2871,7 +2887,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       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");
       }
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._name = nullptr;
       bind._stage = atoi(pieces[1].c_str());
       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");
       }
       ShaderTexSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._name = nullptr;
       bind._stage = atoi(pieces[1].c_str());
       bind._part = STO_light_i_shadow_map;
@@ -2961,7 +2977,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_texpad_x;
@@ -2978,7 +2994,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
         return false;
       }
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_row3;
       bind._func = SMF_first;
       bind._part[0] = SMO_texpix_x;
@@ -3007,7 +3023,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   // user-defined input.
   if (const ::ShaderType::SampledImage *sampler = type->as_sampled_image()) {
     ShaderTexSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._part = STO_named_input;
     bind._name = name;
     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()) {
     ShaderImgSpec bind;
-    bind._id = arg_id;
+    bind._id = param;
     bind._name = name;
     bind._desired_type = image->get_texture_type();
     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()) {
     if (matrix->get_num_columns() == 3 && matrix->get_num_rows() == 3) {
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_upper3x3;
       bind._func = SMF_first;
       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) {
       ShaderMatSpec bind;
-      bind._id = arg_id;
+      bind._id = param;
       bind._piece = SMP_whole;
       bind._func = SMF_first;
       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) {
       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.
       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.
         // We can't know yet, so we always have to handle it specially.
         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) {
           // Special exception for shadowMatrix, which is deprecated because it
           // 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._arg[0] = nullptr;
           bind._part[1] = SMO_mat_constant_x_attrib;
-          bind._arg[1] = ((InternalName *)name.p())->append("shadowViewMatrix");
+          bind._arg[1] = ((InternalName *)name)->append("shadowViewMatrix");
         }
         else {
           bind._func = SMF_first;
@@ -3125,7 +3141,11 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
       }
 
       // 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;
       }
     }
@@ -3134,6 +3154,7 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
   }
   else if (const ::ShaderType::Array *array_type = type->as_array()) {
     // 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()) {
       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);
 
           // 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;
           }
         }
@@ -3164,15 +3188,9 @@ bind_parameter(CPT_InternalName name, const ::ShaderType *type, int location) {
 
   ShaderPtrSpec bind;
   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);
 
-    // 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) {
     //  // Backward compatibility, disables certain checks.
     //  bind._dim[0] = -1;

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

@@ -293,10 +293,11 @@ public:
     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 {
@@ -307,11 +308,6 @@ public:
     SPT_unknown = ScalarType::ST_unknown,
   };
 
-  struct ShaderArgInfo {
-    ShaderArgId _id;
-    const ::ShaderType *_type;
-  };
-
   // Container structure for data of parameters ShaderPtrSpec.
   struct ShaderPtrData {
   private:
@@ -378,7 +374,7 @@ public:
    */
   struct ShaderMatSpec {
     size_t _cache_offset[2];
-    ShaderArgId       _id;
+    Parameter         _id;
     ShaderMatFunc     _func;
     ShaderMatInput    _part[2];
     CPT(InternalName) _arg[2];
@@ -389,7 +385,7 @@ public:
   };
 
   struct ShaderTexSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     CPT(InternalName) _name;
     ShaderTexInput    _part;
     int               _stage;
@@ -398,14 +394,14 @@ public:
   };
 
   struct ShaderImgSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     CPT(InternalName) _name;
     int               _desired_type;
     bool              _writable;
   };
 
   struct ShaderVarSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     PT(InternalName)  _name;
     int               _append_uv;
     int               _elements;
@@ -413,11 +409,9 @@ public:
   };
 
   struct ShaderPtrSpec {
-    ShaderArgId       _id;
+    Parameter         _id;
     uint32_t          _dim[3]; //n_elements,rows,cols
-    int               _dep[2];
     CPT(InternalName) _arg;
-    ShaderArgInfo     _info;
     ScalarType        _type;
   };
 
@@ -482,7 +476,7 @@ public:
   void cp_add_mat_spec(ShaderMatSpec &spec);
   size_t cp_get_mat_cache_size() const;
 
-  bool compile_parameter(ShaderArgId &p);
+  bool compile_parameter(Parameter &p);
 
   void clear_parameters();
 
@@ -589,7 +583,7 @@ private:
 public:
   bool link();
   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;
   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.type = type;
   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));
 }
 
+/**
+ * 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.
  */
@@ -174,8 +191,9 @@ get_num_elements() const {
  * Constructs an image type.
  */
 INLINE ShaderType::Image::
-Image(Texture::TextureType type, Access access) :
+Image(Texture::TextureType type, ScalarType sampled_type, Access access) :
   _texture_type(type),
+  _sampled_type(sampled_type),
   _access(access) {
 }
 
@@ -187,6 +205,14 @@ get_texture_type() const {
   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.
  */
@@ -207,8 +233,9 @@ is_writable() const {
  * Constructs a sampled image type.
  */
 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 {
   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
+/**
+ * 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.
  */
@@ -213,6 +232,15 @@ compare_to_impl(const ShaderType &other) const {
        - (_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.
  */
@@ -267,6 +295,28 @@ compare_to_impl(const ShaderType &other) const {
   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
  * this type.
@@ -326,6 +376,24 @@ compare_to_impl(const ShaderType &other) const {
        - (_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
  * this type.
@@ -340,6 +408,11 @@ get_num_parameter_locations() const {
  */
 void ShaderType::Image::
 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];
 }
 
@@ -350,8 +423,16 @@ output(std::ostream &out) const {
 int ShaderType::Image::
 compare_to_impl(const ShaderType &other) const {
   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::
 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];
 }
 
@@ -387,7 +473,11 @@ output(std::ostream &out) const {
 int ShaderType::SampledImage::
 compare_to_impl(const ShaderType &other) const {
   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

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

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

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

@@ -14,7 +14,7 @@
 /**
  * Returns a pointer to the raw words.
  */
-const uint32_t *ShaderModuleSpirV::
+INLINE const uint32_t *ShaderModuleSpirV::
 get_data() const {
   return _instructions.get_data();
 }
@@ -22,11 +22,41 @@ get_data() const {
 /**
  * Returns the number of words in the module.
  */
-size_t ShaderModuleSpirV::
+INLINE size_t ShaderModuleSpirV::
 get_data_size() const {
   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.
  */
@@ -133,6 +163,35 @@ begin_annotations() {
   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.
  */
@@ -147,7 +206,7 @@ end() {
  * instruction.
  */
 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());
 }
 
@@ -157,7 +216,7 @@ insert(iterator &it, spv::Op opcode, std::initializer_list<uint32_t > args) {
  * instruction.
  */
 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];
 
   // 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]);
 }
 
+/**
+ * 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
  * insertion point, but returns a new iterator pointing to the next element.
  */
 INLINE ShaderModuleSpirV::InstructionIterator ShaderModuleSpirV::InstructionStream::
-erase(iterator &it) {
+erase(const iterator &it) {
   ptrdiff_t offset = it._words - &_words[0];
 
   // If this triggers, you used an invalid iterator.
@@ -190,7 +279,7 @@ erase(iterator &it) {
  * Erases the given argument of the given instruction.
  */
 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];
 
   // 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;
 
+  /**
+   * A single instruction as returned by the InstructionIterator.
+   */
   struct Instruction {
     const spv::Op opcode;
     const uint32_t nargs;
     uint32_t *args;
+
+    INLINE bool is_debug() const;
+    INLINE bool is_annotation() const;
   };
 
+  /**
+   * Provided by InstructionStream to iterate over the instructions.
+   */
   class InstructionIterator {
   public:
     constexpr InstructionIterator() = default;
@@ -79,15 +88,17 @@ public:
 
     INLINE operator std::vector<uint32_t> & ();
 
-    InstructionStream strip() const;
-
     INLINE iterator begin();
     INLINE iterator begin_annotations();
+    INLINE iterator end_annotations();
+    INLINE iterator begin_functions();
     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 size_t get_data_size() const;
@@ -103,7 +114,6 @@ public:
 
   InstructionStream _instructions;
 
-protected:
   enum DefinitionType {
     DT_none,
     DT_type,
@@ -113,6 +123,18 @@ protected:
     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,
    * type or type pointer in the SPIR-V file.
@@ -124,38 +146,73 @@ protected:
     int _location = -1;
     spv::BuiltIn _builtin = spv::BuiltInMax;
     uint32_t _constant = 0;
-    vector_string _member_names;
+    uint32_t _type_id = 0;
+    MemberDefinitions _members;
     bool _used = false;
 
     // Only defined for DT_variable.
     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:
-  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 flatten_struct(Definitions &defs, uint32_t type_id);
   void strip();
 
+private:
   int _index;
 
 public:

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