diff options
| author | 2019-08-16 16:25:02 -0400 | |
|---|---|---|
| committer | 2019-10-04 18:52:50 -0400 | |
| commit | 47e4f6a52c5eb34916e2c1f4c876e6e8624e3840 (patch) | |
| tree | 60ca95508197ceb868b004791caf81a042b22842 /src/video_core/shader/ast.cpp | |
| parent | gl_shader_decompiler: Implement AST decompiling (diff) | |
| download | yuzu-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.cpp | 98 |
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 | ||
| 366 | ASTManager::ASTManager() = default; | 366 | ASTManager::ASTManager(bool full_decompile) : full_decompile{full_decompile} {}; |
| 367 | 367 | ||
| 368 | ASTManager::~ASTManager() { | 368 | ASTManager::~ASTManager() { |
| 369 | Clear(); | 369 | Clear(); |
| @@ -383,6 +383,7 @@ ASTManager::ASTManager(ASTManager&& other) | |||
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | ASTManager& ASTManager::operator=(ASTManager&& other) { | 385 | ASTManager& 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 | |||
| 508 | bool 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 | |||
| 533 | ASTNode 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 | ||
| 479 | bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { | 567 | bool ASTManager::IndirectlyRelated(ASTNode first, ASTNode second) { |