Browse Source

shaderpipeline: WIP support for SPIR-V, shader reflection, glslang compiler

rdb 5 years ago
parent
commit
aae03b5f95
30 changed files with 4241 additions and 165 deletions
  1. 4 2
      makepanda/makepanda.py
  2. 2 1
      panda/src/display/graphicsStateGuardian.cxx
  3. 2 1
      panda/src/display/graphicsStateGuardian.h
  4. 54 0
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  5. 6 0
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  6. 190 52
      panda/src/glstuff/glShaderContext_src.cxx
  7. 10 6
      panda/src/glstuff/glShaderContext_src.h
  8. 330 75
      panda/src/glstuff/panda_glext.h
  9. 2 0
      panda/src/gobj/config_gobj.cxx
  10. 1 0
      panda/src/gobj/p3gobj_composite2.cxx
  11. 411 12
      panda/src/gobj/shader.cxx
  12. 19 5
      panda/src/gobj/shader.h
  13. 176 0
      panda/src/gobj/shaderType.I
  14. 199 0
      panda/src/gobj/shaderType.cxx
  15. 346 0
      panda/src/gobj/shaderType.h
  16. 1176 0
      panda/src/gobj/spirv.h
  17. 1 1
      panda/src/pgraph/shaderAttrib.cxx
  18. 1 1
      panda/src/pgraph/shaderAttrib.h
  19. 10 0
      panda/src/shaderpipeline/config_shaderpipeline.cxx
  20. 2 0
      panda/src/shaderpipeline/p3shaderpipeline_composite1.cxx
  21. 1 0
      panda/src/shaderpipeline/shaderCompilerGlslPreProc.cxx
  22. 234 0
      panda/src/shaderpipeline/shaderCompilerGlslang.cxx
  23. 69 0
      panda/src/shaderpipeline/shaderCompilerGlslang.h
  24. 87 0
      panda/src/shaderpipeline/shaderModule.I
  25. 29 0
      panda/src/shaderpipeline/shaderModule.cxx
  26. 64 9
      panda/src/shaderpipeline/shaderModule.h
  27. 8 0
      panda/src/shaderpipeline/shaderModuleGlsl.cxx
  28. 2 0
      panda/src/shaderpipeline/shaderModuleGlsl.h
  29. 698 0
      panda/src/shaderpipeline/shaderModuleSpirV.cxx
  30. 107 0
      panda/src/shaderpipeline/shaderModuleSpirV.h

+ 4 - 2
makepanda/makepanda.py

@@ -814,6 +814,7 @@ if (COMPILER=="GCC"):
     SmartPkgEnable("OPUS",      "opusfile",  ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
     SmartPkgEnable("JPEG",      "",          ("jpeg"), "jpeglib.h")
     SmartPkgEnable("PNG",       "libpng",    ("png"), "png.h", tool = "libpng-config")
+    SmartPkgEnable("GLSLANG",   "",          ("glslang", "SPIRV"), "glslang/Public/ShaderLang.h")
 
     # Copy freetype libraries to be specified after harfbuzz libraries as well,
     # because there's a circular dependency between the two libraries.
@@ -3702,7 +3703,7 @@ PyTargetAdd('p3display_ext_composite.obj', opts=OPTS, input='p3display_ext_compo
 # DIRECTORY: panda/src/shaderpipeline/
 #
 
-OPTS=['DIR:panda/src/shaderpipeline', 'BUILDING:PANDA']
+OPTS=['DIR:panda/src/shaderpipeline', 'BUILDING:PANDA', 'GLSLANG']
 TargetAdd('p3shaderpipeline_composite1.obj', opts=OPTS, input='p3shaderpipeline_composite1.cxx')
 
 OPTS=['DIR:panda/src/shaderpipeline']
@@ -3892,7 +3893,7 @@ TargetAdd('libp3dxml.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dxml', 'SRCDIR:p
 OPTS=['DIR:panda/metalibs/panda', 'BUILDING:PANDA', 'JPEG', 'PNG', 'HARFBUZZ',
     'TIFF', 'OPENEXR', 'ZLIB', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2',
     'SQUISH', 'NVIDIACG', 'VORBIS', 'OPUS', 'WINUSER', 'WINMM', 'WINGDI', 'IPHLPAPI',
-    'SETUPAPI', 'IOKIT']
+    'SETUPAPI', 'IOKIT', 'GLSLANG']
 
 TargetAdd('panda_panda.obj', opts=OPTS, input='panda.cxx')
 
@@ -4029,6 +4030,7 @@ PyTargetAdd('core.pyd', input='libp3recorder_igate.obj')
 PyTargetAdd('core.pyd', input='libp3pgraphnodes_igate.obj')
 PyTargetAdd('core.pyd', input='libp3pgraph_igate.obj')
 PyTargetAdd('core.pyd', input='libp3movies_igate.obj')
+PyTargetAdd('core.pyd', input='libp3shaderpipeline_igate.obj')
 PyTargetAdd('core.pyd', input='libp3grutil_igate.obj')
 PyTargetAdd('core.pyd', input='libp3chan_igate.obj')
 PyTargetAdd('core.pyd', input='libp3pstatclient_igate.obj')

+ 2 - 1
panda/src/display/graphicsStateGuardian.cxx

@@ -246,6 +246,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _supports_compute_shaders = false;
   _supports_glsl = false;
   _supports_hlsl = false;
+  _supports_spir_v = false;
 
   _supports_stencil = false;
   _supports_stencil_wrap = false;
@@ -961,7 +962,7 @@ fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) {
  * See fetch_specified_value
  */
 const LMatrix4 *GraphicsStateGuardian::
-fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
+fetch_specified_part(Shader::ShaderMatInput part, const InternalName *name,
                      LMatrix4 &t, int index) {
   switch (part) {
   case Shader::SMO_identity: {

+ 2 - 1
panda/src/display/graphicsStateGuardian.h

@@ -337,7 +337,7 @@ public:
   virtual void clear(DrawableRegion *clearable);
 
   const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, int altered);
-  const LMatrix4 *fetch_specified_part(Shader::ShaderMatInput input, InternalName *name,
+  const LMatrix4 *fetch_specified_part(Shader::ShaderMatInput input, const InternalName *name,
                                        LMatrix4 &t, int index);
   const LMatrix4 *fetch_specified_member(const NodePath &np, CPT_InternalName member, LMatrix4 &t);
   PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
@@ -623,6 +623,7 @@ protected:
   bool _supports_compute_shaders;
   bool _supports_glsl;
   bool _supports_hlsl;
+  bool _supports_spir_v;
   bool _supports_framebuffer_multisample;
   bool _supports_framebuffer_blit;
 

+ 54 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1726,6 +1726,30 @@ reset() {
 #endif
   _shader_caps._supports_glsl = _supports_glsl;
 
+  // Check for SPIR-V support.
+#ifndef OPENGLES
+  _supports_spir_v = has_extension("GL_ARB_gl_spirv");
+  if (_supports_spir_v) {
+    _glShaderBinary = (PFNGLSHADERBINARYPROC)
+      get_extension_func("glShaderBinary");
+    _glSpecializeShader = (PFNGLSPECIALIZESHADERARBPROC)
+      get_extension_func("glSpecializeShaderARB");
+
+    if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_separate_shader_objects")) {
+      _glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)
+        get_extension_func("glProgramUniform1i");
+
+    } else if (has_extension("GL_EXT_separate_shader_objects") ||
+               has_extension("GL_EXT_direct_state_access")) {
+      _glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC)
+        get_extension_func("glProgramUniform1iEXT");
+
+    } else {
+      _supports_spir_v = false;
+    }
+  }
+#endif
+
   // Check for support for other types of shaders that can be used by Cg.
   _supports_basic_shaders = false;
 #if defined(HAVE_CG) && !defined(OPENGLES)
@@ -3439,6 +3463,36 @@ reset() {
     } else {
       GLCAT.debug() << "No program binary formats supported.\n";
     }
+
+    // Also show supported shader binary formats.
+#ifdef OPENGLES
+    if (true) {
+#else
+    if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_ES2_compatibility")) {
+#endif
+      GLint num_binary_formats = 0;
+      glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &num_binary_formats);
+
+      if (num_binary_formats >= 0) {
+        GLCAT.debug()
+          << "Supported shader binary formats:\n";
+        GLCAT.debug() << " ";
+
+        GLenum *binary_formats = (GLenum *)alloca(sizeof(GLenum) * num_binary_formats);
+        glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)binary_formats);
+
+        for (int i = 0; i < num_binary_formats; ++i) {
+          char number[16];
+          sprintf(number, "0x%04X", binary_formats[i]);
+          GLCAT.debug(false) << " " << number << "";
+        }
+        GLCAT.debug(false) << "\n";
+      } else {
+        GLCAT.debug() << "No program binary formats supported.\n";
+      }
+    } else {
+      GLCAT.debug() << "Shader binary loading not supported.\n";
+    }
   }
 #endif
 

+ 6 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -166,6 +166,7 @@ typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSi
 typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
 typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
 typedef void (APIENTRYP PFNGLSHADERSOURCEPROC_P) (GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length);
+typedef void (APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const GLchar *, GLuint, const GLuint *, const GLuint *);
 typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
 typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
 typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
@@ -993,8 +994,13 @@ public:
   PFNGLGETSHADERINFOLOGPROC _glGetShaderInfoLog;
   PFNGLGETUNIFORMLOCATIONPROC _glGetUniformLocation;
   PFNGLLINKPROGRAMPROC _glLinkProgram;
+  PFNGLSPECIALIZESHADERARBPROC _glSpecializeShader;
+  PFNGLSHADERBINARYPROC _glShaderBinary;
   PFNGLSHADERSOURCEPROC_P _glShaderSource;
   PFNGLUSEPROGRAMPROC  _glUseProgram;
+#ifndef OPENGLES
+  PFNGLPROGRAMUNIFORM1IPROC _glProgramUniform1i;
+#endif
   PFNGLUNIFORM4FPROC _glUniform4f;
   PFNGLUNIFORM1IPROC _glUniform1i;
   PFNGLUNIFORM1FVPROC _glUniform1fv;

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

@@ -27,6 +27,7 @@
 #include "clipPlaneAttrib.h"
 #include "bamCache.h"
 #include "shaderModuleGlsl.h"
+#include "shaderModuleSpirV.h"
 
 using std::dec;
 using std::hex;
@@ -276,12 +277,99 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
 
   // We compile and analyze the shader here, instead of in shader.cxx, to
   // avoid gobj getting a dependency on GL stuff.
-  if (!glsl_compile_and_link()) {
+  if (!compile_and_link()) {
     release_resources();
     s->_error_flag = true;
     return;
   }
 
+  // Is this a SPIR-V shader?  If so, we've already done the reflection.
+  if (true) {//s->get_language() != Shader::SL_GLSL) {
+    // Do we have unbound inputs?  Ask the driver for their locations.
+    size_t num_inputs = s->_mat_spec.size();
+    for (size_t i = 0; i < num_inputs;) {
+      Shader::ShaderMatSpec &spec = s->_mat_spec[i];
+
+      if (spec._id._seqno < 0) {
+        GLint p = _glgsg->_glGetUniformLocation(_glsl_program, spec._id._name.c_str());
+        if (p < 0) {
+          if (GLCAT.is_debug()) {
+            GLCAT.debug()
+              << "Unused uniform " << spec._id._name << " is removed\n";
+          }
+
+          // If p is still -1, then the driver says that the input is actually
+          // unused.  Remove it.
+          s->_mat_spec.erase(s->_mat_spec.begin() + i);
+          --num_inputs;
+          continue;
+        }
+
+        spec._id._seqno = p;
+
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Active uniform " << spec._id._name << " is bound to location " << p << "\n";
+        }
+      }
+      ++i;
+    }
+
+    // Rebind the texture and image inputs.
+    size_t num_textures = s->_tex_spec.size();
+    for (size_t i = 0; i < num_textures;) {
+      const Shader::ShaderTexSpec &spec = s->_tex_spec[i];
+      nassertd(spec._id._seqno >= 0) continue;
+
+#ifndef OPENGLES
+      _glgsg->_glProgramUniform1i(_glsl_program, spec._id._seqno, (int)i);
+#endif
+      ++i;
+    }
+
+    size_t num_images = min(s->_img_spec.size(), (size_t)glgsg->_max_image_units);
+    for (size_t i = 0; i < num_images;) {
+      const Shader::ShaderImgSpec &spec = s->_img_spec[i];
+      nassertd(spec._id._seqno >= 0) continue;
+
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Active uniform " << spec._id._name << " is bound to location " << spec._id._seqno << " (image binding " << i << ")\n";
+      }
+      ImageInput input = {spec._name, nullptr, spec._writable};
+      _glsl_img_inputs.push_back(std::move(input));
+
+#ifndef OPENGLES
+      _glgsg->_glProgramUniform1i(_glsl_program, spec._id._seqno, (int)i);
+#endif
+      ++i;
+    }
+
+    // Do we have a p3d_Color attribute?
+    for (auto it = s->_var_spec.begin(); it != s->_var_spec.end(); ++it) {
+      Shader::ShaderVarSpec &spec = *it;
+      if (spec._id._name == "p3d_Color") {
+        _color_attrib_index = spec._id._seqno;
+        break;
+      }
+    }
+
+    // Temporary hacks until array inputs are integrated into the rest of
+    // the shader input system.
+    //_transform_table_index = _shader->_transform_table_index;
+    //_transform_table_size = _shader->_transform_table_size;
+    //_slider_table_index = _shader->_slider_table_index;
+    //_slider_table_size = _shader->_slider_table_size;
+
+    if (_transform_table_size > 0 && _transform_table_index == -1) {
+      _transform_table_index = _glgsg->_glGetUniformLocation(_glsl_program, "p3d_TransformTable");
+    }
+    if (_slider_table_size > 0 && _slider_table_index == -1) {
+      _slider_table_index = _glgsg->_glGetUniformLocation(_glsl_program, "p3d_SliderTable");
+    }
+    return;
+  }
+
   // Process the vertex attributes first.
   GLint param_count = 0;
   GLint name_buflen = 0;
@@ -1926,20 +2014,18 @@ release_resources() {
     return;
   }
   if (_glsl_program != 0) {
-    GLSLShaders::const_iterator it;
-    for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) {
-      _glgsg->_glDetachShader(_glsl_program, *it);
+    for (Module &module : _modules) {
+      _glgsg->_glDetachShader(_glsl_program, module._handle);
     }
     _glgsg->_glDeleteProgram(_glsl_program);
     _glsl_program = 0;
   }
 
-  GLSLShaders::const_iterator it;
-  for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) {
-    _glgsg->_glDeleteShader(*it);
+  for (Module &module : _modules) {
+    _glgsg->_glDeleteShader(module._handle);
   }
 
-  _glsl_shaders.clear();
+  _modules.clear();
 
   _glgsg->report_my_gl_errors();
 }
@@ -1966,7 +2052,7 @@ void CLP(ShaderContext)::
 bind() {
   if (!_validated) {
     _glgsg->_glValidateProgram(_glsl_program);
-    glsl_report_program_errors(_glsl_program, false);
+    report_program_errors(_glsl_program, false);
     _validated = true;
   }
 
@@ -2951,24 +3037,30 @@ update_shader_buffer_bindings(ShaderContext *prev) {
  * This subroutine prints the infolog for a shader.
  */
 void CLP(ShaderContext)::
-glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fatal) {
+report_shader_errors(const Module &module, bool fatal) {
   char *info_log;
   GLint length = 0;
   GLint num_chars  = 0;
 
-  _glgsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
+  _glgsg->_glGetShaderiv(module._handle, GL_INFO_LOG_LENGTH, &length);
 
   if (length <= 1) {
     return;
   }
 
   info_log = (char *) alloca(length);
-  _glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log);
+  _glgsg->_glGetShaderInfoLog(module._handle, length, &num_chars, info_log);
   if (strcmp(info_log, "Success.\n") == 0 ||
       strcmp(info_log, "No errors.\n") == 0) {
     return;
   }
 
+  const ShaderModuleGlsl *glsl_module = DCAST(ShaderModuleGlsl, module._module);
+  if (glsl_module == nullptr) {
+    GLCAT.error(false) << info_log;
+    return;
+  }
+
   // Parse the errors so that we can substitute in actual file locations
   // instead of source indices.
   std::istringstream log(info_log);
@@ -2981,14 +3073,14 @@ glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fa
     if (sscanf(line.c_str(), "ERROR: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
         && prefixlen > 0) {
 
-      Filename fn = module->get_filename_from_index(fileno);
+      Filename fn = glsl_module->get_filename_from_index(fileno);
       GLCAT.error(false)
         << "ERROR: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n";
 
     } else if (sscanf(line.c_str(), "WARNING: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
                && prefixlen > 0) {
 
-      Filename fn = module->get_filename_from_index(fileno);
+      Filename fn = glsl_module->get_filename_from_index(fileno);
       GLCAT.warning(false)
         << "WARNING: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n";
 
@@ -2996,7 +3088,7 @@ glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fa
                && prefixlen > 0) {
 
       // This is the format NVIDIA uses.
-      Filename fn = module->get_filename_from_index(fileno);
+      Filename fn = glsl_module->get_filename_from_index(fileno);
       GLCAT.error(false)
         << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
 
@@ -3004,7 +3096,7 @@ glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fa
                && prefixlen > 0) {
 
       // This is the format for Mesa's OpenGL ES 2 implementation.
-      Filename fn = module->get_filename_from_index(fileno);
+      Filename fn = glsl_module->get_filename_from_index(fileno);
       GLCAT.error(false)
         << fn << ":" << lineno << "(" << colno << "): " << (line.c_str() + prefixlen) << "\n";
 
@@ -3021,7 +3113,7 @@ glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fa
  * This subroutine prints the infolog for a program.
  */
 void CLP(ShaderContext)::
-glsl_report_program_errors(GLuint program, bool fatal) {
+report_program_errors(GLuint program, bool fatal) {
   char *info_log;
   GLint length = 0;
   GLint num_chars  = 0;
@@ -3050,16 +3142,8 @@ glsl_report_program_errors(GLuint program, bool fatal) {
  * Compiles the given ShaderModuleGlsl and attaches it to the program.
  */
 bool CLP(ShaderContext)::
-glsl_compile_shader(const ShaderModule *module) {
+attach_shader(const ShaderModule *module) {
   ShaderModule::Stage stage = module->get_stage();
-  if (GLCAT.is_debug()) {
-    GLCAT.debug()
-      << "Compiling GLSL " << stage << " shader "
-      << module->get_source_filename() << "\n";
-  }
-
-  const ShaderModuleGlsl *glsl_module;
-  DCAST_INTO_R(glsl_module, module, false);
 
   GLuint handle = 0;
   switch (stage) {
@@ -3106,28 +3190,45 @@ glsl_compile_shader(const ShaderModule *module) {
     _glgsg->_glObjectLabel(GL_SHADER, handle, name.size(), name.data());
   }
 
-  string text_str = module->get_ir();
-  const char* text = text_str.c_str();
-  _glgsg->_glShaderSource(handle, 1, &text, nullptr);
-  _glgsg->_glCompileShader(handle);
-  GLint status;
-  _glgsg->_glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
+#ifndef OPENGLES
+  if (module->is_of_type(ShaderModuleSpirV::get_class_type())) {
+    // Load a SPIR-V binary.
+    if (GLCAT.is_debug()) {
+      GLCAT.debug()
+        << "Attaching SPIR-V " << stage << " shader binary "
+        << module->get_source_filename() << "\n";
+    }
+    ShaderModuleSpirV *spv = (ShaderModuleSpirV *)module;
+    _glgsg->_glShaderBinary(1, &handle, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB,
+                            (const char *)spv->get_data(),
+                            spv->get_data_size() * sizeof(uint32_t));
+    _glgsg->_glSpecializeShader(handle, "main", 0, nullptr, nullptr);
+  } else
+#endif
+  if (module->is_of_type(ShaderModuleGlsl::get_class_type())) {
+    // Legacy preprocessed GLSL.
+    if (GLCAT.is_debug()) {
+      GLCAT.debug()
+        << "Compiling GLSL " << stage << " shader "
+        << module->get_source_filename() << "\n";
+    }
 
-  if (status != GL_TRUE) {
+    ShaderModuleGlsl *glsl_module = (ShaderModuleGlsl *)module;
+    std::string text = glsl_module->get_ir();
+    const char *text_str = text.c_str();
+    _glgsg->_glShaderSource(handle, 1, &text_str, nullptr);
+  } else {
     GLCAT.error()
-      << "An error occurred while compiling GLSL " << stage
-      << " shader " << module->get_source_filename() << ":\n";
-    glsl_report_shader_errors(handle, glsl_module, true);
-    _glgsg->_glDeleteShader(handle);
-    _glgsg->report_my_gl_errors();
+      << "Unsupported shader module type " << module->get_type() << "!\n";
     return false;
   }
 
+  // Don't check compile status yet, which would force the compile to complete
+  // synchronously.
   _glgsg->_glAttachShader(_glsl_program, handle);
-  _glsl_shaders.push_back(handle);
 
-  // There might be warnings, so report those.
-  glsl_report_shader_errors(handle, glsl_module, false);
+  Module moddef = {module, handle};
+  _modules.push_back(std::move(moddef));
 
   return true;
 }
@@ -3136,8 +3237,8 @@ glsl_compile_shader(const ShaderModule *module) {
  * This subroutine compiles a GLSL shader.
  */
 bool CLP(ShaderContext)::
-glsl_compile_and_link() {
-  _glsl_shaders.clear();
+compile_and_link() {
+  _modules.clear();
   _glsl_program = _glgsg->_glCreateProgram();
   if (!_glsl_program) {
     return false;
@@ -3174,17 +3275,25 @@ glsl_compile_and_link() {
 
   bool valid = true;
 
-  for (const ShaderModule *module : _shader->_modules) {
-    valid &= glsl_compile_shader(module);
+  for (COWPT(ShaderModule) const &cow_module : _shader->_modules) {
+    valid &= attach_shader(cow_module.get_read_pointer());
   }
 
   if (!valid) {
     return false;
   }
 
+  // Now compile the individual shaders.  NVIDIA drivers seem to cope better
+  // when we compile them all in one go.
+  for (Module &module : _modules) {
+    if (module._module->is_of_type(ShaderModuleGlsl::get_class_type())) {
+      _glgsg->_glCompileShader(module._handle);
+    }
+  }
+
   // There might be warnings, so report those.  GLSLShaders::const_iterator
-  // it; for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) {
-  // glsl_report_shader_errors(*it); }
+  // it; for (it = _modules.begin(); it != _modules.end(); ++it) {
+  // report_shader_errors(*it); }
 
   // Under OpenGL's compatibility profile, we have to make sure that we bind
   // something to attribute 0.  Make sure that this is the position array.
@@ -3228,22 +3337,51 @@ glsl_compile_and_link() {
 
   if (GLCAT.is_debug()) {
     GLCAT.debug()
-      << "Linking GLSL shader " << _shader->get_filename() << "\n";
+      << "Linking shader " << _shader->get_filename() << "\n";
   }
 
   _glgsg->_glLinkProgram(_glsl_program);
 
-  GLint status;
+  // Query the link status.  This will cause the application to wait for the
+  // link to be finished.
+  GLint status = GL_FALSE;
   _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
   if (status != GL_TRUE) {
-    GLCAT.error() << "An error occurred while linking GLSL shader "
+    // The link failed.  Is it because one of the shaders failed to compile?
+    bool any_failed = false;
+    for (Module &module : _modules) {
+      _glgsg->_glGetShaderiv(module._handle, GL_COMPILE_STATUS, &status);
+
+      if (status != GL_TRUE) {
+        GLCAT.error()
+          << "An error occurred while compiling shader module "
+          << module._module->get_source_filename() << ":\n";
+        report_shader_errors(module, true);
+        any_failed = true;
+      } else {
+        // Report any warnings.
+        report_shader_errors(module, false);
+      }
+
+      // Delete the shader, we don't need it any more.
+      _glgsg->_glDeleteShader(module._handle);
+    }
+    _modules.clear();
+
+    if (any_failed) {
+      // One or more of the shaders failed to compile, which would explain the
+      // link failure.  We know enough.
+      return false;
+    }
+
+    GLCAT.error() << "An error occurred while linking shader "
                   << _shader->get_filename() << "\n";
-    glsl_report_program_errors(_glsl_program, true);
+    report_program_errors(_glsl_program, true);
     return false;
   }
 
   // Report any warnings.
-  glsl_report_program_errors(_glsl_program, false);
+  report_program_errors(_glsl_program, false);
 
   if (retrieve_binary) {
     GLint length = 0;

+ 10 - 6
panda/src/glstuff/glShaderContext_src.h

@@ -68,8 +68,12 @@ public:
 private:
   bool _validated;
   GLuint _glsl_program;
-  typedef pvector<GLuint> GLSLShaders;
-  GLSLShaders _glsl_shaders;
+  struct Module {
+    const ShaderModule *_module;
+    GLuint _handle;
+  };
+  typedef pvector<Module> Modules;
+  Modules _modules;
 
   WCPT(RenderState) _state_rs;
   CPT(TransformState) _modelview_transform;
@@ -118,10 +122,10 @@ private:
 
   bool _uses_standard_vertex_arrays;
 
-  void glsl_report_shader_errors(GLuint shader, const ShaderModuleGlsl *module, bool fatal);
-  void glsl_report_program_errors(GLuint program, bool fatal);
-  bool glsl_compile_shader(const ShaderModule *module);
-  bool glsl_compile_and_link();
+  void report_shader_errors(const Module &module, bool fatal);
+  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);
   void release_resources();
 

+ 330 - 75
panda/src/glstuff/panda_glext.h

@@ -1,5 +1,5 @@
-#ifndef __glext_h_
-#define __glext_h_ 1
+#ifndef __gl_glext_h_
+#define __gl_glext_h_ 1
 
 #ifdef __cplusplus
 extern "C" {
@@ -51,7 +51,7 @@ extern "C" {
 #define GLAPI extern
 #endif
 
-#define GL_GLEXT_VERSION 20180525
+#define GL_GLEXT_VERSION 20191206
 
 /* Generated C header for:
  * API: gl
@@ -1383,45 +1383,8 @@ GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIn
 #ifndef GL_VERSION_3_2
 #define GL_VERSION_3_2 1
 typedef struct __GLsync *GLsync;
-#ifndef GLEXT_64_TYPES_DEFINED
-/* This code block is duplicated in glxext.h, so must be protected */
-#define GLEXT_64_TYPES_DEFINED
-/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
-/* (as used in the GL_EXT_timer_query extension). */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-#include <inttypes.h>
-#elif defined(__sun__) || defined(__digital__)
-#include <inttypes.h>
-#if defined(__STDC__)
-#if defined(__arch64__) || defined(_LP64)
-typedef long int int64_t;
-typedef unsigned long int uint64_t;
-#else
-typedef long long int int64_t;
-typedef unsigned long long int uint64_t;
-#endif /* __arch64__ */
-#endif /* __STDC__ */
-#elif defined( __VMS ) || defined(__sgi)
-#include <inttypes.h>
-#elif defined(__SCO__) || defined(__USLC__)
-#include <stdint.h>
-#elif defined(__UNIXOS2__) || defined(__SOL64__)
-typedef long int int32_t;
-typedef long long int int64_t;
-typedef unsigned long long int uint64_t;
-#elif defined(_WIN32) && defined(__GNUC__)
-#include <stdint.h>
-#elif defined(_WIN32)
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-#else
-/* Fallback if nothing above works */
-#include <inttypes.h>
-#endif
-#endif
-typedef uint64_t GLuint64;
-typedef int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_int64_t GLint64;
 #define GL_CONTEXT_CORE_PROFILE_BIT       0x00000001
 #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
 #define GL_LINES_ADJACENCY                0x000A
@@ -1497,7 +1460,7 @@ typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
 typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
 typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
 typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
-typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
 typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
 typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
 typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
@@ -1517,7 +1480,7 @@ GLAPI void APIENTRY glDeleteSync (GLsync sync);
 GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
 GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
 GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
-GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
 GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
 GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
 GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
@@ -1773,8 +1736,8 @@ typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location,
 typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
 typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
 typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
-typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
-typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
 typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
 typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
 typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
@@ -1820,8 +1783,8 @@ GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *pa
 GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
 GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
 GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
-GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
-GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
 GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
 GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
 GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
@@ -2175,7 +2138,7 @@ GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data)
 typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
 typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
 typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
-typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params);
 typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
 typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
 typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
@@ -2188,7 +2151,7 @@ typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum m
 GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
 GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
 GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
-GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params);
 GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
 GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
 GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers);
@@ -2469,7 +2432,7 @@ typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
 typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
 typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
 typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
-typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params);
 typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
 typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
 typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
@@ -2481,7 +2444,7 @@ typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum
 typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
 typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
 typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
-typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params);
 typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
 typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
 typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
@@ -2513,7 +2476,7 @@ GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
 GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
 GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
 GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
-GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params);
 GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
 GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
 GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
@@ -2525,7 +2488,7 @@ GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const
 GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
 GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
 GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
-GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params);
 GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
 GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
 GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
@@ -2654,7 +2617,7 @@ typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint fram
 typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
 typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
 typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
-//typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target);
 typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param);
@@ -2777,7 +2740,7 @@ GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLs
 GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
 GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
 GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
-//GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
 GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
 GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target);
 GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param);
@@ -2936,7 +2899,7 @@ GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLflo
 
 #ifndef GL_ARB_bindless_texture
 #define GL_ARB_bindless_texture 1
-typedef uint64_t GLuint64EXT;
+typedef khronos_uint64_t GLuint64EXT;
 #define GL_UNSIGNED_INT64_ARB             0x140F
 typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture);
 typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler);
@@ -3496,7 +3459,7 @@ GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, G
 
 #ifndef GL_ARB_half_float_pixel
 #define GL_ARB_half_float_pixel 1
-typedef unsigned short GLhalfARB;
+typedef khronos_uint16_t GLhalfARB;
 #define GL_HALF_FLOAT_ARB                 0x140B
 #endif /* GL_ARB_half_float_pixel */
 
@@ -3666,6 +3629,25 @@ GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
 #ifndef GL_ARB_internalformat_query2
 #define GL_ARB_internalformat_query2 1
 #define GL_SRGB_DECODE_ARB                0x8299
+#define GL_VIEW_CLASS_EAC_R11             0x9383
+#define GL_VIEW_CLASS_EAC_RG11            0x9384
+#define GL_VIEW_CLASS_ETC2_RGB            0x9385
+#define GL_VIEW_CLASS_ETC2_RGBA           0x9386
+#define GL_VIEW_CLASS_ETC2_EAC_RGBA       0x9387
+#define GL_VIEW_CLASS_ASTC_4x4_RGBA       0x9388
+#define GL_VIEW_CLASS_ASTC_5x4_RGBA       0x9389
+#define GL_VIEW_CLASS_ASTC_5x5_RGBA       0x938A
+#define GL_VIEW_CLASS_ASTC_6x5_RGBA       0x938B
+#define GL_VIEW_CLASS_ASTC_6x6_RGBA       0x938C
+#define GL_VIEW_CLASS_ASTC_8x5_RGBA       0x938D
+#define GL_VIEW_CLASS_ASTC_8x6_RGBA       0x938E
+#define GL_VIEW_CLASS_ASTC_8x8_RGBA       0x938F
+#define GL_VIEW_CLASS_ASTC_10x5_RGBA      0x9390
+#define GL_VIEW_CLASS_ASTC_10x6_RGBA      0x9391
+#define GL_VIEW_CLASS_ASTC_10x8_RGBA      0x9392
+#define GL_VIEW_CLASS_ASTC_10x10_RGBA     0x9393
+#define GL_VIEW_CLASS_ASTC_12x10_RGBA     0x9394
+#define GL_VIEW_CLASS_ASTC_12x12_RGBA     0x9395
 #endif /* GL_ARB_internalformat_query2 */
 
 #ifndef GL_ARB_invalidate_subdata
@@ -4713,9 +4695,8 @@ GLAPI void APIENTRY glVertexBlendARB (GLint count);
 
 #ifndef GL_ARB_vertex_buffer_object
 #define GL_ARB_vertex_buffer_object 1
-#include <stddef.h>
-typedef ptrdiff_t GLsizeiptrARB;
-typedef ptrdiff_t GLintptrARB;
+typedef khronos_ssize_t GLsizeiptrARB;
+typedef khronos_intptr_t GLintptrARB;
 #define GL_BUFFER_SIZE_ARB                0x8764
 #define GL_BUFFER_USAGE_ARB               0x8765
 #define GL_ARRAY_BUFFER_ARB               0x8892
@@ -5010,6 +4991,22 @@ GLAPI void APIENTRY glMaxShaderCompilerThreadsKHR (GLuint count);
 #define GL_CONTEXT_ROBUST_ACCESS          0x90F3
 #endif /* GL_KHR_robustness */
 
+#ifndef GL_KHR_shader_subgroup
+#define GL_KHR_shader_subgroup 1
+#define GL_SUBGROUP_SIZE_KHR              0x9532
+#define GL_SUBGROUP_SUPPORTED_STAGES_KHR  0x9533
+#define GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534
+#define GL_SUBGROUP_QUAD_ALL_STAGES_KHR   0x9535
+#define GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001
+#define GL_SUBGROUP_FEATURE_VOTE_BIT_KHR  0x00000002
+#define GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004
+#define GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008
+#define GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010
+#define GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020
+#define GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040
+#define GL_SUBGROUP_FEATURE_QUAD_BIT_KHR  0x00000080
+#endif /* GL_KHR_shader_subgroup */
+
 #ifndef GL_KHR_texture_compression_astc_hdr
 #define GL_KHR_texture_compression_astc_hdr 1
 #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR   0x93B0
@@ -5116,7 +5113,7 @@ GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords);
 
 #ifndef GL_OES_fixed_point
 #define GL_OES_fixed_point 1
-typedef GLint GLfixed;
+typedef khronos_int32_t GLfixed;
 #define GL_FIXED_OES                      0x140C
 typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref);
 typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
@@ -5412,12 +5409,12 @@ typedef void (APIENTRY  *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severi
 typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
 typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
 typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
-typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
 GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
 GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
-GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
 #endif
 #endif /* GL_AMD_debug_output */
 
@@ -5441,6 +5438,22 @@ GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRG
 #endif
 #endif /* GL_AMD_draw_buffers_blend */
 
+#ifndef GL_AMD_framebuffer_multisample_advanced
+#define GL_AMD_framebuffer_multisample_advanced 1
+#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2
+#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3
+#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4
+#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5
+#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6
+#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleAdvancedAMD (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleAdvancedAMD (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_AMD_framebuffer_multisample_advanced */
+
 #ifndef GL_AMD_framebuffer_sample_positions
 #define GL_AMD_framebuffer_sample_positions 1
 #define GL_SUBSAMPLE_DISTANCE_AMD         0x883F
@@ -5486,7 +5499,7 @@ GLAPI void APIENTRY glGetNamedFramebufferParameterfvAMD (GLuint framebuffer, GLe
 
 #ifndef GL_AMD_gpu_shader_int64
 #define GL_AMD_gpu_shader_int64 1
-typedef int64_t GLint64EXT;
+typedef khronos_int64_t GLint64EXT;
 #define GL_INT64_NV                       0x140E
 #define GL_UNSIGNED_INT64_NV              0x140F
 #define GL_INT8_NV                        0x8FE0
@@ -6467,6 +6480,10 @@ GLAPI void APIENTRY glEGLImageTargetTextureStorageEXT (GLuint texture, GLeglImag
 #endif
 #endif /* GL_EXT_EGL_image_storage */
 
+#ifndef GL_EXT_EGL_sync
+#define GL_EXT_EGL_sync 1
+#endif /* GL_EXT_EGL_sync */
+
 #ifndef GL_EXT_abgr
 #define GL_EXT_abgr 1
 #define GL_ABGR_EXT                       0x8000
@@ -7796,6 +7813,18 @@ GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern);
 #endif
 #endif /* GL_EXT_multisample */
 
+#ifndef GL_EXT_multiview_tessellation_geometry_shader
+#define GL_EXT_multiview_tessellation_geometry_shader 1
+#endif /* GL_EXT_multiview_tessellation_geometry_shader */
+
+#ifndef GL_EXT_multiview_texture_multisample
+#define GL_EXT_multiview_texture_multisample 1
+#endif /* GL_EXT_multiview_texture_multisample */
+
+#ifndef GL_EXT_multiview_timer_query
+#define GL_EXT_multiview_timer_query 1
+#endif /* GL_EXT_multiview_timer_query */
+
 #ifndef GL_EXT_packed_depth_stencil
 #define GL_EXT_packed_depth_stencil 1
 #define GL_DEPTH_STENCIL_EXT              0x84F9
@@ -8514,6 +8543,11 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
 #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
 #endif /* GL_EXT_texture_sRGB */
 
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT                        0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
 #ifndef GL_EXT_texture_sRGB_decode
 #define GL_EXT_texture_sRGB_decode 1
 #define GL_TEXTURE_SRGB_DECODE_EXT        0x8A48
@@ -8521,6 +8555,10 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
 #define GL_SKIP_DECODE_EXT                0x8A4A
 #endif /* GL_EXT_texture_sRGB_decode */
 
+#ifndef GL_EXT_texture_shadow_lod
+#define GL_EXT_texture_shadow_lod 1
+#endif /* GL_EXT_texture_shadow_lod */
+
 #ifndef GL_EXT_texture_shared_exponent
 #define GL_EXT_texture_shared_exponent 1
 #define GL_RGB9_E5_EXT                    0x8C3D
@@ -9240,6 +9278,17 @@ GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLen
 #define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
 #endif /* GL_MESAX_texture_stack */
 
+#ifndef GL_MESA_framebuffer_flip_y
+#define GL_MESA_framebuffer_flip_y 1
+#define GL_FRAMEBUFFER_FLIP_Y_MESA        0x8BBB
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIMESAPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVMESAPROC) (GLenum target, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFramebufferParameteriMESA (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameterivMESA (GLenum target, GLenum pname, GLint *params);
+#endif
+#endif /* GL_MESA_framebuffer_flip_y */
+
 #ifndef GL_MESA_pack_invert
 #define GL_MESA_pack_invert 1
 #define GL_PACK_INVERT_MESA               0x8758
@@ -9353,6 +9402,25 @@ GLAPI void APIENTRY glEndConditionalRenderNVX (void);
 #define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
 #endif /* GL_NVX_gpu_memory_info */
 
+#ifndef GL_NVX_gpu_multicast2
+#define GL_NVX_gpu_multicast2 1
+#define GL_UPLOAD_GPU_MASK_NVX            0x954A
+typedef void (APIENTRYP PFNGLUPLOADGPUMASKNVXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTPOSITIONWSCALENVXPROC) (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff);
+typedef void (APIENTRYP PFNGLMULTICASTSCISSORARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLint *v);
+typedef GLuint (APIENTRYP PFNGLASYNCCOPYBUFFERSUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray);
+typedef GLuint (APIENTRYP PFNGLASYNCCOPYIMAGESUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUploadGpuMaskNVX (GLbitfield mask);
+GLAPI void APIENTRY glMulticastViewportArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glMulticastViewportPositionWScaleNVX (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff);
+GLAPI void APIENTRY glMulticastScissorArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLint *v);
+GLAPI GLuint APIENTRY glAsyncCopyBufferSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray);
+GLAPI GLuint APIENTRY glAsyncCopyImageSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray);
+#endif
+#endif /* GL_NVX_gpu_multicast2 */
+
 #ifndef GL_NVX_linked_gpu_multicast
 #define GL_NVX_linked_gpu_multicast 1
 #define GL_LGPU_SEPARATE_STORAGE_BIT_NVX  0x0800
@@ -9367,6 +9435,20 @@ GLAPI void APIENTRY glLGPUInterlockNVX (void);
 #endif
 #endif /* GL_NVX_linked_gpu_multicast */
 
+#ifndef GL_NVX_progress_fence
+#define GL_NVX_progress_fence 1
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRESSFENCENVXPROC) (void);
+typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREUI64NVXPROC) (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+typedef void (APIENTRYP PFNGLWAITSEMAPHOREUI64NVXPROC) (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+typedef void (APIENTRYP PFNGLCLIENTWAITSEMAPHOREUI64NVXPROC) (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glCreateProgressFenceNVX (void);
+GLAPI void APIENTRY glSignalSemaphoreui64NVX (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+GLAPI void APIENTRY glWaitSemaphoreui64NVX (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+GLAPI void APIENTRY glClientWaitSemaphoreui64NVX (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray);
+#endif
+#endif /* GL_NVX_progress_fence */
+
 #ifndef GL_NV_alpha_to_coverage_dither_control
 #define GL_NV_alpha_to_coverage_dither_control 1
 #define GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV 0x934D
@@ -9579,6 +9661,10 @@ GLAPI void APIENTRY glCallCommandListNV (GLuint list);
 #define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
 #endif /* GL_NV_compute_program5 */
 
+#ifndef GL_NV_compute_shader_derivatives
+#define GL_NV_compute_shader_derivatives 1
+#endif /* GL_NV_compute_shader_derivatives */
+
 #ifndef GL_NV_conditional_render
 #define GL_NV_conditional_render 1
 #define GL_QUERY_WAIT_NV                  0x8E13
@@ -9877,6 +9963,10 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons
 #define GL_NV_fragment_program_option 1
 #endif /* GL_NV_fragment_program_option */
 
+#ifndef GL_NV_fragment_shader_barycentric
+#define GL_NV_fragment_shader_barycentric 1
+#endif /* GL_NV_fragment_shader_barycentric */
+
 #ifndef GL_NV_fragment_shader_interlock
 #define GL_NV_fragment_shader_interlock 1
 #endif /* GL_NV_fragment_shader_interlock */
@@ -9892,11 +9982,11 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons
 #define GL_COVERAGE_MODULATION_NV         0x9332
 #define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
 typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
-typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufSize, GLfloat *v);
 typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
 #ifdef GL_GLEXT_PROTOTYPES
 GLAPI void APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
-GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufSize, GLfloat *v);
 GLAPI void APIENTRY glCoverageModulationNV (GLenum components);
 #endif
 #endif /* GL_NV_framebuffer_mixed_samples */
@@ -10149,9 +10239,9 @@ GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfN
 #define GL_SUPERSAMPLE_SCALE_X_NV         0x9372
 #define GL_SUPERSAMPLE_SCALE_Y_NV         0x9373
 #define GL_CONFORMANT_NV                  0x9374
-typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params);
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params);
 #endif
 #endif /* GL_NV_internalformat_sample_query */
 
@@ -10161,6 +10251,96 @@ GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum interna
 #define GL_MAX_SPOT_EXPONENT_NV           0x8505
 #endif /* GL_NV_light_max_exponent */
 
+#ifndef GL_NV_memory_attachment
+#define GL_NV_memory_attachment 1
+#define GL_ATTACHED_MEMORY_OBJECT_NV      0x95A4
+#define GL_ATTACHED_MEMORY_OFFSET_NV      0x95A5
+#define GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6
+#define GL_MEMORY_ATTACHABLE_SIZE_NV      0x95A7
+#define GL_MEMORY_ATTACHABLE_NV           0x95A8
+#define GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9
+#define GL_DETACHED_TEXTURES_NV           0x95AA
+#define GL_DETACHED_BUFFERS_NV            0x95AB
+#define GL_MAX_DETACHED_TEXTURES_NV       0x95AC
+#define GL_MAX_DETACHED_BUFFERS_NV        0x95AD
+typedef void (APIENTRYP PFNGLGETMEMORYOBJECTDETACHEDRESOURCESUIVNVPROC) (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+typedef void (APIENTRYP PFNGLRESETMEMORYOBJECTPARAMETERNVPROC) (GLuint memory, GLenum pname);
+typedef void (APIENTRYP PFNGLTEXATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLBUFFERATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLTEXTUREATTACHMEMORYNVPROC) (GLuint texture, GLuint memory, GLuint64 offset);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERATTACHMEMORYNVPROC) (GLuint buffer, GLuint memory, GLuint64 offset);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMemoryObjectDetachedResourcesuivNV (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params);
+GLAPI void APIENTRY glResetMemoryObjectParameterNV (GLuint memory, GLenum pname);
+GLAPI void APIENTRY glTexAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glBufferAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glTextureAttachMemoryNV (GLuint texture, GLuint memory, GLuint64 offset);
+GLAPI void APIENTRY glNamedBufferAttachMemoryNV (GLuint buffer, GLuint memory, GLuint64 offset);
+#endif
+#endif /* GL_NV_memory_attachment */
+
+#ifndef GL_NV_mesh_shader
+#define GL_NV_mesh_shader 1
+#define GL_MESH_SHADER_NV                 0x9559
+#define GL_TASK_SHADER_NV                 0x955A
+#define GL_MAX_MESH_UNIFORM_BLOCKS_NV     0x8E60
+#define GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV 0x8E61
+#define GL_MAX_MESH_IMAGE_UNIFORMS_NV     0x8E62
+#define GL_MAX_MESH_UNIFORM_COMPONENTS_NV 0x8E63
+#define GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV 0x8E64
+#define GL_MAX_MESH_ATOMIC_COUNTERS_NV    0x8E65
+#define GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV 0x8E66
+#define GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV 0x8E67
+#define GL_MAX_TASK_UNIFORM_BLOCKS_NV     0x8E68
+#define GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV 0x8E69
+#define GL_MAX_TASK_IMAGE_UNIFORMS_NV     0x8E6A
+#define GL_MAX_TASK_UNIFORM_COMPONENTS_NV 0x8E6B
+#define GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV 0x8E6C
+#define GL_MAX_TASK_ATOMIC_COUNTERS_NV    0x8E6D
+#define GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV 0x8E6E
+#define GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV 0x8E6F
+#define GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV 0x95A2
+#define GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV 0x95A3
+#define GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV  0x9536
+#define GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV  0x9537
+#define GL_MAX_MESH_OUTPUT_VERTICES_NV    0x9538
+#define GL_MAX_MESH_OUTPUT_PRIMITIVES_NV  0x9539
+#define GL_MAX_TASK_OUTPUT_COUNT_NV       0x953A
+#define GL_MAX_DRAW_MESH_TASKS_COUNT_NV   0x953D
+#define GL_MAX_MESH_VIEWS_NV              0x9557
+#define GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV 0x92DF
+#define GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV 0x9543
+#define GL_MAX_MESH_WORK_GROUP_SIZE_NV    0x953B
+#define GL_MAX_TASK_WORK_GROUP_SIZE_NV    0x953C
+#define GL_MESH_WORK_GROUP_SIZE_NV        0x953E
+#define GL_TASK_WORK_GROUP_SIZE_NV        0x953F
+#define GL_MESH_VERTICES_OUT_NV           0x9579
+#define GL_MESH_PRIMITIVES_OUT_NV         0x957A
+#define GL_MESH_OUTPUT_TYPE_NV            0x957B
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV 0x959C
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV 0x959D
+#define GL_REFERENCED_BY_MESH_SHADER_NV   0x95A0
+#define GL_REFERENCED_BY_TASK_SHADER_NV   0x95A1
+#define GL_MESH_SHADER_BIT_NV             0x00000040
+#define GL_TASK_SHADER_BIT_NV             0x00000080
+#define GL_MESH_SUBROUTINE_NV             0x957C
+#define GL_TASK_SUBROUTINE_NV             0x957D
+#define GL_MESH_SUBROUTINE_UNIFORM_NV     0x957E
+#define GL_TASK_SUBROUTINE_UNIFORM_NV     0x957F
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV 0x959E
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV 0x959F
+typedef void (APIENTRYP PFNGLDRAWMESHTASKSNVPROC) (GLuint first, GLuint count);
+typedef void (APIENTRYP PFNGLDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect);
+typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTCOUNTNVPROC) (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshTasksNV (GLuint first, GLuint count);
+GLAPI void APIENTRY glDrawMeshTasksIndirectNV (GLintptr indirect);
+GLAPI void APIENTRY glMultiDrawMeshTasksIndirectNV (GLintptr indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawMeshTasksIndirectCountNV (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#endif
+#endif /* GL_NV_mesh_shader */
+
 #ifndef GL_NV_multisample_coverage
 #define GL_NV_multisample_coverage 1
 #endif /* GL_NV_multisample_coverage */
@@ -10442,7 +10622,7 @@ typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, co
 typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
 typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
 typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
-typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params);
 typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
 typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
 typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
@@ -10507,7 +10687,7 @@ GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fo
 GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
 GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
 GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
-GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params);
 GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
 GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
 GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
@@ -10596,9 +10776,9 @@ GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
 #define GL_QUERY_RESOURCE_TEXTURE_NV      0x9545
 #define GL_QUERY_RESOURCE_RENDERBUFFER_NV 0x9546
 #define GL_QUERY_RESOURCE_BUFFEROBJECT_NV 0x9547
-typedef GLint (APIENTRYP PFNGLQUERYRESOURCENVPROC) (GLenum queryType, GLint tagId, GLuint bufSize, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLQUERYRESOURCENVPROC) (GLenum queryType, GLint tagId, GLuint count, GLint *buffer);
 #ifdef GL_GLEXT_PROTOTYPES
-GLAPI GLint APIENTRY glQueryResourceNV (GLenum queryType, GLint tagId, GLuint bufSize, GLint *buffer);
+GLAPI GLint APIENTRY glQueryResourceNV (GLenum queryType, GLint tagId, GLuint count, GLint *buffer);
 #endif
 #endif /* GL_NV_query_resource */
 
@@ -10706,6 +10886,11 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname,
 #endif
 #endif /* GL_NV_register_combiners2 */
 
+#ifndef GL_NV_representative_fragment_test
+#define GL_NV_representative_fragment_test 1
+#define GL_REPRESENTATIVE_FRAGMENT_TEST_NV 0x937F
+#endif /* GL_NV_representative_fragment_test */
+
 #ifndef GL_NV_robustness_video_memory_purge
 #define GL_NV_robustness_video_memory_purge 1
 #define GL_PURGED_CONTEXT_RESET_NV        0x92BB
@@ -10735,6 +10920,18 @@ GLAPI void APIENTRY glResolveDepthValuesNV (void);
 #define GL_NV_sample_mask_override_coverage 1
 #endif /* GL_NV_sample_mask_override_coverage */
 
+#ifndef GL_NV_scissor_exclusive
+#define GL_NV_scissor_exclusive 1
+#define GL_SCISSOR_TEST_EXCLUSIVE_NV      0x9555
+#define GL_SCISSOR_BOX_EXCLUSIVE_NV       0x9556
+typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVENVPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVEARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glScissorExclusiveNV (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorExclusiveArrayvNV (GLuint first, GLsizei count, const GLint *v);
+#endif
+#endif /* GL_NV_scissor_exclusive */
+
 #ifndef GL_NV_shader_atomic_counters
 #define GL_NV_shader_atomic_counters 1
 #endif /* GL_NV_shader_atomic_counters */
@@ -10799,6 +10996,15 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs
 #define GL_NV_shader_storage_buffer_object 1
 #endif /* GL_NV_shader_storage_buffer_object */
 
+#ifndef GL_NV_shader_subgroup_partitioned
+#define GL_NV_shader_subgroup_partitioned 1
+#define GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV 0x00000100
+#endif /* GL_NV_shader_subgroup_partitioned */
+
+#ifndef GL_NV_shader_texture_footprint
+#define GL_NV_shader_texture_footprint 1
+#endif /* GL_NV_shader_texture_footprint */
+
 #ifndef GL_NV_shader_thread_group
 #define GL_NV_shader_thread_group 1
 #define GL_WARP_SIZE_NV                   0x9339
@@ -10810,6 +11016,47 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs
 #define GL_NV_shader_thread_shuffle 1
 #endif /* GL_NV_shader_thread_shuffle */
 
+#ifndef GL_NV_shading_rate_image
+#define GL_NV_shading_rate_image 1
+#define GL_SHADING_RATE_IMAGE_NV          0x9563
+#define GL_SHADING_RATE_NO_INVOCATIONS_NV 0x9564
+#define GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV 0x9565
+#define GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV 0x9566
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV 0x9567
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV 0x9568
+#define GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV 0x9569
+#define GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV 0x956A
+#define GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV 0x956B
+#define GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV 0x956C
+#define GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV 0x956D
+#define GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV 0x956E
+#define GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV 0x956F
+#define GL_SHADING_RATE_IMAGE_BINDING_NV  0x955B
+#define GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV 0x955C
+#define GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV 0x955D
+#define GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV 0x955E
+#define GL_MAX_COARSE_FRAGMENT_SAMPLES_NV 0x955F
+#define GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV 0x95AE
+#define GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV 0x95AF
+#define GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV 0x95B0
+typedef void (APIENTRYP PFNGLBINDSHADINGRATEIMAGENVPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLGETSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint entry, GLenum *rate);
+typedef void (APIENTRYP PFNGLGETSHADINGRATESAMPLELOCATIONIVNVPROC) (GLenum rate, GLuint samples, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEBARRIERNVPROC) (GLboolean synchronize);
+typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates);
+typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERNVPROC) (GLenum order);
+typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERCUSTOMNVPROC) (GLenum rate, GLuint samples, const GLint *locations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindShadingRateImageNV (GLuint texture);
+GLAPI void APIENTRY glGetShadingRateImagePaletteNV (GLuint viewport, GLuint entry, GLenum *rate);
+GLAPI void APIENTRY glGetShadingRateSampleLocationivNV (GLenum rate, GLuint samples, GLuint index, GLint *location);
+GLAPI void APIENTRY glShadingRateImageBarrierNV (GLboolean synchronize);
+GLAPI void APIENTRY glShadingRateImagePaletteNV (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates);
+GLAPI void APIENTRY glShadingRateSampleOrderNV (GLenum order);
+GLAPI void APIENTRY glShadingRateSampleOrderCustomNV (GLenum rate, GLuint samples, const GLint *locations);
+#endif
+#endif /* GL_NV_shading_rate_image */
+
 #ifndef GL_NV_stereo_view_rendering
 #define GL_NV_stereo_view_rendering 1
 #endif /* GL_NV_stereo_view_rendering */
@@ -11102,7 +11349,7 @@ typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const
 typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
 typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
 typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
-typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
 typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
 typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
 typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
@@ -11113,13 +11360,21 @@ GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSu
 GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
 GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface);
 GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface);
-GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
 GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access);
 GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
 GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
 #endif
 #endif /* GL_NV_vdpau_interop */
 
+#ifndef GL_NV_vdpau_interop2
+#define GL_NV_vdpau_interop2 1
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACEWITHPICTURESTRUCTURENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceWithPictureStructureNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure);
+#endif
+#endif /* GL_NV_vdpau_interop2 */
+
 #ifndef GL_NV_vertex_array_range
 #define GL_NV_vertex_array_range 1
 #define GL_VERTEX_ARRAY_RANGE_NV          0x851D

+ 2 - 0
panda/src/gobj/config_gobj.cxx

@@ -53,6 +53,7 @@
 #include "samplerState.h"
 #include "shader.h"
 #include "shaderContext.h"
+#include "shaderType.h"
 #include "transformBlend.h"
 #include "transformBlendTable.h"
 #include "transformTable.h"
@@ -587,6 +588,7 @@ ConfigureFn(config_gobj) {
   SamplerState::init_type();
   ShaderContext::init_type();
   Shader::init_type();
+  ShaderType::init_type();
   SliderTable::init_type();
   Texture::init_type();
   TextureContext::init_type();

+ 1 - 0
panda/src/gobj/p3gobj_composite2.cxx

@@ -8,6 +8,7 @@
 #include "shaderBuffer.cxx"
 #include "shaderContext.cxx"
 #include "shader.cxx"
+#include "shaderType.cxx"
 #include "simpleAllocator.cxx"
 #include "simpleLru.cxx"
 #include "sliderTable.cxx"

+ 411 - 12
panda/src/gobj/shader.cxx

@@ -2400,6 +2400,7 @@ read(const ShaderFile &sfile, BamCacheRecord *record) {
       return false;
     }
 
+    // Read the various stages in order.
     if (!sfile._vertex.empty() &&
         !do_read_source(Stage::vertex, sfile._vertex, record)) {
       return false;
@@ -2451,9 +2452,10 @@ read(const ShaderFile &sfile, BamCacheRecord *record) {
       return false;
     }
 
-    for (ShaderModule *module : _modules) {
-      module->set_source_filename(fn);
-    }
+    //FIXME
+    //for (ShaderModule *module : _modules) {
+    //  module->set_source_filename(fn);
+    //}
 
   } else {
     shader_cat.error()
@@ -2461,6 +2463,10 @@ read(const ShaderFile &sfile, BamCacheRecord *record) {
     return false;
   }
 
+  if (!link()) {
+    return false;
+  }
+
   _prepare_shader_pcollector = PStatCollector(std::string("Draw:Prepare:Shader:") + _debug_name);
 
   _loaded = true;
@@ -2534,6 +2540,10 @@ load(const ShaderFile &sbody, BamCacheRecord *record) {
     return false;
   }
 
+  if (!link()) {
+    return false;
+  }
+
   _debug_name = "created-shader";
   _prepare_shader_pcollector = PStatCollector("Draw:Prepare:Shader:created-shader");
 
@@ -2578,7 +2588,7 @@ do_read_source(Stage stage, const Filename &fn, BamCacheRecord *record) {
   }
 
   shader_cat.info() << "Reading shader file: " << fn << "\n";
-  if (!do_read_source(stage, *in, record)) {
+  if (!do_read_source(stage, *in, fn, record)) {
     vf->close_read_file(in);
     return false;
   }
@@ -2586,10 +2596,6 @@ do_read_source(Stage stage, const Filename &fn, BamCacheRecord *record) {
   //_last_modified = std::max(_last_modified, vf->get_timestamp());
   //_source_files.push_back(fullpath);
 
-  // Update module source filename, should find a better way to do this...
-  PT(ShaderModule) module = _modules.back();
-  module->set_source_filename(fn);
-
   vf->close_read_file(in);
 
   if (!_debug_name.empty()) {
@@ -2608,11 +2614,12 @@ do_read_source(Stage stage, const Filename &fn, BamCacheRecord *record) {
  * it 'invalid'.
  */
 bool Shader::
-do_read_source(ShaderModule::Stage stage, std::istream &in, BamCacheRecord *record) {
+do_read_source(ShaderModule::Stage stage, std::istream &in,
+               const Filename &source_filename, BamCacheRecord *record) {
   ShaderCompiler *compiler = get_compiler(_language);
   nassertr(compiler != nullptr, false);
 
-  PT(ShaderModule) module = compiler->compile_now(stage, in, "created-shader", record);
+  PT(ShaderModule) module = compiler->compile_now(stage, in, source_filename, record);
   if (!module) {
     return false;
   }
@@ -2633,6 +2640,33 @@ do_read_source(ShaderModule::Stage stage, std::istream &in, BamCacheRecord *reco
 #endif
   }
 
+  if (!source_filename.empty()) {
+    module->set_source_filename(source_filename);
+  }
+
+  // Link its inputs up with the previous stage.
+  if (!_modules.empty()) {
+    if (!module->link_inputs(_modules.back().get_read_pointer())) {
+      shader_cat.error()
+        << "Unable to match shader module interfaces.\n";
+      return false;
+    }
+  }
+  else if (stage == Stage::vertex) {
+    // Bind vertex inputs right away.
+    bool success = true;
+    for (const ShaderModule::Variable &var : module->_inputs) {
+      if (!bind_vertex_input(var.name, var.type, var.get_location())) {
+        success = false;
+      }
+    }
+    if (!success) {
+      shader_cat.error()
+        << "Failed to bind vertex inputs.\n";
+      return false;
+    }
+  }
+
   _modules.push_back(std::move(module));
   _module_mask |= (1 << (int)stage);
 
@@ -2649,7 +2683,370 @@ do_read_source(ShaderModule::Stage stage, std::istream &in, BamCacheRecord *reco
 bool Shader::
 do_load_source(ShaderModule::Stage stage, const std::string &source, BamCacheRecord *record) {
   std::istringstream in(source);
-  return do_read_source(stage, in, record);
+  return do_read_source(stage, in, Filename("created-shader"), record);
+}
+
+/**
+ * Completes the binding between the different shader stages.
+ */
+bool Shader::
+link() {
+  // Go through all the modules to fetch the parameters.
+  pmap<CPT_InternalName, const ShaderModule::Variable *> parameters;
+  BitArray used_locations;
+
+  for (COWPT(ShaderModule) &cow_module : _modules) {
+    const ShaderModule *module = cow_module.get_read_pointer();
+    pmap<int, int> remap;
+
+    for (const ShaderModule::Variable &var : module->_parameters) {
+      const auto result = parameters.insert({var.name, &var});
+      const 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) {
+          shader_cat.error()
+            << "Parameter " << var.name << " in module " << *module
+            << " is declared in another stage with a mismatching type!\n";
+          return false;
+        }
+
+        if (it->second->get_location() != var.get_location()) {
+          // Different location; need to remap this.
+          remap[var.get_location()] = it->second->get_location();
+        }
+      } else if (var.has_location()) {
+        if (used_locations.get_bit(var.get_location())) {
+          // This location is already used.
+          int location = used_locations.get_lowest_off_bit();
+          used_locations.set_bit(location);
+          remap[var.get_location()] = location;
+        } else {
+          used_locations.set_bit(var.get_location());
+        }
+      }
+    }
+
+    if (!remap.empty()) {
+      PT(ShaderModule) module = cow_module.get_write_pointer();
+      if (shader_cat.is_debug()) {
+        shader_cat.debug()
+          << "Remapping " << remap.size() << " locations for module " << *module << "\n";
+      }
+      module->remap_parameter_locations(remap);
+    }
+  }
+
+  // Now bind all of the parameters.
+  bool success = true;
+  for (const auto &pair : parameters) {
+    const ShaderModule::Variable &var = *pair.second;
+
+    if (!bind_parameter(var.name, var.type, var.get_location())) {
+      success = false;
+    }
+  }
+
+  return success;
+}
+
+/**
+ * Binds a vertex input parameter with the given type.
+ */
+bool Shader::
+bind_vertex_input(const InternalName *name, const ::ShaderType *type, int location) {
+  std::string name_str = name->get_name();
+
+  Shader::ShaderVarSpec bind;
+  bind._id._name = name_str;
+  bind._id._seqno = location;
+  bind._name = nullptr;
+  bind._append_uv = -1;
+  bind._elements = 1;
+  bind._numeric_type = SPT_float;
+
+  // Check if it has a p3d_ prefix - if so, assign special meaning.
+  if (name_str.compare(0, 4, "p3d_") == 0) {
+    if (name_str == "p3d_Vertex") {
+      bind._name = InternalName::get_vertex();
+
+    } else if (name_str == "p3d_Normal") {
+      bind._name = InternalName::get_normal();
+
+    } else if (name_str == "p3d_Color") {
+      bind._name = InternalName::get_color();
+
+    } else if (name_str.compare(4, 7, "Tangent") == 0) {
+      bind._name = InternalName::get_tangent();
+      if (name_str.size() > 7) {
+        bind._append_uv = atoi(name_str.substr(7).c_str());
+      }
+
+    } else if (name_str.compare(4, 8, "Binormal") == 0) {
+      bind._name = InternalName::get_binormal();
+      if (name_str.size() > 8) {
+        bind._append_uv = atoi(name_str.substr(8).c_str());
+      }
+
+    } else if (name_str.compare(4, 13, "MultiTexCoord") == 0) {
+      bind._name = InternalName::get_texcoord();
+      bind._append_uv = atoi(name_str.substr(13).c_str());
+
+    } else {
+      shader_cat.error()
+        << "Unrecognized built-in vertex input name '" << name_str << "'!\n";
+      return false;
+    }
+  } else {
+    // Arbitrarily named attribute.
+    bind._name = InternalName::make(name_str);
+  }
+
+  _var_spec.push_back(bind);
+  return true;
+}
+
+/**
+ * Binds a uniform parameter with the given type.
+ */
+bool Shader::
+bind_parameter(const InternalName *name, const ::ShaderType *type, int location) {
+  std::string name_str = name->get_name();
+
+  Shader::ShaderArgId arg_id;
+  arg_id._name = name_str;
+  arg_id._seqno = location;
+
+  // Check if it has a p3d_ prefix - if so, assign special meaning.
+  if (name_str.compare(0, 4, "p3d_") == 0) {
+    if (name_str == "p3d_ModelViewProjectionMatrix") {
+      Shader::ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._func = SMF_compose;
+      bind._piece = SMP_whole;
+      bind._arg[0] = nullptr;
+      bind._arg[1] = nullptr;
+      bind._part[0] = SMO_model_to_apiview;
+      bind._part[1] = SMO_apiview_to_apiclip;
+
+      cp_optimize_mat_spec(bind);
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0] | bind._dep[1];
+      return true;
+    }
+    if (name_str.compare(4, 7, "Texture") == 0) {
+      ShaderTexSpec bind;
+      bind._id = arg_id;
+      bind._part = STO_stage_i;
+      bind._name = 0;
+      bind._desired_type = Texture::TT_2d_texture;
+
+      string tail;
+      bind._stage = string_to_int(name_str.substr(11), tail);
+      if (!tail.empty()) {
+        shader_cat.error()
+          << "Error parsing shader input name: unexpected '"
+          << tail << "' in '" << name_str << "'\n";
+        return false;
+      }
+
+      _tex_spec.push_back(bind);
+      return true;
+    }
+    if (name_str == "p3d_ColorScale") {
+      ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._func = SMF_first;
+      bind._part[0] = SMO_attr_colorscale;
+      bind._arg[0] = nullptr;
+      bind._dep[0] = SSD_general | SSD_colorscale;
+      bind._part[1] = SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = SSD_NONE;
+      bind._piece = SMP_row3;
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0];
+      return true;
+    }
+    if (name_str == "p3d_TexAlphaOnly") {
+      ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._func = SMF_first;
+      bind._index = 0;
+      bind._part[0] = SMO_tex_is_alpha_i;
+      bind._arg[0] = nullptr;
+      bind._dep[0] = SSD_general | SSD_texture | SSD_frame;
+      bind._part[1] = SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = SSD_NONE;
+      bind._piece = SMP_row3;
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0] | bind._dep[1];
+      return true;
+    }
+
+    shader_cat.error() << "Unrecognized uniform name '" << name_str << "'!\n";
+    return false;
+  }
+
+  if (const ::ShaderType::Array *array = type->as_array()) {
+    // A uniform array.
+    const ::ShaderType *element_type = array->get_element_type();
+
+    Shader::ShaderPtrSpec bind;
+    bind._id = arg_id;
+
+    if (const ::ShaderType::Matrix *matrix = element_type->as_matrix()) {
+      size_t num_rows = matrix->get_num_rows();
+      if (matrix->get_num_columns() != num_rows) {
+        shader_cat.error()
+          << "Uniform parameter '" << name_str << "' has unsupported non-square matrix type\n";
+        return false;
+      }
+
+      bind._dim[1] = num_rows * num_rows;
+      bind._type = SPT_float;
+    }
+    else if (const ::ShaderType::Vector *vector = element_type->as_vector()) {
+      bind._dim[1] = 4;
+      bind._type = SPT_float;
+    }
+    else if (const ::ShaderType::Scalar *scalar = element_type->as_scalar()) {
+      bind._dim[1] = 1;
+      bind._type = SPT_float;
+    }
+
+    bind._arg = name;
+    bind._dim[0] = array->get_num_elements();
+    bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
+    bind._dep[1] = SSD_NONE;
+    _ptr_spec.push_back(bind);
+    return true;
+  }
+  else if (const ::ShaderType::SampledImage *sampler = type->as_sampled_image()) {
+    ShaderTexSpec bind;
+    bind._id = arg_id;
+    bind._part = STO_named_input;
+    bind._name = name;
+    bind._desired_type = sampler->get_texture_type();
+    bind._stage = 0;
+    _tex_spec.push_back(bind);
+    return true;
+  }
+  else if (const ::ShaderType::Image *image = type->as_image()) {
+    ShaderImgSpec bind;
+    bind._id = arg_id;
+    bind._name = name;
+    bind._desired_type = image->get_texture_type();
+    bind._writable = image->is_writable();
+    _img_spec.push_back(bind);
+    return true;
+  }
+  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._piece = SMP_upper3x3;
+      bind._func = SMF_first;
+      bind._part[0] = SMO_mat_constant_x;
+      bind._arg[0] = name;
+      bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
+      bind._part[1] = SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = SSD_NONE;
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0];
+      return true;
+    }
+    else if (matrix->get_num_columns() == 4 && matrix->get_num_rows() == 4) {
+      ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._piece = SMP_whole;
+      bind._func = SMF_first;
+      bind._part[1] = SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = SSD_NONE;
+
+      if (name->get_parent() != InternalName::get_root()) {
+        // It might be something like an attribute of a shader input, like a
+        // light parameter.  It might also just be a custom struct
+        // parameter.  We can't know yet, sadly.
+        if (name->get_basename() == "shadowMatrix") {
+          // Special exception for shadowMatrix, which is deprecated,
+          // because it includes the model transformation.  It is far more
+          // efficient to do that in the shader instead.
+          static bool warned = false;
+          if (!warned) {
+            warned = true;
+            shader_cat.warning()
+              << "light.shadowMatrix inputs are deprecated; use "
+                 "shadowViewMatrix instead, which transforms from view "
+                 "space instead of model space.\n";
+          }
+          bind._func = SMF_compose;
+          bind._part[0] = SMO_model_to_apiview;
+          bind._arg[0] = nullptr;
+          bind._dep[0] = SSD_general | SSD_transform;
+          bind._part[1] = SMO_mat_constant_x_attrib;
+          bind._arg[1] = name->get_parent()->append("shadowViewMatrix");
+          bind._dep[1] = SSD_general | SSD_shaderinputs | SSD_frame | SSD_view_transform;
+        } else {
+          bind._part[0] = SMO_mat_constant_x_attrib;
+          bind._arg[0] = name;
+          bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame | SSD_view_transform;
+        }
+      } else {
+        bind._part[0] = SMO_mat_constant_x;
+        bind._arg[0] = name;
+        bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
+      }
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0];
+      return true;
+    }
+  }
+  else if (type == ::ShaderType::float_type) {
+    if (name->get_parent() != InternalName::get_root()) {
+      // It might be something like an attribute of a shader input, like a
+      // light parameter.  It might also just be a custom struct
+      // parameter.  We can't know yet, sadly.
+      ShaderMatSpec bind;
+      bind._id = arg_id;
+      bind._piece = SMP_row3x1;
+      bind._func = SMF_first;
+      bind._part[0] = SMO_vec_constant_x_attrib;
+      bind._arg[0] = name;
+      // We need SSD_view_transform since some attributes (eg. light
+      // position) have to be transformed to view space.
+      bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame | SSD_view_transform;
+      bind._part[1] = SMO_identity;
+      bind._arg[1] = nullptr;
+      bind._dep[1] = SSD_NONE;
+      _mat_spec.push_back(bind);
+      _mat_deps |= bind._dep[0];
+      return true;
+    }
+    else {
+      ShaderPtrSpec bind;
+      bind._id = arg_id;
+      bind._arg = name;
+      bind._dim[0] = 1;
+      bind._dim[1] = 1;
+      bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame;
+      bind._dep[1] = SSD_NONE;
+      bind._type = SPT_float;
+      _ptr_spec.push_back(bind);
+      return true;
+    }
+  }
+
+  shader_cat.error()
+    << "Uniform parameter '" << name_str << "' has unsupported type "
+    << *type << "\n";
+  return false;
 }
 
 /**
@@ -2658,7 +3055,9 @@ do_load_source(ShaderModule::Stage stage, const std::string &source, BamCacheRec
  */
 bool Shader::
 check_modified() const {
-  for (ShaderModule *module : _modules) {
+  for (COWPT(ShaderModule) const &cow_module : _modules) {
+    const ShaderModule *module = cow_module.get_read_pointer();
+
     if (module->_record != nullptr && !module->_record->dependents_unchanged()) {
       return true;
     }

+ 19 - 5
panda/src/gobj/shader.h

@@ -36,6 +36,7 @@
 #include "epvector.h"
 #include "asyncFuture.h"
 #include "shaderModule.h"
+#include "copyOnWritePointer.h"
 
 #ifdef HAVE_CG
 // I don't want to include the Cg header file into panda as a whole.  Instead,
@@ -414,7 +415,7 @@ public:
     ShaderArgId       _id;
     ShaderMatFunc     _func;
     ShaderMatInput    _part[2];
-    PT(InternalName)  _arg[2];
+    CPT(InternalName) _arg[2];
     int               _dep[2];
     int               _index;
     ShaderMatPiece    _piece;
@@ -422,13 +423,20 @@ public:
 
   struct ShaderTexSpec {
     ShaderArgId       _id;
-    PT(InternalName)  _name;
+    CPT(InternalName) _name;
     ShaderTexInput    _part;
     int               _stage;
     int               _desired_type;
     PT(InternalName)  _suffix;
   };
 
+  struct ShaderImgSpec {
+    ShaderArgId       _id;
+    CPT(InternalName) _name;
+    int               _desired_type;
+    bool              _writable;
+  };
+
   struct ShaderVarSpec {
     ShaderArgId       _id;
     PT(InternalName)  _name;
@@ -441,7 +449,7 @@ public:
     ShaderArgId       _id;
     int               _dim[3]; //n_elements,rows,cols
     int               _dep[2];
-    PT(InternalName)  _arg;
+    CPT(InternalName) _arg;
     ShaderArgInfo     _info;
     ShaderPtrType     _type;
   };
@@ -567,13 +575,14 @@ public:
   pvector<ShaderPtrSpec> _ptr_spec;
   epvector<ShaderMatSpec> _mat_spec;
   pvector<ShaderTexSpec> _tex_spec;
+  pvector<ShaderImgSpec> _img_spec;
   pvector<ShaderVarSpec> _var_spec;
   int _mat_deps;
 
   bool _error_flag;
   ShaderFile _text;
 
-  typedef pvector<PT(ShaderModule)> Modules;
+  typedef pvector<COWPT(ShaderModule)> Modules;
   Modules _modules;
   int _module_mask = 0;
 
@@ -615,9 +624,14 @@ private:
   bool read(const ShaderFile &sfile, BamCacheRecord *record = nullptr);
   bool load(const ShaderFile &sbody, BamCacheRecord *record = nullptr);
   bool do_read_source(ShaderModule::Stage stage, const Filename &fn, BamCacheRecord *record);
-  bool do_read_source(ShaderModule::Stage stage, std::istream &in, BamCacheRecord *record);
+  bool do_read_source(ShaderModule::Stage stage, std::istream &in,
+                      const Filename &source_filename, BamCacheRecord *record);
   bool do_load_source(ShaderModule::Stage stage, const std::string &source, BamCacheRecord *record);
 
+  bool link();
+  bool bind_vertex_input(const InternalName *name, const ::ShaderType *type, int location);
+  bool bind_parameter(const InternalName *name, const ::ShaderType *type, int location);
+
   bool check_modified() const;
   ShaderCompiler *get_compiler(ShaderLanguage lang) const;
 

+ 176 - 0
panda/src/gobj/shaderType.I

@@ -0,0 +1,176 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderType.I
+ * @author rdb
+ * @date 2019-03-12
+ */
+
+/**
+ * Takes an rvalue ShaderType and returns a uniquified pointer to an equivalent
+ * ShaderType object.
+ */
+template<class Type>
+const Type *ShaderType::
+register_type(Type &&type) {
+  nassertr(_registered_types != nullptr, nullptr);
+
+  Registry::iterator it = _registered_types->find(&type);
+  if (it != _registered_types->end()) {
+    return (const Type *)*it;
+  }
+
+  Type *new_type = new Type(std::move(type));
+  _registered_types->insert(new_type);
+  return new_type;
+}
+
+/**
+ * Provides an arbitrary ordering among all unique shader types, so we can
+ * store the essentially different ones in a big set and throw away the rest.
+ */
+INLINE int ShaderType::
+compare_to(const ShaderType &other) const {
+  TypeHandle this_type = get_type();
+  TypeHandle other_type = other.get_type();
+  if (this_type == other_type) {
+    return compare_to_impl(other);
+  }
+  return (this_type > other_type) - (this_type < other_type);
+}
+
+/**
+ * Constructs a scalar type.
+ */
+INLINE ShaderType::Scalar::
+Scalar(GeomEnums::NumericType numeric_type) : _numeric_type(numeric_type) {
+}
+
+/**
+ * Returns the base numeric type.
+ */
+INLINE GeomEnums::NumericType ShaderType::Scalar::
+get_numeric_type() const {
+  return _numeric_type;
+}
+
+/**
+ * Constructs a vector from a scalar type and number of elements.
+ */
+INLINE ShaderType::Vector::
+Vector(const ShaderType *base_type, size_t num_elements) :
+  _base_type(base_type),
+  _num_elements(num_elements) {
+}
+
+/**
+ * Returns the scalar type that this vector consists of.
+ */
+INLINE const ShaderType *ShaderType::Vector::
+get_base_type() const {
+  return _base_type;
+}
+
+/**
+ * Constructs a matrix type from a scalar type, a number of rows and columns.
+ */
+INLINE ShaderType::Matrix::
+Matrix(const ShaderType *base_type, size_t num_rows, size_t num_columns) :
+  _base_type(base_type),
+  _num_rows(num_rows),
+  _num_columns(num_columns) {
+}
+
+/**
+ * Returns the scalar type that this matrix consists of.
+ */
+INLINE const ShaderType *ShaderType::Matrix::
+get_base_type() const {
+  return _base_type;
+}
+
+/**
+ * Returns the number of rows in this matrix type.
+ */
+INLINE size_t ShaderType::Matrix::
+get_num_rows() const {
+  return _num_rows;
+}
+
+/**
+ * Returns the number of columns in this matrix type.
+ */
+INLINE size_t ShaderType::Matrix::
+get_num_columns() const {
+  return _num_columns;
+}
+
+/**
+ * Returns the type of elements in this array.
+ */
+INLINE const ShaderType *ShaderType::Array::
+get_element_type() const {
+  return _element_type;
+}
+
+/**
+ * Returns the number of elements in this array.
+ */
+INLINE size_t ShaderType::Array::
+get_num_elements() const {
+  return _num_elements;
+}
+
+/**
+ * Constructs an image type.
+ */
+INLINE ShaderType::Image::
+Image(Texture::TextureType type, Access access) :
+  _texture_type(type),
+  _access(access) {
+}
+
+/**
+ * Returns the type of texture this image samples.
+ */
+INLINE Texture::TextureType ShaderType::Image::
+get_texture_type() const {
+  return _texture_type;
+}
+
+/**
+ * Returns the way this image is accessed.
+ */
+INLINE ShaderType::Image::Access ShaderType::Image::
+get_access() const {
+  return _access;
+}
+
+/**
+ * Returns true if this image input is writable.
+ */
+INLINE bool ShaderType::Image::
+is_writable() const {
+  return ((int)_access & (int)Access::write_only) != 0;
+}
+
+/**
+ * Constructs a sampled image type.
+ */
+INLINE ShaderType::SampledImage::
+SampledImage(Texture::TextureType type) :
+  _texture_type(type) {
+}
+
+/**
+ * Returns the type of texture this image samples.
+ */
+INLINE Texture::TextureType ShaderType::SampledImage::
+get_texture_type() const {
+  return _texture_type;
+}

+ 199 - 0
panda/src/gobj/shaderType.cxx

@@ -0,0 +1,199 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderType.cxx
+ * @author rdb
+ * @date 2019-03-12
+ */
+
+#include "shaderType.h"
+
+const char *texture_type_suffixes[] = {
+  "1D", "2D", "3D", "2DArray", "Cube", "Buffer", "CubeArray", "1DArray",
+};
+
+ShaderType::Registry *ShaderType::_registered_types = nullptr;
+TypeHandle ShaderType::_type_handle;
+TypeHandle ShaderType::Scalar::_type_handle;
+TypeHandle ShaderType::Vector::_type_handle;
+TypeHandle ShaderType::Matrix::_type_handle;
+TypeHandle ShaderType::Struct::_type_handle;
+TypeHandle ShaderType::Array::_type_handle;
+TypeHandle ShaderType::Image::_type_handle;
+TypeHandle ShaderType::SampledImage::_type_handle;
+
+const ShaderType::Scalar *ShaderType::bool_type;
+const ShaderType::Scalar *ShaderType::int_type;
+const ShaderType::Scalar *ShaderType::uint_type;
+const ShaderType::Scalar *ShaderType::float_type;
+
+/**
+ *
+ */
+void ShaderType::
+init_type() {
+  if (_registered_types == nullptr) {
+    _registered_types = new Registry;
+  }
+
+  TypedReferenceCount::init_type();
+  ::register_type(_type_handle, "ShaderType",
+                  TypedReferenceCount::get_class_type());
+
+  ::register_type(Scalar::_type_handle, "ShaderType::Scalar", _type_handle);
+  ::register_type(Vector::_type_handle, "ShaderType::Vector", _type_handle);
+  ::register_type(Matrix::_type_handle, "ShaderType::Matrix", _type_handle);
+  ::register_type(Struct::_type_handle, "ShaderType::Struct", _type_handle);
+  ::register_type(Array::_type_handle, "ShaderType::Array", _type_handle);
+  ::register_type(Image::_type_handle, "ShaderType::Image", _type_handle);
+  ::register_type(SampledImage::_type_handle, "ShaderType::SampledImage", _type_handle);
+  //::register_type(Sampler::_type_handle, "ShaderType::Sampler", _type_handle);
+
+  bool_type = nullptr;
+  int_type = ShaderType::register_type(ShaderType::Scalar(GeomEnums::NT_int32));
+  uint_type = ShaderType::register_type(ShaderType::Scalar(GeomEnums::NT_uint32));
+  float_type = ShaderType::register_type(ShaderType::Scalar(GeomEnums::NT_float32));
+}
+
+#ifndef CPPPARSER
+/**
+ *
+ */
+void ShaderType::Scalar::
+output(std::ostream &out) const {
+  if (this == bool_type) {
+    out << "bool";
+  } else if (this == int_type) {
+    out << "int";
+  } else if (this == uint_type) {
+    out << "uint";
+  } else if (this == float_type) {
+    out << "float";
+  } else {
+    out << "unknown";
+  }
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+int ShaderType::Scalar::
+compare_to_impl(const ShaderType &other) const {
+  const Scalar &other_scalar = (const Scalar &)other;
+  return (_numeric_type > other_scalar._numeric_type)
+       - (_numeric_type < other_scalar._numeric_type);
+}
+
+/**
+ *
+ */
+void ShaderType::Vector::
+output(std::ostream &out) const {
+  out << *_base_type << _num_elements;
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+int ShaderType::Vector::
+compare_to_impl(const ShaderType &other) const {
+  const Vector &other_vector = (const Vector &)other;
+  if (_base_type != other_vector._base_type) {
+    return _base_type < other_vector._base_type ? -1 : 1;
+  }
+  return (_num_elements > other_vector._num_elements)
+       - (_num_elements < other_vector._num_elements);
+}
+
+/**
+ *
+ */
+void ShaderType::Matrix::
+output(std::ostream &out) const {
+  out << *_base_type << _num_rows << "x" << _num_columns;
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+int ShaderType::Matrix::
+compare_to_impl(const ShaderType &other) const {
+  const Matrix &other_matrix = (const Matrix &)other;
+  if (_base_type != other_matrix._base_type) {
+    return _base_type < other_matrix._base_type ? -1 : 1;
+  }
+  if (_num_rows != other_matrix._num_rows) {
+    return _num_rows < other_matrix._num_rows ? -1 : 1;
+  }
+  return (_num_columns > other_matrix._num_columns)
+       - (_num_columns < other_matrix._num_columns);
+}
+
+/**
+ *
+ */
+void ShaderType::Array::
+output(std::ostream &out) const {
+  out << *_element_type << "[" << _num_elements << "]";
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+int ShaderType::Array::
+compare_to_impl(const ShaderType &other) const {
+  const Array &other_array = (const Array &)other;
+  if (_element_type != other_array._element_type) {
+    return _element_type < other_array._element_type ? -1 : 1;
+  }
+  return (_num_elements > other_array._num_elements)
+       - (_num_elements < other_array._num_elements);
+}
+
+/**
+ *
+ */
+void ShaderType::Image::
+output(std::ostream &out) const {
+  out << "image" << texture_type_suffixes[_texture_type];
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+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);
+}
+
+/**
+ *
+ */
+void ShaderType::SampledImage::
+output(std::ostream &out) const {
+  out << "sampler" << texture_type_suffixes[_texture_type];
+}
+
+/**
+ * Private implementation of compare_to, only called for types with the same
+ * TypeHandle.
+ */
+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);
+}
+#endif  // CPPPARSER

+ 346 - 0
panda/src/gobj/shaderType.h

@@ -0,0 +1,346 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderType.h
+ * @author rdb
+ * @date 2019-03-12
+ */
+
+#ifndef SHADERTYPE_H
+#define SHADERTYPE_H
+
+#include "typedObject.h"
+#include "geomEnums.h"
+#include "pmap.h"
+#include "stl_compares.h"
+#include "texture.h"
+
+/**
+ * This represents a single type as defined in a shader.  There is only ever a
+ * single instance in existence for any particular type.
+ */
+class EXPCL_PANDA_GOBJ ShaderType : public TypedWritable {
+public:
+  template<class Type>
+  static const Type *register_type(Type &&type);
+
+  INLINE int compare_to(const ShaderType &other) const;
+  virtual int compare_to_impl(const ShaderType &other) const=0;
+
+  virtual void output(std::ostream &out) const=0;
+
+private:
+  typedef pset<const ShaderType *, indirect_compare_to<const ShaderType *> > Registry;
+  static Registry *_registered_types;
+
+PUBLISHED:
+  class Scalar;
+  class Vector;
+  class Matrix;
+  class Struct;
+  class Array;
+  class Image;
+  class Sampler;
+  class SampledImage;
+
+  // Fundamental types.
+  static const ShaderType::Scalar *bool_type;
+  static const ShaderType::Scalar *int_type;
+  static const ShaderType::Scalar *uint_type;
+  static const ShaderType::Scalar *float_type;
+
+public:
+  virtual const Scalar *as_scalar() const { return nullptr; }
+  virtual const Vector *as_vector() const { return nullptr; }
+  virtual const Matrix *as_matrix() const { return nullptr; }
+  virtual const Struct *as_struct() const { return nullptr; }
+  virtual const Array *as_array() const { return nullptr; }
+  virtual const Image *as_image() const { return nullptr; }
+  virtual const Sampler *as_sampler() const { return nullptr; }
+  virtual const SampledImage *as_sampled_image() const { return nullptr; }
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type();
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() override {
+    init_type();
+    return get_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+INLINE std::ostream &operator << (std::ostream &out, const ShaderType &stype) {
+  stype.output(out);
+  return out;
+}
+
+/**
+ * A numeric scalar type, like int or float.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Scalar final : public ShaderType {
+private:
+  INLINE Scalar(GeomEnums::NumericType numeric_type);
+
+  INLINE GeomEnums::NumericType get_numeric_type() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const Scalar *as_scalar() const override { return this; }
+
+private:
+  GeomEnums::NumericType _numeric_type;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * Multiple scalar types.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Vector final : public ShaderType {
+public:
+  INLINE Vector(const ShaderType *base_type, size_t num_elements);
+  Vector(const Vector &copy) = default;
+
+  INLINE const ShaderType *get_base_type() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+public:
+  const Vector *as_vector() const override { return this; }
+
+private:
+  const ShaderType *_base_type;
+  size_t _num_elements;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * Matrix consisting of multiple column vectors.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Matrix final : public ShaderType {
+public:
+  INLINE Matrix(const ShaderType *base_type, size_t num_rows, size_t num_columns);
+
+  INLINE const ShaderType *get_base_type() const;
+  INLINE size_t get_num_rows() const;
+  INLINE size_t get_num_columns() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const Matrix *as_matrix() const override { return this; }
+
+private:
+  const ShaderType *_base_type;
+  size_t _num_rows;
+  size_t _num_columns;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * A structure type, with named members.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Struct final : public ShaderType {
+public:
+  struct Member;
+
+  size_t get_num_members() const;
+  const Member &get_member() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const Struct *as_struct() const override { return this; }
+
+PUBLISHED:
+  MAKE_SEQ_PROPERTY(members, get_num_members, get_member);
+
+  struct Member {
+    const ShaderType *type;
+    CPT(InternalName) name;
+  };
+
+private:
+  pvector<Member> _members;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * An array type.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Array final : public ShaderType {
+public:
+  INLINE const ShaderType *get_element_type() const;
+  INLINE size_t get_num_elements() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const Array *as_array() const override { return this; }
+
+PUBLISHED:
+  MAKE_PROPERTY(element_type, get_element_type);
+  MAKE_PROPERTY(num_elements, get_num_elements);
+
+private:
+  const ShaderType *_element_type;
+  size_t _num_elements;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * Image type.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::Image final : public ShaderType {
+PUBLISHED:
+  enum class Access {
+    unknown = 0,
+    read_only = 1,
+    write_only = 2,
+    read_write = 3,
+  };
+
+public:
+  INLINE Image(Texture::TextureType texture_type, Access access);
+
+  INLINE Texture::TextureType get_texture_type() const;
+  INLINE Access get_access() const;
+  INLINE bool is_writable() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const Image *as_image() const override { return this; }
+
+PUBLISHED:
+  MAKE_PROPERTY(texture_type, get_texture_type);
+  MAKE_PROPERTY(access, get_access);
+  MAKE_PROPERTY(writable, is_writable);
+
+private:
+  Texture::TextureType _texture_type;
+  Access _access;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+/**
+ * Sampled image type.
+ */
+class EXPCL_PANDA_GOBJ ShaderType::SampledImage final : public ShaderType {
+public:
+  INLINE SampledImage(Texture::TextureType texture_type);
+
+  INLINE Texture::TextureType get_texture_type() const;
+
+  virtual void output(std::ostream &out) const override;
+  virtual int compare_to_impl(const ShaderType &other) const override;
+
+  const SampledImage *as_sampled_image() const override { return this; }
+
+private:
+  Texture::TextureType _texture_type;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class ShaderType;
+};
+
+#ifndef CPPPARSER
+#include "shaderType.I"
+#endif
+
+#endif  // SHADERTYPE_H

+ 1176 - 0
panda/src/gobj/spirv.h

@@ -0,0 +1,1176 @@
+/*
+** Copyright (c) 2014-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and/or associated documentation files (the "Materials"),
+** to deal in the Materials without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute, sublicense,
+** and/or sell copies of the Materials, and to permit persons to whom the
+** Materials are furnished to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in
+** all copies or substantial portions of the Materials.
+**
+** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
+** IN THE MATERIALS.
+*/
+
+/*
+** This header is automatically generated by the same tool that creates
+** the Binary Section of the SPIR-V specification.
+*/
+
+/*
+** Enumeration tokens for SPIR-V, in various styles:
+**   C, C++, C++11, JSON, Lua, Python
+**
+** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
+** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
+** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
+** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
+** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
+**
+** Some tokens act like mask values, which can be OR'd together,
+** while others are mutually exclusive.  The mask-like ones have
+** "Mask" in their name, and a parallel enum that has the shift
+** amount (1 << x) for each corresponding enumerant.
+*/
+
+#ifndef spirv_H
+#define spirv_H
+
+typedef unsigned int SpvId;
+
+#define SPV_VERSION 0x10300
+#define SPV_REVISION 1
+
+static const unsigned int SpvMagicNumber = 0x07230203;
+static const unsigned int SpvVersion = 0x00010300;
+static const unsigned int SpvRevision = 1;
+static const unsigned int SpvOpCodeMask = 0xffff;
+static const unsigned int SpvWordCountShift = 16;
+
+typedef enum SpvSourceLanguage_ {
+    SpvSourceLanguageUnknown = 0,
+    SpvSourceLanguageESSL = 1,
+    SpvSourceLanguageGLSL = 2,
+    SpvSourceLanguageOpenCL_C = 3,
+    SpvSourceLanguageOpenCL_CPP = 4,
+    SpvSourceLanguageHLSL = 5,
+    SpvSourceLanguageMax = 0x7fffffff,
+} SpvSourceLanguage;
+
+typedef enum SpvExecutionModel_ {
+    SpvExecutionModelVertex = 0,
+    SpvExecutionModelTessellationControl = 1,
+    SpvExecutionModelTessellationEvaluation = 2,
+    SpvExecutionModelGeometry = 3,
+    SpvExecutionModelFragment = 4,
+    SpvExecutionModelGLCompute = 5,
+    SpvExecutionModelKernel = 6,
+    SpvExecutionModelTaskNV = 5267,
+    SpvExecutionModelMeshNV = 5268,
+    SpvExecutionModelRayGenerationNVX = 5313,
+    SpvExecutionModelIntersectionNVX = 5314,
+    SpvExecutionModelAnyHitNVX = 5315,
+    SpvExecutionModelClosestHitNVX = 5316,
+    SpvExecutionModelMissNVX = 5317,
+    SpvExecutionModelCallableNVX = 5318,
+    SpvExecutionModelMax = 0x7fffffff,
+} SpvExecutionModel;
+
+typedef enum SpvAddressingModel_ {
+    SpvAddressingModelLogical = 0,
+    SpvAddressingModelPhysical32 = 1,
+    SpvAddressingModelPhysical64 = 2,
+    SpvAddressingModelMax = 0x7fffffff,
+} SpvAddressingModel;
+
+typedef enum SpvMemoryModel_ {
+    SpvMemoryModelSimple = 0,
+    SpvMemoryModelGLSL450 = 1,
+    SpvMemoryModelOpenCL = 2,
+    SpvMemoryModelVulkanKHR = 3,
+    SpvMemoryModelMax = 0x7fffffff,
+} SpvMemoryModel;
+
+typedef enum SpvExecutionMode_ {
+    SpvExecutionModeInvocations = 0,
+    SpvExecutionModeSpacingEqual = 1,
+    SpvExecutionModeSpacingFractionalEven = 2,
+    SpvExecutionModeSpacingFractionalOdd = 3,
+    SpvExecutionModeVertexOrderCw = 4,
+    SpvExecutionModeVertexOrderCcw = 5,
+    SpvExecutionModePixelCenterInteger = 6,
+    SpvExecutionModeOriginUpperLeft = 7,
+    SpvExecutionModeOriginLowerLeft = 8,
+    SpvExecutionModeEarlyFragmentTests = 9,
+    SpvExecutionModePointMode = 10,
+    SpvExecutionModeXfb = 11,
+    SpvExecutionModeDepthReplacing = 12,
+    SpvExecutionModeDepthGreater = 14,
+    SpvExecutionModeDepthLess = 15,
+    SpvExecutionModeDepthUnchanged = 16,
+    SpvExecutionModeLocalSize = 17,
+    SpvExecutionModeLocalSizeHint = 18,
+    SpvExecutionModeInputPoints = 19,
+    SpvExecutionModeInputLines = 20,
+    SpvExecutionModeInputLinesAdjacency = 21,
+    SpvExecutionModeTriangles = 22,
+    SpvExecutionModeInputTrianglesAdjacency = 23,
+    SpvExecutionModeQuads = 24,
+    SpvExecutionModeIsolines = 25,
+    SpvExecutionModeOutputVertices = 26,
+    SpvExecutionModeOutputPoints = 27,
+    SpvExecutionModeOutputLineStrip = 28,
+    SpvExecutionModeOutputTriangleStrip = 29,
+    SpvExecutionModeVecTypeHint = 30,
+    SpvExecutionModeContractionOff = 31,
+    SpvExecutionModeInitializer = 33,
+    SpvExecutionModeFinalizer = 34,
+    SpvExecutionModeSubgroupSize = 35,
+    SpvExecutionModeSubgroupsPerWorkgroup = 36,
+    SpvExecutionModeSubgroupsPerWorkgroupId = 37,
+    SpvExecutionModeLocalSizeId = 38,
+    SpvExecutionModeLocalSizeHintId = 39,
+    SpvExecutionModePostDepthCoverage = 4446,
+    SpvExecutionModeStencilRefReplacingEXT = 5027,
+    SpvExecutionModeOutputLinesNV = 5269,
+    SpvExecutionModeOutputPrimitivesNV = 5270,
+    SpvExecutionModeDerivativeGroupQuadsNV = 5289,
+    SpvExecutionModeDerivativeGroupLinearNV = 5290,
+    SpvExecutionModeOutputTrianglesNV = 5298,
+    SpvExecutionModeMax = 0x7fffffff,
+} SpvExecutionMode;
+
+typedef enum SpvStorageClass_ {
+    SpvStorageClassUniformConstant = 0,
+    SpvStorageClassInput = 1,
+    SpvStorageClassUniform = 2,
+    SpvStorageClassOutput = 3,
+    SpvStorageClassWorkgroup = 4,
+    SpvStorageClassCrossWorkgroup = 5,
+    SpvStorageClassPrivate = 6,
+    SpvStorageClassFunction = 7,
+    SpvStorageClassGeneric = 8,
+    SpvStorageClassPushConstant = 9,
+    SpvStorageClassAtomicCounter = 10,
+    SpvStorageClassImage = 11,
+    SpvStorageClassStorageBuffer = 12,
+    SpvStorageClassRayPayloadNVX = 5338,
+    SpvStorageClassHitAttributeNVX = 5339,
+    SpvStorageClassIncomingRayPayloadNVX = 5342,
+    SpvStorageClassShaderRecordBufferNVX = 5343,
+    SpvStorageClassMax = 0x7fffffff,
+} SpvStorageClass;
+
+typedef enum SpvDim_ {
+    SpvDim1D = 0,
+    SpvDim2D = 1,
+    SpvDim3D = 2,
+    SpvDimCube = 3,
+    SpvDimRect = 4,
+    SpvDimBuffer = 5,
+    SpvDimSubpassData = 6,
+    SpvDimMax = 0x7fffffff,
+} SpvDim;
+
+typedef enum SpvSamplerAddressingMode_ {
+    SpvSamplerAddressingModeNone = 0,
+    SpvSamplerAddressingModeClampToEdge = 1,
+    SpvSamplerAddressingModeClamp = 2,
+    SpvSamplerAddressingModeRepeat = 3,
+    SpvSamplerAddressingModeRepeatMirrored = 4,
+    SpvSamplerAddressingModeMax = 0x7fffffff,
+} SpvSamplerAddressingMode;
+
+typedef enum SpvSamplerFilterMode_ {
+    SpvSamplerFilterModeNearest = 0,
+    SpvSamplerFilterModeLinear = 1,
+    SpvSamplerFilterModeMax = 0x7fffffff,
+} SpvSamplerFilterMode;
+
+typedef enum SpvImageFormat_ {
+    SpvImageFormatUnknown = 0,
+    SpvImageFormatRgba32f = 1,
+    SpvImageFormatRgba16f = 2,
+    SpvImageFormatR32f = 3,
+    SpvImageFormatRgba8 = 4,
+    SpvImageFormatRgba8Snorm = 5,
+    SpvImageFormatRg32f = 6,
+    SpvImageFormatRg16f = 7,
+    SpvImageFormatR11fG11fB10f = 8,
+    SpvImageFormatR16f = 9,
+    SpvImageFormatRgba16 = 10,
+    SpvImageFormatRgb10A2 = 11,
+    SpvImageFormatRg16 = 12,
+    SpvImageFormatRg8 = 13,
+    SpvImageFormatR16 = 14,
+    SpvImageFormatR8 = 15,
+    SpvImageFormatRgba16Snorm = 16,
+    SpvImageFormatRg16Snorm = 17,
+    SpvImageFormatRg8Snorm = 18,
+    SpvImageFormatR16Snorm = 19,
+    SpvImageFormatR8Snorm = 20,
+    SpvImageFormatRgba32i = 21,
+    SpvImageFormatRgba16i = 22,
+    SpvImageFormatRgba8i = 23,
+    SpvImageFormatR32i = 24,
+    SpvImageFormatRg32i = 25,
+    SpvImageFormatRg16i = 26,
+    SpvImageFormatRg8i = 27,
+    SpvImageFormatR16i = 28,
+    SpvImageFormatR8i = 29,
+    SpvImageFormatRgba32ui = 30,
+    SpvImageFormatRgba16ui = 31,
+    SpvImageFormatRgba8ui = 32,
+    SpvImageFormatR32ui = 33,
+    SpvImageFormatRgb10a2ui = 34,
+    SpvImageFormatRg32ui = 35,
+    SpvImageFormatRg16ui = 36,
+    SpvImageFormatRg8ui = 37,
+    SpvImageFormatR16ui = 38,
+    SpvImageFormatR8ui = 39,
+    SpvImageFormatMax = 0x7fffffff,
+} SpvImageFormat;
+
+typedef enum SpvImageChannelOrder_ {
+    SpvImageChannelOrderR = 0,
+    SpvImageChannelOrderA = 1,
+    SpvImageChannelOrderRG = 2,
+    SpvImageChannelOrderRA = 3,
+    SpvImageChannelOrderRGB = 4,
+    SpvImageChannelOrderRGBA = 5,
+    SpvImageChannelOrderBGRA = 6,
+    SpvImageChannelOrderARGB = 7,
+    SpvImageChannelOrderIntensity = 8,
+    SpvImageChannelOrderLuminance = 9,
+    SpvImageChannelOrderRx = 10,
+    SpvImageChannelOrderRGx = 11,
+    SpvImageChannelOrderRGBx = 12,
+    SpvImageChannelOrderDepth = 13,
+    SpvImageChannelOrderDepthStencil = 14,
+    SpvImageChannelOrdersRGB = 15,
+    SpvImageChannelOrdersRGBx = 16,
+    SpvImageChannelOrdersRGBA = 17,
+    SpvImageChannelOrdersBGRA = 18,
+    SpvImageChannelOrderABGR = 19,
+    SpvImageChannelOrderMax = 0x7fffffff,
+} SpvImageChannelOrder;
+
+typedef enum SpvImageChannelDataType_ {
+    SpvImageChannelDataTypeSnormInt8 = 0,
+    SpvImageChannelDataTypeSnormInt16 = 1,
+    SpvImageChannelDataTypeUnormInt8 = 2,
+    SpvImageChannelDataTypeUnormInt16 = 3,
+    SpvImageChannelDataTypeUnormShort565 = 4,
+    SpvImageChannelDataTypeUnormShort555 = 5,
+    SpvImageChannelDataTypeUnormInt101010 = 6,
+    SpvImageChannelDataTypeSignedInt8 = 7,
+    SpvImageChannelDataTypeSignedInt16 = 8,
+    SpvImageChannelDataTypeSignedInt32 = 9,
+    SpvImageChannelDataTypeUnsignedInt8 = 10,
+    SpvImageChannelDataTypeUnsignedInt16 = 11,
+    SpvImageChannelDataTypeUnsignedInt32 = 12,
+    SpvImageChannelDataTypeHalfFloat = 13,
+    SpvImageChannelDataTypeFloat = 14,
+    SpvImageChannelDataTypeUnormInt24 = 15,
+    SpvImageChannelDataTypeUnormInt101010_2 = 16,
+    SpvImageChannelDataTypeMax = 0x7fffffff,
+} SpvImageChannelDataType;
+
+typedef enum SpvImageOperandsShift_ {
+    SpvImageOperandsBiasShift = 0,
+    SpvImageOperandsLodShift = 1,
+    SpvImageOperandsGradShift = 2,
+    SpvImageOperandsConstOffsetShift = 3,
+    SpvImageOperandsOffsetShift = 4,
+    SpvImageOperandsConstOffsetsShift = 5,
+    SpvImageOperandsSampleShift = 6,
+    SpvImageOperandsMinLodShift = 7,
+    SpvImageOperandsMakeTexelAvailableKHRShift = 8,
+    SpvImageOperandsMakeTexelVisibleKHRShift = 9,
+    SpvImageOperandsNonPrivateTexelKHRShift = 10,
+    SpvImageOperandsVolatileTexelKHRShift = 11,
+    SpvImageOperandsMax = 0x7fffffff,
+} SpvImageOperandsShift;
+
+typedef enum SpvImageOperandsMask_ {
+    SpvImageOperandsMaskNone = 0,
+    SpvImageOperandsBiasMask = 0x00000001,
+    SpvImageOperandsLodMask = 0x00000002,
+    SpvImageOperandsGradMask = 0x00000004,
+    SpvImageOperandsConstOffsetMask = 0x00000008,
+    SpvImageOperandsOffsetMask = 0x00000010,
+    SpvImageOperandsConstOffsetsMask = 0x00000020,
+    SpvImageOperandsSampleMask = 0x00000040,
+    SpvImageOperandsMinLodMask = 0x00000080,
+    SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100,
+    SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200,
+    SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400,
+    SpvImageOperandsVolatileTexelKHRMask = 0x00000800,
+} SpvImageOperandsMask;
+
+typedef enum SpvFPFastMathModeShift_ {
+    SpvFPFastMathModeNotNaNShift = 0,
+    SpvFPFastMathModeNotInfShift = 1,
+    SpvFPFastMathModeNSZShift = 2,
+    SpvFPFastMathModeAllowRecipShift = 3,
+    SpvFPFastMathModeFastShift = 4,
+    SpvFPFastMathModeMax = 0x7fffffff,
+} SpvFPFastMathModeShift;
+
+typedef enum SpvFPFastMathModeMask_ {
+    SpvFPFastMathModeMaskNone = 0,
+    SpvFPFastMathModeNotNaNMask = 0x00000001,
+    SpvFPFastMathModeNotInfMask = 0x00000002,
+    SpvFPFastMathModeNSZMask = 0x00000004,
+    SpvFPFastMathModeAllowRecipMask = 0x00000008,
+    SpvFPFastMathModeFastMask = 0x00000010,
+} SpvFPFastMathModeMask;
+
+typedef enum SpvFPRoundingMode_ {
+    SpvFPRoundingModeRTE = 0,
+    SpvFPRoundingModeRTZ = 1,
+    SpvFPRoundingModeRTP = 2,
+    SpvFPRoundingModeRTN = 3,
+    SpvFPRoundingModeMax = 0x7fffffff,
+} SpvFPRoundingMode;
+
+typedef enum SpvLinkageType_ {
+    SpvLinkageTypeExport = 0,
+    SpvLinkageTypeImport = 1,
+    SpvLinkageTypeMax = 0x7fffffff,
+} SpvLinkageType;
+
+typedef enum SpvAccessQualifier_ {
+    SpvAccessQualifierReadOnly = 0,
+    SpvAccessQualifierWriteOnly = 1,
+    SpvAccessQualifierReadWrite = 2,
+    SpvAccessQualifierMax = 0x7fffffff,
+} SpvAccessQualifier;
+
+typedef enum SpvFunctionParameterAttribute_ {
+    SpvFunctionParameterAttributeZext = 0,
+    SpvFunctionParameterAttributeSext = 1,
+    SpvFunctionParameterAttributeByVal = 2,
+    SpvFunctionParameterAttributeSret = 3,
+    SpvFunctionParameterAttributeNoAlias = 4,
+    SpvFunctionParameterAttributeNoCapture = 5,
+    SpvFunctionParameterAttributeNoWrite = 6,
+    SpvFunctionParameterAttributeNoReadWrite = 7,
+    SpvFunctionParameterAttributeMax = 0x7fffffff,
+} SpvFunctionParameterAttribute;
+
+typedef enum SpvDecoration_ {
+    SpvDecorationRelaxedPrecision = 0,
+    SpvDecorationSpecId = 1,
+    SpvDecorationBlock = 2,
+    SpvDecorationBufferBlock = 3,
+    SpvDecorationRowMajor = 4,
+    SpvDecorationColMajor = 5,
+    SpvDecorationArrayStride = 6,
+    SpvDecorationMatrixStride = 7,
+    SpvDecorationGLSLShared = 8,
+    SpvDecorationGLSLPacked = 9,
+    SpvDecorationCPacked = 10,
+    SpvDecorationBuiltIn = 11,
+    SpvDecorationNoPerspective = 13,
+    SpvDecorationFlat = 14,
+    SpvDecorationPatch = 15,
+    SpvDecorationCentroid = 16,
+    SpvDecorationSample = 17,
+    SpvDecorationInvariant = 18,
+    SpvDecorationRestrict = 19,
+    SpvDecorationAliased = 20,
+    SpvDecorationVolatile = 21,
+    SpvDecorationConstant = 22,
+    SpvDecorationCoherent = 23,
+    SpvDecorationNonWritable = 24,
+    SpvDecorationNonReadable = 25,
+    SpvDecorationUniform = 26,
+    SpvDecorationSaturatedConversion = 28,
+    SpvDecorationStream = 29,
+    SpvDecorationLocation = 30,
+    SpvDecorationComponent = 31,
+    SpvDecorationIndex = 32,
+    SpvDecorationBinding = 33,
+    SpvDecorationDescriptorSet = 34,
+    SpvDecorationOffset = 35,
+    SpvDecorationXfbBuffer = 36,
+    SpvDecorationXfbStride = 37,
+    SpvDecorationFuncParamAttr = 38,
+    SpvDecorationFPRoundingMode = 39,
+    SpvDecorationFPFastMathMode = 40,
+    SpvDecorationLinkageAttributes = 41,
+    SpvDecorationNoContraction = 42,
+    SpvDecorationInputAttachmentIndex = 43,
+    SpvDecorationAlignment = 44,
+    SpvDecorationMaxByteOffset = 45,
+    SpvDecorationAlignmentId = 46,
+    SpvDecorationMaxByteOffsetId = 47,
+    SpvDecorationExplicitInterpAMD = 4999,
+    SpvDecorationOverrideCoverageNV = 5248,
+    SpvDecorationPassthroughNV = 5250,
+    SpvDecorationViewportRelativeNV = 5252,
+    SpvDecorationSecondaryViewportRelativeNV = 5256,
+    SpvDecorationPerPrimitiveNV = 5271,
+    SpvDecorationPerViewNV = 5272,
+    SpvDecorationPerTaskNV = 5273,
+    SpvDecorationPerVertexNV = 5285,
+    SpvDecorationNonUniformEXT = 5300,
+    SpvDecorationHlslCounterBufferGOOGLE = 5634,
+    SpvDecorationHlslSemanticGOOGLE = 5635,
+    SpvDecorationMax = 0x7fffffff,
+} SpvDecoration;
+
+typedef enum SpvBuiltIn_ {
+    SpvBuiltInPosition = 0,
+    SpvBuiltInPointSize = 1,
+    SpvBuiltInClipDistance = 3,
+    SpvBuiltInCullDistance = 4,
+    SpvBuiltInVertexId = 5,
+    SpvBuiltInInstanceId = 6,
+    SpvBuiltInPrimitiveId = 7,
+    SpvBuiltInInvocationId = 8,
+    SpvBuiltInLayer = 9,
+    SpvBuiltInViewportIndex = 10,
+    SpvBuiltInTessLevelOuter = 11,
+    SpvBuiltInTessLevelInner = 12,
+    SpvBuiltInTessCoord = 13,
+    SpvBuiltInPatchVertices = 14,
+    SpvBuiltInFragCoord = 15,
+    SpvBuiltInPointCoord = 16,
+    SpvBuiltInFrontFacing = 17,
+    SpvBuiltInSampleId = 18,
+    SpvBuiltInSamplePosition = 19,
+    SpvBuiltInSampleMask = 20,
+    SpvBuiltInFragDepth = 22,
+    SpvBuiltInHelperInvocation = 23,
+    SpvBuiltInNumWorkgroups = 24,
+    SpvBuiltInWorkgroupSize = 25,
+    SpvBuiltInWorkgroupId = 26,
+    SpvBuiltInLocalInvocationId = 27,
+    SpvBuiltInGlobalInvocationId = 28,
+    SpvBuiltInLocalInvocationIndex = 29,
+    SpvBuiltInWorkDim = 30,
+    SpvBuiltInGlobalSize = 31,
+    SpvBuiltInEnqueuedWorkgroupSize = 32,
+    SpvBuiltInGlobalOffset = 33,
+    SpvBuiltInGlobalLinearId = 34,
+    SpvBuiltInSubgroupSize = 36,
+    SpvBuiltInSubgroupMaxSize = 37,
+    SpvBuiltInNumSubgroups = 38,
+    SpvBuiltInNumEnqueuedSubgroups = 39,
+    SpvBuiltInSubgroupId = 40,
+    SpvBuiltInSubgroupLocalInvocationId = 41,
+    SpvBuiltInVertexIndex = 42,
+    SpvBuiltInInstanceIndex = 43,
+    SpvBuiltInSubgroupEqMask = 4416,
+    SpvBuiltInSubgroupEqMaskKHR = 4416,
+    SpvBuiltInSubgroupGeMask = 4417,
+    SpvBuiltInSubgroupGeMaskKHR = 4417,
+    SpvBuiltInSubgroupGtMask = 4418,
+    SpvBuiltInSubgroupGtMaskKHR = 4418,
+    SpvBuiltInSubgroupLeMask = 4419,
+    SpvBuiltInSubgroupLeMaskKHR = 4419,
+    SpvBuiltInSubgroupLtMask = 4420,
+    SpvBuiltInSubgroupLtMaskKHR = 4420,
+    SpvBuiltInBaseVertex = 4424,
+    SpvBuiltInBaseInstance = 4425,
+    SpvBuiltInDrawIndex = 4426,
+    SpvBuiltInDeviceIndex = 4438,
+    SpvBuiltInViewIndex = 4440,
+    SpvBuiltInBaryCoordNoPerspAMD = 4992,
+    SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993,
+    SpvBuiltInBaryCoordNoPerspSampleAMD = 4994,
+    SpvBuiltInBaryCoordSmoothAMD = 4995,
+    SpvBuiltInBaryCoordSmoothCentroidAMD = 4996,
+    SpvBuiltInBaryCoordSmoothSampleAMD = 4997,
+    SpvBuiltInBaryCoordPullModelAMD = 4998,
+    SpvBuiltInFragStencilRefEXT = 5014,
+    SpvBuiltInViewportMaskNV = 5253,
+    SpvBuiltInSecondaryPositionNV = 5257,
+    SpvBuiltInSecondaryViewportMaskNV = 5258,
+    SpvBuiltInPositionPerViewNV = 5261,
+    SpvBuiltInViewportMaskPerViewNV = 5262,
+    SpvBuiltInFullyCoveredEXT = 5264,
+    SpvBuiltInTaskCountNV = 5274,
+    SpvBuiltInPrimitiveCountNV = 5275,
+    SpvBuiltInPrimitiveIndicesNV = 5276,
+    SpvBuiltInClipDistancePerViewNV = 5277,
+    SpvBuiltInCullDistancePerViewNV = 5278,
+    SpvBuiltInLayerPerViewNV = 5279,
+    SpvBuiltInMeshViewCountNV = 5280,
+    SpvBuiltInMeshViewIndicesNV = 5281,
+    SpvBuiltInBaryCoordNV = 5286,
+    SpvBuiltInBaryCoordNoPerspNV = 5287,
+    SpvBuiltInFragmentSizeNV = 5292,
+    SpvBuiltInInvocationsPerPixelNV = 5293,
+    SpvBuiltInLaunchIdNVX = 5319,
+    SpvBuiltInLaunchSizeNVX = 5320,
+    SpvBuiltInWorldRayOriginNVX = 5321,
+    SpvBuiltInWorldRayDirectionNVX = 5322,
+    SpvBuiltInObjectRayOriginNVX = 5323,
+    SpvBuiltInObjectRayDirectionNVX = 5324,
+    SpvBuiltInRayTminNVX = 5325,
+    SpvBuiltInRayTmaxNVX = 5326,
+    SpvBuiltInInstanceCustomIndexNVX = 5327,
+    SpvBuiltInObjectToWorldNVX = 5330,
+    SpvBuiltInWorldToObjectNVX = 5331,
+    SpvBuiltInHitTNVX = 5332,
+    SpvBuiltInHitKindNVX = 5333,
+    SpvBuiltInMax = 0x7fffffff,
+} SpvBuiltIn;
+
+typedef enum SpvSelectionControlShift_ {
+    SpvSelectionControlFlattenShift = 0,
+    SpvSelectionControlDontFlattenShift = 1,
+    SpvSelectionControlMax = 0x7fffffff,
+} SpvSelectionControlShift;
+
+typedef enum SpvSelectionControlMask_ {
+    SpvSelectionControlMaskNone = 0,
+    SpvSelectionControlFlattenMask = 0x00000001,
+    SpvSelectionControlDontFlattenMask = 0x00000002,
+} SpvSelectionControlMask;
+
+typedef enum SpvLoopControlShift_ {
+    SpvLoopControlUnrollShift = 0,
+    SpvLoopControlDontUnrollShift = 1,
+    SpvLoopControlDependencyInfiniteShift = 2,
+    SpvLoopControlDependencyLengthShift = 3,
+    SpvLoopControlMax = 0x7fffffff,
+} SpvLoopControlShift;
+
+typedef enum SpvLoopControlMask_ {
+    SpvLoopControlMaskNone = 0,
+    SpvLoopControlUnrollMask = 0x00000001,
+    SpvLoopControlDontUnrollMask = 0x00000002,
+    SpvLoopControlDependencyInfiniteMask = 0x00000004,
+    SpvLoopControlDependencyLengthMask = 0x00000008,
+} SpvLoopControlMask;
+
+typedef enum SpvFunctionControlShift_ {
+    SpvFunctionControlInlineShift = 0,
+    SpvFunctionControlDontInlineShift = 1,
+    SpvFunctionControlPureShift = 2,
+    SpvFunctionControlConstShift = 3,
+    SpvFunctionControlMax = 0x7fffffff,
+} SpvFunctionControlShift;
+
+typedef enum SpvFunctionControlMask_ {
+    SpvFunctionControlMaskNone = 0,
+    SpvFunctionControlInlineMask = 0x00000001,
+    SpvFunctionControlDontInlineMask = 0x00000002,
+    SpvFunctionControlPureMask = 0x00000004,
+    SpvFunctionControlConstMask = 0x00000008,
+} SpvFunctionControlMask;
+
+typedef enum SpvMemorySemanticsShift_ {
+    SpvMemorySemanticsAcquireShift = 1,
+    SpvMemorySemanticsReleaseShift = 2,
+    SpvMemorySemanticsAcquireReleaseShift = 3,
+    SpvMemorySemanticsSequentiallyConsistentShift = 4,
+    SpvMemorySemanticsUniformMemoryShift = 6,
+    SpvMemorySemanticsSubgroupMemoryShift = 7,
+    SpvMemorySemanticsWorkgroupMemoryShift = 8,
+    SpvMemorySemanticsCrossWorkgroupMemoryShift = 9,
+    SpvMemorySemanticsAtomicCounterMemoryShift = 10,
+    SpvMemorySemanticsImageMemoryShift = 11,
+    SpvMemorySemanticsOutputMemoryKHRShift = 12,
+    SpvMemorySemanticsMakeAvailableKHRShift = 13,
+    SpvMemorySemanticsMakeVisibleKHRShift = 14,
+    SpvMemorySemanticsMax = 0x7fffffff,
+} SpvMemorySemanticsShift;
+
+typedef enum SpvMemorySemanticsMask_ {
+    SpvMemorySemanticsMaskNone = 0,
+    SpvMemorySemanticsAcquireMask = 0x00000002,
+    SpvMemorySemanticsReleaseMask = 0x00000004,
+    SpvMemorySemanticsAcquireReleaseMask = 0x00000008,
+    SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010,
+    SpvMemorySemanticsUniformMemoryMask = 0x00000040,
+    SpvMemorySemanticsSubgroupMemoryMask = 0x00000080,
+    SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100,
+    SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
+    SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400,
+    SpvMemorySemanticsImageMemoryMask = 0x00000800,
+    SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000,
+    SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000,
+    SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000,
+} SpvMemorySemanticsMask;
+
+typedef enum SpvMemoryAccessShift_ {
+    SpvMemoryAccessVolatileShift = 0,
+    SpvMemoryAccessAlignedShift = 1,
+    SpvMemoryAccessNontemporalShift = 2,
+    SpvMemoryAccessMakePointerAvailableKHRShift = 3,
+    SpvMemoryAccessMakePointerVisibleKHRShift = 4,
+    SpvMemoryAccessNonPrivatePointerKHRShift = 5,
+    SpvMemoryAccessMax = 0x7fffffff,
+} SpvMemoryAccessShift;
+
+typedef enum SpvMemoryAccessMask_ {
+    SpvMemoryAccessMaskNone = 0,
+    SpvMemoryAccessVolatileMask = 0x00000001,
+    SpvMemoryAccessAlignedMask = 0x00000002,
+    SpvMemoryAccessNontemporalMask = 0x00000004,
+    SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008,
+    SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010,
+    SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020,
+} SpvMemoryAccessMask;
+
+typedef enum SpvScope_ {
+    SpvScopeCrossDevice = 0,
+    SpvScopeDevice = 1,
+    SpvScopeWorkgroup = 2,
+    SpvScopeSubgroup = 3,
+    SpvScopeInvocation = 4,
+    SpvScopeQueueFamilyKHR = 5,
+    SpvScopeMax = 0x7fffffff,
+} SpvScope;
+
+typedef enum SpvGroupOperation_ {
+    SpvGroupOperationReduce = 0,
+    SpvGroupOperationInclusiveScan = 1,
+    SpvGroupOperationExclusiveScan = 2,
+    SpvGroupOperationClusteredReduce = 3,
+    SpvGroupOperationPartitionedReduceNV = 6,
+    SpvGroupOperationPartitionedInclusiveScanNV = 7,
+    SpvGroupOperationPartitionedExclusiveScanNV = 8,
+    SpvGroupOperationMax = 0x7fffffff,
+} SpvGroupOperation;
+
+typedef enum SpvKernelEnqueueFlags_ {
+    SpvKernelEnqueueFlagsNoWait = 0,
+    SpvKernelEnqueueFlagsWaitKernel = 1,
+    SpvKernelEnqueueFlagsWaitWorkGroup = 2,
+    SpvKernelEnqueueFlagsMax = 0x7fffffff,
+} SpvKernelEnqueueFlags;
+
+typedef enum SpvKernelProfilingInfoShift_ {
+    SpvKernelProfilingInfoCmdExecTimeShift = 0,
+    SpvKernelProfilingInfoMax = 0x7fffffff,
+} SpvKernelProfilingInfoShift;
+
+typedef enum SpvKernelProfilingInfoMask_ {
+    SpvKernelProfilingInfoMaskNone = 0,
+    SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,
+} SpvKernelProfilingInfoMask;
+
+typedef enum SpvCapability_ {
+    SpvCapabilityMatrix = 0,
+    SpvCapabilityShader = 1,
+    SpvCapabilityGeometry = 2,
+    SpvCapabilityTessellation = 3,
+    SpvCapabilityAddresses = 4,
+    SpvCapabilityLinkage = 5,
+    SpvCapabilityKernel = 6,
+    SpvCapabilityVector16 = 7,
+    SpvCapabilityFloat16Buffer = 8,
+    SpvCapabilityFloat16 = 9,
+    SpvCapabilityFloat64 = 10,
+    SpvCapabilityInt64 = 11,
+    SpvCapabilityInt64Atomics = 12,
+    SpvCapabilityImageBasic = 13,
+    SpvCapabilityImageReadWrite = 14,
+    SpvCapabilityImageMipmap = 15,
+    SpvCapabilityPipes = 17,
+    SpvCapabilityGroups = 18,
+    SpvCapabilityDeviceEnqueue = 19,
+    SpvCapabilityLiteralSampler = 20,
+    SpvCapabilityAtomicStorage = 21,
+    SpvCapabilityInt16 = 22,
+    SpvCapabilityTessellationPointSize = 23,
+    SpvCapabilityGeometryPointSize = 24,
+    SpvCapabilityImageGatherExtended = 25,
+    SpvCapabilityStorageImageMultisample = 27,
+    SpvCapabilityUniformBufferArrayDynamicIndexing = 28,
+    SpvCapabilitySampledImageArrayDynamicIndexing = 29,
+    SpvCapabilityStorageBufferArrayDynamicIndexing = 30,
+    SpvCapabilityStorageImageArrayDynamicIndexing = 31,
+    SpvCapabilityClipDistance = 32,
+    SpvCapabilityCullDistance = 33,
+    SpvCapabilityImageCubeArray = 34,
+    SpvCapabilitySampleRateShading = 35,
+    SpvCapabilityImageRect = 36,
+    SpvCapabilitySampledRect = 37,
+    SpvCapabilityGenericPointer = 38,
+    SpvCapabilityInt8 = 39,
+    SpvCapabilityInputAttachment = 40,
+    SpvCapabilitySparseResidency = 41,
+    SpvCapabilityMinLod = 42,
+    SpvCapabilitySampled1D = 43,
+    SpvCapabilityImage1D = 44,
+    SpvCapabilitySampledCubeArray = 45,
+    SpvCapabilitySampledBuffer = 46,
+    SpvCapabilityImageBuffer = 47,
+    SpvCapabilityImageMSArray = 48,
+    SpvCapabilityStorageImageExtendedFormats = 49,
+    SpvCapabilityImageQuery = 50,
+    SpvCapabilityDerivativeControl = 51,
+    SpvCapabilityInterpolationFunction = 52,
+    SpvCapabilityTransformFeedback = 53,
+    SpvCapabilityGeometryStreams = 54,
+    SpvCapabilityStorageImageReadWithoutFormat = 55,
+    SpvCapabilityStorageImageWriteWithoutFormat = 56,
+    SpvCapabilityMultiViewport = 57,
+    SpvCapabilitySubgroupDispatch = 58,
+    SpvCapabilityNamedBarrier = 59,
+    SpvCapabilityPipeStorage = 60,
+    SpvCapabilityGroupNonUniform = 61,
+    SpvCapabilityGroupNonUniformVote = 62,
+    SpvCapabilityGroupNonUniformArithmetic = 63,
+    SpvCapabilityGroupNonUniformBallot = 64,
+    SpvCapabilityGroupNonUniformShuffle = 65,
+    SpvCapabilityGroupNonUniformShuffleRelative = 66,
+    SpvCapabilityGroupNonUniformClustered = 67,
+    SpvCapabilityGroupNonUniformQuad = 68,
+    SpvCapabilitySubgroupBallotKHR = 4423,
+    SpvCapabilityDrawParameters = 4427,
+    SpvCapabilitySubgroupVoteKHR = 4431,
+    SpvCapabilityStorageBuffer16BitAccess = 4433,
+    SpvCapabilityStorageUniformBufferBlock16 = 4433,
+    SpvCapabilityStorageUniform16 = 4434,
+    SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434,
+    SpvCapabilityStoragePushConstant16 = 4435,
+    SpvCapabilityStorageInputOutput16 = 4436,
+    SpvCapabilityDeviceGroup = 4437,
+    SpvCapabilityMultiView = 4439,
+    SpvCapabilityVariablePointersStorageBuffer = 4441,
+    SpvCapabilityVariablePointers = 4442,
+    SpvCapabilityAtomicStorageOps = 4445,
+    SpvCapabilitySampleMaskPostDepthCoverage = 4447,
+    SpvCapabilityStorageBuffer8BitAccess = 4448,
+    SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449,
+    SpvCapabilityStoragePushConstant8 = 4450,
+    SpvCapabilityFloat16ImageAMD = 5008,
+    SpvCapabilityImageGatherBiasLodAMD = 5009,
+    SpvCapabilityFragmentMaskAMD = 5010,
+    SpvCapabilityStencilExportEXT = 5013,
+    SpvCapabilityImageReadWriteLodAMD = 5015,
+    SpvCapabilitySampleMaskOverrideCoverageNV = 5249,
+    SpvCapabilityGeometryShaderPassthroughNV = 5251,
+    SpvCapabilityShaderViewportIndexLayerEXT = 5254,
+    SpvCapabilityShaderViewportIndexLayerNV = 5254,
+    SpvCapabilityShaderViewportMaskNV = 5255,
+    SpvCapabilityShaderStereoViewNV = 5259,
+    SpvCapabilityPerViewAttributesNV = 5260,
+    SpvCapabilityFragmentFullyCoveredEXT = 5265,
+    SpvCapabilityMeshShadingNV = 5266,
+    SpvCapabilityImageFootprintNV = 5282,
+    SpvCapabilityFragmentBarycentricNV = 5284,
+    SpvCapabilityComputeDerivativeGroupQuadsNV = 5288,
+    SpvCapabilityShadingRateNV = 5291,
+    SpvCapabilityGroupNonUniformPartitionedNV = 5297,
+    SpvCapabilityShaderNonUniformEXT = 5301,
+    SpvCapabilityRuntimeDescriptorArrayEXT = 5302,
+    SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,
+    SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,
+    SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,
+    SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,
+    SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307,
+    SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,
+    SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309,
+    SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
+    SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
+    SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
+    SpvCapabilityRaytracingNVX = 5340,
+    SpvCapabilityVulkanMemoryModelKHR = 5345,
+    SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346,
+    SpvCapabilityComputeDerivativeGroupLinearNV = 5350,
+    SpvCapabilitySubgroupShuffleINTEL = 5568,
+    SpvCapabilitySubgroupBufferBlockIOINTEL = 5569,
+    SpvCapabilitySubgroupImageBlockIOINTEL = 5570,
+    SpvCapabilityMax = 0x7fffffff,
+} SpvCapability;
+
+typedef enum SpvOp_ {
+    SpvOpNop = 0,
+    SpvOpUndef = 1,
+    SpvOpSourceContinued = 2,
+    SpvOpSource = 3,
+    SpvOpSourceExtension = 4,
+    SpvOpName = 5,
+    SpvOpMemberName = 6,
+    SpvOpString = 7,
+    SpvOpLine = 8,
+    SpvOpExtension = 10,
+    SpvOpExtInstImport = 11,
+    SpvOpExtInst = 12,
+    SpvOpMemoryModel = 14,
+    SpvOpEntryPoint = 15,
+    SpvOpExecutionMode = 16,
+    SpvOpCapability = 17,
+    SpvOpTypeVoid = 19,
+    SpvOpTypeBool = 20,
+    SpvOpTypeInt = 21,
+    SpvOpTypeFloat = 22,
+    SpvOpTypeVector = 23,
+    SpvOpTypeMatrix = 24,
+    SpvOpTypeImage = 25,
+    SpvOpTypeSampler = 26,
+    SpvOpTypeSampledImage = 27,
+    SpvOpTypeArray = 28,
+    SpvOpTypeRuntimeArray = 29,
+    SpvOpTypeStruct = 30,
+    SpvOpTypeOpaque = 31,
+    SpvOpTypePointer = 32,
+    SpvOpTypeFunction = 33,
+    SpvOpTypeEvent = 34,
+    SpvOpTypeDeviceEvent = 35,
+    SpvOpTypeReserveId = 36,
+    SpvOpTypeQueue = 37,
+    SpvOpTypePipe = 38,
+    SpvOpTypeForwardPointer = 39,
+    SpvOpConstantTrue = 41,
+    SpvOpConstantFalse = 42,
+    SpvOpConstant = 43,
+    SpvOpConstantComposite = 44,
+    SpvOpConstantSampler = 45,
+    SpvOpConstantNull = 46,
+    SpvOpSpecConstantTrue = 48,
+    SpvOpSpecConstantFalse = 49,
+    SpvOpSpecConstant = 50,
+    SpvOpSpecConstantComposite = 51,
+    SpvOpSpecConstantOp = 52,
+    SpvOpFunction = 54,
+    SpvOpFunctionParameter = 55,
+    SpvOpFunctionEnd = 56,
+    SpvOpFunctionCall = 57,
+    SpvOpVariable = 59,
+    SpvOpImageTexelPointer = 60,
+    SpvOpLoad = 61,
+    SpvOpStore = 62,
+    SpvOpCopyMemory = 63,
+    SpvOpCopyMemorySized = 64,
+    SpvOpAccessChain = 65,
+    SpvOpInBoundsAccessChain = 66,
+    SpvOpPtrAccessChain = 67,
+    SpvOpArrayLength = 68,
+    SpvOpGenericPtrMemSemantics = 69,
+    SpvOpInBoundsPtrAccessChain = 70,
+    SpvOpDecorate = 71,
+    SpvOpMemberDecorate = 72,
+    SpvOpDecorationGroup = 73,
+    SpvOpGroupDecorate = 74,
+    SpvOpGroupMemberDecorate = 75,
+    SpvOpVectorExtractDynamic = 77,
+    SpvOpVectorInsertDynamic = 78,
+    SpvOpVectorShuffle = 79,
+    SpvOpCompositeConstruct = 80,
+    SpvOpCompositeExtract = 81,
+    SpvOpCompositeInsert = 82,
+    SpvOpCopyObject = 83,
+    SpvOpTranspose = 84,
+    SpvOpSampledImage = 86,
+    SpvOpImageSampleImplicitLod = 87,
+    SpvOpImageSampleExplicitLod = 88,
+    SpvOpImageSampleDrefImplicitLod = 89,
+    SpvOpImageSampleDrefExplicitLod = 90,
+    SpvOpImageSampleProjImplicitLod = 91,
+    SpvOpImageSampleProjExplicitLod = 92,
+    SpvOpImageSampleProjDrefImplicitLod = 93,
+    SpvOpImageSampleProjDrefExplicitLod = 94,
+    SpvOpImageFetch = 95,
+    SpvOpImageGather = 96,
+    SpvOpImageDrefGather = 97,
+    SpvOpImageRead = 98,
+    SpvOpImageWrite = 99,
+    SpvOpImage = 100,
+    SpvOpImageQueryFormat = 101,
+    SpvOpImageQueryOrder = 102,
+    SpvOpImageQuerySizeLod = 103,
+    SpvOpImageQuerySize = 104,
+    SpvOpImageQueryLod = 105,
+    SpvOpImageQueryLevels = 106,
+    SpvOpImageQuerySamples = 107,
+    SpvOpConvertFToU = 109,
+    SpvOpConvertFToS = 110,
+    SpvOpConvertSToF = 111,
+    SpvOpConvertUToF = 112,
+    SpvOpUConvert = 113,
+    SpvOpSConvert = 114,
+    SpvOpFConvert = 115,
+    SpvOpQuantizeToF16 = 116,
+    SpvOpConvertPtrToU = 117,
+    SpvOpSatConvertSToU = 118,
+    SpvOpSatConvertUToS = 119,
+    SpvOpConvertUToPtr = 120,
+    SpvOpPtrCastToGeneric = 121,
+    SpvOpGenericCastToPtr = 122,
+    SpvOpGenericCastToPtrExplicit = 123,
+    SpvOpBitcast = 124,
+    SpvOpSNegate = 126,
+    SpvOpFNegate = 127,
+    SpvOpIAdd = 128,
+    SpvOpFAdd = 129,
+    SpvOpISub = 130,
+    SpvOpFSub = 131,
+    SpvOpIMul = 132,
+    SpvOpFMul = 133,
+    SpvOpUDiv = 134,
+    SpvOpSDiv = 135,
+    SpvOpFDiv = 136,
+    SpvOpUMod = 137,
+    SpvOpSRem = 138,
+    SpvOpSMod = 139,
+    SpvOpFRem = 140,
+    SpvOpFMod = 141,
+    SpvOpVectorTimesScalar = 142,
+    SpvOpMatrixTimesScalar = 143,
+    SpvOpVectorTimesMatrix = 144,
+    SpvOpMatrixTimesVector = 145,
+    SpvOpMatrixTimesMatrix = 146,
+    SpvOpOuterProduct = 147,
+    SpvOpDot = 148,
+    SpvOpIAddCarry = 149,
+    SpvOpISubBorrow = 150,
+    SpvOpUMulExtended = 151,
+    SpvOpSMulExtended = 152,
+    SpvOpAny = 154,
+    SpvOpAll = 155,
+    SpvOpIsNan = 156,
+    SpvOpIsInf = 157,
+    SpvOpIsFinite = 158,
+    SpvOpIsNormal = 159,
+    SpvOpSignBitSet = 160,
+    SpvOpLessOrGreater = 161,
+    SpvOpOrdered = 162,
+    SpvOpUnordered = 163,
+    SpvOpLogicalEqual = 164,
+    SpvOpLogicalNotEqual = 165,
+    SpvOpLogicalOr = 166,
+    SpvOpLogicalAnd = 167,
+    SpvOpLogicalNot = 168,
+    SpvOpSelect = 169,
+    SpvOpIEqual = 170,
+    SpvOpINotEqual = 171,
+    SpvOpUGreaterThan = 172,
+    SpvOpSGreaterThan = 173,
+    SpvOpUGreaterThanEqual = 174,
+    SpvOpSGreaterThanEqual = 175,
+    SpvOpULessThan = 176,
+    SpvOpSLessThan = 177,
+    SpvOpULessThanEqual = 178,
+    SpvOpSLessThanEqual = 179,
+    SpvOpFOrdEqual = 180,
+    SpvOpFUnordEqual = 181,
+    SpvOpFOrdNotEqual = 182,
+    SpvOpFUnordNotEqual = 183,
+    SpvOpFOrdLessThan = 184,
+    SpvOpFUnordLessThan = 185,
+    SpvOpFOrdGreaterThan = 186,
+    SpvOpFUnordGreaterThan = 187,
+    SpvOpFOrdLessThanEqual = 188,
+    SpvOpFUnordLessThanEqual = 189,
+    SpvOpFOrdGreaterThanEqual = 190,
+    SpvOpFUnordGreaterThanEqual = 191,
+    SpvOpShiftRightLogical = 194,
+    SpvOpShiftRightArithmetic = 195,
+    SpvOpShiftLeftLogical = 196,
+    SpvOpBitwiseOr = 197,
+    SpvOpBitwiseXor = 198,
+    SpvOpBitwiseAnd = 199,
+    SpvOpNot = 200,
+    SpvOpBitFieldInsert = 201,
+    SpvOpBitFieldSExtract = 202,
+    SpvOpBitFieldUExtract = 203,
+    SpvOpBitReverse = 204,
+    SpvOpBitCount = 205,
+    SpvOpDPdx = 207,
+    SpvOpDPdy = 208,
+    SpvOpFwidth = 209,
+    SpvOpDPdxFine = 210,
+    SpvOpDPdyFine = 211,
+    SpvOpFwidthFine = 212,
+    SpvOpDPdxCoarse = 213,
+    SpvOpDPdyCoarse = 214,
+    SpvOpFwidthCoarse = 215,
+    SpvOpEmitVertex = 218,
+    SpvOpEndPrimitive = 219,
+    SpvOpEmitStreamVertex = 220,
+    SpvOpEndStreamPrimitive = 221,
+    SpvOpControlBarrier = 224,
+    SpvOpMemoryBarrier = 225,
+    SpvOpAtomicLoad = 227,
+    SpvOpAtomicStore = 228,
+    SpvOpAtomicExchange = 229,
+    SpvOpAtomicCompareExchange = 230,
+    SpvOpAtomicCompareExchangeWeak = 231,
+    SpvOpAtomicIIncrement = 232,
+    SpvOpAtomicIDecrement = 233,
+    SpvOpAtomicIAdd = 234,
+    SpvOpAtomicISub = 235,
+    SpvOpAtomicSMin = 236,
+    SpvOpAtomicUMin = 237,
+    SpvOpAtomicSMax = 238,
+    SpvOpAtomicUMax = 239,
+    SpvOpAtomicAnd = 240,
+    SpvOpAtomicOr = 241,
+    SpvOpAtomicXor = 242,
+    SpvOpPhi = 245,
+    SpvOpLoopMerge = 246,
+    SpvOpSelectionMerge = 247,
+    SpvOpLabel = 248,
+    SpvOpBranch = 249,
+    SpvOpBranchConditional = 250,
+    SpvOpSwitch = 251,
+    SpvOpKill = 252,
+    SpvOpReturn = 253,
+    SpvOpReturnValue = 254,
+    SpvOpUnreachable = 255,
+    SpvOpLifetimeStart = 256,
+    SpvOpLifetimeStop = 257,
+    SpvOpGroupAsyncCopy = 259,
+    SpvOpGroupWaitEvents = 260,
+    SpvOpGroupAll = 261,
+    SpvOpGroupAny = 262,
+    SpvOpGroupBroadcast = 263,
+    SpvOpGroupIAdd = 264,
+    SpvOpGroupFAdd = 265,
+    SpvOpGroupFMin = 266,
+    SpvOpGroupUMin = 267,
+    SpvOpGroupSMin = 268,
+    SpvOpGroupFMax = 269,
+    SpvOpGroupUMax = 270,
+    SpvOpGroupSMax = 271,
+    SpvOpReadPipe = 274,
+    SpvOpWritePipe = 275,
+    SpvOpReservedReadPipe = 276,
+    SpvOpReservedWritePipe = 277,
+    SpvOpReserveReadPipePackets = 278,
+    SpvOpReserveWritePipePackets = 279,
+    SpvOpCommitReadPipe = 280,
+    SpvOpCommitWritePipe = 281,
+    SpvOpIsValidReserveId = 282,
+    SpvOpGetNumPipePackets = 283,
+    SpvOpGetMaxPipePackets = 284,
+    SpvOpGroupReserveReadPipePackets = 285,
+    SpvOpGroupReserveWritePipePackets = 286,
+    SpvOpGroupCommitReadPipe = 287,
+    SpvOpGroupCommitWritePipe = 288,
+    SpvOpEnqueueMarker = 291,
+    SpvOpEnqueueKernel = 292,
+    SpvOpGetKernelNDrangeSubGroupCount = 293,
+    SpvOpGetKernelNDrangeMaxSubGroupSize = 294,
+    SpvOpGetKernelWorkGroupSize = 295,
+    SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,
+    SpvOpRetainEvent = 297,
+    SpvOpReleaseEvent = 298,
+    SpvOpCreateUserEvent = 299,
+    SpvOpIsValidEvent = 300,
+    SpvOpSetUserEventStatus = 301,
+    SpvOpCaptureEventProfilingInfo = 302,
+    SpvOpGetDefaultQueue = 303,
+    SpvOpBuildNDRange = 304,
+    SpvOpImageSparseSampleImplicitLod = 305,
+    SpvOpImageSparseSampleExplicitLod = 306,
+    SpvOpImageSparseSampleDrefImplicitLod = 307,
+    SpvOpImageSparseSampleDrefExplicitLod = 308,
+    SpvOpImageSparseSampleProjImplicitLod = 309,
+    SpvOpImageSparseSampleProjExplicitLod = 310,
+    SpvOpImageSparseSampleProjDrefImplicitLod = 311,
+    SpvOpImageSparseSampleProjDrefExplicitLod = 312,
+    SpvOpImageSparseFetch = 313,
+    SpvOpImageSparseGather = 314,
+    SpvOpImageSparseDrefGather = 315,
+    SpvOpImageSparseTexelsResident = 316,
+    SpvOpNoLine = 317,
+    SpvOpAtomicFlagTestAndSet = 318,
+    SpvOpAtomicFlagClear = 319,
+    SpvOpImageSparseRead = 320,
+    SpvOpSizeOf = 321,
+    SpvOpTypePipeStorage = 322,
+    SpvOpConstantPipeStorage = 323,
+    SpvOpCreatePipeFromPipeStorage = 324,
+    SpvOpGetKernelLocalSizeForSubgroupCount = 325,
+    SpvOpGetKernelMaxNumSubgroups = 326,
+    SpvOpTypeNamedBarrier = 327,
+    SpvOpNamedBarrierInitialize = 328,
+    SpvOpMemoryNamedBarrier = 329,
+    SpvOpModuleProcessed = 330,
+    SpvOpExecutionModeId = 331,
+    SpvOpDecorateId = 332,
+    SpvOpGroupNonUniformElect = 333,
+    SpvOpGroupNonUniformAll = 334,
+    SpvOpGroupNonUniformAny = 335,
+    SpvOpGroupNonUniformAllEqual = 336,
+    SpvOpGroupNonUniformBroadcast = 337,
+    SpvOpGroupNonUniformBroadcastFirst = 338,
+    SpvOpGroupNonUniformBallot = 339,
+    SpvOpGroupNonUniformInverseBallot = 340,
+    SpvOpGroupNonUniformBallotBitExtract = 341,
+    SpvOpGroupNonUniformBallotBitCount = 342,
+    SpvOpGroupNonUniformBallotFindLSB = 343,
+    SpvOpGroupNonUniformBallotFindMSB = 344,
+    SpvOpGroupNonUniformShuffle = 345,
+    SpvOpGroupNonUniformShuffleXor = 346,
+    SpvOpGroupNonUniformShuffleUp = 347,
+    SpvOpGroupNonUniformShuffleDown = 348,
+    SpvOpGroupNonUniformIAdd = 349,
+    SpvOpGroupNonUniformFAdd = 350,
+    SpvOpGroupNonUniformIMul = 351,
+    SpvOpGroupNonUniformFMul = 352,
+    SpvOpGroupNonUniformSMin = 353,
+    SpvOpGroupNonUniformUMin = 354,
+    SpvOpGroupNonUniformFMin = 355,
+    SpvOpGroupNonUniformSMax = 356,
+    SpvOpGroupNonUniformUMax = 357,
+    SpvOpGroupNonUniformFMax = 358,
+    SpvOpGroupNonUniformBitwiseAnd = 359,
+    SpvOpGroupNonUniformBitwiseOr = 360,
+    SpvOpGroupNonUniformBitwiseXor = 361,
+    SpvOpGroupNonUniformLogicalAnd = 362,
+    SpvOpGroupNonUniformLogicalOr = 363,
+    SpvOpGroupNonUniformLogicalXor = 364,
+    SpvOpGroupNonUniformQuadBroadcast = 365,
+    SpvOpGroupNonUniformQuadSwap = 366,
+    SpvOpSubgroupBallotKHR = 4421,
+    SpvOpSubgroupFirstInvocationKHR = 4422,
+    SpvOpSubgroupAllKHR = 4428,
+    SpvOpSubgroupAnyKHR = 4429,
+    SpvOpSubgroupAllEqualKHR = 4430,
+    SpvOpSubgroupReadInvocationKHR = 4432,
+    SpvOpGroupIAddNonUniformAMD = 5000,
+    SpvOpGroupFAddNonUniformAMD = 5001,
+    SpvOpGroupFMinNonUniformAMD = 5002,
+    SpvOpGroupUMinNonUniformAMD = 5003,
+    SpvOpGroupSMinNonUniformAMD = 5004,
+    SpvOpGroupFMaxNonUniformAMD = 5005,
+    SpvOpGroupUMaxNonUniformAMD = 5006,
+    SpvOpGroupSMaxNonUniformAMD = 5007,
+    SpvOpFragmentMaskFetchAMD = 5011,
+    SpvOpFragmentFetchAMD = 5012,
+    SpvOpImageSampleFootprintNV = 5283,
+    SpvOpGroupNonUniformPartitionNV = 5296,
+    SpvOpWritePackedPrimitiveIndices4x8NV = 5299,
+    SpvOpReportIntersectionNVX = 5334,
+    SpvOpIgnoreIntersectionNVX = 5335,
+    SpvOpTerminateRayNVX = 5336,
+    SpvOpTraceNVX = 5337,
+    SpvOpTypeAccelerationStructureNVX = 5341,
+    SpvOpSubgroupShuffleINTEL = 5571,
+    SpvOpSubgroupShuffleDownINTEL = 5572,
+    SpvOpSubgroupShuffleUpINTEL = 5573,
+    SpvOpSubgroupShuffleXorINTEL = 5574,
+    SpvOpSubgroupBlockReadINTEL = 5575,
+    SpvOpSubgroupBlockWriteINTEL = 5576,
+    SpvOpSubgroupImageBlockReadINTEL = 5577,
+    SpvOpSubgroupImageBlockWriteINTEL = 5578,
+    SpvOpDecorateStringGOOGLE = 5632,
+    SpvOpMemberDecorateStringGOOGLE = 5633,
+    SpvOpMax = 0x7fffffff,
+} SpvOp;
+
+#endif  // #ifndef spirv_H

+ 1 - 1
panda/src/pgraph/shaderAttrib.cxx

@@ -342,7 +342,7 @@ get_shader_input_nodepath(const InternalName *id) const {
  * if it is not a vector.
  */
 LVecBase4 ShaderAttrib::
-get_shader_input_vector(InternalName *id) const {
+get_shader_input_vector(const InternalName *id) const {
   static LVecBase4 resfail(0,0,0,0);
   Inputs::const_iterator i = _inputs.find(id);
   if (i != _inputs.end()) {

+ 1 - 1
panda/src/pgraph/shaderAttrib.h

@@ -116,7 +116,7 @@ PUBLISHED:
   const ShaderInput &get_shader_input(const std::string &id) const;
 
   NodePath get_shader_input_nodepath(const InternalName *id) const;
-  LVecBase4 get_shader_input_vector(InternalName *id) const;
+  LVecBase4 get_shader_input_vector(const InternalName *id) const;
   Texture *get_shader_input_texture(const InternalName *id, SamplerState *sampler=nullptr) const;
   const Shader::ShaderPtrData *get_shader_input_ptr(const InternalName *id) const;
   bool get_shader_input_ptr(const InternalName *id, Shader::ShaderPtrData &data) const;

+ 10 - 0
panda/src/shaderpipeline/config_shaderpipeline.cxx

@@ -14,9 +14,14 @@
 #include "config_shaderpipeline.h"
 
 #include "shaderCompilerRegistry.h"
+#include "shaderCompilerGlslang.h"
 #include "shaderCompilerGlslPreProc.h"
 #include "shaderCompilerCg.h"
 
+#include "shaderModule.h"
+#include "shaderModuleGlsl.h"
+#include "shaderModuleSpirV.h"
+
 #include "dconfig.h"
 
 
@@ -41,7 +46,12 @@ init_libshaderpipeline() {
   }
   initialized = true;
 
+  ShaderModule::init_type();
+  ShaderModuleSpirV::init_type();
+  ShaderModuleGlsl::init_type();
+
   ShaderCompilerRegistry *reg = ShaderCompilerRegistry::get_global_ptr();
+  reg->register_compiler(new ShaderCompilerGlslang());
   reg->register_compiler(new ShaderCompilerGlslPreProc());
   reg->register_compiler(new ShaderCompilerCg());
 }

+ 2 - 0
panda/src/shaderpipeline/p3shaderpipeline_composite1.cxx

@@ -1,7 +1,9 @@
 #include "config_shaderpipeline.cxx"
 #include "shaderModule.cxx"
 #include "shaderModuleGlsl.cxx"
+#include "shaderModuleSpirV.cxx"
 #include "shaderCompiler.cxx"
+#include "shaderCompilerGlslang.cxx"
 #include "shaderCompilerGlslPreProc.cxx"
 #include "shaderCompilerCg.cxx"
 #include "shaderCompilerRegistry.cxx"

+ 1 - 0
panda/src/shaderpipeline/shaderCompilerGlslPreProc.cxx

@@ -39,6 +39,7 @@ get_name() const {
  */
 ShaderLanguages ShaderCompilerGlslPreProc::
 get_languages() const {
+  //return ShaderLanguages();
   return {
     Shader::SL_GLSL
   };

+ 234 - 0
panda/src/shaderpipeline/shaderCompilerGlslang.cxx

@@ -0,0 +1,234 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerGlslang.cxx
+ * @author rdb
+ * @date 2020-01-02
+ */
+
+#include "shaderCompilerGlslang.h"
+#include "shaderModuleSpirV.h"
+#include "config_shaderpipeline.h"
+#include "virtualFile.h"
+
+#include <glslang/Public/ShaderLang.h>
+#include <glslang/Include/ResourceLimits.h>
+#include <glslang/SPIRV/GlslangToSpv.h>
+
+#include "dcast.h"
+
+#ifndef CPPPARSER
+const TBuiltInResource resource_limits = {
+  /* .MaxLights = */ 32,
+  /* .MaxClipPlanes = */ 6,
+  /* .MaxTextureUnits = */ 32,
+  /* .MaxTextureCoords = */ 32,
+  /* .MaxVertexAttribs = */ 64,
+  /* .MaxVertexUniformComponents = */ 4096,
+  /* .MaxVaryingFloats = */ 64,
+  /* .MaxVertexTextureImageUnits = */ 32,
+  /* .MaxCombinedTextureImageUnits = */ 80,
+  /* .MaxTextureImageUnits = */ 32,
+  /* .MaxFragmentUniformComponents = */ 4096,
+  /* .MaxDrawBuffers = */ 32,
+  /* .MaxVertexUniformVectors = */ 128,
+  /* .MaxVaryingVectors = */ 8,
+  /* .MaxFragmentUniformVectors = */ 16,
+  /* .MaxVertexOutputVectors = */ 16,
+  /* .MaxFragmentInputVectors = */ 15,
+  /* .MinProgramTexelOffset = */ -8,
+  /* .MaxProgramTexelOffset = */ 7,
+  /* .MaxClipDistances = */ 8,
+  /* .MaxComputeWorkGroupCountX = */ 65535,
+  /* .MaxComputeWorkGroupCountY = */ 65535,
+  /* .MaxComputeWorkGroupCountZ = */ 65535,
+  /* .MaxComputeWorkGroupSizeX = */ 1024,
+  /* .MaxComputeWorkGroupSizeY = */ 1024,
+  /* .MaxComputeWorkGroupSizeZ = */ 64,
+  /* .MaxComputeUniformComponents = */ 1024,
+  /* .MaxComputeTextureImageUnits = */ 16,
+  /* .MaxComputeImageUniforms = */ 8,
+  /* .MaxComputeAtomicCounters = */ 8,
+  /* .MaxComputeAtomicCounterBuffers = */ 1,
+  /* .MaxVaryingComponents = */ 60,
+  /* .MaxVertexOutputComponents = */ 64,
+  /* .MaxGeometryInputComponents = */ 64,
+  /* .MaxGeometryOutputComponents = */ 128,
+  /* .MaxFragmentInputComponents = */ 128,
+  /* .MaxImageUnits = */ 8,
+  /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
+  /* .MaxCombinedShaderOutputResources = */ 8,
+  /* .MaxImageSamples = */ 0,
+  /* .MaxVertexImageUniforms = */ 0,
+  /* .MaxTessControlImageUniforms = */ 0,
+  /* .MaxTessEvaluationImageUniforms = */ 0,
+  /* .MaxGeometryImageUniforms = */ 0,
+  /* .MaxFragmentImageUniforms = */ 8,
+  /* .MaxCombinedImageUniforms = */ 8,
+  /* .MaxGeometryTextureImageUnits = */ 16,
+  /* .MaxGeometryOutputVertices = */ 256,
+  /* .MaxGeometryTotalOutputComponents = */ 1024,
+  /* .MaxGeometryUniformComponents = */ 1024,
+  /* .MaxGeometryVaryingComponents = */ 64,
+  /* .MaxTessControlInputComponents = */ 128,
+  /* .MaxTessControlOutputComponents = */ 128,
+  /* .MaxTessControlTextureImageUnits = */ 16,
+  /* .MaxTessControlUniformComponents = */ 1024,
+  /* .MaxTessControlTotalOutputComponents = */ 4096,
+  /* .MaxTessEvaluationInputComponents = */ 128,
+  /* .MaxTessEvaluationOutputComponents = */ 128,
+  /* .MaxTessEvaluationTextureImageUnits = */ 16,
+  /* .MaxTessEvaluationUniformComponents = */ 1024,
+  /* .MaxTessPatchComponents = */ 120,
+  /* .MaxPatchVertices = */ 32,
+  /* .MaxTessGenLevel = */ 64,
+  /* .MaxViewports = */ 16,
+  /* .MaxVertexAtomicCounters = */ 0,
+  /* .MaxTessControlAtomicCounters = */ 0,
+  /* .MaxTessEvaluationAtomicCounters = */ 0,
+  /* .MaxGeometryAtomicCounters = */ 0,
+  /* .MaxFragmentAtomicCounters = */ 8,
+  /* .MaxCombinedAtomicCounters = */ 8,
+  /* .MaxAtomicCounterBindings = */ 1,
+  /* .MaxVertexAtomicCounterBuffers = */ 0,
+  /* .MaxTessControlAtomicCounterBuffers = */ 0,
+  /* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
+  /* .MaxGeometryAtomicCounterBuffers = */ 0,
+  /* .MaxFragmentAtomicCounterBuffers = */ 1,
+  /* .MaxCombinedAtomicCounterBuffers = */ 1,
+  /* .MaxAtomicCounterBufferSize = */ 16384,
+  /* .MaxTransformFeedbackBuffers = */ 4,
+  /* .MaxTransformFeedbackInterleavedComponents = */ 64,
+  /* .MaxCullDistances = */ 8,
+  /* .MaxCombinedClipAndCullDistances = */ 8,
+  /* .MaxSamples = */ 4,
+  /* .maxMeshOutputVerticesNV = */ 256,
+  /* .maxMeshOutputPrimitivesNV = */ 512,
+  /* .maxMeshWorkGroupSizeX_NV = */ 32,
+  /* .maxMeshWorkGroupSizeY_NV = */ 1,
+  /* .maxMeshWorkGroupSizeZ_NV = */ 1,
+  /* .maxTaskWorkGroupSizeX_NV = */ 32,
+  /* .maxTaskWorkGroupSizeY_NV = */ 1,
+  /* .maxTaskWorkGroupSizeZ_NV = */ 1,
+  /* .maxMeshViewCountNV = */ 4,
+
+  /* .limits = */ {
+      /* .nonInductiveForLoops = */ 1,
+      /* .whileLoops = */ 1,
+      /* .doWhileLoops = */ 1,
+      /* .generalUniformIndexing = */ 1,
+      /* .generalAttributeMatrixVectorIndexing = */ 1,
+      /* .generalVaryingIndexing = */ 1,
+      /* .generalSamplerIndexing = */ 1,
+      /* .generalVariableIndexing = */ 1,
+      /* .generalConstantMatrixVectorIndexing = */ 1,
+  }
+};
+#endif
+
+TypeHandle ShaderCompilerGlslang::_type_handle;
+
+/**
+ *
+ */
+ShaderCompilerGlslang::
+ShaderCompilerGlslang() {
+}
+
+/**
+ *
+ */
+std::string ShaderCompilerGlslang::
+get_name() const {
+  return "GLslang";
+}
+
+/**
+ *
+ */
+ShaderLanguages ShaderCompilerGlslang::
+get_languages() const {
+  return {
+    Shader::SL_GLSL
+  };
+}
+
+/**
+ * Compiles the source code from the given input stream, producing a
+ * ShaderModule on success.
+ */
+PT(ShaderModule) ShaderCompilerGlslang::
+compile_now(ShaderModule::Stage stage, std::istream &in,
+            const std::string &filename, BamCacheRecord *record) const {
+
+  vector_uchar code;
+  if (!VirtualFile::simple_read_file(&in, code)) {
+    return nullptr;
+  }
+
+  static bool is_initialized = false;
+  if (!is_initialized) {
+    ShInitialize();
+    is_initialized = true;
+  }
+
+  const char *string = (const char *)code.data();
+  const int length = (int)code.size();
+  const char *fname = filename.c_str();
+
+  glslang::TShader *shader = new glslang::TShader((EShLanguage)stage);
+  shader->setStringsWithLengthsAndNames(&string, &length, &fname, 1);
+  //shader->setEntryPoint("main");
+  //shader->setSourceEntryPoint("main");
+  //shader->setEnvInput(glslang::EShSource::EShSourceGlsl, (EShLanguage)stage, glslang::EShClient::EShClientVulkan, 430);
+  //shader->setEnvClient(glslang::EShClient::EShClientVulkan, glslang::EShTargetVulkan_1_1);
+  shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
+
+  // Have the compilers assign bindings to everything--even if we will end up
+  // changing them, it's useful if there are already location assignments to
+  // overwrite so that we only have to modify instructions and not insert new
+  // ones.
+
+  // This will squelch the warnings about missing bindings and locations, since
+  // we can assign those ourselves.
+  shader->setAutoMapBindings(true);
+  shader->setAutoMapLocations(true);
+
+  glslang::TShader::ForbidIncluder includer;
+  if (!shader->parse(&resource_limits, 110, false, (EShMessages)(EShMsgDefault | EShMsgDebugInfo), includer)) {
+    std::cerr << "failed to parse " << filename << ":\n";
+    std::cerr << shader->getInfoLog() << "\n";
+    std::cerr << shader->getInfoDebugLog() << "\n";
+    return nullptr;
+  }
+
+  glslang::TIntermediate *ir = shader->getIntermediate();
+  if (!ir) {
+    std::cerr << "failed to obtain IR " << filename << ":\n";
+    return nullptr;
+  }
+
+  std::vector<unsigned int> spirv;
+  std::string warningsErrors;
+  spv::SpvBuildLogger logger;
+  glslang::SpvOptions spvOptions;
+  spvOptions.generateDebugInfo = true;
+  spvOptions.disableOptimizer = false;
+  spvOptions.optimizeSize = false;
+  spvOptions.disassemble = false;
+  spvOptions.validate = true;
+  glslang::GlslangToSpv(*ir, spirv, &logger, &spvOptions);
+
+  printf("%s", logger.getAllMessages().c_str());
+  /*if (Options & EOptionOutputHexadecimal) {
+  } else {
+      glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
+  }*/
+
+  return new ShaderModuleSpirV(stage, spirv.data(), spirv.size());
+}

+ 69 - 0
panda/src/shaderpipeline/shaderCompilerGlslang.h

@@ -0,0 +1,69 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderCompilerGlslang.h
+ * @author rdb
+ * @date 2020-01-02
+ */
+
+#ifndef SHADERCOMPILERGLSLANG_H
+#define SHADERCOMPILERGLSLANG_H
+
+#include "pandabase.h"
+
+#include "shaderCompiler.h"
+
+/**
+ * ShaderCompiler implementation that uses the libglslang library to compile
+ * GLSL shaders to SPIR-V.
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderCompilerGlslang : public ShaderCompiler {
+public:
+  ShaderCompilerGlslang();
+
+  virtual std::string get_name() const override;
+  virtual ShaderLanguages get_languages() const override;
+  virtual PT(ShaderModule) compile_now(Stage stage, std::istream &in,
+                                       const std::string &filename = "created-shader",
+                                       BamCacheRecord *record = nullptr) const override;
+
+private:
+  bool r_preprocess_include(ShaderModuleGlsl *module,
+                            std::ostream &out, const std::string &filename,
+                            const Filename &source_dir,
+                            std::set<Filename> &open_files,
+                            BamCacheRecord *record, int depth) const;
+  bool r_preprocess_source(ShaderModuleGlsl *module,
+                           std::ostream &out, std::istream &in,
+                           const std::string &fn, const Filename &full_fn,
+                           std::set<Filename> &open_files,
+                           BamCacheRecord *record,
+                           int fileno = 0, int depth = 0) const;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    ShaderCompiler::init_type();
+    register_type(_type_handle, "ShaderCompilerGlslang",
+                  ShaderCompiler::get_class_type());
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() override {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif

+ 87 - 0
panda/src/shaderpipeline/shaderModule.I

@@ -36,3 +36,90 @@ INLINE void ShaderModule::
 set_source_filename(const Filename &filename) {
   _source_filename = filename;
 }
+
+/**
+ * Returns the number of input variables in this shader stage.
+ */
+INLINE size_t ShaderModule::
+get_num_inputs() const {
+  return _inputs.size();
+}
+
+/**
+ * Returns the nth input variable in this shader stage.
+ */
+INLINE const ShaderModule::Variable &ShaderModule::
+get_input(size_t i) const {
+  return _inputs[i];
+}
+
+/**
+ * Returns the index of the input variable with the given name.
+ */
+INLINE int ShaderModule::
+find_input(CPT_InternalName name) const {
+  for (size_t i = 0; i < _inputs.size(); ++i) {
+    if (_inputs[i].name == name) {
+      return (int)i;
+    }
+  }
+  return -1;
+}
+
+/**
+ * Returns the number of output variables in this shader stage.
+ */
+INLINE size_t ShaderModule::
+get_num_outputs() const {
+  return _outputs.size();
+}
+
+/**
+ * Returns the nth output variable in this shader stage.
+ */
+INLINE const ShaderModule::Variable &ShaderModule::
+get_output(size_t i) const {
+  return _outputs[i];
+}
+
+/**
+ * Returns the index of the output variable with the given name.
+ */
+INLINE int ShaderModule::
+find_output(CPT_InternalName name) const {
+  for (size_t i = 0; i < _outputs.size(); ++i) {
+    if (_outputs[i].name == name) {
+      return (int)i;
+    }
+  }
+  return -1;
+}
+
+/**
+ * Returns the number of parameter variables in this shader stage.
+ */
+INLINE size_t ShaderModule::
+get_num_parameters() const {
+  return _parameters.size();
+}
+
+/**
+ * Returns the nth parameter variable in this shader stage.
+ */
+INLINE const ShaderModule::Variable &ShaderModule::
+get_parameter(size_t i) const {
+  return _parameters[i];
+}
+
+/**
+ * Returns the index of the parameter variable with the given name.
+ */
+INLINE int ShaderModule::
+find_parameter(CPT_InternalName name) const {
+  for (size_t i = 0; i < _parameters.size(); ++i) {
+    if (_parameters[i].name == name) {
+      return (int)i;
+    }
+  }
+  return -1;
+}

+ 29 - 0
panda/src/shaderpipeline/shaderModule.cxx

@@ -29,6 +29,35 @@ ShaderModule::
 ~ShaderModule() {
 }
 
+/**
+ * Adjusts any input bindings necessary to be able to link up with the given
+ * previous stage.  Should return false to indicate that the link is not
+ * possible.
+ */
+bool ShaderModule::
+link_inputs(const ShaderModule *previous) {
+  // By default we need to do nothing special to link it up, as long as the
+  // modules have the same type.
+  return get_stage() > previous->get_stage()
+      && get_type() == previous->get_type();
+}
+
+/**
+ * Remaps parameters with a given location to a given other location.  Locations
+ * not included in the map remain untouched.
+ */
+void ShaderModule::
+remap_parameter_locations(pmap<int, int> &locations) {
+}
+
+/**
+ *
+ */
+void ShaderModule::
+output(std::ostream &out) const {
+  out << get_type() << " " << get_stage();
+}
+
 /**
  * Writes the contents of this object to the datagram for shipping out to a
  * Bam file.

+ 64 - 9
panda/src/shaderpipeline/shaderModule.h

@@ -14,15 +14,20 @@
 #ifndef SHADERMODULE_H
 #define SHADERMODULE_H
 
-#include "typedWritableReferenceCount.h"
+#include "copyOnWriteObject.h"
 #include "bamCacheRecord.h"
+#include "shaderType.h"
 
 /**
  * Represents a single shader module in some intermediate representation for
  * passing to the driver.  This could contain compiled bytecode, or in some
  * cases, preprocessed source code to be given directly to the driver.
+ *
+ * This class inherits from CopyOnWriteObject so that modules can safely be
+ * shared between multiple Shader objects, with a unique copy automatically
+ * being created if the Shader needs to manipulate the module.
  */
-class EXPCL_PANDA_SHADERPIPELINE ShaderModule : public TypedWritableReferenceCount {
+class EXPCL_PANDA_SHADERPIPELINE ShaderModule : public CopyOnWriteObject {
 PUBLISHED:
   enum class Stage {
     vertex,
@@ -33,6 +38,24 @@ PUBLISHED:
     compute,
   };
 
+  /**
+   * Defines an interface variable.
+   */
+  struct Variable {
+  public:
+    int has_location() const { return _location >= 0; }
+    int get_location() const { return _location; }
+
+  PUBLISHED:
+    const ShaderType *type;
+    CPT_InternalName name;
+
+    MAKE_PROPERTY2(location, has_location, get_location);
+
+  public:
+    int _location;
+  };
+
 public:
   ShaderModule(Stage stage);
   virtual ~ShaderModule();
@@ -42,13 +65,41 @@ public:
   INLINE const Filename &get_source_filename() const;
   INLINE void set_source_filename(const Filename &);
 
-  static std::string format_stage(Stage stage);
+  size_t get_num_inputs() const;
+  const Variable &get_input(size_t i) const;
+  int find_input(CPT_InternalName name) const;
+
+  size_t get_num_outputs() const;
+  const Variable &get_output(size_t i) const;
+  int find_output(CPT_InternalName name) const;
+
+  size_t get_num_parameters() const;
+  const Variable &get_parameter(size_t i) const;
+  int find_parameter(CPT_InternalName name) const;
+
+public:
+  typedef pmap<CPT_InternalName, Variable *> VariablesByName;
+
+  virtual bool link_inputs(const ShaderModule *previous);
+  virtual void remap_parameter_locations(pmap<int, int> &remap);
 
 PUBLISHED:
   MAKE_PROPERTY(stage, get_stage);
+  MAKE_SEQ_PROPERTY(inputs, get_num_inputs, get_input);
+  MAKE_SEQ_PROPERTY(outputs, get_num_outputs, get_output);
 
   virtual std::string get_ir() const=0;
 
+public:
+  static std::string format_stage(Stage stage);
+
+  virtual void output(std::ostream &out) const;
+
+  virtual void write_datagram(BamWriter *manager, Datagram &dg) override;
+
+protected:
+  void fillin(DatagramIterator &scan, BamReader *manager) override;
+
 protected:
   Stage _stage;
   PT(BamCacheRecord) _record;
@@ -56,13 +107,12 @@ protected:
   Filename _source_filename;
   //time_t _source_modified = 0;
 
-  friend class Shader;
+  typedef pvector<Variable> Variables;
+  Variables _inputs;
+  Variables _outputs;
+  Variables _parameters;
 
-public:
-  virtual void write_datagram(BamWriter *manager, Datagram &dg) override;
-
-protected:
-  void fillin(DatagramIterator &scan, BamReader *manager) override;
+  friend class Shader;
 
 public:
   static TypeHandle get_class_type() {
@@ -85,6 +135,11 @@ private:
   static TypeHandle _type_handle;
 };
 
+INLINE std::ostream &operator << (std::ostream &out, const ShaderModule &module) {
+  module.output(out);
+  return out;
+}
+
 INLINE std::ostream &operator << (std::ostream &out, ShaderModule::Stage stage) {
   return out << ShaderModule::format_stage(stage);
 }

+ 8 - 0
panda/src/shaderpipeline/shaderModuleGlsl.cxx

@@ -26,6 +26,14 @@ ShaderModuleGlsl::
 ~ShaderModuleGlsl() {
 }
 
+/**
+ * Required to implement CopyOnWriteObject.
+ */
+PT(CopyOnWriteObject) ShaderModuleGlsl::
+make_cow_copy() {
+  return new ShaderModuleGlsl(*this);
+}
+
 std::string ShaderModuleGlsl::
 get_ir() const {
   return this->_raw_source;

+ 2 - 0
panda/src/shaderpipeline/shaderModuleGlsl.h

@@ -24,6 +24,8 @@ public:
   ShaderModuleGlsl(Stage stage);
   virtual ~ShaderModuleGlsl();
 
+  virtual PT(CopyOnWriteObject) make_cow_copy() override;
+
   virtual std::string get_ir() const override;
 
   int add_included_file(Filename fn);

+ 698 - 0
panda/src/shaderpipeline/shaderModuleSpirV.cxx

@@ -0,0 +1,698 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModuleSpirV.cxx
+ * @author rdb
+ * @date 2019-07-15
+ */
+
+#include "shaderModuleSpirV.h"
+#include "string_utils.h"
+#include "shaderType.h"
+
+//#include <glslang/SPIRV/disassemble.h>
+
+TypeHandle ShaderModuleSpirV::_type_handle;
+
+/**
+ * Takes a stream of SPIR-V instructions, and processes it as follows:
+ * - All the definitions are parsed out (requires debug info present)
+ * - Makes sure that all the inputs have location indices assigned.
+ * - Builds up the lists of inputs, outputs and parameters.
+ * - Strips debugging information from the module.
+ */
+ShaderModuleSpirV::
+ShaderModuleSpirV(Stage stage, const uint32_t *words, size_t size) :
+  ShaderModule(stage),
+  _words(words, words + size)
+{
+  Definitions defs;
+  if (!parse(defs)) {
+    shader_cat.error()
+      << "Failed to parse SPIR-V shader code.\n";
+    return;
+  }
+
+  // Add in location decorations for any inputs that are missing it.
+  assign_locations(defs);
+
+  // Identify the inputs and outputs.
+  for (uint32_t id = 0; id < defs.size(); ++id) {
+    Definition &def = defs[id];
+    if (def._dtype == DT_variable && def._builtin == SpvBuiltInMax) {
+      Variable var;
+      var.type = def._type;
+      var.name = def._name;
+      var._location = def._location;
+      //var._id = id;
+
+      if (def._storage_class == SpvStorageClassInput) {
+        _inputs.push_back(std::move(var));
+      }
+      else if (def._storage_class == SpvStorageClassOutput) {
+        _outputs.push_back(std::move(var));
+      }
+      else if (def._storage_class == SpvStorageClassUniformConstant) {
+        _parameters.push_back(std::move(var));
+      }
+    }
+  }
+
+  // We no longer need the debugging information, so it can be safely stripped
+  // from the module.
+  strip();
+
+  //std::vector<uint32_t> words2(_words.begin(), _words.end());
+  //spv::Disassemble(std::cerr, words2);
+}
+
+ShaderModuleSpirV::
+~ShaderModuleSpirV() {
+}
+
+/**
+ * Required to implement CopyOnWriteObject.
+ */
+PT(CopyOnWriteObject) ShaderModuleSpirV::
+make_cow_copy() {
+  return new ShaderModuleSpirV(*this);
+}
+
+std::string ShaderModuleSpirV::
+get_ir() const {
+  return std::string();
+}
+
+/**
+ * Links the stage with the given previous stage, by matching up its inputs with
+ * the outputs of the previous stage and assigning locations.
+ */
+bool ShaderModuleSpirV::
+link_inputs(const ShaderModule *previous) {
+  if (!previous->is_of_type(ShaderModuleSpirV::get_class_type())) {
+    return false;
+  }
+  if (previous->get_stage() >= get_stage()) {
+    return false;
+  }
+
+  pmap<int, int> location_remap;
+
+  ShaderModuleSpirV *spv_prev = (ShaderModuleSpirV *)previous;
+
+  for (const Variable &input : _inputs) {
+    int i = spv_prev->find_output(input.name);
+    if (i < 0) {
+      shader_cat.error()
+        << "Input " << *input.name << " in stage " << get_stage()
+        << " does not match any output in stage " << previous->get_stage() << "!\n";
+      return false;
+    }
+
+    const Variable &output = spv_prev->get_output((size_t)i);
+    if (!output.has_location()) {
+      shader_cat.error()
+        << "Output " << *input.name << " in stage " << previous->get_stage()
+        << " has no output location!\n";
+      return false;
+    }
+
+    if (!input.has_location() || output.get_location() != input.get_location()) {
+      location_remap[input.get_location()] = output.get_location();
+    }
+  }
+
+  if (!location_remap.empty()) {
+    remap_locations(SpvStorageClassInput, location_remap);
+  }
+  return true;
+}
+
+/**
+ * Remaps parameters with a given location to a given other location.  Locations
+ * not included in the map remain untouched.
+ */
+void ShaderModuleSpirV::
+remap_parameter_locations(pmap<int, int> &locations) {
+  remap_locations(SpvStorageClassUniformConstant, locations);
+
+  // If we extracted out the parameters, replace the locations there as well.
+  for (Variable &parameter : _parameters) {
+    if (parameter.has_location()) {
+      pmap<int, int>::const_iterator it = locations.find(parameter.get_location());
+      if (it != locations.end()) {
+        parameter._location = it->second;
+      }
+    }
+  }
+}
+
+/**
+ * Parses the SPIR-V file, extracting the definitions into the given vector.
+ */
+bool ShaderModuleSpirV::
+parse(Definitions &defs) {
+  const uint32_t *words = (const uint32_t *)_words.data();
+  const size_t length = _words.size();
+  const uint32_t *end = words + length;
+
+  if (length < 5) {
+    shader_cat.error()
+      << "Invalid SPIR-V file: too short.\n";
+    return false;
+  }
+
+  if (*words++ != SpvMagicNumber) {
+    shader_cat.error()
+      << "Invalid SPIR-V file: wrong magic number.\n";
+    return false;
+  }
+
+  ++words; // version
+  ++words; // generator
+  uint32_t bound = *words++;
+  ++words; // schema (reserved)
+
+  defs = Definitions(bound);
+
+  while (words < end) {
+    uint16_t wcount = words[0] >> SpvWordCountShift;
+    SpvOp opcode = (SpvOp)(words[0] & SpvOpCodeMask);
+    nassertr(wcount > 0, false);
+
+    if (!parse_instruction(defs, opcode, words + 1, wcount - 1)) {
+      return false;
+    }
+    words += wcount;
+  }
+
+  return true;
+}
+
+/**
+ * Parses the instruction with the given SPIR-V opcode and arguments.
+ */
+bool ShaderModuleSpirV::
+parse_instruction(Definitions &defs, SpvOp opcode, const uint32_t *args, size_t nargs) {
+  switch (opcode) {
+  case SpvOpMemoryModel:
+    if (args[0] != SpvAddressingModelLogical) {
+      shader_cat.error()
+        << "Invalid SPIR-V shader: addressing model Logical must be used.\n";
+      return false;
+    }
+    if (args[1] != SpvMemoryModelGLSL450) {
+      shader_cat.error()
+        << "Invalid SPIR-V shader: memory model GLSL450 must be used.\n";
+      return false;
+    }
+    break;
+
+  case SpvOpEntryPoint:
+    /*switch ((SpvExecutionModel)args[0]) {
+    case SpvExecutionModelVertex:
+      _stage = Stage::vertex;
+      break;
+    case SpvExecutionModelTessellationControl:
+      _stage = Stage::tess_control;
+      break;
+    case SpvExecutionModelTessellationEvaluation:
+      _stage = Stage::tess_evaluation;
+      break;
+    case SpvExecutionModelGeometry:
+      _stage = Stage::geometry;
+      break;
+    case SpvExecutionModelFragment:
+      _stage = Stage::fragment;
+      break;
+    default:
+      break;
+    }*/
+    break;
+
+  case SpvOpName:
+    defs[args[0]]._name = std::string((const char *)&args[1]);
+    break;
+
+  case SpvOpTypeVoid:
+    defs[args[0]].set_type(nullptr);
+    break;
+
+  case SpvOpTypeInt:
+    {
+      if (args[2]) {
+        defs[args[0]].set_type(ShaderType::int_type);
+      } else {
+        defs[args[0]].set_type(ShaderType::uint_type);
+      }
+    }
+    break;
+
+  case SpvOpTypeFloat:
+    {
+      defs[args[0]].set_type(ShaderType::float_type);
+    }
+    break;
+
+  case SpvOpTypeVector:
+    {
+      const ShaderType *component_type = defs[args[1]]._type;
+      uint32_t component_count = args[2];
+      defs[args[0]].set_type(ShaderType::register_type(
+        ShaderType::Vector(component_type, component_count)));
+    }
+    break;
+
+  case SpvOpTypeMatrix:
+    {
+      const ShaderType::Vector *column_type;
+      DCAST_INTO_R(column_type, defs[args[1]]._type, false);
+      uint32_t column_count = args[2];
+      //TODO: handle asymmetric matrices
+      defs[args[0]].set_type(ShaderType::register_type(
+        ShaderType::Matrix(column_type->get_base_type(), column_count, column_count)));
+    }
+    break;
+
+  case SpvOpTypePointer:
+    defs[args[0]].set_type_pointer((SpvStorageClass)args[1], defs[args[2]]._type);
+    break;
+
+  case SpvOpTypeImage:
+    {
+      Texture::TextureType texture_type;
+      switch ((SpvDim)args[2]) {
+      case SpvDim1D:
+        if (args[4]) {
+          texture_type = Texture::TT_1d_texture_array;
+        } else {
+          texture_type = Texture::TT_1d_texture;
+        }
+        break;
+
+      case SpvDim2D:
+        if (args[4]) {
+          texture_type = Texture::TT_2d_texture_array;
+        } else {
+          texture_type = Texture::TT_2d_texture;
+        }
+        break;
+
+      case SpvDim3D:
+        texture_type = Texture::TT_3d_texture;
+        break;
+
+      case SpvDimCube:
+        if (args[4]) {
+          texture_type = Texture::TT_cube_map_array;
+        } else {
+          texture_type = Texture::TT_cube_map;
+        }
+        break;
+      case SpvDimRect:
+        shader_cat.error()
+          << "imageRect shader inputs are not supported.\n";
+        return false;
+
+      case SpvDimBuffer:
+        texture_type = Texture::TT_buffer_texture;
+        break;
+
+      case SpvDimSubpassData:
+        shader_cat.error()
+          << "subpassInput shader inputs are not supported.\n";
+        return false;
+
+      default:
+        shader_cat.error()
+          << "Unknown image dimensionality in OpTypeImage instruction.\n";
+        return false;
+      }
+
+      ShaderType::Image::Access access = ShaderType::Image::Access::unknown;
+      if (nargs > 8) {
+        switch ((SpvAccessQualifier)args[8]) {
+        case SpvAccessQualifierReadOnly:
+          access = ShaderType::Image::Access::read_only;
+          break;
+        case SpvAccessQualifierWriteOnly:
+          access = ShaderType::Image::Access::write_only;
+          break;
+        case SpvAccessQualifierReadWrite:
+          access = ShaderType::Image::Access::read_write;
+          break;
+        default:
+          shader_cat.error()
+            << "Invalid access qualifier in OpTypeImage instruction.\n";
+          break;
+        }
+      }
+
+      defs[args[0]].set_type(ShaderType::register_type(
+        ShaderType::Image(texture_type, access)));
+    }
+    break;
+
+  case SpvOpTypeSampler:
+    // A sampler that's not bound to a particular image.
+    //defs[args[0]].set_type(SAT_sampler);
+    break;
+
+  case SpvOpTypeSampledImage:
+    if (const ShaderType::Image *image = defs[args[1]]._type->as_image()) {
+      defs[args[0]].set_type(ShaderType::register_type(
+        ShaderType::SampledImage(image->get_texture_type())));
+    } else {
+      shader_cat.error()
+        << "OpTypeSampledImage must refer to an image type!\n";
+      return false;
+    }
+    break;
+
+  case SpvOpVariable:
+    {
+      const Definition &ptr = defs[args[0]];
+      if (ptr._dtype != DT_type_pointer) {
+        shader_cat.error()
+          << "Variable with id " << args[1] << " should use pointer type\n";
+        return false;
+      }
+      defs[args[1]].set_variable(ptr._type, (SpvStorageClass)args[2]);
+    }
+    break;
+
+  case SpvOpDecorate:
+    switch ((SpvDecoration)args[1]) {
+    case SpvDecorationBuiltIn:
+      defs[args[0]]._builtin = (SpvBuiltIn)args[2];
+      break;
+
+    case SpvDecorationLocation:
+      defs[args[0]]._location = args[2];
+      break;
+    }
+    /*if (args[1] == SpvDecorationLocation || args[1] == SpvDecorationBinding) {
+      vars[args[0]]._location = args[2];
+    } else if (args[1] == SpvDecorationDescriptorSet) {
+      vars[args[0]]._set = args[2];
+    }*/
+    break;
+  }
+
+  return true;
+}
+
+/**
+ * Assigns location decorations to all input, output and uniform variables that
+ * do not have a location decoration yet.
+ */
+void ShaderModuleSpirV::
+assign_locations(Definitions &defs) {
+  // Determine which locations have already been assigned.
+  bool has_unassigned_locations = false;
+  BitArray input_locations;
+  BitArray output_locations;
+  BitArray uniform_locations;
+
+  for (const Definition &def : defs) {
+    if (def._dtype == DT_variable) {
+      if (def._location < 0) {
+        if (def._builtin == SpvBuiltInMax) {
+          // A non-built-in variable definition without a location.
+          has_unassigned_locations = true;
+        }
+      }
+      else if (def._storage_class == SpvStorageClassInput) {
+        input_locations.set_bit(def._location);
+      }
+      else if (def._storage_class == SpvStorageClassOutput) {
+        output_locations.set_bit(def._location);
+      }
+      else if (def._storage_class == SpvStorageClassUniformConstant) {
+        uniform_locations.set_bit(def._location);
+      }
+    }
+  }
+
+  if (!has_unassigned_locations) {
+    return;
+  }
+
+  // Find the end of the annotation block, so that we know where to insert the
+  // new locations.
+  size_t i = 5;
+  for (; i < _words.size();) {
+    uint16_t wcount = _words[i] >> SpvWordCountShift;
+    SpvOp opcode = (SpvOp)(_words[i] & SpvOpCodeMask);
+    nassertv(wcount > 0);
+
+    if (opcode != SpvOpCapability &&
+        opcode != SpvOpExtension &&
+        opcode != SpvOpExtInstImport &&
+        opcode != SpvOpMemoryModel &&
+        opcode != SpvOpEntryPoint &&
+        opcode != SpvOpExecutionMode &&
+        opcode != SpvOpString &&
+        opcode != SpvOpSourceExtension &&
+        opcode != SpvOpSource &&
+        opcode != SpvOpSourceContinued &&
+        opcode != SpvOpName &&
+        opcode != SpvOpMemberName &&
+        opcode != SpvOpModuleProcessed &&
+        opcode != SpvOpDecorate &&
+        opcode != SpvOpMemberDecorate &&
+        opcode != SpvOpGroupDecorate &&
+        opcode != SpvOpGroupMemberDecorate &&
+        opcode != SpvOpDecorationGroup) {
+      break;
+    }
+
+    i += wcount;
+  }
+
+  // Now insert decorations for every unassigned variable.
+  for (uint32_t id = 0; id < defs.size(); ++id) {
+    Definition &def = defs[id];
+    if (def._dtype == DT_variable &&
+        def._location < 0 &&
+        def._builtin == SpvBuiltInMax) {
+      int location;
+      if (def._storage_class == SpvStorageClassInput) {
+        if (get_stage() == Stage::vertex && !input_locations.get_bit(0)) {
+          if (def._name == "vertex" || def._name == "p3d_Vertex") {
+            // Prefer assigning the vertex column to location 0.
+            location = 0;
+          } else if (!input_locations.get_bit(1)) {
+            location = 1;
+          } else {
+            location = input_locations.get_next_higher_different_bit(1);
+          }
+        } else {
+          location = input_locations.get_lowest_off_bit();
+        }
+        input_locations.set_bit(location);
+
+        if (shader_cat.is_debug()) {
+          shader_cat.debug()
+            << "Assigning " << def._name << " to input location " << location << "\n";
+        }
+      }
+      else if (def._storage_class == SpvStorageClassOutput) {
+        location = output_locations.get_lowest_off_bit();
+        output_locations.set_bit(location);
+
+        if (shader_cat.is_debug()) {
+          shader_cat.debug()
+            << "Assigning " << def._name << " to output location " << location << "\n";
+        }
+      }
+      else if (def._storage_class == SpvStorageClassUniformConstant) {
+        location = uniform_locations.get_lowest_off_bit();
+        uniform_locations.set_bit(location);
+
+        if (shader_cat.is_debug()) {
+          shader_cat.debug()
+            << "Assigning " << def._name << " to uniform location " << location << "\n";
+        }
+      }
+      else {
+        continue;
+      }
+
+      def._location = location;
+      _words.insert(_words.begin() + i, {
+        (4 << SpvWordCountShift) | SpvOpDecorate,
+        id,
+        SpvDecorationLocation,
+        (uint32_t)location,
+      });
+      i += 4;
+    }
+  }
+}
+
+/**
+ * Changes the locations for all inputs of the given storage class based on the
+ * indicated map.  Note that this only works for inputs that already have an
+ * assigned location; assign_locations() may have to be called first to ensure
+ * that.
+ */
+void ShaderModuleSpirV::
+remap_locations(SpvStorageClass storage_class, const pmap<int, int> &locations) {
+  uint32_t *words = (uint32_t *)_words.data();
+  const size_t length = _words.size();
+  const uint32_t *end = words + length;
+
+  pmap<uint32_t, uint32_t *> decorations;
+
+  // Skip header
+  words += 5;
+
+  while (words < end) {
+    uint16_t wcount = words[0] >> SpvWordCountShift;
+    SpvOp opcode = (SpvOp)(words[0] & SpvOpCodeMask);
+    nassertv(wcount > 0);
+
+    if (opcode == SpvOpDecorate) {
+      // Store the location of this decoration in the bytecode.
+      if ((SpvDecoration)words[2] == SpvDecorationLocation && wcount >= 4) {
+        decorations[words[1]] = &words[3];
+      }
+    }
+    else if (opcode == SpvOpVariable && (SpvStorageClass)words[3] == storage_class) {
+      // Found a variable, did we store the location for its decoration?
+      pmap<uint32_t, uint32_t *>::const_iterator it = decorations.find(words[2]);
+      if (it != decorations.end()) {
+        // Yes, do we have a remapping for it?
+        pmap<int, int>::const_iterator it2 = locations.find((int)*(it->second));
+        if (it2 != locations.end()) {
+          // Yes, write the new location into the bytecode.
+          *(it->second) = (uint32_t)it2->second;
+        }
+      }
+    }
+
+    words += wcount;
+  }
+}
+
+/**
+ * Strips debugging information from the SPIR-V binary.
+ */
+void ShaderModuleSpirV::
+strip() {
+  pvector<uint32_t> old_words;
+  old_words.swap(_words);
+
+  const uint32_t *words = (const uint32_t *)old_words.data();
+  const size_t length = old_words.size();
+  const uint32_t *end = words + length;
+
+  // Copy header.
+  _words.insert(_words.end(), words, words + 5);
+  words += 5;
+
+  // Copy all non-debug instructions to the new vector.
+  while (words < end) {
+    uint16_t wcount = words[0] >> SpvWordCountShift;
+    SpvOp opcode = (SpvOp)(words[0] & SpvOpCodeMask);
+    nassertv(wcount > 0);
+
+    if (opcode != SpvOpSourceContinued &&
+        opcode != SpvOpSource &&
+        opcode != SpvOpSourceExtension &&
+        opcode != SpvOpName &&
+        opcode != SpvOpMemberName &&
+        opcode != SpvOpString &&
+        opcode != SpvOpLine &&
+        opcode != SpvOpNoLine &&
+        opcode != SpvOpModuleProcessed) {
+
+      _words.insert(_words.end(), words, words + wcount);
+    }
+    words += wcount;
+  }
+}
+
+/**
+ * Called when an OpType is encountered in the SPIR-V instruction stream.
+ */
+void ShaderModuleSpirV::Definition::
+set_type(const ShaderType *type) {
+  _dtype = DT_type;
+  _type = type;
+
+  if (shader_cat.is_spam()) {
+    if (type != nullptr) {
+      shader_cat.spam()
+        << "Defined type " << *type << "\n";
+    } else {
+      shader_cat.spam()
+        << "Defined type void\n";
+    }
+  }
+}
+
+/**
+ * Called when an OpTypePointer is encountered in the SPIR-V instruction stream.
+ */
+void ShaderModuleSpirV::Definition::
+set_type_pointer(SpvStorageClass storage_class, const ShaderType *type) {
+  _dtype = DT_type_pointer;
+  _type = type;
+}
+
+/**
+ * Called when an OpVariable is encountered in the SPIR-V instruction stream.
+ */
+void ShaderModuleSpirV::Definition::
+set_variable(const ShaderType *type, SpvStorageClass storage_class) {
+  _dtype = DT_variable;
+  _type = type;
+  _storage_class = storage_class;
+
+  if (shader_cat.is_debug()) {
+    shader_cat.debug()
+      << "Defined variable " << _name;
+
+    if (_location >= 0) {
+      shader_cat.debug(false) << " (location " << _location << ")";
+    }
+
+    shader_cat.debug(false) << " with ";
+
+    if (type != nullptr) {
+      shader_cat.debug(false) << "type " << *type << "\n";
+    } else {
+      shader_cat.debug(false) << "unknown type\n";
+    }
+  }
+
+  switch (storage_class) {
+  case SpvStorageClassUniformConstant:
+    //_uniform_constants.push_back(&def);
+    break;
+  case SpvStorageClassInput:
+    //_inputs.push_back(Varying({}));
+    break;
+  case SpvStorageClassUniform:
+    break;
+  case SpvStorageClassOutput:
+    //_outputs.push_back(&def);
+    break;
+  case SpvStorageClassWorkgroup:
+  case SpvStorageClassCrossWorkgroup:
+  case SpvStorageClassPrivate:
+  case SpvStorageClassFunction:
+  case SpvStorageClassGeneric:
+  case SpvStorageClassPushConstant:
+  case SpvStorageClassAtomicCounter:
+  case SpvStorageClassImage:
+    break;
+  }
+}

+ 107 - 0
panda/src/shaderpipeline/shaderModuleSpirV.h

@@ -0,0 +1,107 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file shaderModuleSpirV.h
+ * @author rdb
+ * @date 2019-07-15
+ */
+
+#ifndef SHADERMODULESPIRV_H
+#define SHADERMODULESPIRV_H
+
+#include "shader.h"
+#include "spirv.h"
+
+class ShaderType;
+
+/**
+ * ShaderModule that contains compiled SPIR-V bytecode.  This class can extract
+ * the parameter definitions from the bytecode, assign appropriate locations,
+ * link the module to a previous stage, and strip debug information as needed.
+ */
+class EXPCL_PANDA_SHADERPIPELINE ShaderModuleSpirV final : public ShaderModule {
+public:
+  ShaderModuleSpirV(Stage stage, const uint32_t *words, size_t size);
+  virtual ~ShaderModuleSpirV();
+
+  virtual PT(CopyOnWriteObject) make_cow_copy() override;
+
+  const uint32_t *get_data() const {
+    return &_words[0];
+  }
+  size_t get_data_size() const {
+    return _words.size();
+  }
+
+  virtual bool link_inputs(const ShaderModule *previous) override;
+  virtual void remap_parameter_locations(pmap<int, int> &remap) override;
+
+  virtual std::string get_ir() const override;
+
+protected:
+  pvector<uint32_t> _words;
+
+  enum DefinitionType {
+    DT_none,
+    DT_type,
+    DT_type_pointer,
+    DT_variable,
+  };
+
+  /**
+   * Temporary structure to hold a single definition, which could be a variable,
+   * type or type pointer in the SPIR-V file.
+   */
+  struct Definition {
+    DefinitionType _dtype = DT_none;
+    std::string _name;
+    const ShaderType *_type = nullptr;
+    int _location = -1;
+    SpvBuiltIn _builtin = SpvBuiltInMax;
+
+    // Only defined for DT_variable.
+    SpvStorageClass _storage_class;
+
+    void set_type(const ShaderType *type);
+    void set_type_pointer(SpvStorageClass storage_class, const ShaderType *type);
+    void set_variable(const ShaderType *type, SpvStorageClass storage_class);
+  };
+  typedef pvector<Definition> Definitions;
+
+private:
+  bool parse(Definitions &defs);
+  bool parse_instruction(Definitions &defs, SpvOp opcode,
+                         const uint32_t *args, size_t nargs);
+
+  void assign_locations(Definitions &defs);
+  void remap_locations(SpvStorageClass storage_class, const pmap<int, int> &locations);
+
+  void strip();
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    ShaderModule::init_type();
+    register_type(_type_handle, "ShaderModuleSpirV",
+                  ShaderModule::get_class_type());
+  }
+  virtual TypeHandle get_type() const override {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() override {
+    init_type();
+    return get_class_type();
+  }
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif