Shaders: Implemented the FMNMX shader instruction.

This commit is contained in:
Subv 2018-05-20 17:53:06 -05:00
parent 1b5c02fc37
commit 8440cef223
2 changed files with 26 additions and 6 deletions

View File

@ -193,6 +193,11 @@ union Instruction {
BitField<50, 1, u64> abs_d; BitField<50, 1, u64> abs_d;
BitField<56, 1, u64> negate_imm; BitField<56, 1, u64> negate_imm;
union {
BitField<39, 3, u64> pred;
BitField<42, 1, u64> negate_pred;
} fmnmx;
float GetImm20_19() const { float GetImm20_19() const {
float result{}; float result{};
u32 imm{static_cast<u32>(imm20_19)}; u32 imm{static_cast<u32>(imm20_19)};

View File

@ -580,14 +580,17 @@ private:
* @param instr Instruction to generate the if condition for. * @param instr Instruction to generate the if condition for.
* @returns string containing the predicate condition. * @returns string containing the predicate condition.
*/ */
std::string GetPredicateCondition(Instruction instr) const { std::string GetPredicateCondition(u64 index, bool negate) const {
using Tegra::Shader::Pred; using Tegra::Shader::Pred;
ASSERT(instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)); std::string variable;
std::string variable = // Index 7 is used as an 'Always True' condition.
'p' + std::to_string(static_cast<u64>(instr.pred.pred_index.Value())); if (index == static_cast<u64>(Pred::UnusedIndex))
variable = "true";
else
variable = 'p' + std::to_string(index);
if (instr.negate_pred) { if (negate) {
return "!(" + variable + ')'; return "!(" + variable + ')';
} }
@ -634,7 +637,9 @@ private:
"NeverExecute predicate not implemented"); "NeverExecute predicate not implemented");
if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) { if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
shader.AddLine("if (" + GetPredicateCondition(instr) + ')'); shader.AddLine("if (" +
GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) +
')');
shader.AddLine('{'); shader.AddLine('{');
++shader.scope; ++shader.scope;
} }
@ -730,6 +735,16 @@ private:
} }
break; break;
} }
case OpCode::Id::FMNMX: {
std::string condition =
GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0);
std::string parameters = op_a + ',' + op_b;
regs.SetRegisterToFloat(instr.gpr0, 0,
'(' + condition + ") ? min(" + parameters + ") : max(" +
parameters + ')',
1, 1);
break;
}
case OpCode::Id::RRO: { case OpCode::Id::RRO: {
NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction"); NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction");
break; break;