summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h51
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp153
2 files changed, 190 insertions, 14 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index a57b90632..8d4ea3401 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -156,6 +156,13 @@ enum class PredOperation : u64 {
156 Xor = 2, 156 Xor = 2,
157}; 157};
158 158
159enum class LogicOperation : u64 {
160 And = 0,
161 Or = 1,
162 Xor = 2,
163 PassB = 3,
164};
165
159enum class SubOp : u64 { 166enum class SubOp : u64 {
160 Cos = 0x0, 167 Cos = 0x0,
161 Sin = 0x1, 168 Sin = 0x1,
@@ -202,6 +209,12 @@ union Instruction {
202 BitField<42, 1, u64> negate_pred; 209 BitField<42, 1, u64> negate_pred;
203 } fmnmx; 210 } fmnmx;
204 211
212 union {
213 BitField<53, 2, LogicOperation> operation;
214 BitField<55, 1, u64> invert_a;
215 BitField<56, 1, u64> invert_b;
216 } lop;
217
205 float GetImm20_19() const { 218 float GetImm20_19() const {
206 float result{}; 219 float result{};
207 u32 imm{static_cast<u32>(imm20_19)}; 220 u32 imm{static_cast<u32>(imm20_19)};
@@ -220,6 +233,22 @@ union Instruction {
220 } alu; 233 } alu;
221 234
222 union { 235 union {
236 BitField<39, 5, u64> shift_amount;
237 BitField<20, 19, u64> immediate_low;
238 BitField<56, 1, u64> immediate_high;
239 BitField<48, 1, u64> negate_b;
240 BitField<49, 1, u64> negate_a;
241
242 s32 GetImmediate() const {
243 u32 immediate = static_cast<u32>(immediate_low | (immediate_high << 19));
244 // Sign extend the 20-bit value.
245 u32 mask = 1U << (20 - 1);
246 return static_cast<s32>((immediate ^ mask) - mask);
247 }
248
249 } iscadd;
250
251 union {
223 BitField<48, 1, u64> negate_b; 252 BitField<48, 1, u64> negate_b;
224 BitField<49, 1, u64> negate_c; 253 BitField<49, 1, u64> negate_c;
225 } ffma; 254 } ffma;
@@ -239,15 +268,25 @@ union Instruction {
239 } fsetp; 268 } fsetp;
240 269
241 union { 270 union {
271 BitField<0, 3, u64> pred0;
272 BitField<3, 3, u64> pred3;
273 BitField<39, 3, u64> pred39;
274 BitField<42, 1, u64> neg_pred;
275 BitField<45, 2, PredOperation> op;
276 BitField<48, 1, u64> is_signed;
277 BitField<49, 3, PredCondition> cond;
278 } isetp;
279
280 union {
242 BitField<39, 3, u64> pred39; 281 BitField<39, 3, u64> pred39;
243 BitField<42, 1, u64> neg_pred; 282 BitField<42, 1, u64> neg_pred;
244 BitField<43, 1, u64> neg_a; 283 BitField<43, 1, u64> neg_a;
245 BitField<44, 1, u64> abs_b; 284 BitField<44, 1, u64> abs_b;
246 BitField<45, 2, PredOperation> op; 285 BitField<45, 2, PredOperation> op;
247 BitField<48, 4, PredCondition> cond; 286 BitField<48, 4, PredCondition> cond;
287 BitField<52, 1, u64> bf;
248 BitField<53, 1, u64> neg_b; 288 BitField<53, 1, u64> neg_b;
249 BitField<54, 1, u64> abs_a; 289 BitField<54, 1, u64> abs_a;
250 BitField<52, 1, u64> bf;
251 BitField<55, 1, u64> ftz; 290 BitField<55, 1, u64> ftz;
252 BitField<56, 1, u64> neg_imm; 291 BitField<56, 1, u64> neg_imm;
253 } fset; 292 } fset;
@@ -339,6 +378,9 @@ public:
339 FMUL_R, 378 FMUL_R,
340 FMUL_IMM, 379 FMUL_IMM,
341 FMUL32_IMM, 380 FMUL32_IMM,
381 ISCADD_C, // Scale and Add
382 ISCADD_R,
383 ISCADD_IMM,
342 MUFU, // Multi-Function Operator 384 MUFU, // Multi-Function Operator
343 RRO_C, // Range Reduction Operator 385 RRO_C, // Range Reduction Operator
344 RRO_R, 386 RRO_R,
@@ -381,6 +423,8 @@ public:
381 enum class Type { 423 enum class Type {
382 Trivial, 424 Trivial,
383 Arithmetic, 425 Arithmetic,
426 Logic,
427 ScaledAdd,
384 Ffma, 428 Ffma,
385 Flow, 429 Flow,
386 Memory, 430 Memory,
@@ -504,6 +548,9 @@ private:
504 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), 548 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
505 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), 549 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
506 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), 550 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
551 INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"),
552 INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"),
553 INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"),
507 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 554 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
508 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 555 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
509 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 556 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
@@ -514,7 +561,6 @@ private:
514 INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), 561 INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"),
515 INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), 562 INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"),
516 INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), 563 INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"),
517 INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
518 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), 564 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
519 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), 565 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
520 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), 566 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"),
@@ -525,6 +571,7 @@ private:
525 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), 571 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
526 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), 572 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
527 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), 573 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
574 INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"),
528 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), 575 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
529 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), 576 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
530 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), 577 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 6391f1ad4..eb8d37c9b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -228,6 +228,11 @@ public:
228 return active_type == Type::Integer; 228 return active_type == Type::Integer;
229 } 229 }
230 230
231 /// Returns the current active type of the register
232 Type GetActiveType() const {
233 return active_type;
234 }
235
231 /// Returns the index of the register 236 /// Returns the index of the register
232 size_t GetIndex() const { 237 size_t GetIndex() const {
233 return index; 238 return index;
@@ -359,22 +364,28 @@ public:
359 shader.AddLine(dest + " = " + src + ';'); 364 shader.AddLine(dest + " = " + src + ';');
360 } 365 }
361 366
362 /// Generates code representing a uniform (C buffer) register. 367 /// Generates code representing a uniform (C buffer) register, interpreted as the input type.
363 std::string GetUniform(const Uniform& uniform, const Register& dest_reg) { 368 std::string GetUniform(const Uniform& uniform, GLSLRegister::Type type) {
364 declr_const_buffers[uniform.index].MarkAsUsed(static_cast<unsigned>(uniform.index), 369 declr_const_buffers[uniform.index].MarkAsUsed(static_cast<unsigned>(uniform.index),
365 static_cast<unsigned>(uniform.offset), stage); 370 static_cast<unsigned>(uniform.offset), stage);
366 std::string value = 371 std::string value =
367 'c' + std::to_string(uniform.index) + '[' + std::to_string(uniform.offset) + ']'; 372 'c' + std::to_string(uniform.index) + '[' + std::to_string(uniform.offset) + ']';
368 373
369 if (regs[dest_reg].IsFloat()) { 374 if (type == GLSLRegister::Type::Float) {
370 return value; 375 return value;
371 } else if (regs[dest_reg].IsInteger()) { 376 } else if (type == GLSLRegister::Type::Integer) {
372 return "floatBitsToInt(" + value + ')'; 377 return "floatBitsToInt(" + value + ')';
373 } else { 378 } else {
374 UNREACHABLE(); 379 UNREACHABLE();
375 } 380 }
376 } 381 }
377 382
383 /// Generates code representing a uniform (C buffer) register, interpreted as the type of the
384 /// destination register.
385 std::string GetUniform(const Uniform& uniform, const Register& dest_reg) {
386 return GetUniform(uniform, regs[dest_reg].GetActiveType());
387 }
388
378 /// Add declarations for registers 389 /// Add declarations for registers
379 void GenerateDeclarations() { 390 void GenerateDeclarations() {
380 for (const auto& reg : regs) { 391 for (const auto& reg : regs) {
@@ -643,9 +654,9 @@ private:
643 std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const { 654 std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
644 using Tegra::Shader::PredCondition; 655 using Tegra::Shader::PredCondition;
645 static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = { 656 static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
646 {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="}, 657 {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="},
647 {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"}, 658 {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"},
648 {PredCondition::GreaterEqual, ">="}, 659 {PredCondition::NotEqual, "!="}, {PredCondition::GreaterEqual, ">="},
649 }; 660 };
650 661
651 auto comparison = PredicateComparisonStrings.find(condition); 662 auto comparison = PredicateComparisonStrings.find(condition);
@@ -839,6 +850,73 @@ private:
839 } 850 }
840 break; 851 break;
841 } 852 }
853 case OpCode::Type::Logic: {
854 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false);
855
856 if (instr.alu.lop.invert_a)
857 op_a = "~(" + op_a + ')';
858
859 switch (opcode->GetId()) {
860 case OpCode::Id::LOP32I: {
861 u32 imm = static_cast<u32>(instr.alu.imm20_32.Value());
862
863 if (instr.alu.lop.invert_b)
864 imm = ~imm;
865
866 switch (instr.alu.lop.operation) {
867 case Tegra::Shader::LogicOperation::And: {
868 regs.SetRegisterToInteger(instr.gpr0, false, 0,
869 '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1);
870 break;
871 }
872 case Tegra::Shader::LogicOperation::Or: {
873 regs.SetRegisterToInteger(instr.gpr0, false, 0,
874 '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1);
875 break;
876 }
877 case Tegra::Shader::LogicOperation::Xor: {
878 regs.SetRegisterToInteger(instr.gpr0, false, 0,
879 '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1);
880 break;
881 }
882 default:
883 NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}",
884 static_cast<u32>(instr.alu.lop.operation.Value()));
885 UNREACHABLE();
886 }
887 break;
888 }
889 default: {
890 NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName());
891 UNREACHABLE();
892 }
893 }
894 break;
895 }
896 case OpCode::Type::ScaledAdd: {
897 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
898
899 if (instr.iscadd.negate_a)
900 op_a = '-' + op_a;
901
902 std::string op_b = instr.iscadd.negate_b ? "-" : "";
903
904 if (instr.is_b_imm) {
905 op_b += '(' + std::to_string(instr.iscadd.GetImmediate()) + ')';
906 } else {
907 if (instr.is_b_gpr) {
908 op_b += regs.GetRegisterAsInteger(instr.gpr20);
909 } else {
910 op_b += regs.GetUniform(instr.uniform, instr.gpr0);
911 }
912 }
913
914 std::string shift = std::to_string(instr.iscadd.shift_amount.Value());
915
916 regs.SetRegisterToInteger(instr.gpr0, true, 0,
917 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
918 break;
919 }
842 case OpCode::Type::Ffma: { 920 case OpCode::Type::Ffma: {
843 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 921 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
844 std::string op_b = instr.ffma.negate_b ? "-" : ""; 922 std::string op_b = instr.ffma.negate_b ? "-" : "";
@@ -880,8 +958,7 @@ private:
880 ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); 958 ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented");
881 959
882 switch (opcode->GetId()) { 960 switch (opcode->GetId()) {
883 case OpCode::Id::I2I_R: 961 case OpCode::Id::I2I_R: {
884 case OpCode::Id::I2F_R: {
885 ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); 962 ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
886 963
887 std::string op_a = 964 std::string op_a =
@@ -894,6 +971,17 @@ private:
894 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); 971 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1);
895 break; 972 break;
896 } 973 }
974 case OpCode::Id::I2F_R: {
975 std::string op_a =
976 regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed);
977
978 if (instr.conversion.abs_a) {
979 op_a = "abs(" + op_a + ')';
980 }
981
982 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
983 break;
984 }
897 case OpCode::Id::F2F_R: { 985 case OpCode::Id::F2F_R: {
898 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); 986 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
899 987
@@ -1017,7 +1105,7 @@ private:
1017 if (instr.is_b_gpr) { 1105 if (instr.is_b_gpr) {
1018 op_b += regs.GetRegisterAsFloat(instr.gpr20); 1106 op_b += regs.GetRegisterAsFloat(instr.gpr20);
1019 } else { 1107 } else {
1020 op_b += regs.GetUniform(instr.uniform, instr.gpr0); 1108 op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Float);
1021 } 1109 }
1022 } 1110 }
1023 1111
@@ -1048,6 +1136,42 @@ private:
1048 } 1136 }
1049 break; 1137 break;
1050 } 1138 }
1139 case OpCode::Type::IntegerSetPredicate: {
1140 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed);
1141
1142 std::string op_b{};
1143
1144 ASSERT_MSG(!instr.is_b_imm, "ISETP_IMM not implemented");
1145
1146 if (instr.is_b_gpr) {
1147 op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed);
1148 } else {
1149 op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Integer);
1150 }
1151
1152 using Tegra::Shader::Pred;
1153 // We can't use the constant predicate as destination.
1154 ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
1155
1156 std::string second_pred =
1157 GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0);
1158
1159 std::string comparator = GetPredicateComparison(instr.isetp.cond);
1160 std::string combiner = GetPredicateCombiner(instr.isetp.op);
1161
1162 std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
1163 // Set the primary predicate to the result of Predicate OP SecondPredicate
1164 SetPredicate(instr.isetp.pred3,
1165 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
1166
1167 if (instr.isetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
1168 // Set the secondary predicate to the result of !Predicate OP SecondPredicate,
1169 // if enabled
1170 SetPredicate(instr.isetp.pred0,
1171 "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
1172 }
1173 break;
1174 }
1051 case OpCode::Type::FloatSet: { 1175 case OpCode::Type::FloatSet: {
1052 std::string op_a = instr.fset.neg_a ? "-" : ""; 1176 std::string op_a = instr.fset.neg_a ? "-" : "";
1053 op_a += regs.GetRegisterAsFloat(instr.gpr8); 1177 op_a += regs.GetRegisterAsFloat(instr.gpr8);
@@ -1068,7 +1192,7 @@ private:
1068 if (instr.is_b_gpr) { 1192 if (instr.is_b_gpr) {
1069 op_b += regs.GetRegisterAsFloat(instr.gpr20); 1193 op_b += regs.GetRegisterAsFloat(instr.gpr20);
1070 } else { 1194 } else {
1071 op_b += regs.GetUniform(instr.uniform, instr.gpr0); 1195 op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Float);
1072 } 1196 }
1073 } 1197 }
1074 1198
@@ -1087,7 +1211,12 @@ private:
1087 std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " + 1211 std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
1088 combiner + " (" + second_pred + "))"; 1212 combiner + " (" + second_pred + "))";
1089 1213
1090 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); 1214 if (instr.fset.bf) {
1215 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
1216 } else {
1217 regs.SetRegisterToInteger(instr.gpr0, false, 0, predicate + " ? 0xFFFFFFFF : 0", 1,
1218 1);
1219 }
1091 break; 1220 break;
1092 } 1221 }
1093 default: { 1222 default: {