diff options
| author | 2019-06-28 22:59:43 -0400 | |
|---|---|---|
| committer | 2019-10-04 18:52:49 -0400 | |
| commit | 6fdd501113d5094f9148046c3b17cf2239e99aa5 (patch) | |
| tree | 5a328292210ac4f07696bad5ea237277a7cb9113 /src | |
| parent | shader_ir: Corrections to outward movements and misc stuffs (diff) | |
| download | yuzu-6fdd501113d5094f9148046c3b17cf2239e99aa5.tar.gz yuzu-6fdd501113d5094f9148046c3b17cf2239e99aa5.tar.xz yuzu-6fdd501113d5094f9148046c3b17cf2239e99aa5.zip | |
shader_ir: Declare Manager and pass it to appropiate programs.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/shader/ast.cpp | 139 | ||||
| -rw-r--r-- | src/video_core/shader/ast.h | 74 | ||||
| -rw-r--r-- | src/video_core/shader/control_flow.cpp | 65 | ||||
| -rw-r--r-- | src/video_core/shader/control_flow.h | 8 | ||||
| -rw-r--r-- | src/video_core/shader/decode.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 2 |
7 files changed, 214 insertions, 104 deletions
diff --git a/src/video_core/shader/ast.cpp b/src/video_core/shader/ast.cpp index d521a7b52..0bf289f98 100644 --- a/src/video_core/shader/ast.cpp +++ b/src/video_core/shader/ast.cpp | |||
| @@ -363,6 +363,71 @@ std::string ASTManager::Print() { | |||
| 363 | return printer.GetResult(); | 363 | return printer.GetResult(); |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | ASTManager::ASTManager() = default; | ||
| 367 | |||
| 368 | ASTManager::~ASTManager() { | ||
| 369 | Clear(); | ||
| 370 | } | ||
| 371 | |||
| 372 | void ASTManager::Init() { | ||
| 373 | main_node = ASTBase::Make<ASTProgram>(ASTNode{}); | ||
| 374 | program = std::get_if<ASTProgram>(main_node->GetInnerData()); | ||
| 375 | true_condition = MakeExpr<ExprBoolean>(true); | ||
| 376 | } | ||
| 377 | |||
| 378 | ASTManager::ASTManager(ASTManager&& other) | ||
| 379 | : labels_map(std::move(other.labels_map)), labels_count{other.labels_count}, | ||
| 380 | gotos(std::move(other.gotos)), labels(std::move(other.labels)), variables{other.variables}, | ||
| 381 | program{other.program}, main_node{other.main_node}, true_condition{other.true_condition} { | ||
| 382 | other.main_node.reset(); | ||
| 383 | } | ||
| 384 | |||
| 385 | ASTManager& ASTManager::operator=(ASTManager&& other) { | ||
| 386 | labels_map = std::move(other.labels_map); | ||
| 387 | labels_count = other.labels_count; | ||
| 388 | gotos = std::move(other.gotos); | ||
| 389 | labels = std::move(other.labels); | ||
| 390 | variables = other.variables; | ||
| 391 | program = other.program; | ||
| 392 | main_node = other.main_node; | ||
| 393 | true_condition = other.true_condition; | ||
| 394 | |||
| 395 | other.main_node.reset(); | ||
| 396 | return *this; | ||
| 397 | } | ||
| 398 | |||
| 399 | void ASTManager::DeclareLabel(u32 address) { | ||
| 400 | const auto pair = labels_map.emplace(address, labels_count); | ||
| 401 | if (pair.second) { | ||
| 402 | labels_count++; | ||
| 403 | labels.resize(labels_count); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | void ASTManager::InsertLabel(u32 address) { | ||
| 408 | u32 index = labels_map[address]; | ||
| 409 | ASTNode label = ASTBase::Make<ASTLabel>(main_node, index); | ||
| 410 | labels[index] = label; | ||
| 411 | program->nodes.PushBack(label); | ||
| 412 | } | ||
| 413 | |||
| 414 | void ASTManager::InsertGoto(Expr condition, u32 address) { | ||
| 415 | u32 index = labels_map[address]; | ||
| 416 | ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index); | ||
| 417 | gotos.push_back(goto_node); | ||
| 418 | program->nodes.PushBack(goto_node); | ||
| 419 | } | ||
| 420 | |||
| 421 | void ASTManager::InsertBlock(u32 start_address, u32 end_address) { | ||
| 422 | ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address); | ||
| 423 | program->nodes.PushBack(block); | ||
| 424 | } | ||
| 425 | |||
| 426 | void ASTManager::InsertReturn(Expr condition, bool kills) { | ||
| 427 | ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills); | ||
| 428 | program->nodes.PushBack(node); | ||
| 429 | } | ||
| 430 | |||
| 366 | void ASTManager::Decompile() { | 431 | void ASTManager::Decompile() { |
| 367 | auto it = gotos.begin(); | 432 | auto it = gotos.begin(); |
| 368 | while (it != gotos.end()) { | 433 | while (it != gotos.end()) { |
| @@ -460,7 +525,6 @@ void ASTManager::SanityCheck() { | |||
| 460 | 525 | ||
| 461 | void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { | 526 | void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { |
| 462 | // ShowCurrentState("Before DoWhile Enclose"); | 527 | // ShowCurrentState("Before DoWhile Enclose"); |
| 463 | enclose_count++; | ||
| 464 | ASTZipper& zipper = goto_node->GetManager(); | 528 | ASTZipper& zipper = goto_node->GetManager(); |
| 465 | ASTNode loop_start = label->GetNext(); | 529 | ASTNode loop_start = label->GetNext(); |
| 466 | if (loop_start == goto_node) { | 530 | if (loop_start == goto_node) { |
| @@ -481,7 +545,6 @@ void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) { | |||
| 481 | 545 | ||
| 482 | void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { | 546 | void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { |
| 483 | // ShowCurrentState("Before IfThen Enclose"); | 547 | // ShowCurrentState("Before IfThen Enclose"); |
| 484 | enclose_count++; | ||
| 485 | ASTZipper& zipper = goto_node->GetManager(); | 548 | ASTZipper& zipper = goto_node->GetManager(); |
| 486 | ASTNode if_end = label->GetPrevious(); | 549 | ASTNode if_end = label->GetPrevious(); |
| 487 | if (if_end == goto_node) { | 550 | if (if_end == goto_node) { |
| @@ -514,7 +577,6 @@ void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) { | |||
| 514 | 577 | ||
| 515 | void ASTManager::MoveOutward(ASTNode goto_node) { | 578 | void ASTManager::MoveOutward(ASTNode goto_node) { |
| 516 | // ShowCurrentState("Before MoveOutward"); | 579 | // ShowCurrentState("Before MoveOutward"); |
| 517 | outward_count++; | ||
| 518 | ASTZipper& zipper = goto_node->GetManager(); | 580 | ASTZipper& zipper = goto_node->GetManager(); |
| 519 | ASTNode parent = goto_node->GetParent(); | 581 | ASTNode parent = goto_node->GetParent(); |
| 520 | ASTZipper& zipper2 = parent->GetManager(); | 582 | ASTZipper& zipper2 = parent->GetManager(); |
| @@ -582,4 +644,75 @@ void ASTManager::MoveOutward(ASTNode goto_node) { | |||
| 582 | // ShowCurrentState("After MoveOutward"); | 644 | // ShowCurrentState("After MoveOutward"); |
| 583 | } | 645 | } |
| 584 | 646 | ||
| 647 | class ASTClearer { | ||
| 648 | public: | ||
| 649 | ASTClearer() = default; | ||
| 650 | |||
| 651 | void operator()(ASTProgram& ast) { | ||
| 652 | ASTNode current = ast.nodes.GetFirst(); | ||
| 653 | while (current) { | ||
| 654 | Visit(current); | ||
| 655 | current = current->GetNext(); | ||
| 656 | } | ||
| 657 | } | ||
| 658 | |||
| 659 | void operator()(ASTIfThen& ast) { | ||
| 660 | ASTNode current = ast.nodes.GetFirst(); | ||
| 661 | while (current) { | ||
| 662 | Visit(current); | ||
| 663 | current = current->GetNext(); | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | void operator()(ASTIfElse& ast) { | ||
| 668 | ASTNode current = ast.nodes.GetFirst(); | ||
| 669 | while (current) { | ||
| 670 | Visit(current); | ||
| 671 | current = current->GetNext(); | ||
| 672 | } | ||
| 673 | } | ||
| 674 | |||
| 675 | void operator()(ASTBlockEncoded& ast) {} | ||
| 676 | |||
| 677 | void operator()(ASTBlockDecoded& ast) { | ||
| 678 | ast.nodes.clear(); | ||
| 679 | } | ||
| 680 | |||
| 681 | void operator()(ASTVarSet& ast) {} | ||
| 682 | |||
| 683 | void operator()(ASTLabel& ast) {} | ||
| 684 | |||
| 685 | void operator()(ASTGoto& ast) {} | ||
| 686 | |||
| 687 | void operator()(ASTDoWhile& ast) { | ||
| 688 | ASTNode current = ast.nodes.GetFirst(); | ||
| 689 | while (current) { | ||
| 690 | Visit(current); | ||
| 691 | current = current->GetNext(); | ||
| 692 | } | ||
| 693 | } | ||
| 694 | |||
| 695 | void operator()(ASTReturn& ast) {} | ||
| 696 | |||
| 697 | void operator()(ASTBreak& ast) {} | ||
| 698 | |||
| 699 | void Visit(ASTNode& node) { | ||
| 700 | std::visit(*this, *node->GetInnerData()); | ||
| 701 | node->Clear(); | ||
| 702 | } | ||
| 703 | }; | ||
| 704 | |||
| 705 | void ASTManager::Clear() { | ||
| 706 | if (!main_node) { | ||
| 707 | return; | ||
| 708 | } | ||
| 709 | ASTClearer clearer{}; | ||
| 710 | clearer.Visit(main_node); | ||
| 711 | main_node.reset(); | ||
| 712 | program = nullptr; | ||
| 713 | labels_map.clear(); | ||
| 714 | labels.clear(); | ||
| 715 | gotos.clear(); | ||
| 716 | } | ||
| 717 | |||
| 585 | } // namespace VideoCommon::Shader | 718 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/ast.h b/src/video_core/shader/ast.h index 4276f66a9..958989bcd 100644 --- a/src/video_core/shader/ast.h +++ b/src/video_core/shader/ast.h | |||
| @@ -30,8 +30,8 @@ class ASTDoWhile; | |||
| 30 | class ASTReturn; | 30 | class ASTReturn; |
| 31 | class ASTBreak; | 31 | class ASTBreak; |
| 32 | 32 | ||
| 33 | using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded, ASTVarSet, ASTGoto, | 33 | using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded, |
| 34 | ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>; | 34 | ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>; |
| 35 | 35 | ||
| 36 | using ASTNode = std::shared_ptr<ASTBase>; | 36 | using ASTNode = std::shared_ptr<ASTBase>; |
| 37 | 37 | ||
| @@ -261,6 +261,13 @@ public: | |||
| 261 | return nullptr; | 261 | return nullptr; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | void Clear() { | ||
| 265 | next.reset(); | ||
| 266 | previous.reset(); | ||
| 267 | parent.reset(); | ||
| 268 | manager = nullptr; | ||
| 269 | } | ||
| 270 | |||
| 264 | private: | 271 | private: |
| 265 | friend class ASTZipper; | 272 | friend class ASTZipper; |
| 266 | 273 | ||
| @@ -273,43 +280,26 @@ private: | |||
| 273 | 280 | ||
| 274 | class ASTManager final { | 281 | class ASTManager final { |
| 275 | public: | 282 | public: |
| 276 | explicit ASTManager() { | 283 | ASTManager(); |
| 277 | main_node = ASTBase::Make<ASTProgram>(ASTNode{}); | 284 | ~ASTManager(); |
| 278 | program = std::get_if<ASTProgram>(main_node->GetInnerData()); | ||
| 279 | true_condition = MakeExpr<ExprBoolean>(true); | ||
| 280 | } | ||
| 281 | 285 | ||
| 282 | void DeclareLabel(u32 address) { | 286 | ASTManager(const ASTManager& o) = delete; |
| 283 | const auto pair = labels_map.emplace(address, labels_count); | 287 | ASTManager& operator=(const ASTManager& other) = delete; |
| 284 | if (pair.second) { | ||
| 285 | labels_count++; | ||
| 286 | labels.resize(labels_count); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | 288 | ||
| 290 | void InsertLabel(u32 address) { | 289 | ASTManager(ASTManager&& other); |
| 291 | u32 index = labels_map[address]; | 290 | ASTManager& operator=(ASTManager&& other); |
| 292 | ASTNode label = ASTBase::Make<ASTLabel>(main_node, index); | ||
| 293 | labels[index] = label; | ||
| 294 | program->nodes.PushBack(label); | ||
| 295 | } | ||
| 296 | 291 | ||
| 297 | void InsertGoto(Expr condition, u32 address) { | 292 | void Init(); |
| 298 | u32 index = labels_map[address]; | ||
| 299 | ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index); | ||
| 300 | gotos.push_back(goto_node); | ||
| 301 | program->nodes.PushBack(goto_node); | ||
| 302 | } | ||
| 303 | 293 | ||
| 304 | void InsertBlock(u32 start_address, u32 end_address) { | 294 | void DeclareLabel(u32 address); |
| 305 | ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address); | ||
| 306 | program->nodes.PushBack(block); | ||
| 307 | } | ||
| 308 | 295 | ||
| 309 | void InsertReturn(Expr condition, bool kills) { | 296 | void InsertLabel(u32 address); |
| 310 | ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills); | 297 | |
| 311 | program->nodes.PushBack(node); | 298 | void InsertGoto(Expr condition, u32 address); |
| 312 | } | 299 | |
| 300 | void InsertBlock(u32 start_address, u32 end_address); | ||
| 301 | |||
| 302 | void InsertReturn(Expr condition, bool kills); | ||
| 313 | 303 | ||
| 314 | std::string Print(); | 304 | std::string Print(); |
| 315 | 305 | ||
| @@ -323,6 +313,12 @@ public: | |||
| 323 | return gotos.size() == 0; | 313 | return gotos.size() == 0; |
| 324 | } | 314 | } |
| 325 | 315 | ||
| 316 | ASTNode GetProgram() { | ||
| 317 | return main_node; | ||
| 318 | } | ||
| 319 | |||
| 320 | void Clear(); | ||
| 321 | |||
| 326 | private: | 322 | private: |
| 327 | bool IndirectlyRelated(ASTNode first, ASTNode second); | 323 | bool IndirectlyRelated(ASTNode first, ASTNode second); |
| 328 | 324 | ||
| @@ -332,7 +328,7 @@ private: | |||
| 332 | 328 | ||
| 333 | void EncloseIfThen(ASTNode goto_node, ASTNode label); | 329 | void EncloseIfThen(ASTNode goto_node, ASTNode label); |
| 334 | 330 | ||
| 335 | void MoveOutward(ASTNode goto_node) ; | 331 | void MoveOutward(ASTNode goto_node); |
| 336 | 332 | ||
| 337 | u32 NewVariable() { | 333 | u32 NewVariable() { |
| 338 | u32 new_var = variables; | 334 | u32 new_var = variables; |
| @@ -345,11 +341,9 @@ private: | |||
| 345 | std::vector<ASTNode> labels{}; | 341 | std::vector<ASTNode> labels{}; |
| 346 | std::list<ASTNode> gotos{}; | 342 | std::list<ASTNode> gotos{}; |
| 347 | u32 variables{}; | 343 | u32 variables{}; |
| 348 | ASTProgram* program; | 344 | ASTProgram* program{}; |
| 349 | ASTNode main_node; | 345 | ASTNode main_node{}; |
| 350 | Expr true_condition; | 346 | Expr true_condition{}; |
| 351 | u32 outward_count{}; | ||
| 352 | u32 enclose_count{}; | ||
| 353 | }; | 347 | }; |
| 354 | 348 | ||
| 355 | } // namespace VideoCommon::Shader | 349 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index 7a21d870f..deb3d3ebd 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp | |||
| @@ -57,8 +57,8 @@ struct BlockInfo { | |||
| 57 | 57 | ||
| 58 | struct CFGRebuildState { | 58 | struct CFGRebuildState { |
| 59 | explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size, | 59 | explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size, |
| 60 | const u32 start) | 60 | const u32 start, ASTManager& manager) |
| 61 | : start{start}, program_code{program_code}, program_size{program_size} {} | 61 | : program_code{program_code}, program_size{program_size}, start{start}, manager{manager} {} |
| 62 | 62 | ||
| 63 | u32 start{}; | 63 | u32 start{}; |
| 64 | std::vector<BlockInfo> block_info{}; | 64 | std::vector<BlockInfo> block_info{}; |
| @@ -71,6 +71,7 @@ struct CFGRebuildState { | |||
| 71 | std::unordered_map<u32, BlockStack> stacks{}; | 71 | std::unordered_map<u32, BlockStack> stacks{}; |
| 72 | const ProgramCode& program_code; | 72 | const ProgramCode& program_code; |
| 73 | const std::size_t program_size; | 73 | const std::size_t program_size; |
| 74 | ASTManager& manager; | ||
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | enum class BlockCollision : u32 { None, Found, Inside }; | 77 | enum class BlockCollision : u32 { None, Found, Inside }; |
| @@ -455,29 +456,28 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch) { | |||
| 455 | } | 456 | } |
| 456 | 457 | ||
| 457 | void DecompileShader(CFGRebuildState& state) { | 458 | void DecompileShader(CFGRebuildState& state) { |
| 458 | ASTManager manager{}; | 459 | state.manager.Init(); |
| 459 | for (auto label : state.labels) { | 460 | for (auto label : state.labels) { |
| 460 | manager.DeclareLabel(label); | 461 | state.manager.DeclareLabel(label); |
| 461 | } | 462 | } |
| 462 | for (auto& block : state.block_info) { | 463 | for (auto& block : state.block_info) { |
| 463 | if (state.labels.count(block.start) != 0) { | 464 | if (state.labels.count(block.start) != 0) { |
| 464 | manager.InsertLabel(block.start); | 465 | state.manager.InsertLabel(block.start); |
| 465 | } | 466 | } |
| 466 | u32 end = block.branch.ignore ? block.end + 1 : block.end; | 467 | u32 end = block.branch.ignore ? block.end + 1 : block.end; |
| 467 | manager.InsertBlock(block.start, end); | 468 | state.manager.InsertBlock(block.start, end); |
| 468 | if (!block.branch.ignore) { | 469 | if (!block.branch.ignore) { |
| 469 | InsertBranch(manager, block.branch); | 470 | InsertBranch(state.manager, block.branch); |
| 470 | } | 471 | } |
| 471 | } | 472 | } |
| 472 | //manager.ShowCurrentState("Before Decompiling"); | 473 | // state.manager.ShowCurrentState("Before Decompiling"); |
| 473 | manager.Decompile(); | 474 | state.manager.Decompile(); |
| 474 | //manager.ShowCurrentState("After Decompiling"); | 475 | // state.manager.ShowCurrentState("After Decompiling"); |
| 475 | } | 476 | } |
| 476 | 477 | ||
| 477 | std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | 478 | std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size, |
| 478 | std::size_t program_size, u32 start_address) { | 479 | u32 start_address, ASTManager& manager) { |
| 479 | CFGRebuildState state{program_code, program_size, start_address}; | 480 | CFGRebuildState state{program_code, program_size, start_address, manager}; |
| 480 | |||
| 481 | // Inspect Code and generate blocks | 481 | // Inspect Code and generate blocks |
| 482 | state.labels.clear(); | 482 | state.labels.clear(); |
| 483 | state.labels.emplace(start_address); | 483 | state.labels.emplace(start_address); |
| @@ -503,12 +503,21 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 503 | [](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; }); | 503 | [](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; }); |
| 504 | if (decompiled) { | 504 | if (decompiled) { |
| 505 | DecompileShader(state); | 505 | DecompileShader(state); |
| 506 | decompiled = state.manager.IsFullyDecompiled(); | ||
| 507 | if (!decompiled) { | ||
| 508 | LOG_CRITICAL(HW_GPU, "Failed to remove all the gotos!:"); | ||
| 509 | state.manager.ShowCurrentState("Of Shader"); | ||
| 510 | state.manager.Clear(); | ||
| 511 | } | ||
| 512 | } | ||
| 513 | auto result_out = std::make_unique<ShaderCharacteristics>(); | ||
| 514 | result_out->decompiled = decompiled; | ||
| 515 | result_out->start = start_address; | ||
| 516 | if (decompiled) { | ||
| 517 | result_out->end = state.block_info.back().end + 1; | ||
| 518 | return std::move(result_out); | ||
| 506 | } | 519 | } |
| 507 | ShaderCharacteristics result_out{}; | 520 | for (auto& block : state.block_info) { |
| 508 | result_out.decompilable = decompiled; | ||
| 509 | result_out.start = start_address; | ||
| 510 | result_out.end = start_address; | ||
| 511 | for (const auto& block : state.block_info) { | ||
| 512 | ShaderBlock new_block{}; | 521 | ShaderBlock new_block{}; |
| 513 | new_block.start = block.start; | 522 | new_block.start = block.start; |
| 514 | new_block.end = block.end; | 523 | new_block.end = block.end; |
| @@ -518,26 +527,20 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 518 | new_block.branch.kills = block.branch.kill; | 527 | new_block.branch.kills = block.branch.kill; |
| 519 | new_block.branch.address = block.branch.address; | 528 | new_block.branch.address = block.branch.address; |
| 520 | } | 529 | } |
| 521 | result_out.end = std::max(result_out.end, block.end); | 530 | result_out->end = std::max(result_out->end, block.end); |
| 522 | result_out.blocks.push_back(new_block); | 531 | result_out->blocks.push_back(new_block); |
| 523 | } | ||
| 524 | if (result_out.decompilable) { | ||
| 525 | result_out.labels = std::move(state.labels); | ||
| 526 | return {std::move(result_out)}; | ||
| 527 | } | 532 | } |
| 528 | 533 | auto back = result_out->blocks.begin(); | |
| 529 | // If it's not decompilable, merge the unlabelled blocks together | ||
| 530 | auto back = result_out.blocks.begin(); | ||
| 531 | auto next = std::next(back); | 534 | auto next = std::next(back); |
| 532 | while (next != result_out.blocks.end()) { | 535 | while (next != result_out->blocks.end()) { |
| 533 | if (state.labels.count(next->start) == 0 && next->start == back->end + 1) { | 536 | if (state.labels.count(next->start) == 0 && next->start == back->end + 1) { |
| 534 | back->end = next->end; | 537 | back->end = next->end; |
| 535 | next = result_out.blocks.erase(next); | 538 | next = result_out->blocks.erase(next); |
| 536 | continue; | 539 | continue; |
| 537 | } | 540 | } |
| 538 | back = next; | 541 | back = next; |
| 539 | ++next; | 542 | ++next; |
| 540 | } | 543 | } |
| 541 | return {std::move(result_out)}; | 544 | return std::move(result_out); |
| 542 | } | 545 | } |
| 543 | } // namespace VideoCommon::Shader | 546 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/control_flow.h b/src/video_core/shader/control_flow.h index efd037f1a..2805d975c 100644 --- a/src/video_core/shader/control_flow.h +++ b/src/video_core/shader/control_flow.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include "video_core/engines/shader_bytecode.h" | 11 | #include "video_core/engines/shader_bytecode.h" |
| 12 | #include "video_core/shader/shader_ir.h" | 12 | #include "video_core/shader/shader_ir.h" |
| 13 | #include "video_core/shader/ast.h" | ||
| 13 | 14 | ||
| 14 | namespace VideoCommon::Shader { | 15 | namespace VideoCommon::Shader { |
| 15 | 16 | ||
| @@ -67,13 +68,12 @@ struct ShaderBlock { | |||
| 67 | 68 | ||
| 68 | struct ShaderCharacteristics { | 69 | struct ShaderCharacteristics { |
| 69 | std::list<ShaderBlock> blocks{}; | 70 | std::list<ShaderBlock> blocks{}; |
| 70 | bool decompilable{}; | 71 | bool decompiled{}; |
| 71 | u32 start{}; | 72 | u32 start{}; |
| 72 | u32 end{}; | 73 | u32 end{}; |
| 73 | std::set<u32> labels{}; | ||
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | 76 | std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size, |
| 77 | std::size_t program_size, u32 start_address); | 77 | u32 start_address, ASTManager& manager); |
| 78 | 78 | ||
| 79 | } // namespace VideoCommon::Shader | 79 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 47a9fd961..381e87415 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp | |||
| @@ -39,36 +39,14 @@ void ShaderIR::Decode() { | |||
| 39 | std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); | 39 | std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); |
| 40 | 40 | ||
| 41 | disable_flow_stack = false; | 41 | disable_flow_stack = false; |
| 42 | const auto info = ScanFlow(program_code, program_size, main_offset); | 42 | const auto info = |
| 43 | ScanFlow(program_code, program_size, main_offset, program_manager); | ||
| 43 | if (info) { | 44 | if (info) { |
| 44 | const auto& shader_info = *info; | 45 | const auto& shader_info = *info; |
| 45 | coverage_begin = shader_info.start; | 46 | coverage_begin = shader_info.start; |
| 46 | coverage_end = shader_info.end; | 47 | coverage_end = shader_info.end; |
| 47 | if (shader_info.decompilable) { | 48 | if (shader_info.decompiled) { |
| 48 | disable_flow_stack = true; | 49 | disable_flow_stack = true; |
| 49 | const auto insert_block = [this](NodeBlock& nodes, u32 label) { | ||
| 50 | if (label == static_cast<u32>(exit_branch)) { | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | basic_blocks.insert({label, nodes}); | ||
| 54 | }; | ||
| 55 | const auto& blocks = shader_info.blocks; | ||
| 56 | NodeBlock current_block; | ||
| 57 | u32 current_label = static_cast<u32>(exit_branch); | ||
| 58 | for (auto& block : blocks) { | ||
| 59 | if (shader_info.labels.count(block.start) != 0) { | ||
| 60 | insert_block(current_block, current_label); | ||
| 61 | current_block.clear(); | ||
| 62 | current_label = block.start; | ||
| 63 | } | ||
| 64 | if (!block.ignore_branch) { | ||
| 65 | DecodeRangeInner(current_block, block.start, block.end); | ||
| 66 | InsertControlFlow(current_block, block); | ||
| 67 | } else { | ||
| 68 | DecodeRangeInner(current_block, block.start, block.end + 1); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | insert_block(current_block, current_label); | ||
| 72 | return; | 50 | return; |
| 73 | } | 51 | } |
| 74 | LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method"); | 52 | LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method"); |
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 2c357f310..c79f80e04 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp | |||
| @@ -23,7 +23,7 @@ using Tegra::Shader::PredOperation; | |||
| 23 | using Tegra::Shader::Register; | 23 | using Tegra::Shader::Register; |
| 24 | 24 | ||
| 25 | ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size) | 25 | ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size) |
| 26 | : program_code{program_code}, main_offset{main_offset}, program_size{size} { | 26 | : program_code{program_code}, main_offset{main_offset}, program_size{size}, program_manager{} { |
| 27 | Decode(); | 27 | Decode(); |
| 28 | } | 28 | } |
| 29 | 29 | ||
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 6f666ee30..a91cd7d67 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "video_core/engines/shader_bytecode.h" | 16 | #include "video_core/engines/shader_bytecode.h" |
| 17 | #include "video_core/engines/shader_header.h" | 17 | #include "video_core/engines/shader_header.h" |
| 18 | #include "video_core/shader/node.h" | 18 | #include "video_core/shader/node.h" |
| 19 | #include "video_core/shader/ast.h" | ||
| 19 | 20 | ||
| 20 | namespace VideoCommon::Shader { | 21 | namespace VideoCommon::Shader { |
| 21 | 22 | ||
| @@ -364,6 +365,7 @@ private: | |||
| 364 | 365 | ||
| 365 | std::map<u32, NodeBlock> basic_blocks; | 366 | std::map<u32, NodeBlock> basic_blocks; |
| 366 | NodeBlock global_code; | 367 | NodeBlock global_code; |
| 368 | ASTManager program_manager; | ||
| 367 | 369 | ||
| 368 | std::set<u32> used_registers; | 370 | std::set<u32> used_registers; |
| 369 | std::set<Tegra::Shader::Pred> used_predicates; | 371 | std::set<Tegra::Shader::Pred> used_predicates; |