1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxbc] oDepth no longer treated as standard output register

Fixes a crash in the shader compiler when starting up Tomb Raider.
This commit is contained in:
Philip Rebohle 2017-12-19 12:58:40 +01:00
parent f97ea7fcea
commit 64a74735f8

View File

@ -207,81 +207,92 @@ namespace dxvk {
void DxbcCompiler::emitDclInterfaceReg(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclInterfaceReg(const DxbcShaderInstruction& ins) {
// dcl_input and dcl_output instructions switch (ins.dst[0].type) {
// have the following operands: case DxbcOperandType::Input:
// (dst0) The register to declare case DxbcOperandType::Output: {
// (imm0) The system value (optional) // dcl_input and dcl_output instructions
uint32_t regDim = 0; // have the following operands:
uint32_t regIdx = 0; // (dst0) The register to declare
// (imm0) The system value (optional)
uint32_t regDim = 0;
uint32_t regIdx = 0;
// In the vertex and fragment shader stage, the // In the vertex and fragment shader stage, the
// operand indices will have the following format: // operand indices will have the following format:
// (0) Register index // (0) Register index
// //
// In other stages, the input and output registers // In other stages, the input and output registers
// may be declared as arrays of a fixed size: // may be declared as arrays of a fixed size:
// (0) Array length // (0) Array length
// (1) Register index // (1) Register index
if (ins.dst[0].idxDim == 2) { if (ins.dst[0].idxDim == 2) {
regDim = ins.dst[0].idx[0].offset; regDim = ins.dst[0].idx[0].offset;
regIdx = ins.dst[0].idx[1].offset; regIdx = ins.dst[0].idx[1].offset;
} else if (ins.dst[0].idxDim == 1) { } else if (ins.dst[0].idxDim == 1) {
regIdx = ins.dst[0].idx[0].offset; regIdx = ins.dst[0].idx[0].offset;
} else { } else {
Logger::err(str::format( Logger::err(str::format(
"DxbcCompiler: ", ins.op, "DxbcCompiler: ", ins.op,
": Invalid index dimension")); ": Invalid index dimension"));
return; return;
} }
// This declaration may map an output register to a system // This declaration may map an output register to a system
// value. If that is the case, the system value type will // value. If that is the case, the system value type will
// be stored in the second operand. // be stored in the second operand.
const bool hasSv = const bool hasSv =
ins.op == DxbcOpcode::DclInputSgv ins.op == DxbcOpcode::DclInputSgv
|| ins.op == DxbcOpcode::DclInputSiv || ins.op == DxbcOpcode::DclInputSiv
|| ins.op == DxbcOpcode::DclInputPsSgv || ins.op == DxbcOpcode::DclInputPsSgv
|| ins.op == DxbcOpcode::DclInputPsSiv || ins.op == DxbcOpcode::DclInputPsSiv
|| ins.op == DxbcOpcode::DclOutputSgv || ins.op == DxbcOpcode::DclOutputSgv
|| ins.op == DxbcOpcode::DclOutputSiv; || ins.op == DxbcOpcode::DclOutputSiv;
DxbcSystemValue sv = DxbcSystemValue::None; DxbcSystemValue sv = DxbcSystemValue::None;
if (hasSv) if (hasSv)
sv = static_cast<DxbcSystemValue>(ins.imm[0].u32); sv = static_cast<DxbcSystemValue>(ins.imm[0].u32);
// In the pixel shader, inputs are declared with an // In the pixel shader, inputs are declared with an
// interpolation mode that is part of the op token. // interpolation mode that is part of the op token.
const bool hasInterpolationMode = const bool hasInterpolationMode =
ins.op == DxbcOpcode::DclInputPs ins.op == DxbcOpcode::DclInputPs
|| ins.op == DxbcOpcode::DclInputPsSiv; || ins.op == DxbcOpcode::DclInputPsSiv;
DxbcInterpolationMode im = DxbcInterpolationMode::Undefined; DxbcInterpolationMode im = DxbcInterpolationMode::Undefined;
if (hasInterpolationMode) if (hasInterpolationMode)
im = ins.controls.interpolation; im = ins.controls.interpolation;
// Declare the actual input/output variable // Declare the actual input/output variable
switch (ins.op) { switch (ins.op) {
case DxbcOpcode::DclInput: case DxbcOpcode::DclInput:
case DxbcOpcode::DclInputSgv: case DxbcOpcode::DclInputSgv:
case DxbcOpcode::DclInputSiv: case DxbcOpcode::DclInputSiv:
case DxbcOpcode::DclInputPs: case DxbcOpcode::DclInputPs:
case DxbcOpcode::DclInputPsSgv: case DxbcOpcode::DclInputPsSgv:
case DxbcOpcode::DclInputPsSiv: case DxbcOpcode::DclInputPsSiv:
this->emitDclInput(regIdx, regDim, ins.dst[0].mask, sv, im); this->emitDclInput(regIdx, regDim, ins.dst[0].mask, sv, im);
break; break;
case DxbcOpcode::DclOutput: case DxbcOpcode::DclOutput:
case DxbcOpcode::DclOutputSgv: case DxbcOpcode::DclOutputSgv:
case DxbcOpcode::DclOutputSiv: case DxbcOpcode::DclOutputSiv:
this->emitDclOutput(regIdx, regDim, ins.dst[0].mask, sv, im); this->emitDclOutput(regIdx, regDim, ins.dst[0].mask, sv, im);
break; break;
default:
Logger::err(str::format(
"DxbcCompiler: Unexpected opcode: ",
ins.op));
}
} break;
default: default:
Logger::err(str::format( Logger::err(str::format(
"DxbcCompiler: Unexpected opcode: ", "DxbcCompiler: Unsupported operand type declaration: ",
ins.op)); ins.dst[0].type));
} }
} }
@ -1958,7 +1969,8 @@ namespace dxvk {
// documentation, they are required to match the type of // documentation, they are required to match the type of
// the render target. // the render target.
for (auto e = m_osgn->begin(); e != m_osgn->end(); e++) { for (auto e = m_osgn->begin(); e != m_osgn->end(); e++) {
if (e->systemValue == DxbcSystemValue::None) { if (e->systemValue == DxbcSystemValue::None
&& e->registerId != 0xFFFFFFFF /* depth */) {
DxbcRegisterInfo info; DxbcRegisterInfo info;
info.type.ctype = e->componentType; info.type.ctype = e->componentType;
info.type.ccount = e->componentMask.setCount(); info.type.ccount = e->componentMask.setCount();