|
|
@ -3375,6 +3375,12 @@ private:
|
|
|
|
EmitFragmentOutputsWrite();
|
|
|
|
EmitFragmentOutputsWrite();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
|
|
|
|
|
|
|
|
if (cc != Tegra::Shader::ControlCode::T) {
|
|
|
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "EXIT Control Code used: {}", static_cast<u32>(cc));
|
|
|
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch (instr.flow.cond) {
|
|
|
|
switch (instr.flow.cond) {
|
|
|
|
case Tegra::Shader::FlowCondition::Always:
|
|
|
|
case Tegra::Shader::FlowCondition::Always:
|
|
|
|
shader.AddLine("return true;");
|
|
|
|
shader.AddLine("return true;");
|
|
|
@ -3404,6 +3410,11 @@ private:
|
|
|
|
|
|
|
|
|
|
|
|
// Enclose "discard" in a conditional, so that GLSL compilation does not complain
|
|
|
|
// Enclose "discard" in a conditional, so that GLSL compilation does not complain
|
|
|
|
// about unexecuted instructions that may follow this.
|
|
|
|
// about unexecuted instructions that may follow this.
|
|
|
|
|
|
|
|
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
|
|
|
|
|
|
|
|
if (cc != Tegra::Shader::ControlCode::T) {
|
|
|
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "KIL Control Code used: {}", static_cast<u32>(cc));
|
|
|
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
}
|
|
|
|
shader.AddLine("if (true) {");
|
|
|
|
shader.AddLine("if (true) {");
|
|
|
|
++shader.scope;
|
|
|
|
++shader.scope;
|
|
|
|
shader.AddLine("discard;");
|
|
|
|
shader.AddLine("discard;");
|
|
|
@ -3461,6 +3472,11 @@ private:
|
|
|
|
case OpCode::Id::BRA: {
|
|
|
|
case OpCode::Id::BRA: {
|
|
|
|
ASSERT_MSG(instr.bra.constant_buffer == 0,
|
|
|
|
ASSERT_MSG(instr.bra.constant_buffer == 0,
|
|
|
|
"BRA with constant buffers are not implemented");
|
|
|
|
"BRA with constant buffers are not implemented");
|
|
|
|
|
|
|
|
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
|
|
|
|
|
|
|
|
if (cc != Tegra::Shader::ControlCode::T) {
|
|
|
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "BRA Control Code used: {}", static_cast<u32>(cc));
|
|
|
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
}
|
|
|
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
|
|
|
const u32 target = offset + instr.bra.GetBranchTarget();
|
|
|
|
shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
|
|
|
|
shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -3501,13 +3517,21 @@ private:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OpCode::Id::SYNC: {
|
|
|
|
case OpCode::Id::SYNC: {
|
|
|
|
// The SYNC opcode jumps to the address previously set by the SSY opcode
|
|
|
|
// The SYNC opcode jumps to the address previously set by the SSY opcode
|
|
|
|
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
|
|
|
|
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
|
|
|
|
|
|
|
|
if (cc != Tegra::Shader::ControlCode::T) {
|
|
|
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "SYNC Control Code used: {}", static_cast<u32>(cc));
|
|
|
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
}
|
|
|
|
EmitPopFromFlowStack();
|
|
|
|
EmitPopFromFlowStack();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case OpCode::Id::BRK: {
|
|
|
|
case OpCode::Id::BRK: {
|
|
|
|
// The BRK opcode jumps to the address previously set by the PBK opcode
|
|
|
|
// The BRK opcode jumps to the address previously set by the PBK opcode
|
|
|
|
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
|
|
|
|
const Tegra::Shader::ControlCode cc = instr.flow_control_code;
|
|
|
|
|
|
|
|
if (cc != Tegra::Shader::ControlCode::T) {
|
|
|
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "BRK Control Code used: {}", static_cast<u32>(cc));
|
|
|
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
}
|
|
|
|
EmitPopFromFlowStack();
|
|
|
|
EmitPopFromFlowStack();
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|