summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp12
-rw-r--r--src/video_core/shader/decode/arithmetic_half.cpp11
-rw-r--r--src/video_core/shader/decode/arithmetic_half_immediate.cpp7
-rw-r--r--src/video_core/shader/decode/half_set.cpp12
-rw-r--r--src/video_core/shader/decode/half_set_predicate.cpp8
-rw-r--r--src/video_core/shader/decode/hfma2.cpp12
-rw-r--r--src/video_core/shader/shader_ir.cpp18
-rw-r--r--src/video_core/shader/shader_ir.h26
9 files changed, 72 insertions, 85 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 01e9433c8..44ad21b7f 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -121,14 +121,10 @@ std::string GetTopologyName(Tegra::Shader::OutputTopology topology) {
121 121
122/// Returns true if an object has to be treated as precise 122/// Returns true if an object has to be treated as precise
123bool IsPrecise(Operation operand) { 123bool IsPrecise(Operation operand) {
124 const auto& meta = operand.GetMeta(); 124 const auto& meta{operand.GetMeta()};
125
126 if (const auto arithmetic = std::get_if<MetaArithmetic>(&meta)) { 125 if (const auto arithmetic = std::get_if<MetaArithmetic>(&meta)) {
127 return arithmetic->precise; 126 return arithmetic->precise;
128 } 127 }
129 if (const auto half_arithmetic = std::get_if<MetaHalfArithmetic>(&meta)) {
130 return half_arithmetic->precise;
131 }
132 return false; 128 return false;
133} 129}
134 130
@@ -617,26 +613,7 @@ private:
617 } 613 }
618 614
619 std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) { 615 std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
620 const std::string value = VisitOperand(operation, operand_index); 616 return CastOperand(VisitOperand(operation, operand_index), type);
621 switch (type) {
622 case Type::HalfFloat: {
623 const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta());
624 ASSERT(half_meta);
625
626 switch (half_meta->types.at(operand_index)) {
627 case Tegra::Shader::HalfType::H0_H1:
628 return "toHalf2(" + value + ')';
629 case Tegra::Shader::HalfType::F32:
630 return "vec2(" + value + ')';
631 case Tegra::Shader::HalfType::H0_H0:
632 return "vec2(toHalf2(" + value + ")[0])";
633 case Tegra::Shader::HalfType::H1_H1:
634 return "vec2(toHalf2(" + value + ")[1])";
635 }
636 }
637 default:
638 return CastOperand(value, type);
639 }
640 } 617 }
641 618
642 std::string CastOperand(const std::string& value, Type type) const { 619 std::string CastOperand(const std::string& value, Type type) const {
@@ -650,9 +627,7 @@ private:
650 case Type::Uint: 627 case Type::Uint:
651 return "ftou(" + value + ')'; 628 return "ftou(" + value + ')';
652 case Type::HalfFloat: 629 case Type::HalfFloat:
653 // Can't be handled as a stand-alone value 630 return "toHalf2(" + value + ')';
654 UNREACHABLE();
655 return value;
656 } 631 }
657 UNREACHABLE(); 632 UNREACHABLE();
658 return value; 633 return value;
@@ -1073,6 +1048,25 @@ private:
1073 return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat)); 1048 return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
1074 } 1049 }
1075 1050
1051 std::string HUnpack(Operation operation) {
1052 const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)};
1053 const auto value = [&]() -> std::string {
1054 switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) {
1055 case Tegra::Shader::HalfType::H0_H1:
1056 return operand;
1057 case Tegra::Shader::HalfType::F32:
1058 return "vec2(fromHalf2(" + operand + "))";
1059 case Tegra::Shader::HalfType::H0_H0:
1060 return "vec2(" + operand + "[0])";
1061 case Tegra::Shader::HalfType::H1_H1:
1062 return "vec2(" + operand + "[1])";
1063 }
1064 UNREACHABLE();
1065 return "0";
1066 }();
1067 return "fromHalf2(" + value + ')';
1068 }
1069
1076 std::string HMergeF32(Operation operation) { 1070 std::string HMergeF32(Operation operation) {
1077 return "float(toHalf2(" + Visit(operation[0]) + ")[0])"; 1071 return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
1078 } 1072 }
@@ -1508,6 +1502,7 @@ private:
1508 &GLSLDecompiler::Absolute<Type::HalfFloat>, 1502 &GLSLDecompiler::Absolute<Type::HalfFloat>,
1509 &GLSLDecompiler::HNegate, 1503 &GLSLDecompiler::HNegate,
1510 &GLSLDecompiler::HClamp, 1504 &GLSLDecompiler::HClamp,
1505 &GLSLDecompiler::HUnpack,
1511 &GLSLDecompiler::HMergeF32, 1506 &GLSLDecompiler::HMergeF32,
1512 &GLSLDecompiler::HMergeH0, 1507 &GLSLDecompiler::HMergeH0,
1513 &GLSLDecompiler::HMergeH1, 1508 &GLSLDecompiler::HMergeH1,
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 6ecb0bcb0..beff33ba1 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -76,14 +76,10 @@ constexpr u32 GetGenericAttributeLocation(Attribute::Index attribute) {
76 76
77/// Returns true if an object has to be treated as precise 77/// Returns true if an object has to be treated as precise
78bool IsPrecise(Operation operand) { 78bool IsPrecise(Operation operand) {
79 const auto& meta = operand.GetMeta(); 79 const auto& meta{operand.GetMeta()};
80
81 if (std::holds_alternative<MetaArithmetic>(meta)) { 80 if (std::holds_alternative<MetaArithmetic>(meta)) {
82 return std::get<MetaArithmetic>(meta).precise; 81 return std::get<MetaArithmetic>(meta).precise;
83 } 82 }
84 if (std::holds_alternative<MetaHalfArithmetic>(meta)) {
85 return std::get<MetaHalfArithmetic>(meta).precise;
86 }
87 return false; 83 return false;
88} 84}
89 85
@@ -749,6 +745,11 @@ private:
749 return {}; 745 return {};
750 } 746 }
751 747
748 Id HUnpack(Operation operation) {
749 UNIMPLEMENTED();
750 return {};
751 }
752
752 Id HMergeF32(Operation operation) { 753 Id HMergeF32(Operation operation) {
753 UNIMPLEMENTED(); 754 UNIMPLEMENTED();
754 return {}; 755 return {};
@@ -1222,6 +1223,7 @@ private:
1222 &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>, 1223 &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
1223 &SPIRVDecompiler::HNegate, 1224 &SPIRVDecompiler::HNegate,
1224 &SPIRVDecompiler::HClamp, 1225 &SPIRVDecompiler::HClamp,
1226 &SPIRVDecompiler::HUnpack,
1225 &SPIRVDecompiler::HMergeF32, 1227 &SPIRVDecompiler::HMergeF32,
1226 &SPIRVDecompiler::HMergeH0, 1228 &SPIRVDecompiler::HMergeH0,
1227 &SPIRVDecompiler::HMergeH1, 1229 &SPIRVDecompiler::HMergeH1,
diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp
index 8cf49314d..9467f9417 100644
--- a/src/video_core/shader/decode/arithmetic_half.cpp
+++ b/src/video_core/shader/decode/arithmetic_half.cpp
@@ -29,9 +29,8 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
29 const bool negate_b = 29 const bool negate_b =
30 opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0; 30 opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
31 31
32 const Node op_a = GetOperandAbsNegHalf(GetRegister(instr.gpr8), instr.alu_half.abs_a, negate_a); 32 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.alu_half.type_a);
33 33 op_a = GetOperandAbsNegHalf(op_a, instr.alu_half.abs_a, negate_a);
34 // instr.alu_half.type_a
35 34
36 Node op_b = [&]() { 35 Node op_b = [&]() {
37 switch (opcode->get().GetId()) { 36 switch (opcode->get().GetId()) {
@@ -46,17 +45,17 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
46 return Immediate(0); 45 return Immediate(0);
47 } 46 }
48 }(); 47 }();
48 op_b = UnpackHalfFloat(op_b, instr.alu_half.type_b);
49 op_b = GetOperandAbsNegHalf(op_b, instr.alu_half.abs_b, negate_b); 49 op_b = GetOperandAbsNegHalf(op_b, instr.alu_half.abs_b, negate_b);
50 50
51 Node value = [&]() { 51 Node value = [&]() {
52 MetaHalfArithmetic meta{true, {instr.alu_half_imm.type_a, instr.alu_half.type_b}};
53 switch (opcode->get().GetId()) { 52 switch (opcode->get().GetId()) {
54 case OpCode::Id::HADD2_C: 53 case OpCode::Id::HADD2_C:
55 case OpCode::Id::HADD2_R: 54 case OpCode::Id::HADD2_R:
56 return Operation(OperationCode::HAdd, meta, op_a, op_b); 55 return Operation(OperationCode::HAdd, PRECISE, op_a, op_b);
57 case OpCode::Id::HMUL2_C: 56 case OpCode::Id::HMUL2_C:
58 case OpCode::Id::HMUL2_R: 57 case OpCode::Id::HMUL2_R:
59 return Operation(OperationCode::HMul, meta, op_a, op_b); 58 return Operation(OperationCode::HMul, PRECISE, op_a, op_b);
60 default: 59 default:
61 UNIMPLEMENTED_MSG("Unhandled half float instruction: {}", opcode->get().GetName()); 60 UNIMPLEMENTED_MSG("Unhandled half float instruction: {}", opcode->get().GetName());
62 return Immediate(0); 61 return Immediate(0);
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
index cf4bc0432..fbcd35b18 100644
--- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
@@ -24,18 +24,17 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
24 UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None); 24 UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None);
25 } 25 }
26 26
27 Node op_a = GetRegister(instr.gpr8); 27 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.alu_half_imm.type_a);
28 op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a); 28 op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a);
29 29
30 const Node op_b = UnpackHalfImmediate(instr, true); 30 const Node op_b = UnpackHalfImmediate(instr, true);
31 31
32 Node value = [&]() { 32 Node value = [&]() {
33 MetaHalfArithmetic meta{true, {instr.alu_half_imm.type_a}};
34 switch (opcode->get().GetId()) { 33 switch (opcode->get().GetId()) {
35 case OpCode::Id::HADD2_IMM: 34 case OpCode::Id::HADD2_IMM:
36 return Operation(OperationCode::HAdd, meta, op_a, op_b); 35 return Operation(OperationCode::HAdd, PRECISE, op_a, op_b);
37 case OpCode::Id::HMUL2_IMM: 36 case OpCode::Id::HMUL2_IMM:
38 return Operation(OperationCode::HMul, meta, op_a, op_b); 37 return Operation(OperationCode::HMul, PRECISE, op_a, op_b);
39 default: 38 default:
40 UNREACHABLE(); 39 UNREACHABLE();
41 return Immediate(0); 40 return Immediate(0);
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp
index d07625741..1dd94bf9d 100644
--- a/src/video_core/shader/decode/half_set.cpp
+++ b/src/video_core/shader/decode/half_set.cpp
@@ -22,9 +22,9 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
22 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); 22 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
23 } 23 }
24 24
25 // instr.hset2.type_a 25 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a);
26 // instr.hset2.type_b 26 op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a);
27 Node op_a = GetRegister(instr.gpr8); 27
28 Node op_b = [&]() { 28 Node op_b = [&]() {
29 switch (opcode->get().GetId()) { 29 switch (opcode->get().GetId()) {
30 case OpCode::Id::HSET2_R: 30 case OpCode::Id::HSET2_R:
@@ -34,14 +34,12 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
34 return Immediate(0); 34 return Immediate(0);
35 } 35 }
36 }(); 36 }();
37 37 op_b = UnpackHalfFloat(op_b, instr.hset2.type_b);
38 op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a);
39 op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b); 38 op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b);
40 39
41 const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); 40 const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred);
42 41
43 MetaHalfArithmetic meta{false, {instr.hset2.type_a, instr.hset2.type_b}}; 42 const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b);
44 const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, meta, op_a, op_b);
45 43
46 const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); 44 const OperationCode combiner = GetPredicateCombiner(instr.hset2.op);
47 45
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp
index e68512692..6e59eb650 100644
--- a/src/video_core/shader/decode/half_set_predicate.cpp
+++ b/src/video_core/shader/decode/half_set_predicate.cpp
@@ -19,10 +19,10 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
19 19
20 UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0); 20 UNIMPLEMENTED_IF(instr.hsetp2.ftz != 0);
21 21
22 Node op_a = GetRegister(instr.gpr8); 22 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a);
23 op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a); 23 op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
24 24
25 const Node op_b = [&]() { 25 Node op_b = [&]() {
26 switch (opcode->get().GetId()) { 26 switch (opcode->get().GetId()) {
27 case OpCode::Id::HSETP2_R: 27 case OpCode::Id::HSETP2_R:
28 return GetOperandAbsNegHalf(GetRegister(instr.gpr20), instr.hsetp2.abs_a, 28 return GetOperandAbsNegHalf(GetRegister(instr.gpr20), instr.hsetp2.abs_a,
@@ -32,6 +32,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
32 return Immediate(0); 32 return Immediate(0);
33 } 33 }
34 }(); 34 }();
35 op_b = UnpackHalfFloat(op_b, instr.hsetp2.type_b);
35 36
36 // We can't use the constant predicate as destination. 37 // We can't use the constant predicate as destination.
37 ASSERT(instr.hsetp2.pred3 != static_cast<u64>(Pred::UnusedIndex)); 38 ASSERT(instr.hsetp2.pred3 != static_cast<u64>(Pred::UnusedIndex));
@@ -42,8 +43,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
42 const OperationCode pair_combiner = 43 const OperationCode pair_combiner =
43 instr.hsetp2.h_and ? OperationCode::LogicalAll2 : OperationCode::LogicalAny2; 44 instr.hsetp2.h_and ? OperationCode::LogicalAll2 : OperationCode::LogicalAny2;
44 45
45 MetaHalfArithmetic meta = {false, {instr.hsetp2.type_a, instr.hsetp2.type_b}}; 46 const Node comparison = GetPredicateComparisonHalf(instr.hsetp2.cond, op_a, op_b);
46 const Node comparison = GetPredicateComparisonHalf(instr.hsetp2.cond, meta, op_a, op_b);
47 const Node first_pred = Operation(pair_combiner, comparison); 47 const Node first_pred = Operation(pair_combiner, comparison);
48 48
49 // Set the primary predicate to the result of Predicate OP SecondPredicate 49 // Set the primary predicate to the result of Predicate OP SecondPredicate
diff --git a/src/video_core/shader/decode/hfma2.cpp b/src/video_core/shader/decode/hfma2.cpp
index 7a07c5ec6..5c1becce5 100644
--- a/src/video_core/shader/decode/hfma2.cpp
+++ b/src/video_core/shader/decode/hfma2.cpp
@@ -27,10 +27,6 @@ u32 ShaderIR::DecodeHfma2(NodeBlock& bb, u32 pc) {
27 } 27 }
28 28
29 constexpr auto identity = HalfType::H0_H1; 29 constexpr auto identity = HalfType::H0_H1;
30
31 const HalfType type_a = instr.hfma2.type_a;
32 const Node op_a = GetRegister(instr.gpr8);
33
34 bool neg_b{}, neg_c{}; 30 bool neg_b{}, neg_c{};
35 auto [saturate, type_b, op_b, type_c, 31 auto [saturate, type_b, op_b, type_c,
36 op_c] = [&]() -> std::tuple<bool, HalfType, Node, HalfType, Node> { 32 op_c] = [&]() -> std::tuple<bool, HalfType, Node, HalfType, Node> {
@@ -62,11 +58,11 @@ u32 ShaderIR::DecodeHfma2(NodeBlock& bb, u32 pc) {
62 }(); 58 }();
63 UNIMPLEMENTED_IF_MSG(saturate, "HFMA2 saturation is not implemented"); 59 UNIMPLEMENTED_IF_MSG(saturate, "HFMA2 saturation is not implemented");
64 60
65 op_b = GetOperandAbsNegHalf(op_b, false, neg_b); 61 const Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hfma2.type_a);
66 op_c = GetOperandAbsNegHalf(op_c, false, neg_c); 62 op_b = GetOperandAbsNegHalf(UnpackHalfFloat(op_b, type_b), false, neg_b);
63 op_c = GetOperandAbsNegHalf(UnpackHalfFloat(op_c, type_c), false, neg_c);
67 64
68 MetaHalfArithmetic meta{true, {type_a, type_b, type_c}}; 65 Node value = Operation(OperationCode::HFma, PRECISE, op_a, op_b, op_c);
69 Node value = Operation(OperationCode::HFma, meta, op_a, op_b, op_c);
70 value = HalfMerge(GetRegister(instr.gpr0), value, instr.hfma2.merge); 66 value = HalfMerge(GetRegister(instr.gpr0), value, instr.hfma2.merge);
71 67
72 SetRegister(bb, instr.gpr0, value); 68 SetRegister(bb, instr.gpr0, value);
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index d158b4bfd..17f2f711c 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -189,7 +189,11 @@ Node ShaderIR::UnpackHalfImmediate(Instruction instr, bool has_negation) {
189 const Node first_negate = GetPredicate(instr.half_imm.first_negate != 0); 189 const Node first_negate = GetPredicate(instr.half_imm.first_negate != 0);
190 const Node second_negate = GetPredicate(instr.half_imm.second_negate != 0); 190 const Node second_negate = GetPredicate(instr.half_imm.second_negate != 0);
191 191
192 return Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, first_negate, second_negate); 192 return Operation(OperationCode::HNegate, NO_PRECISE, value, first_negate, second_negate);
193}
194
195Node ShaderIR::UnpackHalfFloat(Node value, Tegra::Shader::HalfType type) {
196 return Operation(OperationCode::HUnpack, type, value);
193} 197}
194 198
195Node ShaderIR::HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge) { 199Node 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) {
209 213
210Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) { 214Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
211 if (absolute) { 215 if (absolute) {
212 value = Operation(OperationCode::HAbsolute, HALF_NO_PRECISE, value); 216 value = Operation(OperationCode::HAbsolute, NO_PRECISE, value);
213 } 217 }
214 if (negate) { 218 if (negate) {
215 value = Operation(OperationCode::HNegate, HALF_NO_PRECISE, value, GetPredicate(true), 219 value = Operation(OperationCode::HNegate, NO_PRECISE, value, GetPredicate(true),
216 GetPredicate(true)); 220 GetPredicate(true));
217 } 221 }
218 return value; 222 return value;
@@ -224,7 +228,7 @@ Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) {
224 } 228 }
225 const Node positive_zero = Immediate(std::copysignf(0, 1)); 229 const Node positive_zero = Immediate(std::copysignf(0, 1));
226 const Node positive_one = Immediate(1.0f); 230 const Node positive_one = Immediate(1.0f);
227 return Operation(OperationCode::HClamp, HALF_NO_PRECISE, value, positive_zero, positive_one); 231 return Operation(OperationCode::HClamp, NO_PRECISE, value, positive_zero, positive_one);
228} 232}
229 233
230Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { 234Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
@@ -292,8 +296,8 @@ Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_si
292 return predicate; 296 return predicate;
293} 297}
294 298
295Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, 299Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a,
296 const MetaHalfArithmetic& meta, Node op_a, Node op_b) { 300 Node op_b) {
297 const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = { 301 const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
298 {PredCondition::LessThan, OperationCode::Logical2HLessThan}, 302 {PredCondition::LessThan, OperationCode::Logical2HLessThan},
299 {PredCondition::Equal, OperationCode::Logical2HEqual}, 303 {PredCondition::Equal, OperationCode::Logical2HEqual},
@@ -311,7 +315,7 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition
311 UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(), 315 UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
312 "Unknown predicate comparison operation"); 316 "Unknown predicate comparison operation");
313 317
314 const Node predicate = Operation(comparison->second, meta, op_a, op_b); 318 const Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b);
315 319
316 return predicate; 320 return predicate;
317} 321}
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index d329da58d..88957e970 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -109,12 +109,13 @@ enum class OperationCode {
109 UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint 109 UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
110 UBitCount, /// (MetaArithmetic, uint) -> uint 110 UBitCount, /// (MetaArithmetic, uint) -> uint
111 111
112 HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 112 HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
113 HMul, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 113 HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
114 HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 114 HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
115 HAbsolute, /// (f16vec2 a) -> f16vec2 115 HAbsolute, /// (f16vec2 a) -> f16vec2
116 HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 116 HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
117 HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 117 HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
118 HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2
118 HMergeF32, /// (f16vec2 src) -> float 119 HMergeF32, /// (f16vec2 src) -> float
119 HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 120 HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
120 HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 121 HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
@@ -287,13 +288,6 @@ struct MetaArithmetic {
287 bool precise{}; 288 bool precise{};
288}; 289};
289 290
290struct MetaHalfArithmetic {
291 bool precise{};
292 std::array<Tegra::Shader::HalfType, 3> types = {Tegra::Shader::HalfType::H0_H1,
293 Tegra::Shader::HalfType::H0_H1,
294 Tegra::Shader::HalfType::H0_H1};
295};
296
297struct MetaTexture { 291struct MetaTexture {
298 const Sampler& sampler; 292 const Sampler& sampler;
299 Node array{}; 293 Node array{};
@@ -305,11 +299,10 @@ struct MetaTexture {
305 u32 element{}; 299 u32 element{};
306}; 300};
307 301
308constexpr MetaArithmetic PRECISE = {true}; 302inline constexpr MetaArithmetic PRECISE = {true};
309constexpr MetaArithmetic NO_PRECISE = {false}; 303inline constexpr MetaArithmetic NO_PRECISE = {false};
310constexpr MetaHalfArithmetic HALF_NO_PRECISE = {false};
311 304
312using Meta = std::variant<MetaArithmetic, MetaHalfArithmetic, MetaTexture>; 305using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
313 306
314/// Holds any kind of operation that can be done in the IR 307/// Holds any kind of operation that can be done in the IR
315class OperationNode final { 308class OperationNode final {
@@ -713,6 +706,8 @@ private:
713 706
714 /// Unpacks a half immediate from an instruction 707 /// Unpacks a half immediate from an instruction
715 Node UnpackHalfImmediate(Tegra::Shader::Instruction instr, bool has_negation); 708 Node UnpackHalfImmediate(Tegra::Shader::Instruction instr, bool has_negation);
709 /// Unpacks a binary value into a half float pair with a type format
710 Node UnpackHalfFloat(Node value, Tegra::Shader::HalfType type);
716 /// Merges a half pair into another value 711 /// Merges a half pair into another value
717 Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge); 712 Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
718 /// Conditionally absolute/negated half float pair. Absolute is applied first 713 /// Conditionally absolute/negated half float pair. Absolute is applied first
@@ -726,8 +721,7 @@ private:
726 Node GetPredicateComparisonInteger(Tegra::Shader::PredCondition condition, bool is_signed, 721 Node GetPredicateComparisonInteger(Tegra::Shader::PredCondition condition, bool is_signed,
727 Node op_a, Node op_b); 722 Node op_a, Node op_b);
728 /// Returns a predicate comparing two half floats. meta consumes how both pairs will be compared 723 /// Returns a predicate comparing two half floats. meta consumes how both pairs will be compared
729 Node GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, 724 Node GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
730 const MetaHalfArithmetic& meta, Node op_a, Node op_b);
731 725
732 /// Returns a predicate combiner operation 726 /// Returns a predicate combiner operation
733 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation); 727 OperationCode GetPredicateCombiner(Tegra::Shader::PredOperation operation);