diff options
| author | 2020-03-15 21:23:04 -0300 | |
|---|---|---|
| committer | 2020-03-15 21:23:04 -0300 | |
| commit | ddafc997763dc67f790958e04a8c07a5317da549 (patch) | |
| tree | da411c4e5830153005d25922218aa837fc83928b | |
| parent | Merge pull request #3503 from makigumo/patch-2 (diff) | |
| parent | clang-format (diff) | |
| download | yuzu-ddafc997763dc67f790958e04a8c07a5317da549.tar.gz yuzu-ddafc997763dc67f790958e04a8c07a5317da549.tar.xz yuzu-ddafc997763dc67f790958e04a8c07a5317da549.zip | |
Merge pull request #3502 from namkazt/patch-3
shader_decode: Reimplement BFE instructions
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 11 | ||||
| -rw-r--r-- | src/video_core/shader/decode/bfe.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/shader/node_helper.cpp | 2 |
3 files changed, 53 insertions, 29 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index c9bc83cd7..eba42deb4 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -911,14 +911,9 @@ union Instruction { | |||
| 911 | } fadd32i; | 911 | } fadd32i; |
| 912 | 912 | ||
| 913 | union { | 913 | union { |
| 914 | BitField<20, 8, u64> shift_position; | 914 | BitField<40, 1, u64> brev; |
| 915 | BitField<28, 8, u64> shift_length; | 915 | BitField<47, 1, u64> rd_cc; |
| 916 | BitField<48, 1, u64> negate_b; | 916 | BitField<48, 1, u64> is_signed; |
| 917 | BitField<49, 1, u64> negate_a; | ||
| 918 | |||
| 919 | u64 GetLeftShiftValue() const { | ||
| 920 | return 32 - (shift_position + shift_length); | ||
| 921 | } | ||
| 922 | } bfe; | 917 | } bfe; |
| 923 | 918 | ||
| 924 | union { | 919 | union { |
diff --git a/src/video_core/shader/decode/bfe.cpp b/src/video_core/shader/decode/bfe.cpp index e02bcd097..8e3b46e8e 100644 --- a/src/video_core/shader/decode/bfe.cpp +++ b/src/video_core/shader/decode/bfe.cpp | |||
| @@ -17,33 +17,60 @@ u32 ShaderIR::DecodeBfe(NodeBlock& bb, u32 pc) { | |||
| 17 | const Instruction instr = {program_code[pc]}; | 17 | const Instruction instr = {program_code[pc]}; |
| 18 | const auto opcode = OpCode::Decode(instr); | 18 | const auto opcode = OpCode::Decode(instr); |
| 19 | 19 | ||
| 20 | UNIMPLEMENTED_IF(instr.bfe.negate_b); | ||
| 21 | |||
| 22 | Node op_a = GetRegister(instr.gpr8); | 20 | Node op_a = GetRegister(instr.gpr8); |
| 23 | op_a = GetOperandAbsNegInteger(op_a, false, instr.bfe.negate_a, false); | 21 | Node op_b = [&] { |
| 24 | 22 | switch (opcode->get().GetId()) { | |
| 25 | switch (opcode->get().GetId()) { | 23 | case OpCode::Id::BFE_R: |
| 26 | case OpCode::Id::BFE_IMM: { | 24 | return GetRegister(instr.gpr20); |
| 27 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 25 | case OpCode::Id::BFE_C: |
| 28 | "Condition codes generation in BFE is not implemented"); | 26 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); |
| 27 | case OpCode::Id::BFE_IMM: | ||
| 28 | return Immediate(instr.alu.GetSignedImm20_20()); | ||
| 29 | default: | ||
| 30 | UNREACHABLE(); | ||
| 31 | return Immediate(0); | ||
| 32 | } | ||
| 33 | }(); | ||
| 29 | 34 | ||
| 30 | const Node inner_shift_imm = Immediate(static_cast<u32>(instr.bfe.GetLeftShiftValue())); | 35 | UNIMPLEMENTED_IF_MSG(instr.bfe.rd_cc, "Condition codes in BFE is not implemented"); |
| 31 | const Node outer_shift_imm = | ||
| 32 | Immediate(static_cast<u32>(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position)); | ||
| 33 | 36 | ||
| 34 | const Node inner_shift = | 37 | const bool is_signed = instr.bfe.is_signed; |
| 35 | Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, op_a, inner_shift_imm); | ||
| 36 | const Node outer_shift = | ||
| 37 | Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, inner_shift, outer_shift_imm); | ||
| 38 | 38 | ||
| 39 | SetInternalFlagsFromInteger(bb, outer_shift, instr.generates_cc); | 39 | // using reverse parallel method in |
| 40 | SetRegister(bb, instr.gpr0, outer_shift); | 40 | // https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel |
| 41 | break; | 41 | // note for later if possible to implement faster method. |
| 42 | } | 42 | if (instr.bfe.brev) { |
| 43 | default: | 43 | const auto swap = [&](u32 s, u32 mask) { |
| 44 | UNIMPLEMENTED_MSG("Unhandled BFE instruction: {}", opcode->get().GetName()); | 44 | Node v1 = |
| 45 | SignedOperation(OperationCode::ILogicalShiftRight, is_signed, op_a, Immediate(s)); | ||
| 46 | if (mask != 0) { | ||
| 47 | v1 = SignedOperation(OperationCode::IBitwiseAnd, is_signed, std::move(v1), | ||
| 48 | Immediate(mask)); | ||
| 49 | } | ||
| 50 | Node v2 = op_a; | ||
| 51 | if (mask != 0) { | ||
| 52 | v2 = SignedOperation(OperationCode::IBitwiseAnd, is_signed, std::move(v2), | ||
| 53 | Immediate(mask)); | ||
| 54 | } | ||
| 55 | v2 = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed, std::move(v2), | ||
| 56 | Immediate(s)); | ||
| 57 | return SignedOperation(OperationCode::IBitwiseOr, is_signed, std::move(v1), | ||
| 58 | std::move(v2)); | ||
| 59 | }; | ||
| 60 | op_a = swap(1, 0x55555555U); | ||
| 61 | op_a = swap(2, 0x33333333U); | ||
| 62 | op_a = swap(4, 0x0F0F0F0FU); | ||
| 63 | op_a = swap(8, 0x00FF00FFU); | ||
| 64 | op_a = swap(16, 0); | ||
| 45 | } | 65 | } |
| 46 | 66 | ||
| 67 | const auto offset = SignedOperation(OperationCode::IBitfieldExtract, is_signed, op_b, | ||
| 68 | Immediate(0), Immediate(8)); | ||
| 69 | const auto bits = SignedOperation(OperationCode::IBitfieldExtract, is_signed, op_b, | ||
| 70 | Immediate(8), Immediate(8)); | ||
| 71 | auto result = SignedOperation(OperationCode::IBitfieldExtract, is_signed, op_a, offset, bits); | ||
| 72 | SetRegister(bb, instr.gpr0, std::move(result)); | ||
| 73 | |||
| 47 | return pc; | 74 | return pc; |
| 48 | } | 75 | } |
| 49 | 76 | ||
diff --git a/src/video_core/shader/node_helper.cpp b/src/video_core/shader/node_helper.cpp index b3dcd291c..76c56abb5 100644 --- a/src/video_core/shader/node_helper.cpp +++ b/src/video_core/shader/node_helper.cpp | |||
| @@ -68,6 +68,8 @@ OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed) | |||
| 68 | return OperationCode::UBitwiseXor; | 68 | return OperationCode::UBitwiseXor; |
| 69 | case OperationCode::IBitwiseNot: | 69 | case OperationCode::IBitwiseNot: |
| 70 | return OperationCode::UBitwiseNot; | 70 | return OperationCode::UBitwiseNot; |
| 71 | case OperationCode::IBitfieldExtract: | ||
| 72 | return OperationCode::UBitfieldExtract; | ||
| 71 | case OperationCode::IBitfieldInsert: | 73 | case OperationCode::IBitfieldInsert: |
| 72 | return OperationCode::UBitfieldInsert; | 74 | return OperationCode::UBitfieldInsert; |
| 73 | case OperationCode::IBitCount: | 75 | case OperationCode::IBitCount: |