Browse Source

shaderpipeline: Do not map round() to roundEven() in Cg shaders

roundEven() is not supported in SM 3.0, and we do not need the tighter guarantee of roundEven() (which was never offered by Cg to begin with)

This is a workaround that can be removed if KhronosGroup/glslang#2451 gets merged
rdb 5 years ago
parent
commit
31f03ab788

+ 32 - 2
panda/src/shaderpipeline/shaderCompilerGlslang.cxx

@@ -304,8 +304,8 @@ compile_now(ShaderModule::Stage stage, std::istream &in,
     }
 
     shader_cat.warning()
-      << "Support for GLSL " << glsl_version << " is deprecated.  Some "
-         "features may not work.  Minimum supported version is GLSL 330.\n";
+      << filename << " uses deprecated GLSL version " << glsl_version
+      << ".  Some features may not work.  Minimum supported version is 330.\n";
 
     // Fall back to GlslPreProc handler.  Cleaner way to do this?
     static ShaderCompilerGlslPreProc preprocessor;
@@ -451,6 +451,10 @@ compile_now(ShaderModule::Stage stage, std::istream &in,
     return nullptr;
   }
 
+  if (is_cg && !postprocess_cg(stream)) {
+    return nullptr;
+  }
+
   // Run it through the optimizer.
   spvtools::Optimizer opt(SPV_ENV_UNIVERSAL_1_0);
   opt.SetMessageConsumer(log_message);
@@ -812,3 +816,29 @@ postprocess_glsl150(ShaderModuleSpirV::InstructionStream &stream) {
 
   return true;
 }
+
+/**
+ * Does any postprocessing needed for Cg.
+ */
+bool ShaderCompilerGlslang::
+postprocess_cg(ShaderModuleSpirV::InstructionStream &stream) {
+  pset<uint32_t> glsl_imports;
+
+  for (ShaderModuleSpirV::Instruction op : stream) {
+    if (op.opcode == spv::OpExtInstImport) {
+      if (strcmp((const char*)&op.args[1], "GLSL.std.450") == 0) {
+        glsl_imports.insert(op.args[0]);
+      }
+    }
+    else if (op.opcode == spv::OpExtInst) {
+      // glslang maps round() to roundEven(), which is correct for SM 4.0+ but
+      // not supported on pre-DX10 hardware, and Cg made no guarantee of
+      // round-to-even behavior to begin with, so we switch it back to round().
+      if (glsl_imports.count(op.args[2]) && op.args[3] == 2) {
+        op.args[3] = 1;
+      }
+    }
+  }
+
+  return true;
+}

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

@@ -40,6 +40,7 @@ private:
                               pset<Filename> &once_files,
                               BamCacheRecord *record = nullptr);
   static bool postprocess_glsl150(ShaderModuleSpirV::InstructionStream &stream);
+  static bool postprocess_cg(ShaderModuleSpirV::InstructionStream &stream);
 
 public:
   static TypeHandle get_class_type() {