summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-06-25 11:10:45 -0400
committerGravatar FernandoS272019-07-09 08:14:38 -0400
commit926b80102f1c00675a9f3956258a066bfe0c3642 (patch)
tree616288030c9e72f8cf6a3ee12ae89faa07b9da79 /src/video_core/shader/decode.cpp
parentshader_ir: propagate shader size to the IR (diff)
downloadyuzu-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.cpp46
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
87void 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
76u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) { 122u32 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)) {