3
0
Fork 0
forked from suyu/suyu

Shader: Implemented compound predicates in fset.

You can specify a predicate in the fset instruction:

Result = ((Value1 Comp Value2) OP P0) ? 1.0 : 0.0;
This commit is contained in:
Subv 2018-05-24 17:28:54 -05:00
parent 126270d963
commit e2cdf54177

View file

@ -609,6 +609,7 @@ private:
{PredCondition::LessThan, "<"}, {PredCondition::LessThan, "<"},
{PredCondition::Equal, "=="}, {PredCondition::Equal, "=="},
{PredCondition::LessEqual, "<="}, {PredCondition::LessEqual, "<="},
{PredCondition::GreaterThan, ">"},
}; };
auto comparison = PredicateComparisonStrings.find(condition); auto comparison = PredicateComparisonStrings.find(condition);
@ -628,7 +629,7 @@ private:
static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = { static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
{PredOperation::And, "&&"}, {PredOperation::And, "&&"},
{PredOperation::Or, "||"}, {PredOperation::Or, "||"},
{PredOperation::Xor, "^"}, {PredOperation::Xor, "^^"},
}; };
auto op = PredicateOperationStrings.find(operation); auto op = PredicateOperationStrings.find(operation);
@ -977,35 +978,18 @@ private:
op_b = "abs(" + op_b + ')'; op_b = "abs(" + op_b + ')';
} }
using Tegra::Shader::Pred;
ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
"Compound predicates are not implemented");
// The fset instruction sets a register to 1.0 if the condition is true, and to 0 // The fset instruction sets a register to 1.0 if the condition is true, and to 0
// otherwise. // otherwise.
using Tegra::Shader::PredCondition; std::string second_pred =
switch (instr.fset.cond) { GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
case PredCondition::LessThan:
regs.SetRegisterToFloat(instr.gpr0, 0, std::string comparator = GetPredicateComparison(instr.fset.cond);
"((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1); std::string combiner = GetPredicateCombiner(instr.fset.op);
break;
case PredCondition::Equal: std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
regs.SetRegisterToFloat(instr.gpr0, 0, combiner + " (" + second_pred + "))";
"((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
break; regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
case PredCondition::LessEqual:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") <= (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::GreaterThan:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
default:
NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
UNREACHABLE();
}
break; break;
} }
default: { default: {