summaryrefslogtreecommitdiff
path: root/src/video_core/shader/decode.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-09-23 22:55:25 -0400
committerGravatar FernandoS272019-10-25 09:01:30 -0400
commit8909f52166bf9c27d52b5a722efbd46d1a11e876 (patch)
tree2e21bbc3c3f5422325d8003d72cdb4bb120a26e5 /src/video_core/shader/decode.cpp
parentShader_Cache: setup connection of ConstBufferLocker (diff)
downloadyuzu-8909f52166bf9c27d52b5a722efbd46d1a11e876.tar.gz
yuzu-8909f52166bf9c27d52b5a722efbd46d1a11e876.tar.xz
yuzu-8909f52166bf9c27d52b5a722efbd46d1a11e876.zip
Shader_IR: Implement Fast BRX and allow multi-branches in the CFG.
Diffstat (limited to 'src/video_core/shader/decode.cpp')
-rw-r--r--src/video_core/shader/decode.cpp34
1 files changed, 24 insertions, 10 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 3f87b87ca..053241128 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -198,24 +198,38 @@ void ShaderIR::InsertControlFlow(NodeBlock& bb, const ShaderBlock& block) {
198 } 198 }
199 return result; 199 return result;
200 }; 200 };
201 if (block.branch.address < 0) { 201 if (std::holds_alternative<SingleBranch>(*block.branch)) {
202 if (block.branch.kills) { 202 auto branch = std::get_if<SingleBranch>(block.branch.get());
203 Node n = Operation(OperationCode::Discard); 203 if (branch->address < 0) {
204 n = apply_conditions(block.branch.cond, n); 204 if (branch->kill) {
205 Node n = Operation(OperationCode::Discard);
206 n = apply_conditions(branch->condition, n);
207 bb.push_back(n);
208 global_code.push_back(n);
209 return;
210 }
211 Node n = Operation(OperationCode::Exit);
212 n = apply_conditions(branch->condition, n);
205 bb.push_back(n); 213 bb.push_back(n);
206 global_code.push_back(n); 214 global_code.push_back(n);
207 return; 215 return;
208 } 216 }
209 Node n = Operation(OperationCode::Exit); 217 Node n = Operation(OperationCode::Branch, Immediate(branch->address));
210 n = apply_conditions(block.branch.cond, n); 218 n = apply_conditions(branch->condition, n);
211 bb.push_back(n); 219 bb.push_back(n);
212 global_code.push_back(n); 220 global_code.push_back(n);
213 return; 221 return;
214 } 222 }
215 Node n = Operation(OperationCode::Branch, Immediate(block.branch.address)); 223 auto multi_branch = std::get_if<MultiBranch>(block.branch.get());
216 n = apply_conditions(block.branch.cond, n); 224 Node op_a = GetRegister(multi_branch->gpr);
217 bb.push_back(n); 225 for (auto& branch_case : multi_branch->branches) {
218 global_code.push_back(n); 226 Node n = Operation(OperationCode::Branch, Immediate(branch_case.address));
227 Node op_b = Immediate(branch_case.cmp_value);
228 Node condition = GetPredicateComparisonInteger(Tegra::Shader::PredCondition::Equal, false, op_a, op_b);
229 auto result = Conditional(condition, {n});
230 bb.push_back(result);
231 global_code.push_back(result);
232 }
219} 233}
220 234
221u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) { 235u32 ShaderIR::DecodeInstr(NodeBlock& bb, u32 pc) {