From ca9901867e91cd0be0cc75094ee8ea2fb2767c47 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 25 Aug 2019 15:32:00 -0400 Subject: vk_shader_compiler: Implement the decompiler in SPIR-V --- .../renderer_vulkan/vk_shader_decompiler.cpp | 298 +++++++++++++++++++-- 1 file changed, 276 insertions(+), 22 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 77fc58f25..505e49570 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -88,6 +88,9 @@ bool IsPrecise(Operation operand) { } // namespace +class ASTDecompiler; +class ExprDecompiler; + class SPIRVDecompiler : public Sirit::Module { public: explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderStage stage) @@ -97,27 +100,7 @@ public: AddExtension("SPV_KHR_variable_pointers"); } - void Decompile() { - AllocateBindings(); - AllocateLabels(); - - DeclareVertex(); - DeclareGeometry(); - DeclareFragment(); - DeclareRegisters(); - DeclarePredicates(); - DeclareLocalMemory(); - DeclareInternalFlags(); - DeclareInputAttributes(); - DeclareOutputAttributes(); - DeclareConstantBuffers(); - DeclareGlobalBuffers(); - DeclareSamplers(); - - execute_function = - Emit(OpFunction(t_void, spv::FunctionControlMask::Inline, TypeFunction(t_void))); - Emit(OpLabel()); - + void DecompileBranchMode() { const u32 first_address = ir.GetBasicBlocks().begin()->first; const Id loop_label = OpLabel("loop"); const Id merge_label = OpLabel("merge"); @@ -174,6 +157,43 @@ public: Emit(continue_label); Emit(OpBranch(loop_label)); Emit(merge_label); + } + + void DecompileAST(); + + void Decompile() { + const bool is_fully_decompiled = ir.IsDecompiled(); + AllocateBindings(); + if (!is_fully_decompiled) { + AllocateLabels(); + } + + DeclareVertex(); + DeclareGeometry(); + DeclareFragment(); + DeclareRegisters(); + DeclarePredicates(); + if (is_fully_decompiled) { + DeclareFlowVariables(); + } + DeclareLocalMemory(); + DeclareInternalFlags(); + DeclareInputAttributes(); + DeclareOutputAttributes(); + DeclareConstantBuffers(); + DeclareGlobalBuffers(); + DeclareSamplers(); + + execute_function = + Emit(OpFunction(t_void, spv::FunctionControlMask::Inline, TypeFunction(t_void))); + Emit(OpLabel()); + + if (is_fully_decompiled) { + DecompileAST(); + } else { + DecompileBranchMode(); + } + Emit(OpReturn()); Emit(OpFunctionEnd()); } @@ -206,6 +226,9 @@ public: } private: + friend class ASTDecompiler; + friend class ExprDecompiler; + static constexpr auto INTERNAL_FLAGS_COUNT = static_cast(InternalFlag::Amount); void AllocateBindings() { @@ -294,6 +317,14 @@ private: } } + void DeclareFlowVariables() { + for (u32 i = 0; i < ir.GetASTNumVariables(); i++) { + const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); + Name(id, fmt::format("flow_var_{}", static_cast(i))); + flow_variables.emplace(i, AddGlobalVariable(id)); + } + } + void DeclareLocalMemory() { if (const u64 local_memory_size = header.GetLocalMemorySize(); local_memory_size > 0) { const auto element_count = static_cast(Common::AlignUp(local_memory_size, 4) / 4); @@ -1019,7 +1050,7 @@ private: return {}; } - Id Exit(Operation operation) { + Id PreExit() { switch (stage) { case ShaderStage::Vertex: { // TODO(Rodrigo): We should use VK_EXT_depth_range_unrestricted instead, but it doesn't @@ -1067,6 +1098,11 @@ private: } } + return {}; + } + + Id Exit(Operation operation) { + PreExit(); BranchingOp([&]() { Emit(OpReturn()); }); return {}; } @@ -1545,6 +1581,7 @@ private: Id per_vertex{}; std::map registers; std::map predicates; + std::map flow_variables; Id local_memory{}; std::array internal_flags{}; std::map input_attributes; @@ -1580,6 +1617,223 @@ private: std::map labels; }; +class ExprDecompiler { +public: + ExprDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} + + void operator()(VideoCommon::Shader::ExprAnd& expr) { + const Id type_def = decomp.GetTypeDefinition(Type::Bool); + const Id op1 = Visit(expr.operand1); + const Id op2 = Visit(expr.operand2); + current_id = decomp.Emit(decomp.OpLogicalAnd(type_def, op1, op2)); + } + + void operator()(VideoCommon::Shader::ExprOr& expr) { + const Id type_def = decomp.GetTypeDefinition(Type::Bool); + const Id op1 = Visit(expr.operand1); + const Id op2 = Visit(expr.operand2); + current_id = decomp.Emit(decomp.OpLogicalOr(type_def, op1, op2)); + } + + void operator()(VideoCommon::Shader::ExprNot& expr) { + const Id type_def = decomp.GetTypeDefinition(Type::Bool); + const Id op1 = Visit(expr.operand1); + current_id = decomp.Emit(decomp.OpLogicalNot(type_def, op1)); + } + + void operator()(VideoCommon::Shader::ExprPredicate& expr) { + auto pred = static_cast(expr.predicate); + current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred))); + } + + void operator()(VideoCommon::Shader::ExprCondCode& expr) { + Node cc = decomp.ir.GetConditionCode(expr.cc); + Id target; + + if (const auto pred = std::get_if(&*cc)) { + const auto index = pred->GetIndex(); + switch (index) { + case Tegra::Shader::Pred::NeverExecute: + target = decomp.v_false; + case Tegra::Shader::Pred::UnusedIndex: + target = decomp.v_true; + default: + target = decomp.predicates.at(index); + } + } else if (const auto flag = std::get_if(&*cc)) { + target = decomp.internal_flags.at(static_cast(flag->GetFlag())); + } + current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, target)); + } + + void operator()(VideoCommon::Shader::ExprVar& expr) { + current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); + } + + void operator()(VideoCommon::Shader::ExprBoolean& expr) { + current_id = expr.value ? decomp.v_true : decomp.v_false; + } + + Id GetResult() { + return current_id; + } + + Id Visit(VideoCommon::Shader::Expr& node) { + std::visit(*this, *node); + return current_id; + } + +private: + Id current_id; + SPIRVDecompiler& decomp; +}; + +class ASTDecompiler { +public: + ASTDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} + + void operator()(VideoCommon::Shader::ASTProgram& ast) { + ASTNode current = ast.nodes.GetFirst(); + while (current) { + Visit(current); + current = current->GetNext(); + } + } + + void operator()(VideoCommon::Shader::ASTIfThen& ast) { + ExprDecompiler expr_parser{decomp}; + const Id condition = expr_parser.Visit(ast.condition); + const Id then_label = decomp.OpLabel(); + const Id endif_label = decomp.OpLabel(); + decomp.Emit(decomp.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone)); + decomp.Emit(decomp.OpBranchConditional(condition, then_label, endif_label)); + decomp.Emit(then_label); + ASTNode current = ast.nodes.GetFirst(); + while (current) { + Visit(current); + current = current->GetNext(); + } + decomp.Emit(endif_label); + } + + void operator()(VideoCommon::Shader::ASTIfElse& ast) { + UNREACHABLE(); + } + + void operator()(VideoCommon::Shader::ASTBlockEncoded& ast) { + UNREACHABLE(); + } + + void operator()(VideoCommon::Shader::ASTBlockDecoded& ast) { + decomp.VisitBasicBlock(ast.nodes); + } + + void operator()(VideoCommon::Shader::ASTVarSet& ast) { + ExprDecompiler expr_parser{decomp}; + const Id condition = expr_parser.Visit(ast.condition); + decomp.Emit(decomp.OpStore(decomp.flow_variables.at(ast.index), condition)); + } + + void operator()(VideoCommon::Shader::ASTLabel& ast) { + // Do nothing + } + + void operator()(VideoCommon::Shader::ASTGoto& ast) { + UNREACHABLE(); + } + + void operator()(VideoCommon::Shader::ASTDoWhile& ast) { + const Id loop_label = decomp.OpLabel(); + const Id endloop_label = decomp.OpLabel(); + const Id loop_start_block = decomp.OpLabel(); + const Id loop_end_block = decomp.OpLabel(); + current_loop_exit = endloop_label; + decomp.Emit(loop_label); + decomp.Emit(decomp.OpLoopMerge(endloop_label, loop_end_block, spv::LoopControlMask::MaskNone)); + decomp.Emit(decomp.OpBranch(loop_start_block)); + decomp.Emit(loop_start_block); + ASTNode current = ast.nodes.GetFirst(); + while (current) { + Visit(current); + current = current->GetNext(); + } + decomp.Emit(decomp.OpBranch(loop_end_block)); + decomp.Emit(loop_end_block); + ExprDecompiler expr_parser{decomp}; + const Id condition = expr_parser.Visit(ast.condition); + decomp.Emit(decomp.OpBranchConditional(condition, loop_label, endloop_label)); + decomp.Emit(endloop_label); + } + + void operator()(VideoCommon::Shader::ASTReturn& ast) { + bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition); + if (!is_true) { + ExprDecompiler expr_parser{decomp}; + const Id condition = expr_parser.Visit(ast.condition); + const Id then_label = decomp.OpLabel(); + const Id endif_label = decomp.OpLabel(); + decomp.Emit(decomp.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone)); + decomp.Emit(decomp.OpBranchConditional(condition, then_label, endif_label)); + decomp.Emit(then_label); + if (ast.kills) { + decomp.Emit(decomp.OpKill()); + } else { + decomp.PreExit(); + decomp.Emit(decomp.OpReturn()); + } + decomp.Emit(endif_label); + } else { + decomp.Emit(decomp.OpLabel()); + if (ast.kills) { + decomp.Emit(decomp.OpKill()); + } else { + decomp.PreExit(); + decomp.Emit(decomp.OpReturn()); + } + decomp.Emit(decomp.OpLabel()); + } + } + + void operator()(VideoCommon::Shader::ASTBreak& ast) { + bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition); + if (!is_true) { + ExprDecompiler expr_parser{decomp}; + const Id condition = expr_parser.Visit(ast.condition); + const Id then_label = decomp.OpLabel(); + const Id endif_label = decomp.OpLabel(); + decomp.Emit(decomp.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone)); + decomp.Emit(decomp.OpBranchConditional(condition, then_label, endif_label)); + decomp.Emit(then_label); + decomp.Emit(decomp.OpBranch(current_loop_exit)); + decomp.Emit(endif_label); + } else { + decomp.Emit(decomp.OpLabel()); + decomp.Emit(decomp.OpBranch(current_loop_exit)); + decomp.Emit(decomp.OpLabel()); + } + } + + void Visit(VideoCommon::Shader::ASTNode& node) { + std::visit(*this, *node->GetInnerData()); + } + +private: + SPIRVDecompiler& decomp; + Id current_loop_exit; +}; + +void SPIRVDecompiler::DecompileAST() { + u32 num_flow_variables = ir.GetASTNumVariables(); + for (u32 i = 0; i < num_flow_variables; i++) { + const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); + Name(id, fmt::format("flow_var_{}", i)); + flow_variables.emplace(i, AddGlobalVariable(id)); + } + ASTDecompiler decompiler{*this}; + VideoCommon::Shader::ASTNode program = ir.GetASTProgram(); + decompiler.Visit(program); +} + DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir, Maxwell::ShaderStage stage) { auto decompiler = std::make_unique(device, ir, stage); -- cgit v1.2.3 From 2e9a810423ef36178ac3947f8feeb7b9a5b29bce Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 20 Sep 2019 21:12:06 -0400 Subject: Shader_IR: allow else derivation to be optional. --- src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 505e49570..72fbc69c4 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -1667,7 +1667,8 @@ public: } void operator()(VideoCommon::Shader::ExprVar& expr) { - current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); + current_id = + decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); } void operator()(VideoCommon::Shader::ExprBoolean& expr) { @@ -1749,7 +1750,8 @@ public: const Id loop_end_block = decomp.OpLabel(); current_loop_exit = endloop_label; decomp.Emit(loop_label); - decomp.Emit(decomp.OpLoopMerge(endloop_label, loop_end_block, spv::LoopControlMask::MaskNone)); + decomp.Emit( + decomp.OpLoopMerge(endloop_label, loop_end_block, spv::LoopControlMask::MaskNone)); decomp.Emit(decomp.OpBranch(loop_start_block)); decomp.Emit(loop_start_block); ASTNode current = ast.nodes.GetFirst(); -- cgit v1.2.3 From 466cd52ad47b125182baf1544c44e52a741fa58f Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 21 Sep 2019 00:45:13 -0400 Subject: vk_shader_compiler: Correct SPIR-V AST Decompiling --- src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 72fbc69c4..4527e9261 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -1714,6 +1714,7 @@ public: Visit(current); current = current->GetNext(); } + decomp.Emit(decomp.OpBranch(endif_label)); decomp.Emit(endif_label); } @@ -1749,6 +1750,7 @@ public: const Id loop_start_block = decomp.OpLabel(); const Id loop_end_block = decomp.OpLabel(); current_loop_exit = endloop_label; + decomp.Emit(decomp.OpBranch(loop_label)); decomp.Emit(loop_label); decomp.Emit( decomp.OpLoopMerge(endloop_label, loop_end_block, spv::LoopControlMask::MaskNone)); @@ -1759,8 +1761,6 @@ public: Visit(current); current = current->GetNext(); } - decomp.Emit(decomp.OpBranch(loop_end_block)); - decomp.Emit(loop_end_block); ExprDecompiler expr_parser{decomp}; const Id condition = expr_parser.Visit(ast.condition); decomp.Emit(decomp.OpBranchConditional(condition, loop_label, endloop_label)); @@ -1785,7 +1785,9 @@ public: } decomp.Emit(endif_label); } else { - decomp.Emit(decomp.OpLabel()); + const Id next_block = decomp.OpLabel(); + decomp.Emit(decomp.OpBranch(next_block)); + decomp.Emit(next_block); if (ast.kills) { decomp.Emit(decomp.OpKill()); } else { @@ -1809,7 +1811,9 @@ public: decomp.Emit(decomp.OpBranch(current_loop_exit)); decomp.Emit(endif_label); } else { - decomp.Emit(decomp.OpLabel()); + const Id next_block = decomp.OpLabel(); + decomp.Emit(decomp.OpBranch(next_block)); + decomp.Emit(next_block); decomp.Emit(decomp.OpBranch(current_loop_exit)); decomp.Emit(decomp.OpLabel()); } @@ -1834,6 +1838,9 @@ void SPIRVDecompiler::DecompileAST() { ASTDecompiler decompiler{*this}; VideoCommon::Shader::ASTNode program = ir.GetASTProgram(); decompiler.Visit(program); + const Id next_block = OpLabel(); + Emit(OpBranch(next_block)); + Emit(next_block); } DecompilerResult Decompile(const VKDevice& device, const VideoCommon::Shader::ShaderIR& ir, -- cgit v1.2.3 From 100a4bd98856cf16c1fe16b6c1f1ab2863916c37 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 22 Sep 2019 20:15:09 -0400 Subject: vk_shader_compiler: Don't enclose branches with if(true) to avoid crashing AMD --- .../renderer_vulkan/vk_shader_decompiler.cpp | 49 +++++++++++++++------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 4527e9261..11effe4a1 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -646,7 +646,9 @@ private: Emit(OpBranchConditional(condition, true_label, skip_label)); Emit(true_label); + ++conditional_nest_count; VisitBasicBlock(conditional->GetCode()); + --conditional_nest_count; Emit(OpBranch(skip_label)); Emit(skip_label); @@ -1011,7 +1013,10 @@ private: UNIMPLEMENTED_IF(!target); Emit(OpStore(jmp_to, Constant(t_uint, target->GetValue()))); - BranchingOp([&]() { Emit(OpBranch(continue_label)); }); + Emit(OpBranch(continue_label)); + if (conditional_nest_count == 0) { + Emit(OpLabel()); + } return {}; } @@ -1019,7 +1024,10 @@ private: const Id op_a = VisitOperand(operation, 0); Emit(OpStore(jmp_to, op_a)); - BranchingOp([&]() { Emit(OpBranch(continue_label)); }); + Emit(OpBranch(continue_label)); + if (conditional_nest_count == 0) { + Emit(OpLabel()); + } return {}; } @@ -1046,7 +1054,10 @@ private: Emit(OpStore(flow_stack_top, previous)); Emit(OpStore(jmp_to, target)); - BranchingOp([&]() { Emit(OpBranch(continue_label)); }); + Emit(OpBranch(continue_label)); + if (conditional_nest_count == 0) { + Emit(OpLabel()); + } return {}; } @@ -1103,12 +1114,28 @@ private: Id Exit(Operation operation) { PreExit(); - BranchingOp([&]() { Emit(OpReturn()); }); + if (conditional_nest_count > 0) { + Emit(OpReturn()); + } else { + const Id dummy = OpLabel(); + Emit(OpBranch(dummy)); + Emit(dummy); + Emit(OpReturn()); + Emit(OpLabel()); + } return {}; } Id Discard(Operation operation) { - BranchingOp([&]() { Emit(OpKill()); }); + if (conditional_nest_count > 0) { + Emit(OpKill()); + } else { + const Id dummy = OpLabel(); + Emit(OpBranch(dummy)); + Emit(dummy); + Emit(OpKill()); + Emit(OpLabel()); + } return {}; } @@ -1303,17 +1330,6 @@ private: return {}; } - void BranchingOp(std::function call) { - const Id true_label = OpLabel(); - const Id skip_label = OpLabel(); - Emit(OpSelectionMerge(skip_label, spv::SelectionControlMask::Flatten)); - Emit(OpBranchConditional(v_true, true_label, skip_label, 1, 0)); - Emit(true_label); - call(); - - Emit(skip_label); - } - std::tuple CreateFlowStack() { // TODO(Rodrigo): Figure out the actual depth of the flow stack, for now it seems unlikely // that shaders will use 20 nested SSYs and PBKs. @@ -1519,6 +1535,7 @@ private: const ShaderIR& ir; const ShaderStage stage; const Tegra::Shader::Header header; + u64 conditional_nest_count{}; const Id t_void = Name(TypeVoid(), "void"); -- cgit v1.2.3 From 000ad558dd21a0f1f0be57ddbb59540956314896 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Tue, 24 Sep 2019 10:57:45 -0400 Subject: vk_shader_decompiler: Clean code and be const correct. --- src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 11effe4a1..4bc7da198 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -1659,12 +1659,12 @@ public: } void operator()(VideoCommon::Shader::ExprPredicate& expr) { - auto pred = static_cast(expr.predicate); + const auto pred = static_cast(expr.predicate); current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred))); } void operator()(VideoCommon::Shader::ExprCondCode& expr) { - Node cc = decomp.ir.GetConditionCode(expr.cc); + const Node cc = decomp.ir.GetConditionCode(expr.cc); Id target; if (const auto pred = std::get_if(&*cc)) { @@ -1785,8 +1785,7 @@ public: } void operator()(VideoCommon::Shader::ASTReturn& ast) { - bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition); - if (!is_true) { + if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) { ExprDecompiler expr_parser{decomp}; const Id condition = expr_parser.Visit(ast.condition); const Id then_label = decomp.OpLabel(); @@ -1816,8 +1815,7 @@ public: } void operator()(VideoCommon::Shader::ASTBreak& ast) { - bool is_true = VideoCommon::Shader::ExprIsTrue(ast.condition); - if (!is_true) { + if (!VideoCommon::Shader::ExprIsTrue(ast.condition)) { ExprDecompiler expr_parser{decomp}; const Id condition = expr_parser.Visit(ast.condition); const Id then_label = decomp.OpLabel(); @@ -1846,7 +1844,7 @@ private: }; void SPIRVDecompiler::DecompileAST() { - u32 num_flow_variables = ir.GetASTNumVariables(); + const u32 num_flow_variables = ir.GetASTNumVariables(); for (u32 i = 0; i < num_flow_variables; i++) { const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); Name(id, fmt::format("flow_var_{}", i)); -- cgit v1.2.3 From 507a9c6a402d6ee277e0a8f0cda57d04526c05dd Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 14:34:08 -0400 Subject: vk_shader_decompiler: Correct Branches inside conditionals. --- src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 4bc7da198..2b55a3727 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -650,7 +650,11 @@ private: VisitBasicBlock(conditional->GetCode()); --conditional_nest_count; - Emit(OpBranch(skip_label)); + if (inside_branch == 0) { + Emit(OpBranch(skip_label)); + } else { + inside_branch--; + } Emit(skip_label); return {}; @@ -1014,6 +1018,7 @@ private: Emit(OpStore(jmp_to, Constant(t_uint, target->GetValue()))); Emit(OpBranch(continue_label)); + inside_branch = conditional_nest_count; if (conditional_nest_count == 0) { Emit(OpLabel()); } @@ -1025,6 +1030,7 @@ private: Emit(OpStore(jmp_to, op_a)); Emit(OpBranch(continue_label)); + inside_branch = conditional_nest_count; if (conditional_nest_count == 0) { Emit(OpLabel()); } @@ -1055,6 +1061,7 @@ private: Emit(OpStore(flow_stack_top, previous)); Emit(OpStore(jmp_to, target)); Emit(OpBranch(continue_label)); + inside_branch = conditional_nest_count; if (conditional_nest_count == 0) { Emit(OpLabel()); } @@ -1114,6 +1121,7 @@ private: Id Exit(Operation operation) { PreExit(); + inside_branch = conditional_nest_count; if (conditional_nest_count > 0) { Emit(OpReturn()); } else { @@ -1127,6 +1135,7 @@ private: } Id Discard(Operation operation) { + inside_branch = conditional_nest_count; if (conditional_nest_count > 0) { Emit(OpKill()); } else { @@ -1536,6 +1545,7 @@ private: const ShaderStage stage; const Tegra::Shader::Header header; u64 conditional_nest_count{}; + u64 inside_branch{}; const Id t_void = Name(TypeVoid(), "void"); -- cgit v1.2.3 From 3c09d9abe6d268ada063fd67c08d09fc0fcad613 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 28 Sep 2019 15:16:19 -0400 Subject: Shader_Ir: Address Feedback and clang format. --- .../renderer_vulkan/vk_shader_decompiler.cpp | 43 +++++++++------------- 1 file changed, 18 insertions(+), 25 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 2b55a3727..8bcd04221 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp @@ -1646,34 +1646,34 @@ private: class ExprDecompiler { public: - ExprDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} + explicit ExprDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} - void operator()(VideoCommon::Shader::ExprAnd& expr) { + Id operator()(VideoCommon::Shader::ExprAnd& expr) { const Id type_def = decomp.GetTypeDefinition(Type::Bool); const Id op1 = Visit(expr.operand1); const Id op2 = Visit(expr.operand2); - current_id = decomp.Emit(decomp.OpLogicalAnd(type_def, op1, op2)); + return decomp.Emit(decomp.OpLogicalAnd(type_def, op1, op2)); } - void operator()(VideoCommon::Shader::ExprOr& expr) { + Id operator()(VideoCommon::Shader::ExprOr& expr) { const Id type_def = decomp.GetTypeDefinition(Type::Bool); const Id op1 = Visit(expr.operand1); const Id op2 = Visit(expr.operand2); - current_id = decomp.Emit(decomp.OpLogicalOr(type_def, op1, op2)); + return decomp.Emit(decomp.OpLogicalOr(type_def, op1, op2)); } - void operator()(VideoCommon::Shader::ExprNot& expr) { + Id operator()(VideoCommon::Shader::ExprNot& expr) { const Id type_def = decomp.GetTypeDefinition(Type::Bool); const Id op1 = Visit(expr.operand1); - current_id = decomp.Emit(decomp.OpLogicalNot(type_def, op1)); + return decomp.Emit(decomp.OpLogicalNot(type_def, op1)); } - void operator()(VideoCommon::Shader::ExprPredicate& expr) { + Id operator()(VideoCommon::Shader::ExprPredicate& expr) { const auto pred = static_cast(expr.predicate); - current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred))); + return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.predicates.at(pred))); } - void operator()(VideoCommon::Shader::ExprCondCode& expr) { + Id operator()(VideoCommon::Shader::ExprCondCode& expr) { const Node cc = decomp.ir.GetConditionCode(expr.cc); Id target; @@ -1690,35 +1690,28 @@ public: } else if (const auto flag = std::get_if(&*cc)) { target = decomp.internal_flags.at(static_cast(flag->GetFlag())); } - current_id = decomp.Emit(decomp.OpLoad(decomp.t_bool, target)); + return decomp.Emit(decomp.OpLoad(decomp.t_bool, target)); } - void operator()(VideoCommon::Shader::ExprVar& expr) { - current_id = - decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); + Id operator()(VideoCommon::Shader::ExprVar& expr) { + return decomp.Emit(decomp.OpLoad(decomp.t_bool, decomp.flow_variables.at(expr.var_index))); } - void operator()(VideoCommon::Shader::ExprBoolean& expr) { - current_id = expr.value ? decomp.v_true : decomp.v_false; - } - - Id GetResult() { - return current_id; + Id operator()(VideoCommon::Shader::ExprBoolean& expr) { + return expr.value ? decomp.v_true : decomp.v_false; } Id Visit(VideoCommon::Shader::Expr& node) { - std::visit(*this, *node); - return current_id; + return std::visit(*this, *node); } private: - Id current_id; SPIRVDecompiler& decomp; }; class ASTDecompiler { public: - ASTDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} + explicit ASTDecompiler(SPIRVDecompiler& decomp) : decomp{decomp} {} void operator()(VideoCommon::Shader::ASTProgram& ast) { ASTNode current = ast.nodes.GetFirst(); @@ -1850,7 +1843,7 @@ public: private: SPIRVDecompiler& decomp; - Id current_loop_exit; + Id current_loop_exit{}; }; void SPIRVDecompiler::DecompileAST() { -- cgit v1.2.3