summaryrefslogtreecommitdiff
path: root/src/video_core/shader/ast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/shader/ast.cpp')
-rw-r--r--src/video_core/shader/ast.cpp185
1 files changed, 137 insertions, 48 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp
index 56a1b29f3..d521a7b52 100644
--- a/src/video_core/shader/ast.cpp
+++ b/src/video_core/shader/ast.cpp
@@ -12,18 +12,22 @@
12namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
13 13
14ASTZipper::ASTZipper() = default; 14ASTZipper::ASTZipper() = default;
15ASTZipper::ASTZipper(ASTNode new_first) : first{}, last{} { 15
16void ASTZipper::Init(ASTNode new_first, ASTNode parent) {
17 ASSERT(new_first->manager == nullptr);
16 first = new_first; 18 first = new_first;
17 last = new_first; 19 last = new_first;
18 ASTNode current = first; 20 ASTNode current = first;
19 while (current) { 21 while (current) {
20 current->manager = this; 22 current->manager = this;
23 current->parent = parent;
21 last = current; 24 last = current;
22 current = current->next; 25 current = current->next;
23 } 26 }
24} 27}
25 28
26void ASTZipper::PushBack(ASTNode new_node) { 29void ASTZipper::PushBack(ASTNode new_node) {
30 ASSERT(new_node->manager == nullptr);
27 new_node->previous = last; 31 new_node->previous = last;
28 if (last) { 32 if (last) {
29 last->next = new_node; 33 last->next = new_node;
@@ -37,38 +41,55 @@ void ASTZipper::PushBack(ASTNode new_node) {
37} 41}
38 42
39void ASTZipper::PushFront(ASTNode new_node) { 43void ASTZipper::PushFront(ASTNode new_node) {
44 ASSERT(new_node->manager == nullptr);
40 new_node->previous.reset(); 45 new_node->previous.reset();
41 new_node->next = first; 46 new_node->next = first;
42 if (first) { 47 if (first) {
43 first->previous = first; 48 first->previous = new_node;
44 } 49 }
45 first = new_node; 50 if (last == first) {
46 if (!last) {
47 last = new_node; 51 last = new_node;
48 } 52 }
53 first = new_node;
49 new_node->manager = this; 54 new_node->manager = this;
50} 55}
51 56
52void ASTZipper::InsertAfter(ASTNode new_node, ASTNode at_node) { 57void ASTZipper::InsertAfter(ASTNode new_node, ASTNode at_node) {
58 ASSERT(new_node->manager == nullptr);
53 if (!at_node) { 59 if (!at_node) {
54 PushFront(new_node); 60 PushFront(new_node);
55 return; 61 return;
56 } 62 }
63 ASTNode next = at_node->next;
64 if (next) {
65 next->previous = new_node;
66 }
57 new_node->previous = at_node; 67 new_node->previous = at_node;
58 if (at_node == last) { 68 if (at_node == last) {
59 last = new_node; 69 last = new_node;
60 } 70 }
61 new_node->next = at_node->next; 71 new_node->next = next;
62 at_node->next = new_node; 72 at_node->next = new_node;
63 new_node->manager = this; 73 new_node->manager = this;
64} 74}
65 75
66void ASTZipper::SetParent(ASTNode new_parent) { 76void ASTZipper::InsertBefore(ASTNode new_node, ASTNode at_node) {
67 ASTNode current = first; 77 ASSERT(new_node->manager == nullptr);
68 while (current) { 78 if (!at_node) {
69 current->parent = new_parent; 79 PushBack(new_node);
70 current = current->next; 80 return;
71 } 81 }
82 ASTNode previous = at_node->previous;
83 if (previous) {
84 previous->next = new_node;
85 }
86 new_node->next = at_node;
87 if (at_node == first) {
88 first = new_node;
89 }
90 new_node->previous = previous;
91 at_node->previous = new_node;
92 new_node->manager = this;
72} 93}
73 94
74void ASTZipper::DetachTail(ASTNode node) { 95void ASTZipper::DetachTail(ASTNode node) {
@@ -80,11 +101,22 @@ void ASTZipper::DetachTail(ASTNode node) {
80 } 101 }
81 102
82 last = node->previous; 103 last = node->previous;
104 last->next.reset();
83 node->previous.reset(); 105 node->previous.reset();
106 ASTNode current = node;
107 while (current) {
108 current->manager = nullptr;
109 current->parent.reset();
110 current = current->next;
111 }
84} 112}
85 113
86void ASTZipper::DetachSegment(ASTNode start, ASTNode end) { 114void ASTZipper::DetachSegment(ASTNode start, ASTNode end) {
87 ASSERT(start->manager == this && end->manager == this); 115 ASSERT(start->manager == this && end->manager == this);
116 if (start == end) {
117 DetachSingle(start);
118 return;
119 }
88 ASTNode prev = start->previous; 120 ASTNode prev = start->previous;
89 ASTNode post = end->next; 121 ASTNode post = end->next;
90 if (!prev) { 122 if (!prev) {
@@ -131,7 +163,6 @@ void ASTZipper::DetachSingle(ASTNode node) {
131 node->parent.reset(); 163 node->parent.reset();
132} 164}
133 165
134
135void ASTZipper::Remove(ASTNode node) { 166void ASTZipper::Remove(ASTNode node) {
136 ASSERT(node->manager == this); 167 ASSERT(node->manager == this);
137 ASTNode next = node->next; 168 ASTNode next = node->next;
@@ -178,12 +209,7 @@ public:
178 } 209 }
179 210
180 void operator()(ExprPredicate const& expr) { 211 void operator()(ExprPredicate const& expr) {
181 u32 pred = static_cast<u32>(expr.predicate); 212 inner += "P" + std::to_string(expr.predicate);
182 if (pred > 7) {
183 inner += "!";
184 pred -= 8;
185 }
186 inner += "P" + std::to_string(pred);
187 } 213 }
188 214
189 void operator()(ExprCondCode const& expr) { 215 void operator()(ExprCondCode const& expr) {
@@ -253,6 +279,10 @@ public:
253 ");\n"; 279 ");\n";
254 } 280 }
255 281
282 void operator()(ASTBlockDecoded& ast) {
283 inner += Ident() + "Block;\n";
284 }
285
256 void operator()(ASTVarSet& ast) { 286 void operator()(ASTVarSet& ast) {
257 ExprPrinter expr_parser{}; 287 ExprPrinter expr_parser{};
258 std::visit(expr_parser, *ast.condition); 288 std::visit(expr_parser, *ast.condition);
@@ -282,7 +312,7 @@ public:
282 current = current->GetNext(); 312 current = current->GetNext();
283 } 313 }
284 scope--; 314 scope--;
285 inner += Ident() + "} while (" + expr_parser.GetResult() + ")\n"; 315 inner += Ident() + "} while (" + expr_parser.GetResult() + ");\n";
286 } 316 }
287 317
288 void operator()(ASTReturn& ast) { 318 void operator()(ASTReturn& ast) {
@@ -333,8 +363,6 @@ std::string ASTManager::Print() {
333 return printer.GetResult(); 363 return printer.GetResult();
334} 364}
335 365
336#pragma optimize("", off)
337
338void ASTManager::Decompile() { 366void ASTManager::Decompile() {
339 auto it = gotos.begin(); 367 auto it = gotos.begin();
340 while (it != gotos.end()) { 368 while (it != gotos.end()) {
@@ -348,11 +376,12 @@ void ASTManager::Decompile() {
348 } 376 }
349 if (DirectlyRelated(goto_node, label)) { 377 if (DirectlyRelated(goto_node, label)) {
350 u32 goto_level = goto_node->GetLevel(); 378 u32 goto_level = goto_node->GetLevel();
351 u32 label_level = goto_node->GetLevel(); 379 u32 label_level = label->GetLevel();
352 while (label_level > goto_level) { 380 while (label_level < goto_level) {
353 MoveOutward(goto_node); 381 MoveOutward(goto_node);
354 goto_level++; 382 goto_level--;
355 } 383 }
384 // TODO(Blinkhawk): Implement Lifting and Inward Movements
356 } 385 }
357 if (label->GetParent() == goto_node->GetParent()) { 386 if (label->GetParent() == goto_node->GetParent()) {
358 bool is_loop = false; 387 bool is_loop = false;
@@ -375,13 +404,11 @@ void ASTManager::Decompile() {
375 } 404 }
376 it++; 405 it++;
377 } 406 }
378 /*
379 for (ASTNode label : labels) { 407 for (ASTNode label : labels) {
380 auto& manager = label->GetManager(); 408 auto& manager = label->GetManager();
381 manager.Remove(label); 409 manager.Remove(label);
382 } 410 }
383 labels.clear(); 411 labels.clear();
384 */
385} 412}
386 413
387bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { 414bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) {
@@ -410,87 +437,149 @@ bool ASTManager::DirectlyRelated(ASTNode first, ASTNode second) {
410 max = second; 437 max = second;
411 } 438 }
412 439
413 while (min_level < max_level) { 440 while (max_level > min_level) {
414 min_level++; 441 max_level--;
415 min = min->GetParent(); 442 max = max->GetParent();
416 } 443 }
417 444
418 return (min->GetParent() == max->GetParent()); 445 return (min->GetParent() == max->GetParent());
419} 446}
420 447
448void ASTManager::ShowCurrentState(std::string state) {
449 LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print());
450 SanityCheck();
451}
452
453void ASTManager::SanityCheck() {
454 for (auto label : labels) {
455 if (!label->GetParent()) {
456 LOG_CRITICAL(HW_GPU, "Sanity Check Failed");
457 }
458 }
459}
460
421void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { 461void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) {
462 // ShowCurrentState("Before DoWhile Enclose");
463 enclose_count++;
422 ASTZipper& zipper = goto_node->GetManager(); 464 ASTZipper& zipper = goto_node->GetManager();
423 ASTNode loop_start = label->GetNext(); 465 ASTNode loop_start = label->GetNext();
424 if (loop_start == goto_node) { 466 if (loop_start == goto_node) {
425 zipper.Remove(goto_node); 467 zipper.Remove(goto_node);
468 // ShowCurrentState("Ignore DoWhile Enclose");
426 return; 469 return;
427 } 470 }
428 ASTNode parent = label->GetParent(); 471 ASTNode parent = label->GetParent();
429 Expr condition = goto_node->GetGotoCondition(); 472 Expr condition = goto_node->GetGotoCondition();
430 zipper.DetachSegment(loop_start, goto_node); 473 zipper.DetachSegment(loop_start, goto_node);
431 ASTNode do_while_node = ASTBase::Make<ASTDoWhile>(parent, condition, ASTZipper(loop_start)); 474 ASTNode do_while_node = ASTBase::Make<ASTDoWhile>(parent, condition);
432 zipper.InsertAfter(do_while_node, label);
433 ASTZipper* sub_zipper = do_while_node->GetSubNodes(); 475 ASTZipper* sub_zipper = do_while_node->GetSubNodes();
434 sub_zipper->SetParent(do_while_node); 476 sub_zipper->Init(loop_start, do_while_node);
477 zipper.InsertAfter(do_while_node, label);
435 sub_zipper->Remove(goto_node); 478 sub_zipper->Remove(goto_node);
479 // ShowCurrentState("After DoWhile Enclose");
436} 480}
437 481
438void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { 482void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) {
483 // ShowCurrentState("Before IfThen Enclose");
484 enclose_count++;
439 ASTZipper& zipper = goto_node->GetManager(); 485 ASTZipper& zipper = goto_node->GetManager();
440 ASTNode if_end = label->GetPrevious(); 486 ASTNode if_end = label->GetPrevious();
441 if (if_end == goto_node) { 487 if (if_end == goto_node) {
442 zipper.Remove(goto_node); 488 zipper.Remove(goto_node);
489 // ShowCurrentState("Ignore IfThen Enclose");
443 return; 490 return;
444 } 491 }
445 ASTNode prev = goto_node->GetPrevious(); 492 ASTNode prev = goto_node->GetPrevious();
446 ASTNode parent = label->GetParent();
447 Expr condition = goto_node->GetGotoCondition(); 493 Expr condition = goto_node->GetGotoCondition();
448 Expr neg_condition = MakeExpr<ExprNot>(condition); 494 bool do_else = false;
495 if (prev->IsIfThen()) {
496 Expr if_condition = prev->GetIfCondition();
497 do_else = ExprAreEqual(if_condition, condition);
498 }
499 ASTNode parent = label->GetParent();
449 zipper.DetachSegment(goto_node, if_end); 500 zipper.DetachSegment(goto_node, if_end);
450 ASTNode if_node = ASTBase::Make<ASTIfThen>(parent, condition, ASTZipper(goto_node)); 501 ASTNode if_node;
451 zipper.InsertAfter(if_node, prev); 502 if (do_else) {
503 if_node = ASTBase::Make<ASTIfElse>(parent);
504 } else {
505 Expr neg_condition = MakeExprNot(condition);
506 if_node = ASTBase::Make<ASTIfThen>(parent, neg_condition);
507 }
452 ASTZipper* sub_zipper = if_node->GetSubNodes(); 508 ASTZipper* sub_zipper = if_node->GetSubNodes();
453 sub_zipper->SetParent(if_node); 509 sub_zipper->Init(goto_node, if_node);
510 zipper.InsertAfter(if_node, prev);
454 sub_zipper->Remove(goto_node); 511 sub_zipper->Remove(goto_node);
512 // ShowCurrentState("After IfThen Enclose");
455} 513}
456 514
457void ASTManager::MoveOutward(ASTNode goto_node) { 515void ASTManager::MoveOutward(ASTNode goto_node) {
516 // ShowCurrentState("Before MoveOutward");
517 outward_count++;
458 ASTZipper& zipper = goto_node->GetManager(); 518 ASTZipper& zipper = goto_node->GetManager();
459 ASTNode parent = goto_node->GetParent(); 519 ASTNode parent = goto_node->GetParent();
520 ASTZipper& zipper2 = parent->GetManager();
521 ASTNode grandpa = parent->GetParent();
460 bool is_loop = parent->IsLoop(); 522 bool is_loop = parent->IsLoop();
461 bool is_if = parent->IsIfThen() || parent->IsIfElse(); 523 bool is_else = parent->IsIfElse();
524 bool is_if = parent->IsIfThen();
462 525
463 ASTNode prev = goto_node->GetPrevious(); 526 ASTNode prev = goto_node->GetPrevious();
527 ASTNode post = goto_node->GetNext();
464 528
465 Expr condition = goto_node->GetGotoCondition(); 529 Expr condition = goto_node->GetGotoCondition();
466 u32 var_index = NewVariable();
467 Expr var_condition = MakeExpr<ExprVar>(var_index);
468 ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
469 zipper.DetachSingle(goto_node); 530 zipper.DetachSingle(goto_node);
470 zipper.InsertAfter(var_node, prev);
471 goto_node->SetGotoCondition(var_condition);
472 if (is_loop) { 531 if (is_loop) {
532 u32 var_index = NewVariable();
533 Expr var_condition = MakeExpr<ExprVar>(var_index);
534 ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
535 ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, true_condition);
536 zipper2.InsertBefore(var_node_init, parent);
537 zipper.InsertAfter(var_node, prev);
538 goto_node->SetGotoCondition(var_condition);
473 ASTNode break_node = ASTBase::Make<ASTBreak>(parent, var_condition); 539 ASTNode break_node = ASTBase::Make<ASTBreak>(parent, var_condition);
474 zipper.InsertAfter(break_node, var_node); 540 zipper.InsertAfter(break_node, var_node);
475 } else if (is_if) { 541 } else if (is_if || is_else) {
476 ASTNode post = var_node->GetNext();
477 if (post) { 542 if (post) {
543 u32 var_index = NewVariable();
544 Expr var_condition = MakeExpr<ExprVar>(var_index);
545 ASTNode var_node = ASTBase::Make<ASTVarSet>(parent, var_index, condition);
546 ASTNode var_node_init = ASTBase::Make<ASTVarSet>(parent, var_index, true_condition);
547 if (is_if) {
548 zipper2.InsertBefore(var_node_init, parent);
549 } else {
550 zipper2.InsertBefore(var_node_init, parent->GetPrevious());
551 }
552 zipper.InsertAfter(var_node, prev);
553 goto_node->SetGotoCondition(var_condition);
478 zipper.DetachTail(post); 554 zipper.DetachTail(post);
479 ASTNode if_node = ASTBase::Make<ASTIfThen>(parent, var_condition, ASTZipper(post)); 555 ASTNode if_node = ASTBase::Make<ASTIfThen>(parent, MakeExprNot(var_condition));
480 zipper.InsertAfter(if_node, var_node);
481 ASTZipper* sub_zipper = if_node->GetSubNodes(); 556 ASTZipper* sub_zipper = if_node->GetSubNodes();
482 sub_zipper->SetParent(if_node); 557 sub_zipper->Init(post, if_node);
558 zipper.InsertAfter(if_node, var_node);
559 } else {
560 Expr if_condition;
561 if (is_if) {
562 if_condition = parent->GetIfCondition();
563 } else {
564 ASTNode if_node = parent->GetPrevious();
565 if_condition = MakeExprNot(if_node->GetIfCondition());
566 }
567 Expr new_condition = MakeExprAnd(if_condition, condition);
568 goto_node->SetGotoCondition(new_condition);
483 } 569 }
484 } else { 570 } else {
485 UNREACHABLE(); 571 UNREACHABLE();
486 } 572 }
487 ASTZipper& zipper2 = parent->GetManager();
488 ASTNode next = parent->GetNext(); 573 ASTNode next = parent->GetNext();
489 if (is_if && next && next->IsIfElse()) { 574 if (is_if && next && next->IsIfElse()) {
490 zipper2.InsertAfter(goto_node, next); 575 zipper2.InsertAfter(goto_node, next);
576 goto_node->SetParent(grandpa);
577 // ShowCurrentState("After MoveOutward");
491 return; 578 return;
492 } 579 }
493 zipper2.InsertAfter(goto_node, parent); 580 zipper2.InsertAfter(goto_node, parent);
581 goto_node->SetParent(grandpa);
582 // ShowCurrentState("After MoveOutward");
494} 583}
495 584
496} // namespace VideoCommon::Shader 585} // namespace VideoCommon::Shader