Browse Source

Fix assertion when using aux render targets in DX9

rdb 9 years ago
parent
commit
fa7730819f
3 changed files with 69 additions and 2 deletions
  1. 2 0
      doc/ReleaseNotes
  2. 4 2
      panda/src/dxgsg9/wdxGraphicsBuffer9.cxx
  3. 63 0
      panda/src/gobj/shader.cxx

+ 2 - 0
doc/ReleaseNotes

@@ -21,6 +21,8 @@ This issue fixes several bugs that were still found in 1.9.2.
 * Fix cull issue when rendering cube map (or any multi-lens setup)
 * Fix crash rendering with the same camera to different contexts
 * Fix compile error when making static build with DX9 renderer
+* Fix assertion when using aux render targets in DX9
+* Work around Cg bug generating invalid ASM for saturated tex loads
 
 ------------------------  RELEASE 1.9.2  ------------------------
 

+ 4 - 2
panda/src/dxgsg9/wdxGraphicsBuffer9.cxx

@@ -329,16 +329,18 @@ rebuild_bitplanes() {
         case RTP_aux_float_3:
           {
             CDWriter cdataw(_cycler, cdata, false);
-            nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
             cdataw->_textures[i]._rtm_mode = RTM_none;
           }
+          // Creating the CDWriter invalidated the CDLockedReader.
+          cdata = CDLockedReader(_cycler);
           break;
         default:
           {
             CDWriter cdataw(_cycler, cdata, false);
-            nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
             cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
           }
+          // Creating the CDWriter invalidated the CDLockedReader.
+          cdata = CDLockedReader(_cycler);
           break;
         }
       }

+ 63 - 0
panda/src/gobj/shader.cxx

@@ -1620,6 +1620,69 @@ cg_compile_shader(const ShaderCaps &caps, CGcontext context) {
     return false;
   }
 
+  // This is present to work around a bug in the Cg compiler for Direct3D 9.
+  // It generates "texld_sat" instructions that the result in an
+  // D3DXERR_INVALIDDATA error when trying to load the shader, since the _sat
+  // modifier may not be used on tex* instructions.
+  if (_cg_fprofile == CG_PROFILE_PS_2_0 ||
+      _cg_fprofile == CG_PROFILE_PS_2_X ||
+      _cg_fprofile == CG_PROFILE_PS_3_0) {
+    vector_string lines;
+    tokenize(cgGetProgramString(_cg_fprogram, CG_COMPILED_PROGRAM), lines, "\n");
+
+    ostringstream out;
+    int num_modified = 0;
+
+    for (size_t i = 0; i < lines.size(); ++i) {
+      const string &line = lines[i];
+
+      size_t space = line.find(' ');
+      if (space == string::npos) {
+        out << line << '\n';
+        continue;
+      }
+
+      string instr = line.substr(0, space);
+
+      // Look for a texld instruction with _sat modifier.
+      if (instr.compare(0, 5, "texld") == 0 &&
+          instr.compare(instr.size() - 4, 4, "_sat") == 0) {
+        // Which destination register are we operating on?
+        string reg = line.substr(space + 1, line.find(',', space) - space - 1);
+
+        // Move the saturation operation to a separate instruction.
+        instr.resize(instr.size() - 4);
+        out << instr << ' ' << line.substr(space + 1) << '\n';
+        out << "mov_sat " << reg << ", " << reg << '\n';
+        ++num_modified;
+      } else {
+        out << line << '\n';
+      }
+    }
+
+    if (num_modified > 0) {
+      string result = out.str();
+      CGprogram new_program;
+      new_program = cgCreateProgram(context, CG_OBJECT, result.c_str(),
+                                    (CGprofile)_cg_fprofile, "fshader",
+                                    (const char**)NULL);
+      if (new_program) {
+        cgDestroyProgram(_cg_fprogram);
+        _cg_fprogram = new_program;
+
+        if (shader_cat.is_debug()) {
+          shader_cat.debug()
+            << "Replaced " << num_modified << " invalid texld_sat instruction"
+            << ((num_modified == 1) ? "" : "s") << " in compiled shader\n";
+        }
+      } else {
+        shader_cat.warning()
+          << "Failed to load shader with fixed texld_sat instructions: "
+          << cgGetErrorString(cgGetError()) << "\n";
+      }
+    }
+  }
+
   // DEBUG: output the generated program
   if (shader_cat.is_debug()) {
     const char *vertex_program;