diff options
| author | 2021-05-14 00:40:54 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:31 -0400 | |
| commit | d54d7de40e7295827b0e4e4026441b53d3fc9569 (patch) | |
| tree | 29b5074f851292dace7aeb5da7716675544b3735 /src/shader_recompiler/backend/spirv | |
| parent | glasm: Implement Storage atomics (diff) | |
| download | yuzu-d54d7de40e7295827b0e4e4026441b53d3fc9569.tar.gz yuzu-d54d7de40e7295827b0e4e4026441b53d3fc9569.tar.xz yuzu-d54d7de40e7295827b0e4e4026441b53d3fc9569.zip | |
glasm: Rework control flow introducing a syntax list
This commit regresses VertexA shaders, their transformation pass has to
be adapted to the new control flow.
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
5 files changed, 74 insertions, 49 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index 9759591bd..a98e08392 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -463,7 +463,6 @@ EmitContext::EmitContext(const Profile& profile_, IR::Program& program, Bindings | |||
| 463 | DefineImages(program.info, image_binding); | 463 | DefineImages(program.info, image_binding); |
| 464 | DefineAttributeMemAccess(program.info); | 464 | DefineAttributeMemAccess(program.info); |
| 465 | DefineGlobalMemoryFunctions(program.info); | 465 | DefineGlobalMemoryFunctions(program.info); |
| 466 | DefineLabels(program); | ||
| 467 | } | 466 | } |
| 468 | 467 | ||
| 469 | EmitContext::~EmitContext() = default; | 468 | EmitContext::~EmitContext() = default; |
| @@ -487,8 +486,6 @@ Id EmitContext::Def(const IR::Value& value) { | |||
| 487 | return Const(value.F32()); | 486 | return Const(value.F32()); |
| 488 | case IR::Type::F64: | 487 | case IR::Type::F64: |
| 489 | return Constant(F64[1], value.F64()); | 488 | return Constant(F64[1], value.F64()); |
| 490 | case IR::Type::Label: | ||
| 491 | return value.Label()->Definition<Id>(); | ||
| 492 | default: | 489 | default: |
| 493 | throw NotImplementedException("Immediate type {}", value.Type()); | 490 | throw NotImplementedException("Immediate type {}", value.Type()); |
| 494 | } | 491 | } |
| @@ -1139,12 +1136,6 @@ void EmitContext::DefineImages(const Info& info, u32& binding) { | |||
| 1139 | } | 1136 | } |
| 1140 | } | 1137 | } |
| 1141 | 1138 | ||
| 1142 | void EmitContext::DefineLabels(IR::Program& program) { | ||
| 1143 | for (IR::Block* const block : program.blocks) { | ||
| 1144 | block->SetDefinition(OpLabel()); | ||
| 1145 | } | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | void EmitContext::DefineInputs(const Info& info) { | 1139 | void EmitContext::DefineInputs(const Info& info) { |
| 1149 | if (info.uses_workgroup_id) { | 1140 | if (info.uses_workgroup_id) { |
| 1150 | workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId); | 1141 | workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 8b000f1ec..d2b79f6c1 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -296,7 +296,6 @@ private: | |||
| 296 | void DefineImages(const Info& info, u32& binding); | 296 | void DefineImages(const Info& info, u32& binding); |
| 297 | void DefineAttributeMemAccess(const Info& info); | 297 | void DefineAttributeMemAccess(const Info& info); |
| 298 | void DefineGlobalMemoryFunctions(const Info& info); | 298 | void DefineGlobalMemoryFunctions(const Info& info); |
| 299 | void DefineLabels(IR::Program& program); | ||
| 300 | 299 | ||
| 301 | void DefineInputs(const Info& info); | 300 | void DefineInputs(const Info& info); |
| 302 | void DefineOutputs(const IR::Program& program); | 301 | void DefineOutputs(const IR::Program& program); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 2dad87e87..c22edfec2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -41,8 +41,6 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) { | |||
| 41 | return arg; | 41 | return arg; |
| 42 | } else if constexpr (std::is_same_v<ArgType, u32>) { | 42 | } else if constexpr (std::is_same_v<ArgType, u32>) { |
| 43 | return arg.U32(); | 43 | return arg.U32(); |
| 44 | } else if constexpr (std::is_same_v<ArgType, IR::Block*>) { | ||
| 45 | return arg.Label(); | ||
| 46 | } else if constexpr (std::is_same_v<ArgType, IR::Attribute>) { | 44 | } else if constexpr (std::is_same_v<ArgType, IR::Attribute>) { |
| 47 | return arg.Attribute(); | 45 | return arg.Attribute(); |
| 48 | } else if constexpr (std::is_same_v<ArgType, IR::Patch>) { | 46 | } else if constexpr (std::is_same_v<ArgType, IR::Patch>) { |
| @@ -109,15 +107,74 @@ Id TypeId(const EmitContext& ctx, IR::Type type) { | |||
| 109 | } | 107 | } |
| 110 | } | 108 | } |
| 111 | 109 | ||
| 110 | void Traverse(EmitContext& ctx, IR::Program& program) { | ||
| 111 | IR::Block* current_block{}; | ||
| 112 | for (const IR::AbstractSyntaxNode& node : program.syntax_list) { | ||
| 113 | switch (node.type) { | ||
| 114 | case IR::AbstractSyntaxNode::Type::Block: | ||
| 115 | const Id label{node.block->Definition<Id>()}; | ||
| 116 | if (current_block) { | ||
| 117 | ctx.OpBranch(label); | ||
| 118 | } | ||
| 119 | current_block = node.block; | ||
| 120 | ctx.AddLabel(label); | ||
| 121 | for (IR::Inst& inst : node.block->Instructions()) { | ||
| 122 | EmitInst(ctx, &inst); | ||
| 123 | } | ||
| 124 | break; | ||
| 125 | case IR::AbstractSyntaxNode::Type::If: { | ||
| 126 | const Id if_label{node.if_node.body->Definition<Id>()}; | ||
| 127 | const Id endif_label{node.if_node.merge->Definition<Id>()}; | ||
| 128 | ctx.OpSelectionMerge(endif_label, spv::SelectionControlMask::MaskNone); | ||
| 129 | ctx.OpBranchConditional(ctx.Def(node.if_node.cond), if_label, endif_label); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | case IR::AbstractSyntaxNode::Type::Loop: { | ||
| 133 | const Id body_label{node.loop.body->Definition<Id>()}; | ||
| 134 | const Id continue_label{node.loop.continue_block->Definition<Id>()}; | ||
| 135 | const Id endloop_label{node.loop.merge->Definition<Id>()}; | ||
| 136 | |||
| 137 | ctx.OpLoopMerge(endloop_label, continue_label, spv::LoopControlMask::MaskNone); | ||
| 138 | ctx.OpBranch(node.loop.body->Definition<Id>()); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | case IR::AbstractSyntaxNode::Type::Break: { | ||
| 142 | const Id break_label{node.break_node.merge->Definition<Id>()}; | ||
| 143 | const Id skip_label{node.break_node.skip->Definition<Id>()}; | ||
| 144 | ctx.OpBranchConditional(ctx.Def(node.break_node.cond), break_label, skip_label); | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | case IR::AbstractSyntaxNode::Type::EndIf: | ||
| 148 | if (current_block) { | ||
| 149 | ctx.OpBranch(node.end_if.merge->Definition<Id>()); | ||
| 150 | } | ||
| 151 | break; | ||
| 152 | case IR::AbstractSyntaxNode::Type::Repeat: { | ||
| 153 | const Id loop_header_label{node.repeat.loop_header->Definition<Id>()}; | ||
| 154 | const Id merge_label{node.repeat.merge->Definition<Id>()}; | ||
| 155 | ctx.OpBranchConditional(ctx.Def(node.repeat.cond), loop_header_label, merge_label); | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | case IR::AbstractSyntaxNode::Type::Return: | ||
| 159 | ctx.OpReturn(); | ||
| 160 | break; | ||
| 161 | case IR::AbstractSyntaxNode::Type::Unreachable: | ||
| 162 | ctx.OpUnreachable(); | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | if (node.type != IR::AbstractSyntaxNode::Type::Block) { | ||
| 166 | current_block = nullptr; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 112 | Id DefineMain(EmitContext& ctx, IR::Program& program) { | 171 | Id DefineMain(EmitContext& ctx, IR::Program& program) { |
| 113 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; | 172 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; |
| 114 | const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; | 173 | const Id main{ctx.OpFunction(ctx.void_id, spv::FunctionControlMask::MaskNone, void_function)}; |
| 115 | for (IR::Block* const block : program.blocks) { | 174 | for (IR::Block* const block : program.blocks) { |
| 116 | ctx.AddLabel(block->Definition<Id>()); | 175 | block->SetDefinition(ctx.OpLabel()); |
| 117 | for (IR::Inst& inst : block->Instructions()) { | ||
| 118 | EmitInst(ctx, &inst); | ||
| 119 | } | ||
| 120 | } | 176 | } |
| 177 | Traverse(ctx, program); | ||
| 121 | ctx.OpFunctionEnd(); | 178 | ctx.OpFunctionEnd(); |
| 122 | return main; | 179 | return main; |
| 123 | } | 180 | } |
| @@ -411,6 +468,8 @@ Id EmitIdentity(EmitContext& ctx, const IR::Value& value) { | |||
| 411 | return id; | 468 | return id; |
| 412 | } | 469 | } |
| 413 | 470 | ||
| 471 | void EmitBranchConditionRef(EmitContext&) {} | ||
| 472 | |||
| 414 | void EmitGetZeroFromOp(EmitContext&) { | 473 | void EmitGetZeroFromOp(EmitContext&) { |
| 415 | throw LogicError("Unreachable instruction"); | 474 | throw LogicError("Unreachable instruction"); |
| 416 | } | 475 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp index 6154c46be..d33486f28 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp | |||
| @@ -7,40 +7,21 @@ | |||
| 7 | 7 | ||
| 8 | namespace Shader::Backend::SPIRV { | 8 | namespace Shader::Backend::SPIRV { |
| 9 | 9 | ||
| 10 | void EmitBranch(EmitContext& ctx, Id label) { | ||
| 11 | ctx.OpBranch(label); | ||
| 12 | } | ||
| 13 | |||
| 14 | void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label) { | ||
| 15 | ctx.OpBranchConditional(condition, true_label, false_label); | ||
| 16 | } | ||
| 17 | |||
| 18 | void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label) { | ||
| 19 | ctx.OpLoopMerge(merge_label, continue_label, spv::LoopControlMask::MaskNone); | ||
| 20 | } | ||
| 21 | |||
| 22 | void EmitSelectionMerge(EmitContext& ctx, Id merge_label) { | ||
| 23 | ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone); | ||
| 24 | } | ||
| 25 | |||
| 26 | void EmitReturn(EmitContext& ctx) { | ||
| 27 | ctx.OpReturn(); | ||
| 28 | } | ||
| 29 | |||
| 30 | void EmitJoin(EmitContext&) { | 10 | void EmitJoin(EmitContext&) { |
| 31 | throw NotImplementedException("Join shouldn't be emitted"); | 11 | throw NotImplementedException("Join shouldn't be emitted"); |
| 32 | } | 12 | } |
| 33 | 13 | ||
| 34 | void EmitUnreachable(EmitContext& ctx) { | 14 | void EmitDemoteToHelperInvocation(EmitContext& ctx) { |
| 35 | ctx.OpUnreachable(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label) { | ||
| 39 | if (ctx.profile.support_demote_to_helper_invocation) { | 15 | if (ctx.profile.support_demote_to_helper_invocation) { |
| 40 | ctx.OpDemoteToHelperInvocationEXT(); | 16 | ctx.OpDemoteToHelperInvocationEXT(); |
| 41 | ctx.OpBranch(continue_label); | ||
| 42 | } else { | 17 | } else { |
| 18 | const Id kill_label{ctx.OpLabel()}; | ||
| 19 | const Id impossible_label{ctx.OpLabel()}; | ||
| 20 | ctx.OpSelectionMerge(impossible_label, spv::SelectionControlMask::MaskNone); | ||
| 21 | ctx.OpBranchConditional(ctx.true_value, kill_label, impossible_label); | ||
| 22 | ctx.AddLabel(kill_label); | ||
| 43 | ctx.OpKill(); | 23 | ctx.OpKill(); |
| 24 | ctx.AddLabel(impossible_label); | ||
| 44 | } | 25 | } |
| 45 | } | 26 | } |
| 46 | 27 | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index a1ca3f43d..2f4f6e59e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -23,14 +23,9 @@ class EmitContext; | |||
| 23 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); | 23 | Id EmitPhi(EmitContext& ctx, IR::Inst* inst); |
| 24 | void EmitVoid(EmitContext& ctx); | 24 | void EmitVoid(EmitContext& ctx); |
| 25 | Id EmitIdentity(EmitContext& ctx, const IR::Value& value); | 25 | Id EmitIdentity(EmitContext& ctx, const IR::Value& value); |
| 26 | void EmitBranch(EmitContext& ctx, Id label); | 26 | void EmitBranchConditionRef(EmitContext&); |
| 27 | void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label); | ||
| 28 | void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label); | ||
| 29 | void EmitSelectionMerge(EmitContext& ctx, Id merge_label); | ||
| 30 | void EmitReturn(EmitContext& ctx); | ||
| 31 | void EmitJoin(EmitContext& ctx); | 27 | void EmitJoin(EmitContext& ctx); |
| 32 | void EmitUnreachable(EmitContext& ctx); | 28 | void EmitDemoteToHelperInvocation(EmitContext& ctx); |
| 33 | void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label); | ||
| 34 | void EmitBarrier(EmitContext& ctx); | 29 | void EmitBarrier(EmitContext& ctx); |
| 35 | void EmitWorkgroupMemoryBarrier(EmitContext& ctx); | 30 | void EmitWorkgroupMemoryBarrier(EmitContext& ctx); |
| 36 | void EmitDeviceMemoryBarrier(EmitContext& ctx); | 31 | void EmitDeviceMemoryBarrier(EmitContext& ctx); |