summaryrefslogtreecommitdiff
path: root/src/video_core/shader
diff options
context:
space:
mode:
authorGravatar bunnei2020-04-30 12:56:36 -0400
committerGravatar GitHub2020-04-30 12:56:36 -0400
commitc7b5a87c9038f37e5fec07336de575498a84b534 (patch)
treeaaefec229f8ddcb6744b405757d2559c1dcf0b92 /src/video_core/shader
parentMerge pull request #3805 from ReinUsesLisp/preserve-contents (diff)
parentshader/arithmetic_integer: Fix tracking issue in temporary (diff)
downloadyuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.gz
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.xz
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.zip
Merge pull request #3799 from ReinUsesLisp/iadd-cc
shader: Implement P2R CC, IADD Rd.CC and IADD.X
Diffstat (limited to 'src/video_core/shader')
-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
3 files changed, 58 insertions, 27 deletions
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