summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h28
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp110
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp27
-rw-r--r--src/video_core/shader/decode.cpp2
-rw-r--r--src/video_core/shader/decode/xmad.cpp12
-rw-r--r--src/video_core/shader/node.h21
-rw-r--r--src/video_core/shader/shader_ir.cpp109
7 files changed, 173 insertions, 136 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 8dae754d4..e7cb87589 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -168,18 +168,22 @@ enum class Pred : u64 {
168}; 168};
169 169
170enum class PredCondition : u64 { 170enum class PredCondition : u64 {
171 LessThan = 1, 171 F = 0, // Always false
172 Equal = 2, 172 LT = 1, // Ordered less than
173 LessEqual = 3, 173 EQ = 2, // Ordered equal
174 GreaterThan = 4, 174 LE = 3, // Ordered less than or equal
175 NotEqual = 5, 175 GT = 4, // Ordered greater than
176 GreaterEqual = 6, 176 NE = 5, // Ordered not equal
177 LessThanWithNan = 9, 177 GE = 6, // Ordered greater than or equal
178 LessEqualWithNan = 11, 178 NUM = 7, // Ordered
179 GreaterThanWithNan = 12, 179 NAN_ = 8, // Unordered
180 NotEqualWithNan = 13, 180 LTU = 9, // Unordered less than
181 GreaterEqualWithNan = 14, 181 EQU = 10, // Unordered equal
182 // TODO(Subv): Other condition types 182 LEU = 11, // Unordered less than or equal
183 GTU = 12, // Unordered greater than
184 NEU = 13, // Unordered not equal
185 GEU = 14, // Unordered greater than or equal
186 T = 15, // Always true
183}; 187};
184 188
185enum class PredOperation : u64 { 189enum class PredOperation : u64 {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 99fd4ae2c..960ebf1a1 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1840,34 +1840,40 @@ private:
1840 Type::HalfFloat}; 1840 Type::HalfFloat};
1841 } 1841 }
1842 1842
1843 template <Type type> 1843 template <const std::string_view& op, Type type, bool unordered = false>
1844 Expression LogicalLessThan(Operation operation) { 1844 Expression Comparison(Operation operation) {
1845 return GenerateBinaryInfix(operation, "<", Type::Bool, type, type); 1845 static_assert(!unordered || type == Type::Float);
1846 } 1846
1847 1847 const Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type);
1848 template <Type type> 1848
1849 Expression LogicalEqual(Operation operation) { 1849 if constexpr (op.compare("!=") == 0 && type == Type::Float && !unordered) {
1850 return GenerateBinaryInfix(operation, "==", Type::Bool, type, type); 1850 // GLSL's operator!=(float, float) doesn't seem be ordered. This happens on both AMD's
1851 } 1851 // and Nvidia's proprietary stacks. Manually force an ordered comparison.
1852 1852 return {fmt::format("({} && !isnan({}) && !isnan({}))", expr.AsBool(),
1853 template <Type type> 1853 VisitOperand(operation, 0).AsFloat(),
1854 Expression LogicalLessEqual(Operation operation) { 1854 VisitOperand(operation, 1).AsFloat()),
1855 return GenerateBinaryInfix(operation, "<=", Type::Bool, type, type); 1855 Type::Bool};
1856 } 1856 }
1857 1857 if constexpr (!unordered) {
1858 template <Type type> 1858 return expr;
1859 Expression LogicalGreaterThan(Operation operation) { 1859 }
1860 return GenerateBinaryInfix(operation, ">", Type::Bool, type, type); 1860 // Unordered comparisons are always true for NaN operands.
1861 return {fmt::format("({} || isnan({}) || isnan({}))", expr.AsBool(),
1862 VisitOperand(operation, 0).AsFloat(),
1863 VisitOperand(operation, 1).AsFloat()),
1864 Type::Bool};
1861 } 1865 }
1862 1866
1863 template <Type type> 1867 Expression FOrdered(Operation operation) {
1864 Expression LogicalNotEqual(Operation operation) { 1868 return {fmt::format("(!isnan({}) && !isnan({}))", VisitOperand(operation, 0).AsFloat(),
1865 return GenerateBinaryInfix(operation, "!=", Type::Bool, type, type); 1869 VisitOperand(operation, 1).AsFloat()),
1870 Type::Bool};
1866 } 1871 }
1867 1872
1868 template <Type type> 1873 Expression FUnordered(Operation operation) {
1869 Expression LogicalGreaterEqual(Operation operation) { 1874 return {fmt::format("(isnan({}) || isnan({}))", VisitOperand(operation, 0).AsFloat(),
1870 return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type); 1875 VisitOperand(operation, 1).AsFloat()),
1876 Type::Bool};
1871 } 1877 }
1872 1878
1873 Expression LogicalAddCarry(Operation operation) { 1879 Expression LogicalAddCarry(Operation operation) {
@@ -2324,6 +2330,13 @@ private:
2324 Func() = delete; 2330 Func() = delete;
2325 ~Func() = delete; 2331 ~Func() = delete;
2326 2332
2333 static constexpr std::string_view LessThan = "<";
2334 static constexpr std::string_view Equal = "==";
2335 static constexpr std::string_view LessEqual = "<=";
2336 static constexpr std::string_view GreaterThan = ">";
2337 static constexpr std::string_view NotEqual = "!=";
2338 static constexpr std::string_view GreaterEqual = ">=";
2339
2327 static constexpr std::string_view Add = "Add"; 2340 static constexpr std::string_view Add = "Add";
2328 static constexpr std::string_view Min = "Min"; 2341 static constexpr std::string_view Min = "Min";
2329 static constexpr std::string_view Max = "Max"; 2342 static constexpr std::string_view Max = "Max";
@@ -2425,27 +2438,34 @@ private:
2425 &GLSLDecompiler::LogicalPick2, 2438 &GLSLDecompiler::LogicalPick2,
2426 &GLSLDecompiler::LogicalAnd2, 2439 &GLSLDecompiler::LogicalAnd2,
2427 2440
2428 &GLSLDecompiler::LogicalLessThan<Type::Float>, 2441 &GLSLDecompiler::Comparison<Func::LessThan, Type::Float, false>,
2429 &GLSLDecompiler::LogicalEqual<Type::Float>, 2442 &GLSLDecompiler::Comparison<Func::Equal, Type::Float, false>,
2430 &GLSLDecompiler::LogicalLessEqual<Type::Float>, 2443 &GLSLDecompiler::Comparison<Func::LessEqual, Type::Float, false>,
2431 &GLSLDecompiler::LogicalGreaterThan<Type::Float>, 2444 &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Float, false>,
2432 &GLSLDecompiler::LogicalNotEqual<Type::Float>, 2445 &GLSLDecompiler::Comparison<Func::NotEqual, Type::Float, false>,
2433 &GLSLDecompiler::LogicalGreaterEqual<Type::Float>, 2446 &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Float, false>,
2434 &GLSLDecompiler::LogicalFIsNan, 2447 &GLSLDecompiler::FOrdered,
2435 2448 &GLSLDecompiler::FUnordered,
2436 &GLSLDecompiler::LogicalLessThan<Type::Int>, 2449 &GLSLDecompiler::Comparison<Func::LessThan, Type::Float, true>,
2437 &GLSLDecompiler::LogicalEqual<Type::Int>, 2450 &GLSLDecompiler::Comparison<Func::Equal, Type::Float, true>,
2438 &GLSLDecompiler::LogicalLessEqual<Type::Int>, 2451 &GLSLDecompiler::Comparison<Func::LessEqual, Type::Float, true>,
2439 &GLSLDecompiler::LogicalGreaterThan<Type::Int>, 2452 &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Float, true>,
2440 &GLSLDecompiler::LogicalNotEqual<Type::Int>, 2453 &GLSLDecompiler::Comparison<Func::NotEqual, Type::Float, true>,
2441 &GLSLDecompiler::LogicalGreaterEqual<Type::Int>, 2454 &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Float, true>,
2442 2455
2443 &GLSLDecompiler::LogicalLessThan<Type::Uint>, 2456 &GLSLDecompiler::Comparison<Func::LessThan, Type::Int>,
2444 &GLSLDecompiler::LogicalEqual<Type::Uint>, 2457 &GLSLDecompiler::Comparison<Func::Equal, Type::Int>,
2445 &GLSLDecompiler::LogicalLessEqual<Type::Uint>, 2458 &GLSLDecompiler::Comparison<Func::LessEqual, Type::Int>,
2446 &GLSLDecompiler::LogicalGreaterThan<Type::Uint>, 2459 &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Int>,
2447 &GLSLDecompiler::LogicalNotEqual<Type::Uint>, 2460 &GLSLDecompiler::Comparison<Func::NotEqual, Type::Int>,
2448 &GLSLDecompiler::LogicalGreaterEqual<Type::Uint>, 2461 &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Int>,
2462
2463 &GLSLDecompiler::Comparison<Func::LessThan, Type::Uint>,
2464 &GLSLDecompiler::Comparison<Func::Equal, Type::Uint>,
2465 &GLSLDecompiler::Comparison<Func::LessEqual, Type::Uint>,
2466 &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Uint>,
2467 &GLSLDecompiler::Comparison<Func::NotEqual, Type::Uint>,
2468 &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Uint>,
2449 2469
2450 &GLSLDecompiler::LogicalAddCarry, 2470 &GLSLDecompiler::LogicalAddCarry,
2451 2471
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 18678968c..167e20e91 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1618,6 +1618,24 @@ private:
1618 return {}; 1618 return {};
1619 } 1619 }
1620 1620
1621 Expression LogicalFOrdered(Operation operation) {
1622 // Emulate SPIR-V's OpOrdered
1623 const Id op_a = AsFloat(Visit(operation[0]));
1624 const Id op_b = AsFloat(Visit(operation[1]));
1625 const Id is_num_a = OpFOrdEqual(t_bool, op_a, op_a);
1626 const Id is_num_b = OpFOrdEqual(t_bool, op_b, op_b);
1627 return {OpLogicalAnd(t_bool, is_num_a, is_num_b), Type::Bool};
1628 }
1629
1630 Expression LogicalFUnordered(Operation operation) {
1631 // Emulate SPIR-V's OpUnordered
1632 const Id op_a = AsFloat(Visit(operation[0]));
1633 const Id op_b = AsFloat(Visit(operation[1]));
1634 const Id is_nan_a = OpIsNan(t_bool, op_a);
1635 const Id is_nan_b = OpIsNan(t_bool, op_b);
1636 return {OpLogicalOr(t_bool, is_nan_a, is_nan_b), Type::Bool};
1637 }
1638
1621 Id GetTextureSampler(Operation operation) { 1639 Id GetTextureSampler(Operation operation) {
1622 const auto& meta = std::get<MetaTexture>(operation.GetMeta()); 1640 const auto& meta = std::get<MetaTexture>(operation.GetMeta());
1623 ASSERT(!meta.sampler.is_buffer); 1641 ASSERT(!meta.sampler.is_buffer);
@@ -2511,7 +2529,14 @@ private:
2511 &SPIRVDecompiler::Binary<&Module::OpFOrdGreaterThan, Type::Bool, Type::Float>, 2529 &SPIRVDecompiler::Binary<&Module::OpFOrdGreaterThan, Type::Bool, Type::Float>,
2512 &SPIRVDecompiler::Binary<&Module::OpFOrdNotEqual, Type::Bool, Type::Float>, 2530 &SPIRVDecompiler::Binary<&Module::OpFOrdNotEqual, Type::Bool, Type::Float>,
2513 &SPIRVDecompiler::Binary<&Module::OpFOrdGreaterThanEqual, Type::Bool, Type::Float>, 2531 &SPIRVDecompiler::Binary<&Module::OpFOrdGreaterThanEqual, Type::Bool, Type::Float>,
2514 &SPIRVDecompiler::Unary<&Module::OpIsNan, Type::Bool, Type::Float>, 2532 &SPIRVDecompiler::LogicalFOrdered,
2533 &SPIRVDecompiler::LogicalFUnordered,
2534 &SPIRVDecompiler::Binary<&Module::OpFUnordLessThan, Type::Bool, Type::Float>,
2535 &SPIRVDecompiler::Binary<&Module::OpFUnordEqual, Type::Bool, Type::Float>,
2536 &SPIRVDecompiler::Binary<&Module::OpFUnordLessThanEqual, Type::Bool, Type::Float>,
2537 &SPIRVDecompiler::Binary<&Module::OpFUnordGreaterThan, Type::Bool, Type::Float>,
2538 &SPIRVDecompiler::Binary<&Module::OpFUnordNotEqual, Type::Bool, Type::Float>,
2539 &SPIRVDecompiler::Binary<&Module::OpFUnordGreaterThanEqual, Type::Bool, Type::Float>,
2515 2540
2516 &SPIRVDecompiler::Binary<&Module::OpSLessThan, Type::Bool, Type::Int>, 2541 &SPIRVDecompiler::Binary<&Module::OpSLessThan, Type::Bool, Type::Int>,
2517 &SPIRVDecompiler::Binary<&Module::OpIEqual, Type::Bool, Type::Int>, 2542 &SPIRVDecompiler::Binary<&Module::OpIEqual, Type::Bool, Type::Int>,
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index a75a5cc63..eeac328a6 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -255,7 +255,7 @@ void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) {
255 Node n = Operation(OperationCode::Branch, Immediate(branch_case.address)); 255 Node n = Operation(OperationCode::Branch, Immediate(branch_case.address));
256 Node op_b = Immediate(branch_case.cmp_value); 256 Node op_b = Immediate(branch_case.cmp_value);
257 Node condition = 257 Node condition =
258 GetPredicateComparisonInteger(Tegra::Shader::PredCondition::Equal, false, op_a, op_b); 258 GetPredicateComparisonInteger(Tegra::Shader::PredCondition::EQ, false, op_a, op_b);
259 auto result = Conditional(condition, {n}); 259 auto result = Conditional(condition, {n});
260 bb.push_back(result); 260 bb.push_back(result);
261 global_code.push_back(result); 261 global_code.push_back(result);
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index 6191ffba1..c83dc6615 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -97,19 +97,19 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
97 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b); 97 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b);
98 } 98 }
99 case Tegra::Shader::XmadMode::CSfu: { 99 case Tegra::Shader::XmadMode::CSfu: {
100 const Node comp_a = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_a, 100 const Node comp_a =
101 op_a, Immediate(0)); 101 GetPredicateComparisonInteger(PredCondition::EQ, is_signed_a, op_a, Immediate(0));
102 const Node comp_b = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_b, 102 const Node comp_b =
103 op_b, Immediate(0)); 103 GetPredicateComparisonInteger(PredCondition::EQ, is_signed_b, op_b, Immediate(0));
104 const Node comp = Operation(OperationCode::LogicalOr, comp_a, comp_b); 104 const Node comp = Operation(OperationCode::LogicalOr, comp_a, comp_b);
105 105
106 const Node comp_minus_a = GetPredicateComparisonInteger( 106 const Node comp_minus_a = GetPredicateComparisonInteger(
107 PredCondition::NotEqual, is_signed_a, 107 PredCondition::NE, is_signed_a,
108 SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, op_a, 108 SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, op_a,
109 Immediate(0x80000000)), 109 Immediate(0x80000000)),
110 Immediate(0)); 110 Immediate(0));
111 const Node comp_minus_b = GetPredicateComparisonInteger( 111 const Node comp_minus_b = GetPredicateComparisonInteger(
112 PredCondition::NotEqual, is_signed_b, 112 PredCondition::NE, is_signed_b,
113 SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, op_b, 113 SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, op_b,
114 Immediate(0x80000000)), 114 Immediate(0x80000000)),
115 Immediate(0)); 115 Immediate(0));
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 601c822d2..f75b62240 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -110,13 +110,20 @@ enum class OperationCode {
110 LogicalPick2, /// (bool2 pair, uint index) -> bool 110 LogicalPick2, /// (bool2 pair, uint index) -> bool
111 LogicalAnd2, /// (bool2 a) -> bool 111 LogicalAnd2, /// (bool2 a) -> bool
112 112
113 LogicalFLessThan, /// (float a, float b) -> bool 113 LogicalFOrdLessThan, /// (float a, float b) -> bool
114 LogicalFEqual, /// (float a, float b) -> bool 114 LogicalFOrdEqual, /// (float a, float b) -> bool
115 LogicalFLessEqual, /// (float a, float b) -> bool 115 LogicalFOrdLessEqual, /// (float a, float b) -> bool
116 LogicalFGreaterThan, /// (float a, float b) -> bool 116 LogicalFOrdGreaterThan, /// (float a, float b) -> bool
117 LogicalFNotEqual, /// (float a, float b) -> bool 117 LogicalFOrdNotEqual, /// (float a, float b) -> bool
118 LogicalFGreaterEqual, /// (float a, float b) -> bool 118 LogicalFOrdGreaterEqual, /// (float a, float b) -> bool
119 LogicalFIsNan, /// (float a) -> bool 119 LogicalFOrdered, /// (float a, float b) -> bool
120 LogicalFUnordered, /// (float a, float b) -> bool
121 LogicalFUnordLessThan, /// (float a, float b) -> bool
122 LogicalFUnordEqual, /// (float a, float b) -> bool
123 LogicalFUnordLessEqual, /// (float a, float b) -> bool
124 LogicalFUnordGreaterThan, /// (float a, float b) -> bool
125 LogicalFUnordNotEqual, /// (float a, float b) -> bool
126 LogicalFUnordGreaterEqual, /// (float a, float b) -> bool
120 127
121 LogicalILessThan, /// (int a, int b) -> bool 128 LogicalILessThan, /// (int a, int b) -> bool
122 LogicalIEqual, /// (int a, int b) -> bool 129 LogicalIEqual, /// (int a, int b) -> bool
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 822674926..e322c3402 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -10,6 +10,7 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "video_core/engines/shader_bytecode.h" 12#include "video_core/engines/shader_bytecode.h"
13#include "video_core/shader/node.h"
13#include "video_core/shader/node_helper.h" 14#include "video_core/shader/node_helper.h"
14#include "video_core/shader/registry.h" 15#include "video_core/shader/registry.h"
15#include "video_core/shader/shader_ir.h" 16#include "video_core/shader/shader_ir.h"
@@ -243,56 +244,44 @@ Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) {
243} 244}
244 245
245Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { 246Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
247 if (condition == PredCondition::T) {
248 return GetPredicate(true);
249 } else if (condition == PredCondition::F) {
250 return GetPredicate(false);
251 }
252
246 static constexpr std::array comparison_table{ 253 static constexpr std::array comparison_table{
247 std::pair{PredCondition::LessThan, OperationCode::LogicalFLessThan}, 254 OperationCode(0),
248 std::pair{PredCondition::Equal, OperationCode::LogicalFEqual}, 255 OperationCode::LogicalFOrdLessThan, // LT
249 std::pair{PredCondition::LessEqual, OperationCode::LogicalFLessEqual}, 256 OperationCode::LogicalFOrdEqual, // EQ
250 std::pair{PredCondition::GreaterThan, OperationCode::LogicalFGreaterThan}, 257 OperationCode::LogicalFOrdLessEqual, // LE
251 std::pair{PredCondition::NotEqual, OperationCode::LogicalFNotEqual}, 258 OperationCode::LogicalFOrdGreaterThan, // GT
252 std::pair{PredCondition::GreaterEqual, OperationCode::LogicalFGreaterEqual}, 259 OperationCode::LogicalFOrdNotEqual, // NE
253 std::pair{PredCondition::LessThanWithNan, OperationCode::LogicalFLessThan}, 260 OperationCode::LogicalFOrdGreaterEqual, // GE
254 std::pair{PredCondition::NotEqualWithNan, OperationCode::LogicalFNotEqual}, 261 OperationCode::LogicalFOrdered, // NUM
255 std::pair{PredCondition::LessEqualWithNan, OperationCode::LogicalFLessEqual}, 262 OperationCode::LogicalFUnordered, // NAN
256 std::pair{PredCondition::GreaterThanWithNan, OperationCode::LogicalFGreaterThan}, 263 OperationCode::LogicalFUnordLessThan, // LTU
257 std::pair{PredCondition::GreaterEqualWithNan, OperationCode::LogicalFGreaterEqual}, 264 OperationCode::LogicalFUnordEqual, // EQU
265 OperationCode::LogicalFUnordLessEqual, // LEU
266 OperationCode::LogicalFUnordGreaterThan, // GTU
267 OperationCode::LogicalFUnordNotEqual, // NEU
268 OperationCode::LogicalFUnordGreaterEqual, // GEU
258 }; 269 };
270 const std::size_t index = static_cast<std::size_t>(condition);
271 ASSERT_MSG(index < std::size(comparison_table), "Invalid condition={}", index);
259 272
260 const auto comparison = 273 return Operation(comparison_table[index], op_a, op_b);
261 std::find_if(comparison_table.cbegin(), comparison_table.cend(),
262 [condition](const auto entry) { return condition == entry.first; });
263 UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(),
264 "Unknown predicate comparison operation");
265
266 Node predicate = Operation(comparison->second, NO_PRECISE, op_a, op_b);
267
268 if (condition == PredCondition::LessThanWithNan ||
269 condition == PredCondition::NotEqualWithNan ||
270 condition == PredCondition::LessEqualWithNan ||
271 condition == PredCondition::GreaterThanWithNan ||
272 condition == PredCondition::GreaterEqualWithNan) {
273 predicate = Operation(OperationCode::LogicalOr, predicate,
274 Operation(OperationCode::LogicalFIsNan, op_a));
275 predicate = Operation(OperationCode::LogicalOr, predicate,
276 Operation(OperationCode::LogicalFIsNan, op_b));
277 }
278
279 return predicate;
280} 274}
281 275
282Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a, 276Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a,
283 Node op_b) { 277 Node op_b) {
284 static constexpr std::array comparison_table{ 278 static constexpr std::array comparison_table{
285 std::pair{PredCondition::LessThan, OperationCode::LogicalILessThan}, 279 std::pair{PredCondition::LT, OperationCode::LogicalILessThan},
286 std::pair{PredCondition::Equal, OperationCode::LogicalIEqual}, 280 std::pair{PredCondition::EQ, OperationCode::LogicalIEqual},
287 std::pair{PredCondition::LessEqual, OperationCode::LogicalILessEqual}, 281 std::pair{PredCondition::LE, OperationCode::LogicalILessEqual},
288 std::pair{PredCondition::GreaterThan, OperationCode::LogicalIGreaterThan}, 282 std::pair{PredCondition::GT, OperationCode::LogicalIGreaterThan},
289 std::pair{PredCondition::NotEqual, OperationCode::LogicalINotEqual}, 283 std::pair{PredCondition::NE, OperationCode::LogicalINotEqual},
290 std::pair{PredCondition::GreaterEqual, OperationCode::LogicalIGreaterEqual}, 284 std::pair{PredCondition::GE, OperationCode::LogicalIGreaterEqual},
291 std::pair{PredCondition::LessThanWithNan, OperationCode::LogicalILessThan},
292 std::pair{PredCondition::NotEqualWithNan, OperationCode::LogicalINotEqual},
293 std::pair{PredCondition::LessEqualWithNan, OperationCode::LogicalILessEqual},
294 std::pair{PredCondition::GreaterThanWithNan, OperationCode::LogicalIGreaterThan},
295 std::pair{PredCondition::GreaterEqualWithNan, OperationCode::LogicalIGreaterEqual},
296 }; 285 };
297 286
298 const auto comparison = 287 const auto comparison =
@@ -301,32 +290,24 @@ Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_si
301 UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(), 290 UNIMPLEMENTED_IF_MSG(comparison == comparison_table.cend(),
302 "Unknown predicate comparison operation"); 291 "Unknown predicate comparison operation");
303 292
304 Node predicate = SignedOperation(comparison->second, is_signed, NO_PRECISE, std::move(op_a), 293 return SignedOperation(comparison->second, is_signed, NO_PRECISE, std::move(op_a),
305 std::move(op_b)); 294 std::move(op_b));
306
307 UNIMPLEMENTED_IF_MSG(condition == PredCondition::LessThanWithNan ||
308 condition == PredCondition::NotEqualWithNan ||
309 condition == PredCondition::LessEqualWithNan ||
310 condition == PredCondition::GreaterThanWithNan ||
311 condition == PredCondition::GreaterEqualWithNan,
312 "NaN comparisons for integers are not implemented");
313 return predicate;
314} 295}
315 296
316Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a, 297Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a,
317 Node op_b) { 298 Node op_b) {
318 static constexpr std::array comparison_table{ 299 static constexpr std::array comparison_table{
319 std::pair{PredCondition::LessThan, OperationCode::Logical2HLessThan}, 300 std::pair{PredCondition::LT, OperationCode::Logical2HLessThan},
320 std::pair{PredCondition::Equal, OperationCode::Logical2HEqual}, 301 std::pair{PredCondition::EQ, OperationCode::Logical2HEqual},
321 std::pair{PredCondition::LessEqual, OperationCode::Logical2HLessEqual}, 302 std::pair{PredCondition::LE, OperationCode::Logical2HLessEqual},
322 std::pair{PredCondition::GreaterThan, OperationCode::Logical2HGreaterThan}, 303 std::pair{PredCondition::GT, OperationCode::Logical2HGreaterThan},
323 std::pair{PredCondition::NotEqual, OperationCode::Logical2HNotEqual}, 304 std::pair{PredCondition::NE, OperationCode::Logical2HNotEqual},
324 std::pair{PredCondition::GreaterEqual, OperationCode::Logical2HGreaterEqual}, 305 std::pair{PredCondition::GE, OperationCode::Logical2HGreaterEqual},
325 std::pair{PredCondition::LessThanWithNan, OperationCode::Logical2HLessThanWithNan}, 306 std::pair{PredCondition::LTU, OperationCode::Logical2HLessThanWithNan},
326 std::pair{PredCondition::NotEqualWithNan, OperationCode::Logical2HNotEqualWithNan}, 307 std::pair{PredCondition::LEU, OperationCode::Logical2HLessEqualWithNan},
327 std::pair{PredCondition::LessEqualWithNan, OperationCode::Logical2HLessEqualWithNan}, 308 std::pair{PredCondition::GTU, OperationCode::Logical2HGreaterThanWithNan},
328 std::pair{PredCondition::GreaterThanWithNan, OperationCode::Logical2HGreaterThanWithNan}, 309 std::pair{PredCondition::NEU, OperationCode::Logical2HNotEqualWithNan},
329 std::pair{PredCondition::GreaterEqualWithNan, OperationCode::Logical2HGreaterEqualWithNan}, 310 std::pair{PredCondition::GEU, OperationCode::Logical2HGreaterEqualWithNan},
330 }; 311 };
331 312
332 const auto comparison = 313 const auto comparison =
@@ -397,7 +378,7 @@ void ShaderIR::SetInternalFlagsFromFloat(NodeBlock& bb, Node value, bool sets_cc
397 if (!sets_cc) { 378 if (!sets_cc) {
398 return; 379 return;
399 } 380 }
400 Node zerop = Operation(OperationCode::LogicalFEqual, std::move(value), Immediate(0.0f)); 381 Node zerop = Operation(OperationCode::LogicalFOrdEqual, std::move(value), Immediate(0.0f));
401 SetInternalFlag(bb, InternalFlag::Zero, std::move(zerop)); 382 SetInternalFlag(bb, InternalFlag::Zero, std::move(zerop));
402 LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete"); 383 LOG_WARNING(HW_GPU, "Condition codes implementation is incomplete");
403} 384}