summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/shader_bytecode.h43
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp72
2 files changed, 112 insertions, 3 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index b0da805db..fb639a417 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -109,6 +109,8 @@ union OpCode {
109 109
110 FSETP_R = 0x5BB, 110 FSETP_R = 0x5BB,
111 FSETP_C = 0x4BB, 111 FSETP_C = 0x4BB,
112 FSETP_IMM = 0x36B,
113 FSETP_NEG_IMM = 0x37B,
112 EXIT = 0xE30, 114 EXIT = 0xE30,
113 KIL = 0xE33, 115 KIL = 0xE33,
114 116
@@ -124,6 +126,7 @@ union OpCode {
124 Ffma, 126 Ffma,
125 Flow, 127 Flow,
126 Memory, 128 Memory,
129 FloatPredicate,
127 Unknown, 130 Unknown,
128 }; 131 };
129 132
@@ -164,6 +167,9 @@ union OpCode {
164 case Id::FSETP_C: 167 case Id::FSETP_C:
165 case Id::KIL: 168 case Id::KIL:
166 return op4; 169 return op4;
170 case Id::FSETP_IMM:
171 case Id::FSETP_NEG_IMM:
172 return Id::FSETP_IMM;
167 } 173 }
168 174
169 switch (op5) { 175 switch (op5) {
@@ -241,8 +247,9 @@ union OpCode {
241 info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; 247 info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"};
242 info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; 248 info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"};
243 info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"}; 249 info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"};
244 info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; 250 info_table[Id::FSETP_C] = {Type::FloatPredicate, "fsetp_c"};
245 info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; 251 info_table[Id::FSETP_R] = {Type::FloatPredicate, "fsetp_r"};
252 info_table[Id::FSETP_IMM] = {Type::FloatPredicate, "fsetp_imm"};
246 info_table[Id::EXIT] = {Type::Trivial, "exit"}; 253 info_table[Id::EXIT] = {Type::Trivial, "exit"};
247 info_table[Id::IPA] = {Type::Trivial, "ipa"}; 254 info_table[Id::IPA] = {Type::Trivial, "ipa"};
248 info_table[Id::KIL] = {Type::Flow, "kil"}; 255 info_table[Id::KIL] = {Type::Flow, "kil"};
@@ -286,7 +293,23 @@ namespace Shader {
286 293
287enum class Pred : u64 { 294enum class Pred : u64 {
288 UnusedIndex = 0x7, 295 UnusedIndex = 0x7,
289 NeverExecute = 0xf, 296 NeverExecute = 0xF,
297};
298
299enum class PredCondition : u64 {
300 LessThan = 1,
301 Equal = 2,
302 LessEqual = 3,
303 GreaterThan = 4,
304 NotEqual = 5,
305 GreaterEqual = 6,
306 // TODO(Subv): Other condition types
307};
308
309enum class PredOperation : u64 {
310 And = 0,
311 Or = 1,
312 Xor = 2,
290}; 313};
291 314
292enum class SubOp : u64 { 315enum class SubOp : u64 {
@@ -346,6 +369,20 @@ union Instruction {
346 BitField<49, 1, u64> negate_c; 369 BitField<49, 1, u64> negate_c;
347 } ffma; 370 } ffma;
348 371
372 union {
373 BitField<0, 3, u64> pred0;
374 BitField<3, 3, u64> pred3;
375 BitField<7, 1, u64> abs_a;
376 BitField<39, 3, u64> pred39;
377 BitField<42, 1, u64> neg_pred;
378 BitField<43, 1, u64> neg_a;
379 BitField<44, 1, u64> abs_b;
380 BitField<45, 2, PredOperation> op;
381 BitField<47, 1, u64> ftz;
382 BitField<48, 4, PredCondition> cond;
383 BitField<56, 1, u64> neg_b;
384 } fsetp;
385
349 BitField<61, 1, u64> is_b_imm; 386 BitField<61, 1, u64> is_b_imm;
350 BitField<60, 1, u64> is_b_gpr; 387 BitField<60, 1, u64> is_b_gpr;
351 BitField<59, 1, u64> is_c_gpr; 388 BitField<59, 1, u64> is_c_gpr;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 6db0b7d39..2e0203a68 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -279,6 +279,21 @@ private:
279 } 279 }
280 280
281 /* 281 /*
282 * Writes code that assigns a predicate boolean variable.
283 * @param pred The id of the predicate to write to.
284 * @param value The expression value to assign to the predicate.
285 */
286 void SetPredicate(u64 pred, const std::string& value) {
287 using Tegra::Shader::Pred;
288 // Can't assign to the constant predicate.
289 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex));
290
291 std::string variable = 'p' + std::to_string(pred);
292 shader.AddLine(variable + " = " + value + ';');
293 declr_predicates.insert(std::move(variable));
294 }
295
296 /*
282 * Returns whether the instruction at the specified offset is a 'sched' instruction. 297 * Returns whether the instruction at the specified offset is a 'sched' instruction.
283 * Sched instructions always appear before a sequence of 3 instructions. 298 * Sched instructions always appear before a sequence of 3 instructions.
284 */ 299 */
@@ -468,7 +483,57 @@ private:
468 } 483 }
469 break; 484 break;
470 } 485 }
486 case OpCode::Type::FloatPredicate: {
487 std::string op_a = instr.fsetp.neg_a ? "-" : "";
488 op_a += GetRegister(instr.gpr8);
489
490 if (instr.fsetp.abs_a) {
491 op_a = "abs(" + op_a + ')';
492 }
493
494 std::string op_b{};
495
496 if (instr.is_b_imm) {
497 if (instr.fsetp.neg_b) {
498 // Only the immediate version of fsetp has a neg_b bit.
499 op_b += '-';
500 }
501 op_b += '(' + GetImmediate19(instr) + ')';
502 } else {
503 if (instr.is_b_gpr) {
504 op_b += GetRegister(instr.gpr20);
505 } else {
506 op_b += GetUniform(instr.uniform);
507 }
508 }
509
510 if (instr.fsetp.abs_b) {
511 op_b = "abs(" + op_b + ')';
512 }
471 513
514 using Tegra::Shader::Pred;
515 ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
516 instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
517 "Compound predicates are not implemented");
518
519 // We can't use the constant predicate as destination.
520 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
521
522 using Tegra::Shader::PredCondition;
523 switch (instr.fsetp.cond) {
524 case PredCondition::LessThan:
525 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')');
526 break;
527 case PredCondition::Equal:
528 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')');
529 break;
530 default:
531 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
532 static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b);
533 UNREACHABLE();
534 }
535 break;
536 }
472 default: { 537 default: {
473 switch (instr.opcode.EffectiveOpCode()) { 538 switch (instr.opcode.EffectiveOpCode()) {
474 case OpCode::Id::EXIT: { 539 case OpCode::Id::EXIT: {
@@ -623,6 +688,12 @@ private:
623 declarations.AddNewLine(); 688 declarations.AddNewLine();
624 ++const_buffer_layout; 689 ++const_buffer_layout;
625 } 690 }
691
692 declarations.AddNewLine();
693 for (const auto& pred : declr_predicates) {
694 declarations.AddLine("bool " + pred + " = false;");
695 }
696 declarations.AddNewLine();
626 } 697 }
627 698
628private: 699private:
@@ -636,6 +707,7 @@ private:
636 707
637 // Declarations 708 // Declarations
638 std::set<std::string> declr_register; 709 std::set<std::string> declr_register;
710 std::set<std::string> declr_predicates;
639 std::set<Attribute::Index> declr_input_attribute; 711 std::set<Attribute::Index> declr_input_attribute;
640 std::set<Attribute::Index> declr_output_attribute; 712 std::set<Attribute::Index> declr_output_attribute;
641 std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; 713 std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers;