diff options
| author | 2019-06-25 13:03:51 -0400 | |
|---|---|---|
| committer | 2019-07-09 08:14:39 -0400 | |
| commit | d5533b440c764093c04a4859b30fc78ddb0e0bbe (patch) | |
| tree | f9fea3823e0f55787549f2f1d9fc332118449bfc /src/video_core/shader/decode.cpp | |
| parent | shader_ir: Decompile Flow Stack (diff) | |
| download | yuzu-d5533b440c764093c04a4859b30fc78ddb0e0bbe.tar.gz yuzu-d5533b440c764093c04a4859b30fc78ddb0e0bbe.tar.xz yuzu-d5533b440c764093c04a4859b30fc78ddb0e0bbe.zip | |
shader_ir: Unify blocks in decompiled shaders.
Diffstat (limited to 'src/video_core/shader/decode.cpp')
| -rw-r--r-- | src/video_core/shader/decode.cpp | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 1a74b70cb..f9b1960da 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp | |||
| @@ -38,32 +38,47 @@ constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) { | |||
| 38 | void ShaderIR::Decode() { | 38 | 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 | ShaderCharacteristics shader_info{}; | 42 | ShaderCharacteristics shader_info{}; |
| 42 | bool can_proceed = ScanFlow(program_code, program_code.size(), main_offset, shader_info); | 43 | bool can_proceed = ScanFlow(program_code, program_code.size(), main_offset, shader_info); |
| 43 | if (can_proceed) { | 44 | if (can_proceed) { |
| 44 | coverage_begin = shader_info.start; | 45 | coverage_begin = shader_info.start; |
| 45 | coverage_end = shader_info.end; | 46 | coverage_end = shader_info.end; |
| 46 | if (shader_info.decompilable) { | 47 | if (shader_info.decompilable) { |
| 48 | disable_flow_stack = true; | ||
| 49 | auto insert_block = ([this](NodeBlock& nodes, u32 label) { | ||
| 50 | if (label == exit_branch) { | ||
| 51 | return; | ||
| 52 | } | ||
| 53 | basic_blocks.insert({label, nodes}); | ||
| 54 | }); | ||
| 47 | std::list<ShaderBlock>& blocks = shader_info.blocks; | 55 | std::list<ShaderBlock>& blocks = shader_info.blocks; |
| 56 | NodeBlock current_block; | ||
| 57 | u32 current_label = exit_branch; | ||
| 48 | for (auto& block : blocks) { | 58 | for (auto& block : blocks) { |
| 49 | NodeBlock nodes; | 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 | } | ||
| 50 | if (!block.ignore_branch) { | 64 | if (!block.ignore_branch) { |
| 51 | nodes = DecodeRange(block.start, block.end); | 65 | DecodeRangeInner(current_block, block.start, block.end); |
| 52 | InsertControlFlow(nodes, block); | 66 | InsertControlFlow(current_block, block); |
| 53 | } else { | 67 | } else { |
| 54 | nodes = DecodeRange(block.start, block.end + 1); | 68 | DecodeRangeInner(current_block, block.start, block.end + 1); |
| 55 | } | 69 | } |
| 56 | basic_blocks.insert({block.start, nodes}); | ||
| 57 | } | 70 | } |
| 71 | insert_block(current_block, current_label); | ||
| 58 | return; | 72 | return; |
| 59 | } | 73 | } |
| 74 | LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method"); | ||
| 60 | // we can't decompile it, fallback to standard method | 75 | // we can't decompile it, fallback to standard method |
| 61 | for (const auto& block : shader_info.blocks) { | 76 | for (const auto& block : shader_info.blocks) { |
| 62 | basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)}); | 77 | basic_blocks.insert({block.start, DecodeRange(block.start, block.end + 1)}); |
| 63 | } | 78 | } |
| 64 | return; | 79 | return; |
| 65 | } | 80 | } |
| 66 | LOG_WARNING(HW_GPU, "Flow Analysis failed, falling back to brute force compiling"); | 81 | LOG_WARNING(HW_GPU, "Flow Analysis Failed! Falling back to brute force compiling"); |
| 67 | 82 | ||
| 68 | // Now we need to deal with an undecompilable shader. We need to brute force | 83 | // Now we need to deal with an undecompilable shader. We need to brute force |
| 69 | // a shader that captures every position. | 84 | // a shader that captures every position. |
| @@ -78,10 +93,14 @@ void ShaderIR::Decode() { | |||
| 78 | 93 | ||
| 79 | NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) { | 94 | NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) { |
| 80 | NodeBlock basic_block; | 95 | NodeBlock basic_block; |
| 96 | DecodeRangeInner(basic_block, begin, end); | ||
| 97 | return basic_block; | ||
| 98 | } | ||
| 99 | |||
| 100 | void ShaderIR::DecodeRangeInner(NodeBlock& bb, u32 begin, u32 end) { | ||
| 81 | for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) { | 101 | for (u32 pc = begin; pc < (begin > end ? MAX_PROGRAM_LENGTH : end);) { |
| 82 | pc = DecodeInstr(basic_block, pc); | 102 | pc = DecodeInstr(bb, pc); |
| 83 | } | 103 | } |
| 84 | return basic_block; | ||
| 85 | } | 104 | } |
| 86 | 105 | ||
| 87 | void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) { | 106 | void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) { |