summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp11
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp31
-rw-r--r--src/video_core/shader/decode/register_set_predicate.cpp52
-rw-r--r--src/video_core/shader/node.h2
6 files changed, 83 insertions, 27 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index cde3a26b9..8dae754d4 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -814,6 +814,10 @@ union Instruction {
814 } alu_integer; 814 } alu_integer;
815 815
816 union { 816 union {
817 BitField<43, 1, u64> x;
818 } iadd;
819
820 union {
817 BitField<39, 1, u64> ftz; 821 BitField<39, 1, u64> ftz;
818 BitField<32, 1, u64> saturate; 822 BitField<32, 1, u64> saturate;
819 BitField<49, 2, HalfMerge> merge; 823 BitField<49, 2, HalfMerge> merge;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 0cd3ad7e1..3803a6f3a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1870,6 +1870,14 @@ private:
1870 return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type); 1870 return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type);
1871 } 1871 }
1872 1872
1873 Expression LogicalAddCarry(Operation operation) {
1874 const std::string carry = code.GenerateTemporary();
1875 code.AddLine("uint {};", carry);
1876 code.AddLine("uaddCarry({}, {}, {});", VisitOperand(operation, 0).AsUint(),
1877 VisitOperand(operation, 1).AsUint(), carry);
1878 return {fmt::format("({} != 0)", carry), Type::Bool};
1879 }
1880
1873 Expression LogicalFIsNan(Operation operation) { 1881 Expression LogicalFIsNan(Operation operation) {
1874 return GenerateUnary(operation, "isnan", Type::Bool, Type::Float); 1882 return GenerateUnary(operation, "isnan", Type::Bool, Type::Float);
1875 } 1883 }
@@ -2441,6 +2449,8 @@ private:
2441 &GLSLDecompiler::LogicalNotEqual<Type::Uint>, 2449 &GLSLDecompiler::LogicalNotEqual<Type::Uint>,
2442 &GLSLDecompiler::LogicalGreaterEqual<Type::Uint>, 2450 &GLSLDecompiler::LogicalGreaterEqual<Type::Uint>,
2443 2451
2452 &GLSLDecompiler::LogicalAddCarry,
2453
2444 &GLSLDecompiler::Logical2HLessThan<false>, 2454 &GLSLDecompiler::Logical2HLessThan<false>,
2445 &GLSLDecompiler::Logical2HEqual<false>, 2455 &GLSLDecompiler::Logical2HEqual<false>,
2446 &GLSLDecompiler::Logical2HLessEqual<false>, 2456 &GLSLDecompiler::Logical2HLessEqual<false>,
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index aaa138f52..20b6ca0ad 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1584,6 +1584,15 @@ private:
1584 return {OpCompositeConstruct(t_half, low, high), Type::HalfFloat}; 1584 return {OpCompositeConstruct(t_half, low, high), Type::HalfFloat};
1585 } 1585 }
1586 1586
1587 Expression LogicalAddCarry(Operation operation) {
1588 const Id op_a = AsUint(Visit(operation[0]));
1589 const Id op_b = AsUint(Visit(operation[1]));
1590
1591 const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b);
1592 const Id carry = OpCompositeExtract(t_uint, result, 1);
1593 return {OpINotEqual(t_bool, carry, Constant(t_uint, 0)), Type::Bool};
1594 }
1595
1587 Expression LogicalAssign(Operation operation) { 1596 Expression LogicalAssign(Operation operation) {
1588 const Node& dest = operation[0]; 1597 const Node& dest = operation[0];
1589 const Node& src = operation[1]; 1598 const Node& src = operation[1];
@@ -2518,6 +2527,8 @@ private:
2518 &SPIRVDecompiler::Binary<&Module::OpINotEqual, Type::Bool, Type::Uint>, 2527 &SPIRVDecompiler::Binary<&Module::OpINotEqual, Type::Bool, Type::Uint>,
2519 &SPIRVDecompiler::Binary<&Module::OpUGreaterThanEqual, Type::Bool, Type::Uint>, 2528 &SPIRVDecompiler::Binary<&Module::OpUGreaterThanEqual, Type::Bool, Type::Uint>,
2520 2529
2530 &SPIRVDecompiler::LogicalAddCarry,
2531
2521 &SPIRVDecompiler::Binary<&Module::OpFOrdLessThan, Type::Bool2, Type::HalfFloat>, 2532 &SPIRVDecompiler::Binary<&Module::OpFOrdLessThan, Type::Bool2, Type::HalfFloat>,
2522 &SPIRVDecompiler::Binary<&Module::OpFOrdEqual, Type::Bool2, Type::HalfFloat>, 2533 &SPIRVDecompiler::Binary<&Module::OpFOrdEqual, Type::Bool2, Type::HalfFloat>,
2523 &SPIRVDecompiler::Binary<&Module::OpFOrdLessThanEqual, Type::Bool2, Type::HalfFloat>, 2534 &SPIRVDecompiler::Binary<&Module::OpFOrdLessThanEqual, Type::Bool2, Type::HalfFloat>,
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index 9af8c606d..a041519b7 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -35,15 +35,38 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
35 case OpCode::Id::IADD_C: 35 case OpCode::Id::IADD_C:
36 case OpCode::Id::IADD_R: 36 case OpCode::Id::IADD_R:
37 case OpCode::Id::IADD_IMM: { 37 case OpCode::Id::IADD_IMM: {
38 UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD saturation not implemented"); 38 UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD.SAT");
39 UNIMPLEMENTED_IF_MSG(instr.iadd.x && instr.generates_cc, "IADD.X Rd.CC");
39 40
40 op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true); 41 op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true);
41 op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true); 42 op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true);
42 43
43 const Node value = Operation(OperationCode::IAdd, PRECISE, op_a, op_b); 44 Node value = Operation(OperationCode::UAdd, op_a, op_b);
44 45
45 SetInternalFlagsFromInteger(bb, value, instr.generates_cc); 46 if (instr.iadd.x) {
46 SetRegister(bb, instr.gpr0, value); 47 Node carry = GetInternalFlag(InternalFlag::Carry);
48 Node x = Operation(OperationCode::Select, std::move(carry), Immediate(1), Immediate(0));
49 value = Operation(OperationCode::UAdd, std::move(value), std::move(x));
50 }
51
52 if (instr.generates_cc) {
53 const Node i0 = Immediate(0);
54
55 Node zero = Operation(OperationCode::LogicalIEqual, value, i0);
56 Node sign = Operation(OperationCode::LogicalILessThan, value, i0);
57 Node carry = Operation(OperationCode::LogicalAddCarry, op_a, op_b);
58
59 Node pos_a = Operation(OperationCode::LogicalIGreaterThan, op_a, i0);
60 Node pos_b = Operation(OperationCode::LogicalIGreaterThan, op_b, i0);
61 Node pos = Operation(OperationCode::LogicalAnd, std::move(pos_a), std::move(pos_b));
62 Node overflow = Operation(OperationCode::LogicalAnd, pos, sign);
63
64 SetInternalFlag(bb, InternalFlag::Zero, std::move(zero));
65 SetInternalFlag(bb, InternalFlag::Sign, std::move(sign));
66 SetInternalFlag(bb, InternalFlag::Carry, std::move(carry));
67 SetInternalFlag(bb, InternalFlag::Overflow, std::move(overflow));
68 }
69 SetRegister(bb, instr.gpr0, std::move(value));
47 break; 70 break;
48 } 71 }
49 case OpCode::Id::IADD3_C: 72 case OpCode::Id::IADD3_C:
diff --git a/src/video_core/shader/decode/register_set_predicate.cpp b/src/video_core/shader/decode/register_set_predicate.cpp
index 8d54cce34..6116c31aa 100644
--- a/src/video_core/shader/decode/register_set_predicate.cpp
+++ b/src/video_core/shader/decode/register_set_predicate.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <utility>
6
5#include "common/assert.h" 7#include "common/assert.h"
6#include "common/common_types.h" 8#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 9#include "video_core/engines/shader_bytecode.h"
@@ -10,20 +12,20 @@
10 12
11namespace VideoCommon::Shader { 13namespace VideoCommon::Shader {
12 14
15using std::move;
13using Tegra::Shader::Instruction; 16using Tegra::Shader::Instruction;
14using Tegra::Shader::OpCode; 17using Tegra::Shader::OpCode;
15 18
16namespace { 19namespace {
17constexpr u64 NUM_PROGRAMMABLE_PREDICATES = 7; 20constexpr u64 NUM_CONDITION_CODES = 4;
18} 21constexpr u64 NUM_PREDICATES = 7;
22} // namespace
19 23
20u32 ShaderIR::DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc) { 24u32 ShaderIR::DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc) {
21 const Instruction instr = {program_code[pc]}; 25 const Instruction instr = {program_code[pc]};
22 const auto opcode = OpCode::Decode(instr); 26 const auto opcode = OpCode::Decode(instr);
23 27
24 UNIMPLEMENTED_IF(instr.p2r_r2p.mode != Tegra::Shader::R2pMode::Pr); 28 Node apply_mask = [this, opcode, instr] {
25
26 const Node apply_mask = [&] {
27 switch (opcode->get().GetId()) { 29 switch (opcode->get().GetId()) {
28 case OpCode::Id::R2P_IMM: 30 case OpCode::Id::R2P_IMM:
29 case OpCode::Id::P2R_IMM: 31 case OpCode::Id::P2R_IMM:
@@ -34,39 +36,43 @@ u32 ShaderIR::DecodeRegisterSetPredicate(NodeBlock& bb, u32 pc) {
34 } 36 }
35 }(); 37 }();
36 38
37 const auto offset = static_cast<u32>(instr.p2r_r2p.byte) * 8; 39 const u32 offset = static_cast<u32>(instr.p2r_r2p.byte) * 8;
40
41 const bool cc = instr.p2r_r2p.mode == Tegra::Shader::R2pMode::Cc;
42 const u64 num_entries = cc ? NUM_CONDITION_CODES : NUM_PREDICATES;
43 const auto get_entry = [this, cc](u64 entry) {
44 return cc ? GetInternalFlag(static_cast<InternalFlag>(entry)) : GetPredicate(entry);
45 };
38 46
39 switch (opcode->get().GetId()) { 47 switch (opcode->get().GetId()) {
40 case OpCode::Id::R2P_IMM: { 48 case OpCode::Id::R2P_IMM: {
41 const Node mask = GetRegister(instr.gpr8); 49 Node mask = GetRegister(instr.gpr8);
42 50
43 for (u64 pred = 0; pred < NUM_PROGRAMMABLE_PREDICATES; ++pred) { 51 for (u64 entry = 0; entry < num_entries; ++entry) {
44 const auto shift = static_cast<u32>(pred); 52 const u32 shift = static_cast<u32>(entry);
45 53
46 const Node apply_compare = BitfieldExtract(apply_mask, shift, 1); 54 Node apply = BitfieldExtract(apply_mask, shift, 1);
47 const Node condition = 55 Node condition = Operation(OperationCode::LogicalUNotEqual, apply, Immediate(0));
48 Operation(OperationCode::LogicalUNotEqual, apply_compare, Immediate(0));
49 56
50 const Node value_compare = BitfieldExtract(mask, offset + shift, 1); 57 Node compare = BitfieldExtract(mask, offset + shift, 1);
51 const Node value = 58 Node value = Operation(OperationCode::LogicalUNotEqual, move(compare), Immediate(0));
52 Operation(OperationCode::LogicalUNotEqual, value_compare, Immediate(0));
53 59
54 const Node code = Operation(OperationCode::LogicalAssign, GetPredicate(pred), value); 60 Node code = Operation(OperationCode::LogicalAssign, get_entry(entry), move(value));
55 bb.push_back(Conditional(condition, {code})); 61 bb.push_back(Conditional(condition, {move(code)}));
56 } 62 }
57 break; 63 break;
58 } 64 }
59 case OpCode::Id::P2R_IMM: { 65 case OpCode::Id::P2R_IMM: {
60 Node value = Immediate(0); 66 Node value = Immediate(0);
61 for (u64 pred = 0; pred < NUM_PROGRAMMABLE_PREDICATES; ++pred) { 67 for (u64 entry = 0; entry < num_entries; ++entry) {
62 Node bit = Operation(OperationCode::Select, GetPredicate(pred), Immediate(1U << pred), 68 Node bit = Operation(OperationCode::Select, get_entry(entry), Immediate(1U << entry),
63 Immediate(0)); 69 Immediate(0));
64 value = Operation(OperationCode::UBitwiseOr, std::move(value), std::move(bit)); 70 value = Operation(OperationCode::UBitwiseOr, move(value), move(bit));
65 } 71 }
66 value = Operation(OperationCode::UBitwiseAnd, std::move(value), apply_mask); 72 value = Operation(OperationCode::UBitwiseAnd, move(value), apply_mask);
67 value = BitfieldInsert(GetRegister(instr.gpr8), std::move(value), offset, 8); 73 value = BitfieldInsert(GetRegister(instr.gpr8), move(value), offset, 8);
68 74
69 SetRegister(bb, instr.gpr0, std::move(value)); 75 SetRegister(bb, instr.gpr0, move(value));
70 break; 76 break;
71 } 77 }
72 default: 78 default:
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 3eee961f5..3f5a7bc7a 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -132,6 +132,8 @@ enum class OperationCode {
132 LogicalUNotEqual, /// (uint a, uint b) -> bool 132 LogicalUNotEqual, /// (uint a, uint b) -> bool
133 LogicalUGreaterEqual, /// (uint a, uint b) -> bool 133 LogicalUGreaterEqual, /// (uint a, uint b) -> bool
134 134
135 LogicalAddCarry, /// (uint a, uint b) -> bool
136
135 Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 137 Logical2HLessThan, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
136 Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 138 Logical2HEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2
137 Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 139 Logical2HLessEqual, /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2