浏览代码

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 年之前
父节点
当前提交
31f03ab788
共有 2 个文件被更改,包括 33 次插入2 次删除
  1. 32 2
      panda/src/shaderpipeline/shaderCompilerGlslang.cxx
  2. 1 0
      panda/src/shaderpipeline/shaderCompilerGlslang.h

+ 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() {