summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h27
-rw-r--r--src/video_core/shader/decode/conversion.cpp69
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;