summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/shader/control_flow.cpp25
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) {
416std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, 419std::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