فهرست منبع

shaderpipeline: Capability overhaul, support int attributes

Int attributes are waiting for an upstream SPIRV-Cross change to be merged before they work
rdb 2 سال پیش
والد
کامیت
45648ee137

+ 1 - 2
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -2363,8 +2363,7 @@ reset() {
     _supported_shader_caps = ShaderModule::C_basic_shader
                            | ShaderModule::C_vertex_texture
                            | ShaderModule::C_sampler_shadow
-                           | ShaderModule::C_matrix_non_square
-                           | ShaderModule::C_integer
+                           | ShaderModule::C_non_square_matrices
                            | ShaderModule::C_texture_lod;
 
     _supports_geometry_instancing = true;

+ 25 - 6
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1719,10 +1719,12 @@ reset() {
   if (is_at_least_gles_version(3, 0)) {
     _supported_shader_caps |=
       ShaderModule::C_sampler_shadow |
-      ShaderModule::C_matrix_non_square |
-      ShaderModule::C_integer |
+      ShaderModule::C_non_square_matrices |
+      ShaderModule::C_unsigned_int |
+      ShaderModule::C_flat_interpolation |
       ShaderModule::C_texture_lod |
       ShaderModule::C_texture_fetch |
+      ShaderModule::C_int_samplers |
       ShaderModule::C_sampler_cube_shadow |
       ShaderModule::C_vertex_id |
       ShaderModule::C_round_even |
@@ -1795,15 +1797,18 @@ reset() {
     if (_glsl_version >= 120) {
       _supported_shader_caps |=
         ShaderModule::C_invariant |
-        ShaderModule::C_matrix_non_square;
+        ShaderModule::C_non_square_matrices;
     }
 
     // OpenGL 3.0
     if (_glsl_version >= 130) {
       _supported_shader_caps |=
-        ShaderModule::C_integer |
+        ShaderModule::C_unsigned_int |
+        ShaderModule::C_flat_interpolation |
+        ShaderModule::C_noperspective_interpolation |
         ShaderModule::C_texture_lod |
         ShaderModule::C_texture_fetch |
+        ShaderModule::C_int_samplers |
         ShaderModule::C_sampler_cube_shadow |
         ShaderModule::C_vertex_id |
         ShaderModule::C_round_even;
@@ -1817,7 +1822,7 @@ reset() {
         // changed to be able to leverage these.  Most cards that have this
         // extension also support GLSL 1.30, so it might not be worth adding.
         _supported_shader_caps |=
-          //ShaderModule::C_integer |
+          //ShaderModule::C_unsigned_int |
           ShaderModule::C_texture_fetch |
           //ShaderModule::C_sampler_cube_shadow |
           ShaderModule::C_round_even;
@@ -2039,11 +2044,25 @@ reset() {
     _glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)
        get_extension_func("glVertexAttribPointer");
 
-    if (is_at_least_gl_version(2, 1)) {
+    // NVIDIA drivers will (for pview.exe specifically) report only OpenGL 1.2
+    // but also GLSL 120.  But it's not possible to fully support GLSL 120
+    // without the ability to pass non-square matrices, so we assume that these
+    // function pointers do exist, and issue a warning otherwise.
+    if (_glsl_version >= 120 || is_at_least_gl_version(2, 1)) {
       _glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)
          get_extension_func("glUniformMatrix3x4fv");
       _glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)
          get_extension_func("glUniformMatrix4x3fv");
+
+      if (_glUniformMatrix3x4fv == nullptr || _glUniformMatrix4x3fv == nullptr) {
+        _supported_shader_caps &= ~ShaderModule::C_non_square_matrices;
+        GLCAT.warning()
+          << "GLSL 1.20 advertised as supported by OpenGL runtime, but could "
+             "not get pointers to functions to set non-square matrices.\n";
+      }
+    } else {
+      _glUniformMatrix3x4fv = nullptr;
+      _glUniformMatrix4x3fv = nullptr;
     }
 
     if (is_at_least_gl_version(3, 0)) {

+ 12 - 4
panda/src/glstuff/glShaderContext_src.cxx

@@ -2805,14 +2805,18 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
             // It requires us to pass GL_TRUE for normalized.
             _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
                                            GL_TRUE, stride, client_pointer);
-          } else if (bind._scalar_type == ShaderType::ST_float ||
-                     numeric_type == GeomEnums::NT_float32) {
+          }
+          else if (_emulate_float_attribs ||
+                   bind._scalar_type == ShaderType::ST_float ||
+                   numeric_type == GeomEnums::NT_float32) {
             _glgsg->_glVertexAttribPointer(p, num_values, type,
                                            normalized, stride, client_pointer);
-          } else if (bind._scalar_type == ShaderType::ST_double) {
+          }
+          else if (bind._scalar_type == ShaderType::ST_double) {
             _glgsg->_glVertexAttribLPointer(p, num_values, type,
                                             stride, client_pointer);
-          } else {
+          }
+          else {
             _glgsg->_glVertexAttribIPointer(p, num_values, type,
                                             stride, client_pointer);
           }
@@ -3571,6 +3575,10 @@ attach_shader(const ShaderModule *module, Shader::ModuleSpecConstants &consts) {
       options.enable_420pack_extension = false;
       compiler.set_common_options(options);
 
+      if (options.version < 130) {
+        _emulate_float_attribs = true;
+      }
+
       // At this time, SPIRV-Cross doesn't add this extension automatically.
       if (!options.es && options.version < 140 &&
           (module->get_used_capabilities() & ShaderModule::C_instance_id) != 0) {

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

@@ -85,6 +85,7 @@ private:
   bool _needs_reflection = false;
   bool _needs_query_uniform_locations = false;
   bool _remap_uniform_locations = false;
+  bool _emulate_float_attribs = false;
 
   WCPT(RenderState) _state_rs;
   CPT(TransformState) _modelview_transform;

+ 13 - 4
panda/src/gobj/shaderModule.cxx

@@ -137,11 +137,17 @@ output_capabilities(std::ostream &out, int caps) {
   if (caps & C_invariant) {
     out << "invariant ";
   }
-  if (caps & C_matrix_non_square) {
-    out << "matrix_non_square ";
+  if (caps & C_non_square_matrices) {
+    out << "non_square_matrices ";
   }
-  if (caps & C_integer) {
-    out << "integer ";
+  if (caps & C_unsigned_int) {
+    out << "unsigned_int ";
+  }
+  if (caps & C_flat_interpolation) {
+    out << "flat_interpolation ";
+  }
+  if (caps & C_noperspective_interpolation) {
+    out << "noperspective_interpolation ";
   }
   if (caps & C_texture_lod) {
     out << "texture_lod ";
@@ -149,6 +155,9 @@ output_capabilities(std::ostream &out, int caps) {
   if (caps & C_texture_fetch) {
     out << "texture_fetch ";
   }
+  if (caps & C_int_samplers) {
+    out << "int_samplers ";
+  }
   if (caps & C_sampler_cube_shadow) {
     out << "sampler_cube_shadow ";
   }

+ 33 - 29
panda/src/gobj/shaderModule.h

@@ -112,55 +112,59 @@ public:
    * transformation steps may need to be applied.
    */
   enum Capabilities : uint64_t {
-    C_basic_shader = 1 << 0,
-    C_vertex_texture = 1 << 1,
-    C_sampler_shadow = 1 << 2, // 1D and 2D only
+    C_basic_shader = 1ull << 0,
+    C_vertex_texture = 1ull << 1,
+    C_sampler_shadow = 1ull << 2, // 1D and 2D only
+    C_point_sprites = 1ull << 3,
 
     // GLSL 1.20
-    C_invariant = 1 << 3,
-    C_matrix_non_square = 1 << 4,
+    C_invariant = 1ull << 4,
+    C_non_square_matrices = 1ull << 5,
 
     // GLSL 1.30
-    C_integer = 1 << 5,
-    C_texture_lod = 1 << 6, // textureLod in vshader doesn't count, textureGrad does
-    C_texture_fetch = 1 << 7, // texelFetch, textureSize, etc.
-    C_sampler_cube_shadow = 1 << 8,
-    C_vertex_id = 1 << 9,
-    C_round_even = 1 << 10, // roundEven function, also in SM 4.0
+    C_unsigned_int = 1ull << 6,
+    C_flat_interpolation = 1ull << 7, // also necessary for int varyings
+    C_noperspective_interpolation = 1ull << 8, // not supported in GLES
+    C_texture_lod = 1ull << 9, // textureLod in vshader doesn't count, textureGrad does
+    C_texture_fetch = 1ull << 10, // texelFetch, textureSize, etc.
+    C_int_samplers = 1ull << 11, // usampler2D, isampler2D, etc.
+    C_sampler_cube_shadow = 1ull << 12,
+    C_vertex_id = 1ull << 13,
+    C_round_even = 1ull << 14, // roundEven function, also in SM 4.0
 
     // GLSL 1.40 / SM 4.0
-    C_instance_id = 1 << 11,
-    C_buffer_texture = 1 << 12, // ES 3.20
+    C_instance_id = 1ull << 15,
+    C_buffer_texture = 1ull << 16, // ES 3.20
 
     // GLSL 1.50 / SM 4.0
-    C_geometry_shader = 1 << 13,
-    C_primitive_id = 1 << 14,
+    C_geometry_shader = 1ull << 17,
+    C_primitive_id = 1ull << 18,
 
     // GLSL 3.30 / ES 3.00 / SM 4.0
-    C_bit_encoding = 1 << 15,
+    C_bit_encoding = 1ull << 19,
 
     // GLSL 4.00 / ES 3.20 / SM 5.0
-    C_texture_gather = 1 << 16,
-    C_double = 1 << 17,
-    C_cube_map_array = 1 << 18,
-    C_tessellation_shader = 1 << 19,
-    C_sample_variables = 1 << 20,
-    C_extended_arithmetic = 1 << 21,
-    C_texture_query_lod = 1 << 22, // not in ES
+    C_texture_gather = 1ull << 20,
+    C_double = 1ull << 21,
+    C_cube_map_array = 1ull << 22,
+    C_tessellation_shader = 1ull << 23,
+    C_sample_variables = 1ull << 24,
+    C_extended_arithmetic = 1ull << 25,
+    C_texture_query_lod = 1ull << 26, // not in ES
 
     // GLSL 4.20 / ES 3.10 / SM 5.0
-    C_image_load_store = 1 << 23,
+    C_image_load_store = 1ull << 27,
 
     // GLSL 4.30 / ES 3.10 / SM 5.0
-    C_compute_shader = 1 << 24,
-    C_texture_query_levels = 1 << 25, // not in ES
+    C_compute_shader = 1ull << 28,
+    C_texture_query_levels = 1ull << 29, // not in ES
 
     // GLSL 4.40 / ARB_enhanced_layouts
-    C_enhanced_layouts = 1 << 26,
+    C_enhanced_layouts = 1ull << 30,
 
     // GLSL 4.50
-    C_derivative_control = 1 << 27,
-    C_texture_query_samples = 1 << 28,
+    C_derivative_control = 1ull << 31,
+    C_texture_query_samples = 1ull << 32,
   };
 
   static std::string format_stage(Stage stage);

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

@@ -791,6 +791,14 @@ compare_to_impl(const ShaderType &other) const {
        - (_access < other_image._access);
 }
 
+/**
+ * Returns true if this type contains the given scalar type.
+ */
+bool ShaderType::Image::
+contains_scalar_type(ScalarType type) const {
+  return _sampled_type == type;
+}
+
 /**
  * Writes the contents of this object to the datagram for shipping out to a
  * Bam file.
@@ -884,6 +892,14 @@ compare_to_impl(const ShaderType &other) const {
        - (_shadow < other_sampled_image._shadow);
 }
 
+/**
+ * Returns true if this type contains the given scalar type.
+ */
+bool ShaderType::SampledImage::
+contains_scalar_type(ScalarType type) const {
+  return _sampled_type == type;
+}
+
 /**
  * Writes the contents of this object to the datagram for shipping out to a
  * Bam file.

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

@@ -386,6 +386,8 @@ public:
   virtual void output(std::ostream &out) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
 
+  virtual bool contains_scalar_type(ScalarType type) const override;
+
   const Image *as_image() const override { return this; }
 
 PUBLISHED:
@@ -462,6 +464,8 @@ public:
   virtual void output(std::ostream &out) const override;
   virtual int compare_to_impl(const ShaderType &other) const override;
 
+  virtual bool contains_scalar_type(ScalarType type) const override;
+
   const SampledImage *as_sampled_image() const override { return this; }
 
 private:

+ 25 - 8
panda/src/shaderpipeline/shaderModuleSpirV.cxx

@@ -90,6 +90,20 @@ ShaderModuleSpirV(Stage stage, std::vector<uint32_t> words, BamCacheRecord *reco
       }
       break;
 
+    case spv::OpConvertFToU:
+    case spv::OpConvertUToF:
+    case spv::OpUConvert:
+    case spv::OpUDiv:
+    case spv::OpUMod:
+    case spv::OpUMulExtended:
+    case spv::OpUGreaterThan:
+    case spv::OpUGreaterThanEqual:
+    case spv::OpULessThan:
+    case spv::OpULessThanEqual:
+    case spv::OpShiftRightLogical:
+      _used_caps |= C_unsigned_int;
+      break;
+
     default:
       break;
     }
@@ -140,14 +154,14 @@ ShaderModuleSpirV(Stage stage, std::vector<uint32_t> words, BamCacheRecord *reco
         _outputs.push_back(std::move(var));
       }
       else if (def._storage_class == spv::StorageClassUniformConstant) {
-        if (def._flags & DF_dref_sampled) {
+        const ShaderType::SampledImage *sampled_image_type =
+          def._type->as_sampled_image();
+        if (sampled_image_type != nullptr) {
           // Image variable sampled with depth ref.  Make sure this is actually
           // a shadow sampler; this isn't always done by the compiler, and the
           // spec isn't clear that this is necessary, but it helps spirv-cross
           // properly generate shadow samplers.
-          const ShaderType::SampledImage *sampled_image_type =
-            def._type->as_sampled_image();
-          if (sampled_image_type != nullptr && !sampled_image_type->is_shadow()) {
+          if ((def._flags & DF_dref_sampled) != 0 && !sampled_image_type->is_shadow()) {
             // No, change the type of this variable.
             var.type = ShaderType::register_type(ShaderType::SampledImage(
               sampled_image_type->get_texture_type(),
@@ -156,13 +170,16 @@ ShaderModuleSpirV(Stage stage, std::vector<uint32_t> words, BamCacheRecord *reco
 
             writer.set_variable_type(id, var.type);
           }
+          if (sampled_image_type->get_sampled_type() == ShaderType::ST_uint ||
+              sampled_image_type->get_sampled_type() == ShaderType::ST_int) {
+            _used_caps |= C_int_samplers;
+          }
         }
         _parameters.push_back(std::move(var));
       }
 
-      if (def._type->contains_scalar_type(ShaderType::ST_int) ||
-          def._type->contains_scalar_type(ShaderType::ST_uint)) {
-        _used_caps |= C_integer;
+      if (def._type->contains_scalar_type(ShaderType::ST_uint)) {
+        _used_caps |= C_unsigned_int;
       }
     }
     else if (def._dtype == DT_variable && def.is_used() &&
@@ -194,7 +211,7 @@ ShaderModuleSpirV(Stage stage, std::vector<uint32_t> words, BamCacheRecord *reco
     else if (def._dtype == DT_type && def._type != nullptr) {
       if (const ShaderType::Matrix *matrix_type = def._type->as_matrix()) {
         if (matrix_type->get_num_rows() != matrix_type->get_num_columns()) {
-          _used_caps |= C_matrix_non_square;
+          _used_caps |= C_non_square_matrices;
         }
       }
     }