diff options
| author | 2020-05-09 04:55:15 -0300 | |
|---|---|---|
| committer | 2020-05-09 04:55:15 -0300 | |
| commit | 4e57f9d5cfc32b37fe7b6a1563ca2101ec59887c (patch) | |
| tree | 057619ab05268d2c757dda7f5cec30c319a56bcb /src | |
| parent | Merge pull request #3879 from lioncash/global2 (diff) | |
| download | yuzu-4e57f9d5cfc32b37fe7b6a1563ca2101ec59887c.tar.gz yuzu-4e57f9d5cfc32b37fe7b6a1563ca2101ec59887c.tar.xz yuzu-4e57f9d5cfc32b37fe7b6a1563ca2101ec59887c.zip | |
shader_ir: Separate float-point comparisons in ordered and unordered
This allows us to use native SPIR-V instructions without having to
manually check for NAN.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 28 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 99 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/shader/decode.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/xmad.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 21 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 109 |
7 files changed, 163 insertions, 135 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 | ||
| 170 | enum class PredCondition : u64 { | 170 | enum 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 | ||
| 185 | enum class PredOperation : u64 { | 189 | enum 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..d071abd84 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1840,34 +1840,31 @@ 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 | } | ||
| 1847 | |||
| 1848 | template <Type type> | ||
| 1849 | Expression LogicalEqual(Operation operation) { | ||
| 1850 | return GenerateBinaryInfix(operation, "==", Type::Bool, type, type); | ||
| 1851 | } | ||
| 1852 | 1846 | ||
| 1853 | template <Type type> | 1847 | const Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type); |
| 1854 | Expression LogicalLessEqual(Operation operation) { | 1848 | if constexpr (!unordered) { |
| 1855 | return GenerateBinaryInfix(operation, "<=", Type::Bool, type, type); | 1849 | return expr; |
| 1856 | } | 1850 | } |
| 1857 | 1851 | // Unordered comparisons are always true for NaN operands. | |
| 1858 | template <Type type> | 1852 | return {fmt::format("({} || isnan({}) || isnan({}))", expr.AsBool(), |
| 1859 | Expression LogicalGreaterThan(Operation operation) { | 1853 | VisitOperand(operation, 0).AsFloat(), |
| 1860 | return GenerateBinaryInfix(operation, ">", Type::Bool, type, type); | 1854 | VisitOperand(operation, 1).AsFloat()), |
| 1855 | Type::Bool}; | ||
| 1861 | } | 1856 | } |
| 1862 | 1857 | ||
| 1863 | template <Type type> | 1858 | Expression FOrdered(Operation operation) { |
| 1864 | Expression LogicalNotEqual(Operation operation) { | 1859 | return {fmt::format("(!isnan({}) && !isnan({}))", VisitOperand(operation, 0).AsFloat(), |
| 1865 | return GenerateBinaryInfix(operation, "!=", Type::Bool, type, type); | 1860 | VisitOperand(operation, 1).AsFloat()), |
| 1861 | Type::Bool}; | ||
| 1866 | } | 1862 | } |
| 1867 | 1863 | ||
| 1868 | template <Type type> | 1864 | Expression FUnordered(Operation operation) { |
| 1869 | Expression LogicalGreaterEqual(Operation operation) { | 1865 | return {fmt::format("(isnan({}) || isnan({}))", VisitOperand(operation, 0).AsFloat(), |
| 1870 | return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type); | 1866 | VisitOperand(operation, 1).AsFloat()), |
| 1867 | Type::Bool}; | ||
| 1871 | } | 1868 | } |
| 1872 | 1869 | ||
| 1873 | Expression LogicalAddCarry(Operation operation) { | 1870 | Expression LogicalAddCarry(Operation operation) { |
| @@ -2324,6 +2321,13 @@ private: | |||
| 2324 | Func() = delete; | 2321 | Func() = delete; |
| 2325 | ~Func() = delete; | 2322 | ~Func() = delete; |
| 2326 | 2323 | ||
| 2324 | static constexpr std::string_view LessThan = "<"; | ||
| 2325 | static constexpr std::string_view Equal = "=="; | ||
| 2326 | static constexpr std::string_view LessEqual = "<="; | ||
| 2327 | static constexpr std::string_view GreaterThan = ">"; | ||
| 2328 | static constexpr std::string_view NotEqual = "!="; | ||
| 2329 | static constexpr std::string_view GreaterEqual = ">="; | ||
| 2330 | |||
| 2327 | static constexpr std::string_view Add = "Add"; | 2331 | static constexpr std::string_view Add = "Add"; |
| 2328 | static constexpr std::string_view Min = "Min"; | 2332 | static constexpr std::string_view Min = "Min"; |
| 2329 | static constexpr std::string_view Max = "Max"; | 2333 | static constexpr std::string_view Max = "Max"; |
| @@ -2425,27 +2429,34 @@ private: | |||
| 2425 | &GLSLDecompiler::LogicalPick2, | 2429 | &GLSLDecompiler::LogicalPick2, |
| 2426 | &GLSLDecompiler::LogicalAnd2, | 2430 | &GLSLDecompiler::LogicalAnd2, |
| 2427 | 2431 | ||
| 2428 | &GLSLDecompiler::LogicalLessThan<Type::Float>, | 2432 | &GLSLDecompiler::Comparison<Func::LessThan, Type::Float, false>, |
| 2429 | &GLSLDecompiler::LogicalEqual<Type::Float>, | 2433 | &GLSLDecompiler::Comparison<Func::Equal, Type::Float, false>, |
| 2430 | &GLSLDecompiler::LogicalLessEqual<Type::Float>, | 2434 | &GLSLDecompiler::Comparison<Func::LessEqual, Type::Float, false>, |
| 2431 | &GLSLDecompiler::LogicalGreaterThan<Type::Float>, | 2435 | &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Float, false>, |
| 2432 | &GLSLDecompiler::LogicalNotEqual<Type::Float>, | 2436 | &GLSLDecompiler::Comparison<Func::NotEqual, Type::Float, false>, |
| 2433 | &GLSLDecompiler::LogicalGreaterEqual<Type::Float>, | 2437 | &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Float, false>, |
| 2434 | &GLSLDecompiler::LogicalFIsNan, | 2438 | &GLSLDecompiler::FOrdered, |
| 2435 | 2439 | &GLSLDecompiler::FUnordered, | |
| 2436 | &GLSLDecompiler::LogicalLessThan<Type::Int>, | 2440 | &GLSLDecompiler::Comparison<Func::LessThan, Type::Float, true>, |
| 2437 | &GLSLDecompiler::LogicalEqual<Type::Int>, | 2441 | &GLSLDecompiler::Comparison<Func::Equal, Type::Float, true>, |
| 2438 | &GLSLDecompiler::LogicalLessEqual<Type::Int>, | 2442 | &GLSLDecompiler::Comparison<Func::LessEqual, Type::Float, true>, |
| 2439 | &GLSLDecompiler::LogicalGreaterThan<Type::Int>, | 2443 | &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Float, true>, |
| 2440 | &GLSLDecompiler::LogicalNotEqual<Type::Int>, | 2444 | &GLSLDecompiler::Comparison<Func::NotEqual, Type::Float, true>, |
| 2441 | &GLSLDecompiler::LogicalGreaterEqual<Type::Int>, | 2445 | &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Float, true>, |
| 2442 | 2446 | ||
| 2443 | &GLSLDecompiler::LogicalLessThan<Type::Uint>, | 2447 | &GLSLDecompiler::Comparison<Func::LessThan, Type::Int>, |
| 2444 | &GLSLDecompiler::LogicalEqual<Type::Uint>, | 2448 | &GLSLDecompiler::Comparison<Func::Equal, Type::Int>, |
| 2445 | &GLSLDecompiler::LogicalLessEqual<Type::Uint>, | 2449 | &GLSLDecompiler::Comparison<Func::LessEqual, Type::Int>, |
| 2446 | &GLSLDecompiler::LogicalGreaterThan<Type::Uint>, | 2450 | &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Int>, |
| 2447 | &GLSLDecompiler::LogicalNotEqual<Type::Uint>, | 2451 | &GLSLDecompiler::Comparison<Func::NotEqual, Type::Int>, |
| 2448 | &GLSLDecompiler::LogicalGreaterEqual<Type::Uint>, | 2452 | &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Int>, |
| 2453 | |||
| 2454 | &GLSLDecompiler::Comparison<Func::LessThan, Type::Uint>, | ||
| 2455 | &GLSLDecompiler::Comparison<Func::Equal, Type::Uint>, | ||
| 2456 | &GLSLDecompiler::Comparison<Func::LessEqual, Type::Uint>, | ||
| 2457 | &GLSLDecompiler::Comparison<Func::GreaterThan, Type::Uint>, | ||
| 2458 | &GLSLDecompiler::Comparison<Func::NotEqual, Type::Uint>, | ||
| 2459 | &GLSLDecompiler::Comparison<Func::GreaterEqual, Type::Uint>, | ||
| 2449 | 2460 | ||
| 2450 | &GLSLDecompiler::LogicalAddCarry, | 2461 | &GLSLDecompiler::LogicalAddCarry, |
| 2451 | 2462 | ||
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 | ||
| 245 | Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { | 246 | Node 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 | ||
| 282 | Node ShaderIR::GetPredicateComparisonInteger(PredCondition condition, bool is_signed, Node op_a, | 276 | Node 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 | ||
| 316 | Node ShaderIR::GetPredicateComparisonHalf(Tegra::Shader::PredCondition condition, Node op_a, | 297 | Node 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 | } |