diff options
| author | 2019-06-28 20:54:21 -0400 | |
|---|---|---|
| committer | 2019-10-04 18:52:48 -0400 | |
| commit | 8be6e1c5221066a49b6ad27efbd20a999a7c16b3 (patch) | |
| tree | a00263eb962503bec08ec4bc870a9546c3b80d22 /src/video_core/shader/ast.cpp | |
| parent | shader_ir: Add basic goto elimination (diff) | |
| download | yuzu-8be6e1c5221066a49b6ad27efbd20a999a7c16b3.tar.gz yuzu-8be6e1c5221066a49b6ad27efbd20a999a7c16b3.tar.xz yuzu-8be6e1c5221066a49b6ad27efbd20a999a7c16b3.zip | |
shader_ir: Corrections to outward movements and misc stuffs
Diffstat (limited to 'src/video_core/shader/ast.cpp')
| -rw-r--r-- | src/video_core/shader/ast.cpp | 185 |
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 @@ | |||
| 12 | namespace VideoCommon::Shader { | 12 | namespace VideoCommon::Shader { |
| 13 | 13 | ||
| 14 | ASTZipper::ASTZipper() = default; | 14 | ASTZipper::ASTZipper() = default; |
| 15 | ASTZipper::ASTZipper(ASTNode new_first) : first{}, last{} { | 15 | |
| 16 | void 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 | ||
| 26 | void ASTZipper::PushBack(ASTNode new_node) { | 29 | void 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 | ||
| 39 | void ASTZipper::PushFront(ASTNode new_node) { | 43 | void 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 | ||
| 52 | void ASTZipper::InsertAfter(ASTNode new_node, ASTNode at_node) { | 57 | void 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 | ||
| 66 | void ASTZipper::SetParent(ASTNode new_parent) { | 76 | void 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 | ||
| 74 | void ASTZipper::DetachTail(ASTNode node) { | 95 | void 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 | ||
| 86 | void ASTZipper::DetachSegment(ASTNode start, ASTNode end) { | 114 | void 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 | |||
| 135 | void ASTZipper::Remove(ASTNode node) { | 166 | void 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 | |||
| 338 | void ASTManager::Decompile() { | 366 | void 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 | ||
| 387 | bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { | 414 | bool 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 | ||
| 448 | void ASTManager::ShowCurrentState(std::string state) { | ||
| 449 | LOG_CRITICAL(HW_GPU, "\nState {}:\n\n{}\n", state, Print()); | ||
| 450 | SanityCheck(); | ||
| 451 | } | ||
| 452 | |||
| 453 | void ASTManager::SanityCheck() { | ||
| 454 | for (auto label : labels) { | ||
| 455 | if (!label->GetParent()) { | ||
| 456 | LOG_CRITICAL(HW_GPU, "Sanity Check Failed"); | ||
| 457 | } | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 421 | void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { | 461 | void 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 | ||
| 438 | void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { | 482 | void 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 | ||
| 457 | void ASTManager::MoveOutward(ASTNode goto_node) { | 515 | void 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 |