summaryrefslogtreecommitdiff
path: root/src/video_core/shader/ast.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-08-16 16:25:02 -0400
committerGravatar FernandoS272019-10-04 18:52:50 -0400
commit47e4f6a52c5eb34916e2c1f4c876e6e8624e3840 (patch)
tree60ca95508197ceb868b004791caf81a042b22842 /src/video_core/shader/ast.cpp
parentgl_shader_decompiler: Implement AST decompiling (diff)
downloadyuzu-47e4f6a52c5eb34916e2c1f4c876e6e8624e3840.tar.gz
yuzu-47e4f6a52c5eb34916e2c1f4c876e6e8624e3840.tar.xz
yuzu-47e4f6a52c5eb34916e2c1f4c876e6e8624e3840.zip
Shader_Ir: Refactor Decompilation process and allow multiple decompilation modes.
Diffstat (limited to 'src/video_core/shader/ast.cpp')
-rw-r--r--src/video_core/shader/ast.cpp98
1 files changed, 93 insertions, 5 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp
index 68a96cc79..14c50e1c6 100644
--- a/src/video_core/shader/ast.cpp
+++ b/src/video_core/shader/ast.cpp
@@ -363,7 +363,7 @@ std::string ASTManager::Print() {
363 return printer.GetResult(); 363 return printer.GetResult();
364} 364}
365 365
366ASTManager::ASTManager() = default; 366ASTManager::ASTManager(bool full_decompile) : full_decompile{full_decompile} {};
367 367
368ASTManager::~ASTManager() { 368ASTManager::~ASTManager() {
369 Clear(); 369 Clear();
@@ -383,6 +383,7 @@ ASTManager::ASTManager(ASTManager&& other)
383} 383}
384 384
385ASTManager& ASTManager::operator=(ASTManager&& other) { 385ASTManager& ASTManager::operator=(ASTManager&& other) {
386 full_decompile = other.full_decompile;
386 labels_map = std::move(other.labels_map); 387 labels_map = std::move(other.labels_map);
387 labels_count = other.labels_count; 388 labels_count = other.labels_count;
388 gotos = std::move(other.gotos); 389 gotos = std::move(other.gotos);
@@ -434,6 +435,13 @@ void ASTManager::Decompile() {
434 ASTNode goto_node = *it; 435 ASTNode goto_node = *it;
435 u32 label_index = goto_node->GetGotoLabel(); 436 u32 label_index = goto_node->GetGotoLabel();
436 ASTNode label = labels[label_index]; 437 ASTNode label = labels[label_index];
438 if (!full_decompile) {
439 // We only decompile backward jumps
440 if (!IsBackwardsJump(goto_node, label)) {
441 it++;
442 continue;
443 }
444 }
437 if (IndirectlyRelated(goto_node, label)) { 445 if (IndirectlyRelated(goto_node, label)) {
438 while (!DirectlyRelated(goto_node, label)) { 446 while (!DirectlyRelated(goto_node, label)) {
439 MoveOutward(goto_node); 447 MoveOutward(goto_node);
@@ -469,11 +477,91 @@ void ASTManager::Decompile() {
469 } 477 }
470 it++; 478 it++;
471 } 479 }
472 for (ASTNode label : labels) { 480 if (full_decompile) {
473 auto& manager = label->GetManager(); 481 for (ASTNode label : labels) {
474 manager.Remove(label); 482 auto& manager = label->GetManager();
483 manager.Remove(label);
484 }
485 labels.clear();
486 } else {
487 auto it = labels.begin();
488 while (it != labels.end()) {
489 bool can_remove = true;
490 ASTNode label = *it;
491 for (ASTNode goto_node : gotos) {
492 u32 label_index = goto_node->GetGotoLabel();
493 ASTNode glabel = labels[label_index];
494 if (glabel == label) {
495 can_remove = false;
496 break;
497 }
498 }
499 if (can_remove) {
500 auto& manager = label->GetManager();
501 manager.Remove(label);
502 labels.erase(it);
503 }
504 }
475 } 505 }
476 labels.clear(); 506}
507
508bool ASTManager::IsBackwardsJump(ASTNode goto_node, ASTNode label_node) const {
509 u32 goto_level = goto_node->GetLevel();
510 u32 label_level = label_node->GetLevel();
511 while (goto_level > label_level) {
512 goto_level--;
513 goto_node = goto_node->GetParent();
514 }
515 while (label_level > goto_level) {
516 label_level--;
517 label_node = label_node->GetParent();
518 }
519 while (goto_node->GetParent() != label_node->GetParent()) {
520 goto_node = goto_node->GetParent();
521 label_node = label_node->GetParent();
522 }
523 ASTNode current = goto_node->GetPrevious();
524 while (current) {
525 if (current == label_node) {
526 return true;
527 }
528 current = current->GetPrevious();
529 }
530 return false;
531}
532
533ASTNode CommonParent(ASTNode first, ASTNode second) {
534 if (first->GetParent() == second->GetParent()) {
535 return first->GetParent();
536 }
537 u32 first_level = first->GetLevel();
538 u32 second_level = second->GetLevel();
539 u32 min_level;
540 u32 max_level;
541 ASTNode max;
542 ASTNode min;
543 if (first_level > second_level) {
544 min_level = second_level;
545 min = second;
546 max_level = first_level;
547 max = first;
548 } else {
549 min_level = first_level;
550 min = first;
551 max_level = second_level;
552 max = second;
553 }
554
555 while (max_level > min_level) {
556 max_level--;
557 max = max->GetParent();
558 }
559
560 while (min->GetParent() != max->GetParent()) {
561 min = min->GetParent();
562 max = max->GetParent();
563 }
564 return min->GetParent();
477} 565}
478 566
479bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { 567bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) {