diff options
| author | 2020-03-13 19:01:49 +0700 | |
|---|---|---|
| committer | 2020-03-13 19:01:49 +0700 | |
| commit | a16621748028057aa78ddd71ea8e478162212073 (patch) | |
| tree | f0ece9a49a60afc39bf26dff80057c5123585f5a /src | |
| parent | Merge pull request #3483 from namkazt/patch-1 (diff) | |
| download | yuzu-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.cpp | 50 |
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 | ||
| 13 | using Tegra::Shader::Instruction; | 13 | using Tegra::Shader::Instruction; |
| 14 | using Tegra::Shader::OpCode; | 14 | using Tegra::Shader::OpCode; |
| 15 | using Tegra::Shader::PredCondition; | ||
| 15 | 16 | ||
| 16 | u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) { | 17 | u32 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 | }(); |