diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 27 | ||||
| -rw-r--r-- | src/video_core/shader/decode/conversion.cpp | 69 |
2 files changed, 73 insertions, 23 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 2e1e96c81..d5656271c 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -917,21 +917,34 @@ union Instruction { | |||
| 917 | } iset; | 917 | } iset; |
| 918 | 918 | ||
| 919 | union { | 919 | union { |
| 920 | BitField<8, 2, Register::Size> dest_size; | 920 | BitField<41, 2, u64> selector; // i2i and i2f only |
| 921 | BitField<10, 2, Register::Size> src_size; | ||
| 922 | BitField<12, 1, u64> is_output_signed; | ||
| 923 | BitField<13, 1, u64> is_input_signed; | ||
| 924 | BitField<41, 2, u64> selector; | ||
| 925 | BitField<45, 1, u64> negate_a; | 921 | BitField<45, 1, u64> negate_a; |
| 926 | BitField<49, 1, u64> abs_a; | 922 | BitField<49, 1, u64> abs_a; |
| 923 | BitField<10, 2, Register::Size> src_size; | ||
| 924 | BitField<13, 1, u64> is_input_signed; | ||
| 925 | BitField<8, 2, Register::Size> dst_size; | ||
| 926 | BitField<12, 1, u64> is_output_signed; | ||
| 927 | |||
| 928 | union { | ||
| 929 | BitField<39, 2, u64> tab5cb8_2; | ||
| 930 | } i2f; | ||
| 927 | 931 | ||
| 928 | union { | 932 | union { |
| 929 | BitField<39, 2, F2iRoundingOp> rounding; | 933 | BitField<39, 2, F2iRoundingOp> rounding; |
| 930 | } f2i; | 934 | } f2i; |
| 931 | 935 | ||
| 932 | union { | 936 | union { |
| 933 | BitField<39, 4, F2fRoundingOp> rounding; | 937 | BitField<8, 2, Register::Size> src_size; |
| 938 | BitField<10, 2, Register::Size> dst_size; | ||
| 939 | BitField<39, 4, u64> rounding; | ||
| 940 | // H0, H1 extract for F16 missing | ||
| 941 | BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value | ||
| 942 | F2fRoundingOp GetRoundingMode() const { | ||
| 943 | constexpr u64 rounding_mask = 0x0B; | ||
| 944 | return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask); | ||
| 945 | } | ||
| 934 | } f2f; | 946 | } f2f; |
| 947 | |||
| 935 | } conversion; | 948 | } conversion; |
| 936 | 949 | ||
| 937 | union { | 950 | union { |
| @@ -1678,7 +1691,7 @@ private: | |||
| 1678 | INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"), | 1691 | INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"), |
| 1679 | INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | 1692 | INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), |
| 1680 | INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | 1693 | INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), |
| 1681 | INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | 1694 | INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), |
| 1682 | INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), | 1695 | INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), |
| 1683 | INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), | 1696 | INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), |
| 1684 | INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), | 1697 | INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), |
diff --git a/src/video_core/shader/decode/conversion.cpp b/src/video_core/shader/decode/conversion.cpp index 55a6fbbf2..ba15b1115 100644 --- a/src/video_core/shader/decode/conversion.cpp +++ b/src/video_core/shader/decode/conversion.cpp | |||
| @@ -18,13 +18,29 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 18 | const auto opcode = OpCode::Decode(instr); | 18 | const auto opcode = OpCode::Decode(instr); |
| 19 | 19 | ||
| 20 | switch (opcode->get().GetId()) { | 20 | switch (opcode->get().GetId()) { |
| 21 | case OpCode::Id::I2I_R: { | 21 | case OpCode::Id::I2I_R: |
| 22 | case OpCode::Id::I2I_C: | ||
| 23 | case OpCode::Id::I2I_IMM: { | ||
| 22 | UNIMPLEMENTED_IF(instr.conversion.selector); | 24 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 25 | UNIMPLEMENTED_IF(instr.conversion.dst_size != Register::Size::Word); | ||
| 26 | UNIMPLEMENTED_IF(instr.alu.saturate_d); | ||
| 23 | 27 | ||
| 24 | const bool input_signed = instr.conversion.is_input_signed; | 28 | const bool input_signed = instr.conversion.is_input_signed; |
| 25 | const bool output_signed = instr.conversion.is_output_signed; | 29 | const bool output_signed = instr.conversion.is_output_signed; |
| 26 | 30 | ||
| 27 | Node value = GetRegister(instr.gpr20); | 31 | Node value = [&]() { |
| 32 | switch (opcode->get().GetId()) { | ||
| 33 | case OpCode::Id::I2I_R: | ||
| 34 | return GetRegister(instr.gpr20); | ||
| 35 | case OpCode::Id::I2I_C: | ||
| 36 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | ||
| 37 | case OpCode::Id::I2I_IMM: | ||
| 38 | return Immediate(instr.alu.GetSignedImm20_20()); | ||
| 39 | default: | ||
| 40 | UNREACHABLE(); | ||
| 41 | return Immediate(0); | ||
| 42 | } | ||
| 43 | }(); | ||
| 28 | value = ConvertIntegerSize(value, instr.conversion.src_size, input_signed); | 44 | value = ConvertIntegerSize(value, instr.conversion.src_size, input_signed); |
| 29 | 45 | ||
| 30 | value = GetOperandAbsNegInteger(value, instr.conversion.abs_a, instr.conversion.negate_a, | 46 | value = GetOperandAbsNegInteger(value, instr.conversion.abs_a, instr.conversion.negate_a, |
| @@ -38,17 +54,24 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 38 | break; | 54 | break; |
| 39 | } | 55 | } |
| 40 | case OpCode::Id::I2F_R: | 56 | case OpCode::Id::I2F_R: |
| 41 | case OpCode::Id::I2F_C: { | 57 | case OpCode::Id::I2F_C: |
| 42 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); | 58 | case OpCode::Id::I2F_IMM: { |
| 59 | UNIMPLEMENTED_IF(instr.conversion.dst_size != Register::Size::Word); | ||
| 43 | UNIMPLEMENTED_IF(instr.conversion.selector); | 60 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 44 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 61 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 45 | "Condition codes generation in I2F is not implemented"); | 62 | "Condition codes generation in I2F is not implemented"); |
| 46 | 63 | ||
| 47 | Node value = [&]() { | 64 | Node value = [&]() { |
| 48 | if (instr.is_b_gpr) { | 65 | switch (opcode->get().GetId()) { |
| 66 | case OpCode::Id::I2F_R: | ||
| 49 | return GetRegister(instr.gpr20); | 67 | return GetRegister(instr.gpr20); |
| 50 | } else { | 68 | case OpCode::Id::I2F_C: |
| 51 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | 69 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); |
| 70 | case OpCode::Id::I2F_IMM: | ||
| 71 | return Immediate(instr.alu.GetSignedImm20_20()); | ||
| 72 | default: | ||
| 73 | UNREACHABLE(); | ||
| 74 | return Immediate(0); | ||
| 52 | } | 75 | } |
| 53 | }(); | 76 | }(); |
| 54 | const bool input_signed = instr.conversion.is_input_signed; | 77 | const bool input_signed = instr.conversion.is_input_signed; |
| @@ -62,24 +85,31 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 62 | break; | 85 | break; |
| 63 | } | 86 | } |
| 64 | case OpCode::Id::F2F_R: | 87 | case OpCode::Id::F2F_R: |
| 65 | case OpCode::Id::F2F_C: { | 88 | case OpCode::Id::F2F_C: |
| 66 | UNIMPLEMENTED_IF(instr.conversion.dest_size != Register::Size::Word); | 89 | case OpCode::Id::F2F_IMM: { |
| 67 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); | 90 | UNIMPLEMENTED_IF(instr.conversion.f2f.dst_size != Register::Size::Word); |
| 91 | UNIMPLEMENTED_IF(instr.conversion.f2f.src_size != Register::Size::Word); | ||
| 68 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 92 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 69 | "Condition codes generation in F2F is not implemented"); | 93 | "Condition codes generation in F2F is not implemented"); |
| 70 | 94 | ||
| 71 | Node value = [&]() { | 95 | Node value = [&]() { |
| 72 | if (instr.is_b_gpr) { | 96 | switch (opcode->get().GetId()) { |
| 97 | case OpCode::Id::F2F_R: | ||
| 73 | return GetRegister(instr.gpr20); | 98 | return GetRegister(instr.gpr20); |
| 74 | } else { | 99 | case OpCode::Id::F2F_C: |
| 75 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | 100 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); |
| 101 | case OpCode::Id::F2F_IMM: | ||
| 102 | return GetImmediate19(instr); | ||
| 103 | default: | ||
| 104 | UNREACHABLE(); | ||
| 105 | return Immediate(0); | ||
| 76 | } | 106 | } |
| 77 | }(); | 107 | }(); |
| 78 | 108 | ||
| 79 | value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); | 109 | value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); |
| 80 | 110 | ||
| 81 | value = [&]() { | 111 | value = [&]() { |
| 82 | switch (instr.conversion.f2f.rounding) { | 112 | switch (instr.conversion.f2f.GetRoundingMode()) { |
| 83 | case Tegra::Shader::F2fRoundingOp::None: | 113 | case Tegra::Shader::F2fRoundingOp::None: |
| 84 | return value; | 114 | return value; |
| 85 | case Tegra::Shader::F2fRoundingOp::Round: | 115 | case Tegra::Shader::F2fRoundingOp::Round: |
| @@ -102,15 +132,22 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 102 | break; | 132 | break; |
| 103 | } | 133 | } |
| 104 | case OpCode::Id::F2I_R: | 134 | case OpCode::Id::F2I_R: |
| 105 | case OpCode::Id::F2I_C: { | 135 | case OpCode::Id::F2I_C: |
| 136 | case OpCode::Id::F2I_IMM: { | ||
| 106 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); | 137 | UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); |
| 107 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 138 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 108 | "Condition codes generation in F2I is not implemented"); | 139 | "Condition codes generation in F2I is not implemented"); |
| 109 | Node value = [&]() { | 140 | Node value = [&]() { |
| 110 | if (instr.is_b_gpr) { | 141 | switch (opcode->get().GetId()) { |
| 142 | case OpCode::Id::F2I_R: | ||
| 111 | return GetRegister(instr.gpr20); | 143 | return GetRegister(instr.gpr20); |
| 112 | } else { | 144 | case OpCode::Id::F2I_C: |
| 113 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | 145 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); |
| 146 | case OpCode::Id::F2I_IMM: | ||
| 147 | return GetImmediate19(instr); | ||
| 148 | default: | ||
| 149 | UNREACHABLE(); | ||
| 150 | return Immediate(0); | ||
| 114 | } | 151 | } |
| 115 | }(); | 152 | }(); |
| 116 | 153 | ||
| @@ -134,7 +171,7 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 134 | }(); | 171 | }(); |
| 135 | const bool is_signed = instr.conversion.is_output_signed; | 172 | const bool is_signed = instr.conversion.is_output_signed; |
| 136 | value = SignedOperation(OperationCode::ICastFloat, is_signed, PRECISE, value); | 173 | value = SignedOperation(OperationCode::ICastFloat, is_signed, PRECISE, value); |
| 137 | value = ConvertIntegerSize(value, instr.conversion.dest_size, is_signed); | 174 | value = ConvertIntegerSize(value, instr.conversion.dst_size, is_signed); |
| 138 | 175 | ||
| 139 | SetRegister(bb, instr.gpr0, value); | 176 | SetRegister(bb, instr.gpr0, value); |
| 140 | break; | 177 | break; |