From c3a8ea76f180fbaf2d58d0454e7adc2bb1f30009 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 20 Apr 2018 09:16:55 -0500 Subject: ShaderGen: Implemented predicated instruction execution. Each predicated instruction will be wrapped in an `if (predicate) { instruction_body; }` in the GLSL, where `predicate` is one of the predicate boolean variables previously set by fsetp. --- .../renderer_opengl/gl_shader_decompiler.cpp | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/video_core/renderer_opengl/gl_shader_decompiler.cpp') diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 2e0203a68..7aaee9464 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -293,6 +293,25 @@ private: declr_predicates.insert(std::move(variable)); } + /* + * Returns the condition to use in the 'if' for a predicated instruction. + * @param instr Instruction to generate the if condition for. + * @returns string containing the predicate condition. + */ + std::string GetPredicateCondition(Instruction instr) const { + using Tegra::Shader::Pred; + ASSERT(instr.pred.pred_index != static_cast(Pred::UnusedIndex)); + + std::string variable = + 'p' + std::to_string(static_cast(instr.pred.pred_index.Value())); + + if (instr.negate_pred) { + return "!(" + variable + ')'; + } + + return variable; + } + /* * Returns whether the instruction at the specified offset is a 'sched' instruction. * Sched instructions always appear before a sequence of 3 instructions. @@ -320,6 +339,16 @@ private: shader.AddLine("// " + std::to_string(offset) + ": " + OpCode::GetInfo(instr.opcode).name); + using Tegra::Shader::Pred; + ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute, + "NeverExecute predicate not implemented"); + + if (instr.pred.pred_index != static_cast(Pred::UnusedIndex)) { + shader.AddLine("if (" + GetPredicateCondition(instr) + ')'); + shader.AddLine('{'); + ++shader.scope; + } + switch (OpCode::GetInfo(instr.opcode).type) { case OpCode::Type::Arithmetic: { std::string dest = GetRegister(instr.gpr0); @@ -559,6 +588,12 @@ private: } } + // Close the predicate condition scope. + if (instr.pred != Pred::UnusedIndex) { + --shader.scope; + shader.AddLine('}'); + } + return offset + 1; } -- cgit v1.2.3