mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-29 23:06:23 -05:00
shader_ir/decode: Fix half float pre-operations and remove MetaHalfArithmetic
Operations done before the main half float operation (like HAdd) were managing a packed value instead of the unpacked one. Adding an unpacked operation allows us to drop the per-operand MetaHalfArithmetic entry, simplifying the code overall.
This commit is contained in:
parent
abcbcb1b2a
commit
f43995ec53
9 changed files with 72 additions and 85 deletions
|
@ -121,14 +121,10 @@ std::string GetTopologyName(Tegra::Shader::OutputTopology topology) {
|
||||||
|
|
||||||
/// Returns true if an object has to be treated as precise
|
/// Returns true if an object has to be treated as precise
|
||||||
bool IsPrecise(Operation operand) {
|
bool IsPrecise(Operation operand) {
|
||||||
const auto& meta = operand.GetMeta();
|
const auto& meta{operand.GetMeta()};
|
||||||
|
|
||||||
if (const auto arithmetic = std::get_if<MetaArithmetic>(&meta)) {
|
if (const auto arithmetic = std::get_if<MetaArithmetic>(&meta)) {
|
||||||
return arithmetic->precise;
|
return arithmetic->precise;
|
||||||
}
|
}
|
||||||
if (const auto half_arithmetic = std::get_if<MetaHalfArithmetic>(&meta)) {
|
|
||||||
return half_arithmetic->precise;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,26 +613,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
|
std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
|
||||||
const std::string value = VisitOperand(operation, operand_index);
|
return CastOperand(VisitOperand(operation, operand_index), type);
|
||||||
switch (type) {
|
|
||||||
case Type::HalfFloat: {
|
|
||||||
const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta());
|
|
||||||
ASSERT(half_meta);
|
|
||||||
|
|
||||||
switch (half_meta->types.at(operand_index)) {
|
|
||||||
case Tegra::Shader::HalfType::H0_H1:
|
|
||||||
return "toHalf2(" + value + ')';
|
|
||||||
case Tegra::Shader::HalfType::F32:
|
|
||||||
return "vec2(" + value + ')';
|
|
||||||
case Tegra::Shader::HalfType::H0_H0:
|
|
||||||
return "vec2(toHalf2(" + value + ")[0])";
|
|
||||||
case Tegra::Shader::HalfType::H1_H1:
|
|
||||||
return "vec2(toHalf2(" + value + ")[1])";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return CastOperand(value, type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CastOperand(const std::string& value, Type type) const {
|
std::string CastOperand(const std::string& value, Type type) const {
|
||||||
|
@ -650,9 +627,7 @@ private:
|
||||||
case Type::Uint:
|
case Type::Uint:
|
||||||
return "ftou(" + value + ')';
|
return "ftou(" + value + ')';
|
||||||
case Type::HalfFloat:
|
case Type::HalfFloat:
|
||||||
// Can't be handled as a stand-alone value
|
return "toHalf2(" + value + ')';
|
||||||
UNREACHABLE();
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return value;
|
return value;
|
||||||
|
@ -1073,6 +1048,25 @@ private:
|
||||||
return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
|
return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HUnpack(Operation operation) {
|
||||||
|
const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)};
|
||||||
|
const auto value = [&]() -> std::string {
|
||||||
|
switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) {
|
||||||
|
case Tegra::Shader::HalfType::H0_H1:
|
||||||
|
return operand;
|
||||||
|
case Tegra::Shader::HalfType::F32:
|
||||||
|
return "vec2(fromHalf2(" + operand + "))";
|
||||||
|
case Tegra::Shader::HalfType::H0_H0:
|
||||||
|
return "vec2(" + operand + "[0])";
|
||||||
|
case Tegra::Shader::HalfType::H1_H1:
|
||||||
|
return "vec2(" + operand + "[1])";
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return "0";
|
||||||
|
}();
|
||||||
|
return "fromHalf2(" + value + ')';
|
||||||
|
}
|
||||||
|
|
||||||
std::string HMergeF32(Operation operation) {
|
std::string HMergeF32(Operation operation) {
|
||||||
return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
|
return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
|
||||||
}
|
}
|
||||||
|
@ -1508,6 +1502,7 @@ private:
|
||||||
&GLSLDecompiler::Absolute<Type::HalfFloat>,
|
&GLSLDecompiler::Absolute<Type::HalfFloat>,
|
||||||
&GLSLDecompiler::HNegate,
|
&GLSLDecompiler::HNegate,
|
||||||
&GLSLDecompiler::HClamp,
|
&GLSLDecompiler::HClamp,
|
||||||
|
&GLSLDecompiler::HUnpack,
|
||||||
&GLSLDecompiler::HMergeF32,
|
&GLSLDecompiler::HMergeF32,
|
||||||
&GLSLDecompiler::HMergeH0,
|
&GLSLDecompiler::HMergeH0,
|
||||||
&GLSLDecompiler::HMergeH1,
|
&GLSLDecompiler::HMergeH1,
|
||||||
|
|
|
@ -76,14 +76,10 @@ constexpr u32 GetGenericAttributeLocation(Attribute::Index attribute) {
|
||||||
|
|
||||||
/// Returns true if an object has to be treated as precise
|
/// Returns true if an object has to be treated as precise
|
||||||
bool IsPrecise(Operation operand) {
|
bool IsPrecise(Operation operand) {
|
||||||
const auto& meta = operand.GetMeta();
|
const auto& meta{operand.GetMeta()};
|
||||||
|
|
||||||
if (std::holds_alternative<MetaArithmetic>(meta)) {
|
if (std::holds_alternative<MetaArithmetic>(meta)) {
|
||||||
return std::get<MetaArithmetic>(meta).precise;
|
return std::get<MetaArithmetic>(meta).precise;
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<MetaHalfArithmetic>(meta)) {
|
|
||||||
return std::get<MetaHalfArithmetic>(meta).precise;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -749,6 +745,11 @@ private:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id HUnpack(Operation operation) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Id HMergeF32(Operation operation) {
|
Id HMergeF32(Operation operation) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return {};
|
return {};
|
||||||
|
@ -1222,6 +1223,7 @@ private:
|
||||||
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
|
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
|
||||||
&SPIRVDecompiler::HNegate,
|
&SPIRVDecompiler::HNegate,
|
||||||
&SPIRVDecompiler::HClamp,
|
&SPIRVDecompiler::HClamp,
|
||||||
|
&SPIRVDecompiler::HUnpack,
|
||||||
&SPIRVDecompiler::HMergeF32,
|
&SPIRVDecompiler::HMergeF32,
|
||||||
&SPIRVDecompiler::HMergeH0,
|
&SPIRVDecompiler::HMergeH0,
|
||||||
&SPIRVDecompiler::HMergeH1,
|
&SPIRVDecompiler::HMergeH1,
|
||||||
|
|
|
@ -29,9 +29,8 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
|
||||||
const bool negate_b =
|
const bool negate_b =
|
||||||
opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
||||||
|
|
||||||
const Node op_a = GetOperandAbsNegHalf(GetRegister(instr.gpr8), instr.alu_half.abs_a, negate_a);
|
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.alu_half.type_a);
|
||||||
|
op_a = GetOperandAbsNegHalf(op_a, instr.alu_half.abs_a, negate_a);
|
||||||
// instr.alu_half.type_a
|
|
||||||
|
|
||||||
Node op_b = [&]() {
|
Node op_b = [&]() {
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
|
@ -46,17 +45,17 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
op_b = UnpackHalfFloat(op_b, instr.alu_half.type_b);
|
||||||
op_b = GetOperandAbsNegHalf(op_b, instr.alu_half.abs_b, negate_b);
|
op_b = GetOperandAbsNegHalf(op_b, instr.alu_half.abs_b, negate_b);
|
||||||
|
|
||||||
Node value = [&]() {
|
Node value = [&]() {
|
||||||
MetaHalfArithmetic meta{true, {instr.alu_half_imm.type_a, instr.alu_half.type_b}};
|
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HADD2_C:
|
case OpCode::Id::HADD2_C:
|
||||||
case OpCode::Id::HADD2_R:
|
case OpCode::Id::HADD2_R:
|
||||||
return Operation(OperationCode::HAdd, meta, op_a, op_b);
|
return Operation(OperationCode::HAdd, PRECISE, op_a, op_b);
|
||||||
case OpCode::Id::HMUL2_C:
|
case OpCode::Id::HMUL2_C:
|
||||||
case OpCode::Id::HMUL2_R:
|
case OpCode::Id::HMUL2_R:
|
||||||
return Operation(OperationCode::HMul, meta, op_a, op_b);
|
return Operation(OperationCode::HMul, PRECISE, op_a, op_b);
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unhandled half float instruction: {}", opcode->get().GetName());
|
UNIMPLEMENTED_MSG("Unhandled half float instruction: {}", opcode->get().GetName());
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
|
|
|
@ -24,18 +24,17 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
|
||||||
UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None);
|
UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node op_a = GetRegister(instr.gpr8);
|
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.alu_half_imm.type_a);
|
||||||
op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a);
|
op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a);
|
||||||
|
|
||||||
const Node op_b = UnpackHalfImmediate(instr, true);
|
const Node op_b = UnpackHalfImmediate(instr, true);
|
||||||
|
|
||||||
Node value = [&]() {
|
Node value = [&]() {
|
||||||
MetaHalfArithmetic meta{true, {instr.alu_half_imm.type_a}};
|
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HADD2_IMM:
|
case OpCode::Id::HADD2_IMM:
|
||||||
return Operation(OperationCode::HAdd, meta, op_a, op_b);
|
return Operation(OperationCode::HAdd, PRECISE, op_a, op_b);
|
||||||
case OpCode::Id::HMUL2_IMM:
|
case OpCode::Id::HMUL2_IMM:
|
||||||
return Operation(OperationCode::HMul, meta, op_a, op_b);
|
return Operation(OperationCode::HMul, PRECISE, op_a, op_b);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
|
|
|
@ -22,9 +22,9 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
|
||||||
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
|
LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// instr.hset2.type_a
|
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a);
|
||||||
// instr.hset2.type_b
|
op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a);
|
||||||
Node op_a = GetRegister(instr.gpr8);
|
|
||||||
Node op_b = [&]() {
|
Node op_b = [&]() {
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HSET2_R:
|
case OpCode::Id::HSET2_R:
|
||||||
|
@ -34,14 +34,12 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
op_b = UnpackHalfFloat(op_b, instr.hset2.type_b);
|
||||||
op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a);
|
|
||||||
op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b);
|
op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b);
|
||||||
|
|
||||||
const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred);
|
const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred);
|
||||||
|
|
||||||
MetaHalfArithmetic meta{false, {instr.hset2.type_a, instr.hset2.type_b}};
|
const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b);
|
||||||
const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, meta, op_a, op_b);
|
|
||||||
|
|
||||||
const OperationCode combiner = GetPredicateCombiner(instr.hset2.op);
|
const OperationCode combiner = GetPredicateCombiner(instr.hset2.op);
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
|
||||||
|
|
||||||
UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0);
|
UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0);
|
||||||
|
|
||||||
Node op_a = GetRegister(instr.gpr8);
|
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a);
|
||||||
op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
||||||
|
|
||||||
const Node op_b = [&]() {
|
Node op_b = [&]() {
|
||||||
switch (opcode->get().GetId()) {
|
switch (opcode->get().GetId()) {
|
||||||
case OpCode::Id::HSETP2_R:
|
case OpCode::Id::HSETP2_R:
|
||||||
return GetOperandAbsNegHalf(GetRegister(instr.gpr20), instr.hsetp2.abs_a,
|
return GetOperandAbsNegHalf(GetRegister(instr.gpr20), instr.hsetp2.abs_a,
|
||||||
|
@ -32,6 +32,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
op_b = UnpackHalfFloat(op_b, instr.hsetp2.type_b);
|
||||||
|
|
||||||
// We can't use the constant predicate as destination.
|
// We can't use the constant predicate as destination.
|
||||||
ASSERT(instr.hsetp2.pred3 != static_cast<u64>(Pred::UnusedIndex));
|
ASSERT(instr.hsetp2.pred3 != static_cast<u64>(Pred::UnusedIndex));
|
||||||
|
@ -42,8 +43,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
|
||||||
const OperationCode pair_combiner =
|
const OperationCode pair_combiner =
|
||||||
instr.hsetp2.h_and ? OperationCode::LogicalAll2 : OperationCode::LogicalAny2;
|
instr.hsetp2.h_and ? OperationCode::LogicalAll2 : OperationCode::LogicalAny2;
|
||||||
|
|
||||||
MetaHalfArithmetic meta = {false, {instr.hsetp2.type_a, instr.hsetp2.type_b}};
|
const Node comparison = GetPredicateComparisonHalf(instr.hsetp2.cond, op_a, op_b);
|
||||||
const Node comparison = GetPredicateComparisonHalf(instr.hsetp2.cond, meta, op_a, op_b);
|
|
||||||
const Node first_pred = Operation(pair_combiner, comparison);
|
const Node first_pred = Operation(pair_combiner, comparison);
|
||||||
|
|
||||||
// Set the primary predicate to the result of Predicate OP SecondPredicate
|
// Set the primary predicate to the result of Predicate OP SecondPredicate
|
||||||
|
|
|
@ -27,10 +27,6 @@ u32 ShaderIR::DecodeHfma2(NodeBlock& bb, u32 pc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto identity = HalfType::H0_H1;
|
constexpr auto identity = HalfType::H0_H1;
|
||||||
|
|
||||||
const HalfType type_a = instr.hfma2.type_a;
|
|
||||||
const Node op_a = GetRegister(instr.gpr8);
|
|
||||||
|
|
||||||
bool neg_b{}, neg_c{};
|
bool neg_b{}, neg_c{};
|
||||||
auto [saturate, type_b, op_b, type_c,
|
auto [saturate, type_b, op_b, type_c,
|
||||||
op_c] = [&]() -> std::tuple<bool, HalfType, Node, HalfType, Node> {
|
op_c] = [&]() -> std::tuple<bool, HalfType, Node, HalfType, Node> {
|
||||||
|
@ -62,11 +58,11 @@ u32 ShaderIR::DecodeHfma2(NodeBlock& bb, u32 pc) {
|
||||||
}();
|
}();
|
||||||
UNIMPLEMENTED_IF_MSG(saturate, "HFMA2 saturation is not implemented");
|
UNIMPLEMENTED_IF_MSG(saturate, "HFMA2 saturation is not implemented");
|
||||||
|
|
||||||
op_b = GetOperandAbsNegHalf(op_b, false, neg_b);
|
const Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hfma2.type_a);
|
||||||
op_c = GetOperandAbsNegHalf(op_c, false, neg_c);
|
op_b = GetOperandAbsNegHalf(UnpackHalfFloat(op_b, type_b), false, neg_b);
|
||||||
|
op_c = GetOperandAbsNegHalf(UnpackHalfFloat(op_c, type_c), false, neg_c);
|
||||||
|
|
||||||
MetaHalfArithmetic meta{true, {type_a, type_b, type_c}};
|
Node value = Operation(OperationCode::HFma, PRECISE, op_a, op_b, op_c);
|
||||||
Node value = Operation(OperationCode::HFma, meta, op_a, op_b, op_c);
|
|
||||||
value = HalfMerge(GetRegister(instr.gpr0), value, instr.hfma2.merge);
|
value = HalfMerge(GetRegister(instr.gpr0), value, instr.hfma2.merge);
|
||||||
|
|
||||||
SetRegister(bb, instr.gpr0, value);
|
SetRegister(bb, instr.gpr0, value);
|
||||||
|
|
|
@ -189,7 +189,11 @@ Node ShaderIR::UnpackHalfImmediate(Instruction instr, bool has_negation) {
|
||||||
const Node first_negate = GetPredicate(instr.half_imm.first_negate != 0);
|
const Node first_negate = GetPredicate(instr.half_imm.first_negate != 0);
|
||||||
const Node second_negate = GetPredicate(instr.half_imm.second_negate != 0);
|
const Node second_negate = GetPredicate(instr.half_imm.second_negate != 0);
|
||||||
|
|
||||||
return Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, first_negate, second_negate);
|
return Operation(OperationCode::HNegate, NO_PRECISE, value, first_negate, second_negate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node ShaderIR::UnpackHalfFloat(Node value, Tegra::Shader::HalfType type) {
|
||||||
|
return Operation(OperationCode::HUnpack, type, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) {
|
Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) {
|
||||||
|
@ -209,10 +213,10 @@ Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) {
|
||||||
|
|
||||||
Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
|
Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
|
||||||
if (absolute) {
|
if (absolute) {
|
||||||
value = Operation(OperationCode::HAbsolute, HALF_NO_PRECISE, value);
|
value = Operation(OperationCode::HAbsolute, NO_PRECISE, value);
|
||||||
}
|
}
|
||||||
if (negate) {
|
if (negate) {
|
||||||
value = Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, GetPredicate(true),
|
value = Operation(OperationCode::HNegate, NO_PRECISE, value, GetPredicate(true),
|
||||||
GetPredicate(true));
|
GetPredicate(true));
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
@ -224,7 +228,7 @@ Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) {
|
||||||
}
|
}
|
||||||
const Node positive_zero = Immediate(std::copysignf(0, 1));
|
const Node positive_zero = Immediate(std::copysignf(0, 1));
|
||||||
const Node positive_one = Immediate(1.0f);
|
const Node positive_one = Immediate(1.0f);
|
||||||
return Operation(OperationCode::HClamp, HALF_NO_PRECISE, value, positive_zero, positive_one);
|
return Operation(OperationCode::HClamp, NO_PRECISE, value, positive_zero, positive_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
|
Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
|
||||||
|
@ -292,8 +296,8 @@ Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_si
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition,
|
Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a,
|
||||||
const MetaHalfArithmetic& meta, Node op_a, Node op_b) {
|
Node op_b) {
|
||||||
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
||||||
{PredCondition::LessThan, OperationCode::Logical2HLessThan},
|
{PredCondition::LessThan, OperationCode::Logical2HLessThan},
|
||||||
{PredCondition::Equal, OperationCode::Logical2HEqual},
|
{PredCondition::Equal, OperationCode::Logical2HEqual},
|
||||||
|
@ -311,7 +315,7 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition
|
||||||
UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
|
UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
|
||||||
"Unknown predicate comparison operation");
|
"Unknown predicate comparison operation");
|
||||||
|
|
||||||
const Node predicate = Operation(comparison->second, meta, op_a, op_b);
|
const Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b);
|
||||||
|
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,12 +109,13 @@ enum class OperationCode {
|
||||||
UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
|
UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
|
||||||
UBitCount, /// (MetaArithmetic, uint) -> uint
|
UBitCount, /// (MetaArithmetic, uint) -> uint
|
||||||
|
|
||||||
HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
||||||
HMul, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
||||||
HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
|
HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
|
||||||
HAbsolute, /// (f16vec2 a) -> f16vec2
|
HAbsolute, /// (f16vec2 a) -> f16vec2
|
||||||
HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
|
HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
|
||||||
HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
|
HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
|
||||||
|
HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2
|
||||||
HMergeF32, /// (f16vec2 src) -> float
|
HMergeF32, /// (f16vec2 src) -> float
|
||||||
HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
||||||
HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
||||||
|
@ -287,13 +288,6 @@ struct MetaArithmetic {
|
||||||
bool precise{};
|
bool precise{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MetaHalfArithmetic {
|
|
||||||
bool precise{};
|
|
||||||
std::array<Tegra::Shader::HalfType, 3> types = {Tegra::Shader::HalfType::H0_H1,
|
|
||||||
Tegra::Shader::HalfType::H0_H1,
|
|
||||||
Tegra::Shader::HalfType::H0_H1};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MetaTexture {
|
struct MetaTexture {
|
||||||
const Sampler& sampler;
|
const Sampler& sampler;
|
||||||
Node array{};
|
Node array{};
|
||||||
|
@ -305,11 +299,10 @@ struct MetaTexture {
|
||||||
u32 element{};
|
u32 element{};
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr MetaArithmetic PRECISE = {true};
|
inline constexpr MetaArithmetic PRECISE = {true};
|
||||||
constexpr MetaArithmetic NO_PRECISE = {false};
|
inline constexpr MetaArithmetic NO_PRECISE = {false};
|
||||||
constexpr MetaHalfArithmetic HALF_NO_PRECISE = {false};
|
|
||||||
|
|
||||||
using Meta = std::variant<MetaArithmetic, MetaHalfArithmetic, MetaTexture>;
|
using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
|
||||||
|
|
||||||
/// Holds any kind of operation that can be done in the IR
|
/// Holds any kind of operation that can be done in the IR
|
||||||
class OperationNode final {
|
class OperationNode final {
|
||||||
|
@ -713,6 +706,8 @@ private:
|
||||||
|
|
||||||
/// Unpacks a half immediate from an instruction
|
/// Unpacks a half immediate from an instruction
|
||||||
Node UnpackHalfImmediate(Tegra::Shader::Instruction instr, bool has_negation);
|
Node UnpackHalfImmediate(Tegra::Shader::Instruction instr, bool has_negation);
|
||||||
|
/// Unpacks a binary value into a half float pair with a type format
|
||||||
|
Node UnpackHalfFloat(Node value, Tegra::Shader::HalfType type);
|
||||||
/// Merges a half pair into another value
|
/// Merges a half pair into another value
|
||||||
Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
|
Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
|
||||||
/// Conditionally absolute/negated half float pair. Absolute is applied first
|
/// Conditionally absolute/negated half float pair. Absolute is applied first
|
||||||
|
@ -726,8 +721,7 @@ private:
|
||||||
Node GetPredicateComparisonInteger(Tegra::Shader::PredCondition condition, bool is_signed,
|
Node GetPredicateComparisonInteger(Tegra::Shader::PredCondition condition, bool is_signed,
|
||||||
Node op_a, Node op_b);
|
Node op_a, Node op_b);
|
||||||
/// Returns a predicate comparing two half floats. meta consumes how both pairs will be compared
|
/// Returns a predicate comparing two half floats. meta consumes how both pairs will be compared
|
||||||
Node GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition,
|
Node GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
|
||||||
const MetaHalfArithmetic& meta, Node op_a, Node op_b);
|
|
||||||
|
|
||||||
/// Returns a predicate combiner operation
|
/// Returns a predicate combiner operation
|
||||||
OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
|
OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);
|
||||||
|
|
Loading…
Reference in a new issue