Fix assertion when using aux render targets in DX9

This commit is contained in:
rdb 2016-07-10 12:28:11 +02:00
parent f7fde882b8
commit fa7730819f
3 changed files with 69 additions and 2 deletions

View File

@ -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 ------------------------

View File

@ -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;
}
}

View File

@ -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;