diff options
| -rw-r--r-- | src/video_core/shader/control_flow.cpp | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index c2243337c..4d500320a 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp | |||
| @@ -371,10 +371,11 @@ bool TryQuery(CFGRebuildState& state) { | |||
| 371 | if (state.queries.empty()) { | 371 | if (state.queries.empty()) { |
| 372 | return false; | 372 | return false; |
| 373 | } | 373 | } |
| 374 | |||
| 374 | Query& q = state.queries.front(); | 375 | Query& q = state.queries.front(); |
| 375 | const u32 block_index = state.registered[q.address]; | 376 | const u32 block_index = state.registered[q.address]; |
| 376 | BlockInfo& block = state.block_info[block_index]; | 377 | BlockInfo& block = state.block_info[block_index]; |
| 377 | // If the block is visted, check if the stacks match, else gather the ssy/pbk | 378 | // If the block is visited, check if the stacks match, else gather the ssy/pbk |
| 378 | // labels into the current stack and look if the branch at the end of the block | 379 | // labels into the current stack and look if the branch at the end of the block |
| 379 | // consumes a label. Schedule new queries accordingly | 380 | // consumes a label. Schedule new queries accordingly |
| 380 | if (block.visited) { | 381 | if (block.visited) { |
| @@ -385,7 +386,8 @@ bool TryQuery(CFGRebuildState& state) { | |||
| 385 | return all_okay; | 386 | return all_okay; |
| 386 | } | 387 | } |
| 387 | block.visited = true; | 388 | block.visited = true; |
| 388 | state.stacks[q.address] = BlockStack{q}; | 389 | state.stacks.insert_or_assign(q.address, BlockStack{q}); |
| 390 | |||
| 389 | Query q2(q); | 391 | Query q2(q); |
| 390 | state.queries.pop_front(); | 392 | state.queries.pop_front(); |
| 391 | gather_labels(q2.ssy_stack, state.ssy_labels, block); | 393 | gather_labels(q2.ssy_stack, state.ssy_labels, block); |
| @@ -394,6 +396,7 @@ bool TryQuery(CFGRebuildState& state) { | |||
| 394 | q2.address = block.end + 1; | 396 | q2.address = block.end + 1; |
| 395 | state.queries.push_back(q2); | 397 | state.queries.push_back(q2); |
| 396 | } | 398 | } |
| 399 | |||
| 397 | Query conditional_query{q2}; | 400 | Query conditional_query{q2}; |
| 398 | if (block.branch.is_sync) { | 401 | if (block.branch.is_sync) { |
| 399 | if (block.branch.address == unassigned_branch) { | 402 | if (block.branch.address == unassigned_branch) { |
| @@ -408,7 +411,7 @@ bool TryQuery(CFGRebuildState& state) { | |||
| 408 | conditional_query.pbk_stack.pop(); | 411 | conditional_query.pbk_stack.pop(); |
| 409 | } | 412 | } |
| 410 | conditional_query.address = block.branch.address; | 413 | conditional_query.address = block.branch.address; |
| 411 | state.queries.push_back(conditional_query); | 414 | state.queries.push_back(std::move(conditional_query)); |
| 412 | return true; | 415 | return true; |
| 413 | } | 416 | } |
| 414 | } // Anonymous namespace | 417 | } // Anonymous namespace |
| @@ -416,6 +419,7 @@ bool TryQuery(CFGRebuildState& state) { | |||
| 416 | std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | 419 | std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, |
| 417 | std::size_t program_size, u32 start_address) { | 420 | std::size_t program_size, u32 start_address) { |
| 418 | CFGRebuildState state{program_code, program_size, start_address}; | 421 | CFGRebuildState state{program_code, program_size, start_address}; |
| 422 | |||
| 419 | // Inspect Code and generate blocks | 423 | // Inspect Code and generate blocks |
| 420 | state.labels.clear(); | 424 | state.labels.clear(); |
| 421 | state.labels.emplace(start_address); | 425 | state.labels.emplace(start_address); |
| @@ -425,10 +429,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 425 | return {}; | 429 | return {}; |
| 426 | } | 430 | } |
| 427 | } | 431 | } |
| 432 | |||
| 428 | // Decompile Stacks | 433 | // Decompile Stacks |
| 429 | Query start_query{}; | 434 | state.queries.push_back(Query{state.start, {}, {}}); |
| 430 | start_query.address = state.start; | ||
| 431 | state.queries.push_back(start_query); | ||
| 432 | bool decompiled = true; | 435 | bool decompiled = true; |
| 433 | while (!state.queries.empty()) { | 436 | while (!state.queries.empty()) { |
| 434 | if (!TryQuery(state)) { | 437 | if (!TryQuery(state)) { |
| @@ -436,14 +439,15 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 436 | break; | 439 | break; |
| 437 | } | 440 | } |
| 438 | } | 441 | } |
| 442 | |||
| 439 | // Sort and organize results | 443 | // Sort and organize results |
| 440 | std::sort(state.block_info.begin(), state.block_info.end(), | 444 | std::sort(state.block_info.begin(), state.block_info.end(), |
| 441 | [](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; }); | 445 | [](const BlockInfo& a, const BlockInfo& b) { return a.start < b.start; }); |
| 442 | ShaderCharacteristics result_out{}; | 446 | ShaderCharacteristics result_out{}; |
| 443 | result_out.decompilable = decompiled; | 447 | result_out.decompilable = decompiled; |
| 444 | result_out.start = start_address; | 448 | result_out.start = start_address; |
| 445 | result_out.end = start_address; | 449 | result_out.end = start_address; |
| 446 | for (auto& block : state.block_info) { | 450 | for (const auto& block : state.block_info) { |
| 447 | ShaderBlock new_block{}; | 451 | ShaderBlock new_block{}; |
| 448 | new_block.start = block.start; | 452 | new_block.start = block.start; |
| 449 | new_block.end = block.end; | 453 | new_block.end = block.end; |
| @@ -458,8 +462,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 458 | } | 462 | } |
| 459 | if (result_out.decompilable) { | 463 | if (result_out.decompilable) { |
| 460 | result_out.labels = std::move(state.labels); | 464 | result_out.labels = std::move(state.labels); |
| 461 | return {result_out}; | 465 | return {std::move(result_out)}; |
| 462 | } | 466 | } |
| 467 | |||
| 463 | // If it's not decompilable, merge the unlabelled blocks together | 468 | // If it's not decompilable, merge the unlabelled blocks together |
| 464 | auto back = result_out.blocks.begin(); | 469 | auto back = result_out.blocks.begin(); |
| 465 | auto next = std::next(back); | 470 | auto next = std::next(back); |
| @@ -472,6 +477,6 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, | |||
| 472 | back = next; | 477 | back = next; |
| 473 | ++next; | 478 | ++next; |
| 474 | } | 479 | } |
| 475 | return {result_out}; | 480 | return {std::move(result_out)}; |
| 476 | } | 481 | } |
| 477 | } // namespace VideoCommon::Shader | 482 | } // namespace VideoCommon::Shader |