summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Nguyen Dac Nam2020-03-13 19:01:49 +0700
committerGravatar GitHub2020-03-13 19:01:49 +0700
commita16621748028057aa78ddd71ea8e478162212073 (patch)
treef0ece9a49a60afc39bf26dff80057c5123585f5a /src
parentMerge pull request #3483 from namkazt/patch-1 (diff)
downloadyuzu-a16621748028057aa78ddd71ea8e478162212073.tar.gz
yuzu-a16621748028057aa78ddd71ea8e478162212073.tar.xz
yuzu-a16621748028057aa78ddd71ea8e478162212073.zip
shader_decode: implement XMAD mode CSfu
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/decode/xmad.cpp50
1 files changed, 41 insertions, 9 deletions
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index 206961909..61d23649d 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -12,6 +12,7 @@ namespace VideoCommon::Shader {
12 12
13using Tegra::Shader::Instruction; 13using Tegra::Shader::Instruction;
14using Tegra::Shader::OpCode; 14using Tegra::Shader::OpCode;
15using Tegra::Shader::PredCondition;
15 16
16u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) { 17u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
17 const Instruction instr = {program_code[pc]}; 18 const Instruction instr = {program_code[pc]};
@@ -63,15 +64,18 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
63 } 64 }
64 }(); 65 }();
65 66
66 op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16); 67 op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a),
68 instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16));
67 69
68 const Node original_b = op_b; 70 const Node original_b = op_b;
69 op_b = BitfieldExtract(op_b, is_high_b ? 16 : 0, 16); 71 op_b = SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b),
72 is_high_b ? Immediate(16) : Immediate(0), Immediate(16));
70 73
71 // TODO(Rodrigo): Use an appropiate sign for this operation 74 // we already check sign_a and sign_b is difference or not before so just use one in here.
72 Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b); 75 Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b);
73 if (is_psl) { 76 if (is_psl) {
74 product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16)); 77 product =
78 SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_a, product, Immediate(16));
75 } 79 }
76 SetTemporary(bb, 0, product); 80 SetTemporary(bb, 0, product);
77 product = GetTemporary(0); 81 product = GetTemporary(0);
@@ -88,12 +92,40 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
88 return BitfieldExtract(original_c, 16, 16); 92 return BitfieldExtract(original_c, 16, 16);
89 case Tegra::Shader::XmadMode::CBcc: { 93 case Tegra::Shader::XmadMode::CBcc: {
90 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, 94 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
91 NO_PRECISE, original_b, Immediate(16)); 95 original_b, Immediate(16));
92 return SignedOperation(OperationCode::IAdd, is_signed_c, NO_PRECISE, original_c, 96 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b);
93 shifted_b); 97 }
98 case Tegra::Shader::XmadMode::CSfu: {
99 const Node comp_a = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_a,
100 op_a, Immediate(0));
101 const Node comp_b = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_b,
102 op_b, Immediate(0));
103 const Node comp =
104 Operation(OperationCode::LogicalOr, std::move(comp_a), std::move(comp_b));
105
106 const Node comp_minus_a = GetPredicateComparisonInteger(
107 PredCondition::NotEqual, is_signed_a,
108 SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, op_a,
109 Immediate(0x80000000)),
110 Immediate(0));
111 const Node comp_minus_b = GetPredicateComparisonInteger(
112 PredCondition::NotEqual, is_signed_b,
113 SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, op_b,
114 Immediate(0x80000000)),
115 Immediate(0));
116
117 Node new_c = Operation(
118 OperationCode::Select, comp_minus_a,
119 SignedOperation(OperationCode::IAdd, is_signed_c, original_c, Immediate(-65536)),
120 original_c);
121 new_c = Operation(
122 OperationCode::Select, comp_minus_b,
123 SignedOperation(OperationCode::IAdd, is_signed_c, new_c, Immediate(-65536)), new_c);
124
125 return Operation(OperationCode::Select, comp, original_c, new_c);
94 } 126 }
95 default: 127 default:
96 UNIMPLEMENTED_MSG("Unhandled XMAD mode: {}", static_cast<u32>(instr.xmad.mode.Value())); 128 UNREACHABLE();
97 return Immediate(0); 129 return Immediate(0);
98 } 130 }
99 }(); 131 }();