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:
		| @@ -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); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp