mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-11-15 22:30:05 +00:00
Shader: Implemented compound predicates in fsetp.
You can specify three predicates in an fsetp instruction: P1 = (Value1 Comp Value2) OP P0; P2 = !(Value1 Comp Value2) OP P0;
This commit is contained in:
parent
55e6296e71
commit
126270d963
@ -597,6 +597,45 @@ private:
|
|||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the comparison string to use to compare two values in the 'set' family of
|
||||||
|
* instructions.
|
||||||
|
* @params condition The condition used in the 'set'-family instruction.
|
||||||
|
* @returns String corresponding to the GLSL operator that matches the desired comparison.
|
||||||
|
*/
|
||||||
|
std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
|
||||||
|
using Tegra::Shader::PredCondition;
|
||||||
|
static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
|
||||||
|
{PredCondition::LessThan, "<"},
|
||||||
|
{PredCondition::Equal, "=="},
|
||||||
|
{PredCondition::LessEqual, "<="},
|
||||||
|
};
|
||||||
|
|
||||||
|
auto comparison = PredicateComparisonStrings.find(condition);
|
||||||
|
ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
|
||||||
|
"Unknown predicate comparison operation");
|
||||||
|
return comparison->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the operator string to use to combine two predicates in the 'setp' family of
|
||||||
|
* instructions.
|
||||||
|
* @params operation The operator used in the 'setp'-family instruction.
|
||||||
|
* @returns String corresponding to the GLSL operator that matches the desired operator.
|
||||||
|
*/
|
||||||
|
std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const {
|
||||||
|
using Tegra::Shader::PredOperation;
|
||||||
|
static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
|
||||||
|
{PredOperation::And, "&&"},
|
||||||
|
{PredOperation::Or, "||"},
|
||||||
|
{PredOperation::Xor, "^"},
|
||||||
|
};
|
||||||
|
|
||||||
|
auto op = PredicateOperationStrings.find(operation);
|
||||||
|
ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
|
||||||
|
return op->second;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
* Returns whether the instruction at the specified offset is a 'sched' instruction.
|
||||||
* Sched instructions always appear before a sequence of 3 instructions.
|
* Sched instructions always appear before a sequence of 3 instructions.
|
||||||
@ -888,28 +927,25 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
using Tegra::Shader::Pred;
|
using Tegra::Shader::Pred;
|
||||||
ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
|
|
||||||
instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
|
|
||||||
"Compound predicates are not implemented");
|
|
||||||
|
|
||||||
// We can't use the constant predicate as destination.
|
// We can't use the constant predicate as destination.
|
||||||
ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
|
ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
|
||||||
|
|
||||||
using Tegra::Shader::PredCondition;
|
std::string second_pred =
|
||||||
switch (instr.fsetp.cond) {
|
GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
|
||||||
case PredCondition::LessThan:
|
|
||||||
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')');
|
std::string comparator = GetPredicateComparison(instr.fsetp.cond);
|
||||||
break;
|
std::string combiner = GetPredicateCombiner(instr.fsetp.op);
|
||||||
case PredCondition::Equal:
|
|
||||||
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')');
|
std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
|
||||||
break;
|
// Set the primary predicate to the result of Predicate OP SecondPredicate
|
||||||
case PredCondition::LessEqual:
|
SetPredicate(instr.fsetp.pred3,
|
||||||
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')');
|
'(' + predicate + ") " + combiner + " (" + second_pred + ')');
|
||||||
break;
|
|
||||||
default:
|
if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
|
||||||
NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
|
// Set the secondary predicate to the result of !Predicate OP SecondPredicate, if
|
||||||
static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b);
|
// enabled
|
||||||
UNREACHABLE();
|
SetPredicate(instr.fsetp.pred0,
|
||||||
|
"!(" + predicate + ") " + combiner + " (" + second_pred + ')');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user