Bladeren bron

glgsg: Fix error when driver optimizes out input in SPIR-V shader

rdb 5 jaren geleden
bovenliggende
commit
8c0f119047

+ 14 - 0
panda/src/gles2gsg/gles2gsg.h

@@ -242,6 +242,20 @@ typedef char GLchar;
 #define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
 #define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
 #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
 #define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
 #define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
 #define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
 
 
 #undef SUPPORT_IMMEDIATE_MODE
 #undef SUPPORT_IMMEDIATE_MODE
 #define APIENTRY
 #define APIENTRY

+ 26 - 8
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1850,10 +1850,34 @@ reset() {
   }
   }
 #endif
 #endif
 
 
+#ifndef OPENGLES_1
+  _supports_program_interface_query = false;
+
+  if (is_at_least_gl_version(4, 3) || is_at_least_gles_version(3, 1)
+#ifndef OPENGLES
+      || has_extension("GL_ARB_program_interface_query")
+#endif
+      ) {
+
+    _glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)
+       get_extension_func("glGetProgramInterfaceiv");
+    _glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)
+       get_extension_func("glGetProgramResourceName");
+    _glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)
+       get_extension_func("glGetProgramResourceiv");
+
+    if (_glGetProgramInterfaceiv != nullptr &&
+        _glGetProgramResourceName != nullptr &&
+        _glGetProgramResourceiv != nullptr) {
+      _supports_program_interface_query = true;
+    }
+  }
+#endif
+
   // Check for SPIR-V support.
   // Check for SPIR-V support.
 #ifndef OPENGLES
 #ifndef OPENGLES
   _supports_spir_v = false;
   _supports_spir_v = false;
-  if (has_extension("GL_ARB_gl_spirv")) {
+  if (_supports_program_interface_query && has_extension("GL_ARB_gl_spirv")) {
     _glShaderBinary = (PFNGLSHADERBINARYPROC)
     _glShaderBinary = (PFNGLSHADERBINARYPROC)
       get_extension_func("glShaderBinary");
       get_extension_func("glShaderBinary");
     _glSpecializeShader = (PFNGLSPECIALIZESHADERARBPROC)
     _glSpecializeShader = (PFNGLSPECIALIZESHADERARBPROC)
@@ -2125,13 +2149,7 @@ reset() {
 #ifndef OPENGLES
 #ifndef OPENGLES
   // Check for SSBOs.
   // Check for SSBOs.
   if (is_at_least_gl_version(4, 3) || has_extension("ARB_shader_storage_buffer_object")) {
   if (is_at_least_gl_version(4, 3) || has_extension("ARB_shader_storage_buffer_object")) {
-    _supports_shader_buffers = true;
-    _glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC)
-       get_extension_func("glGetProgramInterfaceiv");
-    _glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC)
-       get_extension_func("glGetProgramResourceName");
-    _glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC)
-       get_extension_func("glGetProgramResourceiv");
+    _supports_shader_buffers = _supports_program_interface_query;
   } else
   } else
 #endif
 #endif
   {
   {

+ 12 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -213,6 +213,12 @@ typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
 typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
 typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
 typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+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 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 PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
 typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
 typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
 typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
 typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
 typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
@@ -1055,10 +1061,15 @@ public:
   PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
   PFNGLMAKETEXTUREHANDLENONRESIDENTPROC _glMakeTextureHandleNonResident;
   PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
   PFNGLUNIFORMHANDLEUI64PROC _glUniformHandleui64;
   PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
   PFNGLUNIFORMHANDLEUI64VPROC _glUniformHandleui64v;
+#endif  // !OPENGLES
+
+#ifndef OPENGLES_1
   PFNGLGETPROGRAMINTERFACEIVPROC _glGetProgramInterfaceiv;
   PFNGLGETPROGRAMINTERFACEIVPROC _glGetProgramInterfaceiv;
   PFNGLGETPROGRAMRESOURCENAMEPROC _glGetProgramResourceName;
   PFNGLGETPROGRAMRESOURCENAMEPROC _glGetProgramResourceName;
   PFNGLGETPROGRAMRESOURCEIVPROC _glGetProgramResourceiv;
   PFNGLGETPROGRAMRESOURCEIVPROC _glGetProgramResourceiv;
-#endif  // !OPENGLES
+
+  bool _supports_program_interface_query;
+#endif
 
 
   GLenum _edge_clamp;
   GLenum _edge_clamp;
   GLenum _border_clamp;
   GLenum _border_clamp;

+ 73 - 21
panda/src/glstuff/glShaderContext_src.cxx

@@ -74,6 +74,22 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
         query_uniform_locations(module._module);
         query_uniform_locations(module._module);
       }
       }
     }
     }
+    else {
+      // We still need to query which uniform locations are actually in use,
+      // because the GL driver may have optimized some out.
+      GLint num_active_uniforms = 0;
+      glgsg->_glGetProgramInterfaceiv(_glsl_program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &num_active_uniforms);
+
+      for (GLint i = 0; i < num_active_uniforms; ++i) {
+        GLenum prop = GL_LOCATION;
+        GLint location;
+        glgsg->_glGetProgramResourceiv(_glsl_program, GL_UNIFORM, i, 1, &prop, 1, nullptr, &location);
+        if (location >= 0) {
+          set_uniform_location(location, location);
+        }
+      }
+      _remap_uniform_locations = true;
+    }
 
 
     // Rebind the texture and image inputs.
     // Rebind the texture and image inputs.
     size_t num_textures = s->_tex_spec.size();
     size_t num_textures = s->_tex_spec.size();
@@ -84,11 +100,21 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
       GLint location = get_uniform_location(spec._id._location);
       GLint location = get_uniform_location(spec._id._location);
       if (location < 0) {
       if (location < 0) {
         // Not used.  Optimize it out.
         // Not used.  Optimize it out.
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Uniform " << *spec._id._name << " is unused, unbinding\n";
+        }
         s->_tex_spec.erase(s->_tex_spec.begin() + i);
         s->_tex_spec.erase(s->_tex_spec.begin() + i);
         --num_textures;
         --num_textures;
         continue;
         continue;
       }
       }
 
 
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Uniform " << *spec._id._name << " is bound to location "
+          << location << " (texture binding " << i << ")\n";
+      }
+
       _glgsg->_glUniform1i(location, (int)i);
       _glgsg->_glUniform1i(location, (int)i);
       ++i;
       ++i;
     }
     }
@@ -98,19 +124,24 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
       Shader::ShaderImgSpec &spec = s->_img_spec[i];
       Shader::ShaderImgSpec &spec = s->_img_spec[i];
       nassertd(spec._id._location >= 0) continue;
       nassertd(spec._id._location >= 0) continue;
 
 
-      if (GLCAT.is_debug()) {
-        GLCAT.debug()
-          << "Active uniform " << spec._id._name << " is bound to location " << spec._id._location << " (image binding " << i << ")\n";
-      }
-
       GLint location = get_uniform_location(spec._id._location);
       GLint location = get_uniform_location(spec._id._location);
       if (location < 0) {
       if (location < 0) {
         // Not used.  Optimize it out.
         // Not used.  Optimize it out.
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Uniform " << *spec._id._name << " is unused, unbinding\n";
+        }
         s->_img_spec.erase(s->_img_spec.begin() + i);
         s->_img_spec.erase(s->_img_spec.begin() + i);
         --num_images;
         --num_images;
         continue;
         continue;
       }
       }
 
 
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Uniform " << *spec._id._name << " is bound to location "
+          << location << " (image binding " << i << ")\n";
+      }
+
       ImageInput input = {spec._name, nullptr, spec._writable};
       ImageInput input = {spec._name, nullptr, spec._writable};
       _glsl_img_inputs.push_back(std::move(input));
       _glsl_img_inputs.push_back(std::move(input));
 
 
@@ -118,26 +149,48 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
       ++i;
       ++i;
     }
     }
 
 
-    if (_remap_uniform_locations) {
-      for (auto it = s->_mat_spec.begin(); it != s->_mat_spec.end();) {
-        const Shader::ShaderMatSpec &spec = *it;
-        if (get_uniform_location(spec._id._location) < 0) {
-          // Not used.  Optimize it out.
-          it = s->_mat_spec.erase(it);
-          continue;
+    for (auto it = s->_mat_spec.begin(); it != s->_mat_spec.end();) {
+      const Shader::ShaderMatSpec &spec = *it;
+
+      GLint location = get_uniform_location(spec._id._location);
+      if (location < 0) {
+        // Not used.  Optimize it out.
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Uniform " << *spec._id._name << " is unused, unbinding\n";
         }
         }
-        ++it;
+        it = s->_mat_spec.erase(it);
+        continue;
       }
       }
 
 
-      for (auto it = s->_ptr_spec.begin(); it != s->_ptr_spec.end();) {
-        const Shader::ShaderPtrSpec &spec = *it;
-        if (get_uniform_location(spec._id._location) < 0) {
-          // Not used.  Optimize it out.
-          it = s->_ptr_spec.erase(it);
-          continue;
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Uniform " << *spec._id._name << " is bound to location "
+          << location << "\n";
+      }
+      ++it;
+    }
+
+    for (auto it = s->_ptr_spec.begin(); it != s->_ptr_spec.end();) {
+      const Shader::ShaderPtrSpec &spec = *it;
+
+      GLint location = get_uniform_location(spec._id._location);
+      if (location < 0) {
+        // Not used.  Optimize it out.
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Uniform " << *spec._id._name << " is unused, unbinding\n";
         }
         }
-        ++it;
+        it = s->_ptr_spec.erase(it);
+        continue;
       }
       }
+
+      if (GLCAT.is_debug()) {
+        GLCAT.debug()
+          << "Uniform " << *spec._id._name << " is bound to location "
+          << location << "\n";
+      }
+      ++it;
     }
     }
 
 
     if (s->_frame_number_loc >= 0) {
     if (s->_frame_number_loc >= 0) {
@@ -3282,7 +3335,6 @@ attach_shader(const ShaderModule *module) {
       const char *text_str = text.c_str();
       const char *text_str = text.c_str();
       _glgsg->_glShaderSource(handle, 1, &text_str, nullptr);
       _glgsg->_glShaderSource(handle, 1, &text_str, nullptr);
       needs_compile = true;
       needs_compile = true;
-      _remap_uniform_locations = true;
     }
     }
   } else
   } else
 #endif
 #endif