diff options
| author | 2019-06-25 11:10:45 -0400 | |
|---|---|---|
| committer | 2019-07-09 08:14:38 -0400 | |
| commit | 926b80102f1c00675a9f3956258a066bfe0c3642 (patch) | |
| tree | 616288030c9e72f8cf6a3ee12ae89faa07b9da79 /src/video_core/shader/decode.cpp | |
| parent | shader_ir: propagate shader size to the IR (diff) | |
| download | yuzu-926b80102f1c00675a9f3956258a066bfe0c3642.tar.gz yuzu-926b80102f1c00675a9f3956258a066bfe0c3642.tar.xz yuzu-926b80102f1c00675a9f3956258a066bfe0c3642.zip | |
shader_ir: Decompile Flow Stack
Diffstat (limited to 'src/video_core/shader/decode.cpp')
| -rw-r--r-- | src/video_core/shader/decode.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 09f55bd21..1a74b70cb 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp | |||
| @@ -44,6 +44,17 @@ void ShaderIR::Decode() { | |||
| 44 | coverage_begin = shader_info.start; | 44 | coverage_begin = shader_info.start; |
| 45 | coverage_end = shader_info.end; | 45 | coverage_end = shader_info.end; |
| 46 | if (shader_info.decompilable) { | 46 | if (shader_info.decompilable) { |
| 47 | std::list<ShaderBlock>& blocks = shader_info.blocks; | ||
| 48 | for (auto& block : blocks) { | ||
| 49 | NodeBlock nodes; | ||
| 50 | if (!block.ignore_branch) { | ||
| 51 | nodes = DecodeRange(block.start, block.end); | ||
| 52 | InsertControlFlow(nodes, block); | ||
| 53 | } else { | ||
| 54 | nodes = DecodeRange(block.start, block.end + 1); | ||
| 55 | } | ||
| 56 | basic_blocks.insert({block.start, nodes}); | ||
| 57 | } | ||
| 47 | return; | 58 | return; |
| 48 | } | 59 | } |
| 49 | // we can't decompile it, fallback to standard method | 60 | // we can't decompile it, fallback to standard method |
| @@ -73,6 +84,41 @@ NodeBlock ShaderIR::DecodeRange(u32 begin, u32 end) { | |||
| 73 | return basic_block; | 84 | return basic_block; |
| 74 | } | 85 | } |
| 75 | 86 | ||
| 87 | void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) { | ||
| 88 | auto apply_conditions = ([&](const Condition& cond, Node n) -> Node { | ||
| 89 | Node result = n; | ||
| 90 | if (cond.cc != ConditionCode::T) { | ||
| 91 | result = Conditional(GetConditionCode(cond.cc), {result}); | ||
| 92 | } | ||
| 93 | if (cond.predicate != Pred::UnusedIndex) { | ||
| 94 | u32 pred = static_cast<u32>(cond.predicate); | ||
| 95 | bool is_neg = pred > 7; | ||
| 96 | if (is_neg) | ||
| 97 | pred -= 8; | ||
| 98 | result = Conditional(GetPredicate(pred, is_neg), {result}); | ||
| 99 | } | ||
| 100 | return result; | ||
| 101 | }); | ||
| 102 | if (block.branch.address < 0) { | ||
| 103 | if (block.branch.kills) { | ||
| 104 | Node n = Operation(OperationCode::Discard); | ||
| 105 | n = apply_conditions(block.branch.cond, n); | ||
| 106 | bb.push_back(n); | ||
| 107 | global_code.push_back(n); | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | Node n = Operation(OperationCode::Exit); | ||
| 111 | n = apply_conditions(block.branch.cond, n); | ||
| 112 | bb.push_back(n); | ||
| 113 | global_code.push_back(n); | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | Node n = Operation(OperationCode::Branch, Immediate(block.branch.address)); | ||
| 117 | n = apply_conditions(block.branch.cond, n); | ||
| 118 | bb.push_back(n); | ||
| 119 | global_code.push_back(n); | ||
| 120 | } | ||
| 121 | |||
| 76 | u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) { | 122 | u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) { |
| 77 | // Ignore sched instructions when generating code. | 123 | // Ignore sched instructions when generating code. |
| 78 | if (IsSchedInstruction(pc, main_offset)) { | 124 | if (IsSchedInstruction(pc, main_offset)) { |