summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h3
-rw-r--r--src/video_core/shader/decode/xmad.cpp39
2 files changed, 33 insertions, 9 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 363e53be1..2e1e96c81 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1238,13 +1238,16 @@ union Instruction {
1238 1238
1239 union { 1239 union {
1240 BitField<20, 16, u64> imm20_16; 1240 BitField<20, 16, u64> imm20_16;
1241 BitField<35, 1, u64> high_b_rr; // used on RR
1241 BitField<36, 1, u64> product_shift_left; 1242 BitField<36, 1, u64> product_shift_left;
1242 BitField<37, 1, u64> merge_37; 1243 BitField<37, 1, u64> merge_37;
1243 BitField<48, 1, u64> sign_a; 1244 BitField<48, 1, u64> sign_a;
1244 BitField<49, 1, u64> sign_b; 1245 BitField<49, 1, u64> sign_b;
1246 BitField<50, 2, XmadMode> mode_cbf; // used by CR, RC
1245 BitField<50, 3, XmadMode> mode; 1247 BitField<50, 3, XmadMode> mode;
1246 BitField<52, 1, u64> high_b; 1248 BitField<52, 1, u64> high_b;
1247 BitField<53, 1, u64> high_a; 1249 BitField<53, 1, u64> high_a;
1250 BitField<55, 1, u64> product_shift_left_second; // used on CR
1248 BitField<56, 1, u64> merge_56; 1251 BitField<56, 1, u64> merge_56;
1249 } xmad; 1252 } xmad;
1250 1253
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index c34843307..db15c0718 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -29,39 +29,55 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
29 const bool is_signed_b = instr.xmad.sign_b == 1; 29 const bool is_signed_b = instr.xmad.sign_b == 1;
30 const bool is_signed_c = is_signed_a; 30 const bool is_signed_c = is_signed_a;
31 31
32 auto [is_merge, op_b, op_c] = [&]() -> std::tuple<bool, Node, Node> { 32 auto [is_merge, is_psl, is_high_b, mode, op_b,
33 op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> {
33 switch (opcode->get().GetId()) { 34 switch (opcode->get().GetId()) {
34 case OpCode::Id::XMAD_CR: 35 case OpCode::Id::XMAD_CR:
35 return {instr.xmad.merge_56, 36 return {instr.xmad.merge_56,
37 instr.xmad.product_shift_left_second,
38 instr.xmad.high_b,
39 instr.xmad.mode_cbf,
36 GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()), 40 GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()),
37 GetRegister(instr.gpr39)}; 41 GetRegister(instr.gpr39)};
38 case OpCode::Id::XMAD_RR: 42 case OpCode::Id::XMAD_RR:
39 return {instr.xmad.merge_37, GetRegister(instr.gpr20), GetRegister(instr.gpr39)}; 43 return {instr.xmad.merge_37, instr.xmad.product_shift_left, instr.xmad.high_b_rr,
44 instr.xmad.mode, GetRegister(instr.gpr20), GetRegister(instr.gpr39)};
40 case OpCode::Id::XMAD_RC: 45 case OpCode::Id::XMAD_RC:
41 return {false, GetRegister(instr.gpr39), 46 return {false,
47 false,
48 instr.xmad.high_b,
49 instr.xmad.mode_cbf,
50 GetRegister(instr.gpr39),
42 GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset())}; 51 GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset())};
43 case OpCode::Id::XMAD_IMM: 52 case OpCode::Id::XMAD_IMM:
44 return {instr.xmad.merge_37, Immediate(static_cast<u32>(instr.xmad.imm20_16)), 53 return {instr.xmad.merge_37,
54 instr.xmad.product_shift_left,
55 false,
56 instr.xmad.mode,
57 Immediate(static_cast<u32>(instr.xmad.imm20_16)),
45 GetRegister(instr.gpr39)}; 58 GetRegister(instr.gpr39)};
46 } 59 }
47 UNIMPLEMENTED_MSG("Unhandled XMAD instruction: {}", opcode->get().GetName()); 60 UNIMPLEMENTED_MSG("Unhandled XMAD instruction: {}", opcode->get().GetName());
48 return {false, Immediate(0), Immediate(0)}; 61 return {false, false, false, Tegra::Shader::XmadMode::None, Immediate(0), Immediate(0)};
49 }(); 62 }();
50 63
51 op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16); 64 op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16);
52 65
53 const Node original_b = op_b; 66 const Node original_b = op_b;
54 op_b = BitfieldExtract(op_b, instr.xmad.high_b ? 16 : 0, 16); 67 op_b = BitfieldExtract(op_b, is_high_b ? 16 : 0, 16);
55 68
56 // TODO(Rodrigo): Use an appropiate sign for this operation 69 // TODO(Rodrigo): Use an appropiate sign for this operation
57 Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b); 70 Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b);
58 if (instr.xmad.product_shift_left) { 71 if (is_psl) {
59 product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16)); 72 product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16));
60 } 73 }
74 SetTemporal(bb, 0, product);
75 product = GetTemporal(0);
61 76
62 const Node original_c = op_c; 77 const Node original_c = op_c;
78 const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error
63 op_c = [&]() { 79 op_c = [&]() {
64 switch (instr.xmad.mode) { 80 switch (set_mode) {
65 case Tegra::Shader::XmadMode::None: 81 case Tegra::Shader::XmadMode::None:
66 return original_c; 82 return original_c;
67 case Tegra::Shader::XmadMode::CLo: 83 case Tegra::Shader::XmadMode::CLo:
@@ -80,8 +96,13 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
80 } 96 }
81 }(); 97 }();
82 98
99 SetTemporal(bb, 1, op_c);
100 op_c = GetTemporal(1);
101
83 // TODO(Rodrigo): Use an appropiate sign for this operation 102 // TODO(Rodrigo): Use an appropiate sign for this operation
84 Node sum = Operation(OperationCode::IAdd, product, op_c); 103 Node sum = Operation(OperationCode::IAdd, product, op_c);
104 SetTemporal(bb, 2, sum);
105 sum = GetTemporal(2);
85 if (is_merge) { 106 if (is_merge) {
86 const Node a = BitfieldExtract(sum, 0, 16); 107 const Node a = BitfieldExtract(sum, 0, 16);
87 const Node b = 108 const Node b =
@@ -95,4 +116,4 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
95 return pc; 116 return pc;
96} 117}
97 118
98} // namespace VideoCommon::Shader \ No newline at end of file 119} // namespace VideoCommon::Shader