summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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 fce9733b9..e5b4eadea 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -937,21 +937,34 @@ union Instruction {
937 } iset; 937 } iset;
938 938
939 union { 939 union {
940 BitField<8, 2, Register::Size> dest_size; 940 BitField<41, 2, u64> selector; // i2i and i2f only
941 BitField<10, 2, Register::Size> src_size;
942 BitField<12, 1, u64> is_output_signed;
943 BitField<13, 1, u64> is_input_signed;
944 BitField<41, 2, u64> selector;
945 BitField<45, 1, u64> negate_a; 941 BitField<45, 1, u64> negate_a;
946 BitField<49, 1, u64> abs_a; 942 BitField<49, 1, u64> abs_a;
943 BitField<10, 2, Register::Size> src_size;
944 BitField<13, 1, u64> is_input_signed;
945 BitField<8, 2, Register::Size> dst_size;
946 BitField<12, 1, u64> is_output_signed;
947
948 union {
949 BitField<39, 2, u64> tab5cb8_2;
950 } i2f;
947 951
948 union { 952 union {
949 BitField<39, 2, F2iRoundingOp> rounding; 953 BitField<39, 2, F2iRoundingOp> rounding;
950 } f2i; 954 } f2i;
951 955
952 union { 956 union {
953 BitField<39, 4, F2fRoundingOp> rounding; 957 BitField<8, 2, Register::Size> src_size;
958 BitField<10, 2, Register::Size> dst_size;
959 BitField<39, 4, u64> rounding;
960 // H0, H1 extract for F16 missing
961 BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value
962 F2fRoundingOp GetRoundingMode() const {
963 constexpr u64 rounding_mask = 0x0B;
964 return static_cast<F2fRoundingOp>(rounding.Value() & rounding_mask);
965 }
954 } f2f; 966 } f2f;
967
955 } conversion; 968 } conversion;
956 969
957 union { 970 union {
@@ -1734,7 +1747,7 @@ private:
1734 INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"), 1747 INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"),
1735 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), 1748 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
1736 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), 1749 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
1737 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), 1750 INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
1738 INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"), 1751 INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"),
1739 INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"), 1752 INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"),
1740 INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"), 1753 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;