diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 3 | ||||
| -rw-r--r-- | src/video_core/shader/decode/xmad.cpp | 39 |
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 |