From 2df55985b691d659073dce2d857d46bc152b4842 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 23 Dec 2018 20:59:49 -0300
Subject: [PATCH] shader_decode: Rework HSETP2

---
 .../shader/decode/half_set_predicate.cpp      |  8 ++-
 src/video_core/shader/glsl_decompiler.cpp     | 61 +++++++++++--------
 src/video_core/shader/shader_ir.cpp           | 22 +++----
 src/video_core/shader/shader_ir.h             | 15 ++---
 4 files changed, 58 insertions(+), 48 deletions(-)

diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp
index d7d63d50a4..72cc3d5c85 100644
--- a/src/video_core/shader/decode/half_set_predicate.cpp
+++ b/src/video_core/shader/decode/half_set_predicate.cpp
@@ -39,10 +39,12 @@ u32 ShaderIR::DecodeHalfSetPredicate(BasicBlock& bb, u32 pc) {
     const Node second_pred = GetPredicate(instr.hsetp2.pred39, instr.hsetp2.neg_pred != 0);
 
     const OperationCode combiner = GetPredicateCombiner(instr.hsetp2.op);
+    const OperationCode pair_combiner =
+        instr.hsetp2.h_and ? OperationCode::LogicalAll2 : OperationCode::LogicalAny2;
 
-    MetaHalfArithmetic meta = {
-        false, {instr.hsetp2.type_a, instr.hsetp2.type_b}, instr.hsetp2.h_and != 0};
-    const Node first_pred = GetPredicateComparisonHalf(instr.hsetp2.cond, meta, op_a, op_b);
+    MetaHalfArithmetic meta = {false, {instr.hsetp2.type_a, instr.hsetp2.type_b}};
+    const Node comparison = GetPredicateComparisonHalf(instr.hsetp2.cond, meta, op_a, op_b);
+    const Node first_pred = Operation(pair_combiner, comparison);
 
     // Set the primary predicate to the result of Predicate OP SecondPredicate
     const Node value = Operation(combiner, first_pred, second_pred);
diff --git a/src/video_core/shader/glsl_decompiler.cpp b/src/video_core/shader/glsl_decompiler.cpp
index c364a43cec..8a2cc3c311 100644
--- a/src/video_core/shader/glsl_decompiler.cpp
+++ b/src/video_core/shader/glsl_decompiler.cpp
@@ -31,7 +31,7 @@ using Operation = const OperationNode&;
 enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
 constexpr u32 MAX_CONSTBUFFER_ELEMENTS = 65536 / 16; // TODO(Rodrigo): Use rasterizer's value
 
-enum class Type { Bool, Float, Int, Uint, HalfFloat };
+enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
 
 class ShaderWriter {
 public:
@@ -541,6 +541,7 @@ private:
 
         switch (type) {
         case Type::Bool:
+        case Type::Bool2:
         case Type::Float:
             return value;
         case Type::Int:
@@ -1011,38 +1012,42 @@ private:
         return GenerateUnary(operation, "!", Type::Bool, Type::Bool, false);
     }
 
-    std::string LogicalHComparison(Operation operation, const std::string& func) {
-        const auto& meta = std::get<MetaHalfArithmetic>(operation.GetMeta());
-        const std::string op_a = VisitOperand(operation, 0, Type::HalfFloat);
-        const std::string op_b = VisitOperand(operation, 1, Type::HalfFloat);
-
-        std::string value = meta.and_comparison ? "all" : "any";
-        value += '(' + func + '(' + op_a + ", " + op_b + "))";
-        return value;
+    std::string LogicalAll2(Operation operation) {
+        return GenerateUnary(operation, "all", Type::Bool, Type::Bool2);
     }
 
-    std::string LogicalHLessThan(Operation operation) {
-        return LogicalHComparison(operation, "lessThan");
+    std::string LogicalAny2(Operation operation) {
+        return GenerateUnary(operation, "any", Type::Bool, Type::Bool2);
     }
 
-    std::string LogicalHEqual(Operation operation) {
-        return LogicalHComparison(operation, "equal");
+    std::string Logical2HLessThan(Operation operation) {
+        return GenerateBinaryCall(operation, "lessThan", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
     }
 
-    std::string LogicalHLessEqual(Operation operation) {
-        return LogicalHComparison(operation, "lessThanEqual");
+    std::string Logical2HEqual(Operation operation) {
+        return GenerateBinaryCall(operation, "equal", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
     }
 
-    std::string LogicalHGreaterThan(Operation operation) {
-        return LogicalHComparison(operation, "greaterThan");
+    std::string Logical2HLessEqual(Operation operation) {
+        return GenerateBinaryCall(operation, "lessThanEqual", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
     }
 
-    std::string LogicalHNotEqual(Operation operation) {
-        return LogicalHComparison(operation, "notEqual");
+    std::string Logical2HGreaterThan(Operation operation) {
+        return GenerateBinaryCall(operation, "greaterThan", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
     }
 
-    std::string LogicalHGreaterEqual(Operation operation) {
-        return LogicalHComparison(operation, "greaterThanEqual");
+    std::string Logical2HNotEqual(Operation operation) {
+        return GenerateBinaryCall(operation, "notEqual", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
+    }
+
+    std::string Logical2HGreaterEqual(Operation operation) {
+        return GenerateBinaryCall(operation, "greaterThanEqual", Type::Bool2, Type::HalfFloat,
+                                  Type::HalfFloat);
     }
 
     std::string F4Texture(Operation operation) {
@@ -1301,6 +1306,8 @@ private:
         &LogicalOr,
         &LogicalXor,
         &LogicalNegate,
+        &LogicalAll2,
+        &LogicalAny2,
 
         &LogicalLessThan<Type::Float>,
         &LogicalEqual<Type::Float>,
@@ -1324,12 +1331,12 @@ private:
         &LogicalNotEqual<Type::Uint>,
         &LogicalGreaterEqual<Type::Uint>,
 
-        &LogicalHLessThan,
-        &LogicalHEqual,
-        &LogicalHLessEqual,
-        &LogicalHGreaterThan,
-        &LogicalHNotEqual,
-        &LogicalHGreaterEqual,
+        &Logical2HLessThan,
+        &Logical2HEqual,
+        &Logical2HLessEqual,
+        &Logical2HGreaterThan,
+        &Logical2HNotEqual,
+        &Logical2HGreaterEqual,
 
         &F4Texture,
         &F4TextureLod,
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 1fc838d15d..b076425178 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -289,17 +289,17 @@ Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition
                          "Unimplemented NaN comparison for half floats");
 
     static const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
-        {PredCondition::LessThan, OperationCode::LogicalHLessThan},
-        {PredCondition::Equal, OperationCode::LogicalHEqual},
-        {PredCondition::LessEqual, OperationCode::LogicalHLessEqual},
-        {PredCondition::GreaterThan, OperationCode::LogicalHGreaterThan},
-        {PredCondition::NotEqual, OperationCode::LogicalHNotEqual},
-        {PredCondition::GreaterEqual, OperationCode::LogicalHGreaterEqual},
-        {PredCondition::LessThanWithNan, OperationCode::LogicalHLessThan},
-        {PredCondition::NotEqualWithNan, OperationCode::LogicalHNotEqual},
-        {PredCondition::LessEqualWithNan, OperationCode::LogicalHLessEqual},
-        {PredCondition::GreaterThanWithNan, OperationCode::LogicalHGreaterThan},
-        {PredCondition::GreaterEqualWithNan, OperationCode::LogicalHGreaterEqual}};
+        {PredCondition::LessThan, OperationCode::Logical2HLessThan},
+        {PredCondition::Equal, OperationCode::Logical2HEqual},
+        {PredCondition::LessEqual, OperationCode::Logical2HLessEqual},
+        {PredCondition::GreaterThan, OperationCode::Logical2HGreaterThan},
+        {PredCondition::NotEqual, OperationCode::Logical2HNotEqual},
+        {PredCondition::GreaterEqual, OperationCode::Logical2HGreaterEqual},
+        {PredCondition::LessThanWithNan, OperationCode::Logical2HLessThan},
+        {PredCondition::NotEqualWithNan, OperationCode::Logical2HNotEqual},
+        {PredCondition::LessEqualWithNan, OperationCode::Logical2HLessEqual},
+        {PredCondition::GreaterThanWithNan, OperationCode::Logical2HGreaterThan},
+        {PredCondition::GreaterEqualWithNan, OperationCode::Logical2HGreaterEqual}};
 
     const auto comparison{PredicateComparisonTable.find(condition)};
     UNIMPLEMENTED_IF_MSG(comparison == PredicateComparisonTable.end(),
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 928e3e7d58..5ef0a7779d 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -122,6 +122,8 @@ enum class OperationCode {
     LogicalOr,     /// (bool a, bool b) -> bool
     LogicalXor,    /// (bool a, bool b) -> bool
     LogicalNegate, /// (bool a) -> bool
+    LogicalAll2,   /// (bool2 a) -> bool
+    LogicalAny2,   /// (bool2 a) -> bool
 
     LogicalFLessThan,     /// (float a, float b) -> bool
     LogicalFEqual,        /// (float a, float b) -> bool
@@ -145,12 +147,12 @@ enum class OperationCode {
     LogicalUNotEqual,     /// (uint a, uint b) -> bool
     LogicalUGreaterEqual, /// (uint a, uint b) -> bool
 
-    LogicalHLessThan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
-    LogicalHEqual,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
-    LogicalHLessEqual,    /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
-    LogicalHGreaterThan,  /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
-    LogicalHNotEqual,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
-    LogicalHGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool
+    Logical2HLessThan,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HEqual,        /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HLessEqual,    /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterThan,  /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HNotEqual,     /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
+    Logical2HGreaterEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
 
     F4Texture,                /// (MetaTexture, float[N] coords, float[M] params) -> float4
     F4TextureLod,             /// (MetaTexture, float[N] coords, float[M] params) -> float4
@@ -263,7 +265,6 @@ struct MetaHalfArithmetic {
     std::array<Tegra::Shader::HalfType, 3> types = {Tegra::Shader::HalfType::H0_H1,
                                                     Tegra::Shader::HalfType::H0_H1,
                                                     Tegra::Shader::HalfType::H0_H1};
-    bool and_comparison{};
 };
 
 struct MetaTexture {