summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp41
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h7
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp9
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp24
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp9
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h1
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp71
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp33
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h9
9 files changed, 116 insertions, 88 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 056d8cbf8..51ca83d18 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -117,8 +117,6 @@ auto Arg(EmitContext& ctx, const IR::Value& arg) {
117 return Identity<const IR::Value&>{arg}; 117 return Identity<const IR::Value&>{arg};
118 } else if constexpr (std::is_same_v<ArgType, u32>) { 118 } else if constexpr (std::is_same_v<ArgType, u32>) {
119 return Identity{arg.U32()}; 119 return Identity{arg.U32()};
120 } else if constexpr (std::is_same_v<ArgType, IR::Block*>) {
121 return Identity{arg.Label()};
122 } else if constexpr (std::is_same_v<ArgType, IR::Attribute>) { 120 } else if constexpr (std::is_same_v<ArgType, IR::Attribute>) {
123 return Identity{arg.Attribute()}; 121 return Identity{arg.Attribute()};
124 } else if constexpr (std::is_same_v<ArgType, IR::Patch>) { 122 } else if constexpr (std::is_same_v<ArgType, IR::Patch>) {
@@ -177,6 +175,39 @@ void EmitInst(EmitContext& ctx, IR::Inst* inst) {
177 throw LogicError("Invalid opcode {}", inst->GetOpcode()); 175 throw LogicError("Invalid opcode {}", inst->GetOpcode());
178} 176}
179 177
178void EmitCode(EmitContext& ctx, const IR::Program& program) {
179 const auto eval{
180 [&](const IR::U1& cond) { return ScalarS32{ctx.reg_alloc.Consume(IR::Value{cond})}; }};
181 for (const IR::AbstractSyntaxNode& node : program.syntax_list) {
182 switch (node.type) {
183 case IR::AbstractSyntaxNode::Type::Block:
184 for (IR::Inst& inst : node.block->Instructions()) {
185 EmitInst(ctx, &inst);
186 }
187 break;
188 case IR::AbstractSyntaxNode::Type::If:
189 ctx.Add("MOV.S.CC RC,{};IF NE.x;", eval(node.if_node.cond));
190 break;
191 case IR::AbstractSyntaxNode::Type::EndIf:
192 ctx.Add("ENDIF;");
193 break;
194 case IR::AbstractSyntaxNode::Type::Loop:
195 ctx.Add("REP;");
196 break;
197 case IR::AbstractSyntaxNode::Type::Repeat:
198 ctx.Add("MOV.S.CC RC,{};BRK NE.x;ENDREP;", eval(node.repeat.cond));
199 break;
200 case IR::AbstractSyntaxNode::Type::Break:
201 ctx.Add("MOV.S.CC RC,{};BRK NE.x;", eval(node.repeat.cond));
202 break;
203 case IR::AbstractSyntaxNode::Type::Return:
204 case IR::AbstractSyntaxNode::Type::Unreachable:
205 ctx.Add("RET;");
206 break;
207 }
208 }
209}
210
180void SetupOptions(std::string& header, Info info) { 211void SetupOptions(std::string& header, Info info) {
181 if (info.uses_int64_bit_atomics) { 212 if (info.uses_int64_bit_atomics) {
182 header += "OPTION NV_shader_atomic_int64;"; 213 header += "OPTION NV_shader_atomic_int64;";
@@ -201,11 +232,7 @@ void SetupOptions(std::string& header, Info info) {
201 232
202std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) { 233std::string EmitGLASM(const Profile&, IR::Program& program, Bindings&) {
203 EmitContext ctx{program}; 234 EmitContext ctx{program};
204 for (IR::Block* const block : program.blocks) { 235 EmitCode(ctx, program);
205 for (IR::Inst& inst : block->Instructions()) {
206 EmitInst(ctx, &inst);
207 }
208 }
209 std::string header = "!!NVcp5.0\n" 236 std::string header = "!!NVcp5.0\n"
210 "OPTION NV_internal;"; 237 "OPTION NV_internal;";
211 SetupOptions(header, program.info); 238 SetupOptions(header, program.info);
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
index 8202354fe..0f7f16e6e 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
@@ -22,13 +22,8 @@ class EmitContext;
22void EmitPhi(EmitContext& ctx, IR::Inst& inst); 22void EmitPhi(EmitContext& ctx, IR::Inst& inst);
23void EmitVoid(EmitContext& ctx); 23void EmitVoid(EmitContext& ctx);
24void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 24void EmitIdentity(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
25void EmitBranch(EmitContext& ctx); 25void EmitBranchConditionRef(EmitContext&);
26void EmitBranchConditional(EmitContext& ctx);
27void EmitLoopMerge(EmitContext& ctx);
28void EmitSelectionMerge(EmitContext& ctx);
29void EmitReturn(EmitContext& ctx);
30void EmitJoin(EmitContext& ctx); 26void EmitJoin(EmitContext& ctx);
31void EmitUnreachable(EmitContext& ctx);
32void EmitDemoteToHelperInvocation(EmitContext& ctx); 27void EmitDemoteToHelperInvocation(EmitContext& ctx);
33void EmitBarrier(EmitContext& ctx); 28void EmitBarrier(EmitContext& ctx);
34void EmitWorkgroupMemoryBarrier(EmitContext& ctx); 29void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
index 15fd23356..adcc0404b 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_integer.cpp
@@ -91,7 +91,8 @@ void EmitBitFieldInsert(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scalar
91 if (count.type != Type::Register && offset.type != Type::Register) { 91 if (count.type != Type::Register && offset.type != Type::Register) {
92 ctx.Add("BFI.S {},{{{},{},0,0}},{},{};", ret, count, offset, insert, base); 92 ctx.Add("BFI.S {},{{{},{},0,0}},{},{};", ret, count, offset, insert, base);
93 } else { 93 } else {
94 ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" 94 ctx.Add("MOV.S RC.x,{};"
95 "MOV.S RC.y,{};"
95 "BFI.S {},RC,{},{};", 96 "BFI.S {},RC,{},{};",
96 count, offset, ret, insert, base); 97 count, offset, ret, insert, base);
97 } 98 }
@@ -103,7 +104,8 @@ void EmitBitFieldSExtract(EmitContext& ctx, IR::Inst& inst, ScalarS32 base, Scal
103 if (count.type != Type::Register && offset.type != Type::Register) { 104 if (count.type != Type::Register && offset.type != Type::Register) {
104 ctx.Add("BFE.S {},{{{},{},0,0}},{};", ret, count, offset, base); 105 ctx.Add("BFE.S {},{{{},{},0,0}},{};", ret, count, offset, base);
105 } else { 106 } else {
106 ctx.Add("MOV.S RC.x,{};MOV.U RC.y,{};" 107 ctx.Add("MOV.S RC.x,{};"
108 "MOV.S RC.y,{};"
107 "BFE.S {},RC,{};", 109 "BFE.S {},RC,{};",
108 count, offset, ret, base); 110 count, offset, ret, base);
109 } 111 }
@@ -115,7 +117,8 @@ void EmitBitFieldUExtract(EmitContext& ctx, IR::Inst& inst, ScalarU32 base, Scal
115 if (count.type != Type::Register && offset.type != Type::Register) { 117 if (count.type != Type::Register && offset.type != Type::Register) {
116 ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base); 118 ctx.Add("BFE.U {},{{{},{},0,0}},{};", ret, count, offset, base);
117 } else { 119 } else {
118 ctx.Add("MOV.U RC.x,{};MOV.U RC.y,{};" 120 ctx.Add("MOV.U RC.x,{};"
121 "MOV.U RC.y,{};"
119 "BFE.U {},RC,{};", 122 "BFE.U {},RC,{};",
120 count, offset, ret, base); 123 count, offset, ret, base);
121 } 124 }
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index b40d09f8c..f37ad5587 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -23,34 +23,12 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst) {
23 23
24void EmitVoid(EmitContext&) {} 24void EmitVoid(EmitContext&) {}
25 25
26void EmitBranch(EmitContext& ctx) { 26void EmitBranchConditionRef(EmitContext&) {}
27 NotImplemented();
28}
29
30void EmitBranchConditional(EmitContext& ctx) {
31 NotImplemented();
32}
33
34void EmitLoopMerge(EmitContext& ctx) {
35 NotImplemented();
36}
37
38void EmitSelectionMerge(EmitContext& ctx) {
39 NotImplemented();
40}
41
42void EmitReturn(EmitContext& ctx) {
43 ctx.Add("RET;");
44}
45 27
46void EmitJoin(EmitContext& ctx) { 28void EmitJoin(EmitContext& ctx) {
47 NotImplemented(); 29 NotImplemented();
48} 30}
49 31
50void EmitUnreachable(EmitContext& ctx) {
51 NotImplemented();
52}
53
54void EmitDemoteToHelperInvocation(EmitContext& ctx) { 32void EmitDemoteToHelperInvocation(EmitContext& ctx) {
55 NotImplemented(); 33 NotImplemented();
56} 34}
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
469EmitContext::~EmitContext() = default; 468EmitContext::~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
1142void EmitContext::DefineLabels(IR::Program& program) {
1143 for (IR::Block* const block : program.blocks) {
1144 block->SetDefinition(OpLabel());
1145 }
1146}
1147
1148void EmitContext::DefineInputs(const Info& info) { 1139void 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
110void 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
112Id DefineMain(EmitContext& ctx, IR::Program& program) { 171Id 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
471void EmitBranchConditionRef(EmitContext&) {}
472
414void EmitGetZeroFromOp(EmitContext&) { 473void 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
8namespace Shader::Backend::SPIRV { 8namespace Shader::Backend::SPIRV {
9 9
10void EmitBranch(EmitContext& ctx, Id label) {
11 ctx.OpBranch(label);
12}
13
14void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label) {
15 ctx.OpBranchConditional(condition, true_label, false_label);
16}
17
18void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label) {
19 ctx.OpLoopMerge(merge_label, continue_label, spv::LoopControlMask::MaskNone);
20}
21
22void EmitSelectionMerge(EmitContext& ctx, Id merge_label) {
23 ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone);
24}
25
26void EmitReturn(EmitContext& ctx) {
27 ctx.OpReturn();
28}
29
30void EmitJoin(EmitContext&) { 10void EmitJoin(EmitContext&) {
31 throw NotImplementedException("Join shouldn't be emitted"); 11 throw NotImplementedException("Join shouldn't be emitted");
32} 12}
33 13
34void EmitUnreachable(EmitContext& ctx) { 14void EmitDemoteToHelperInvocation(EmitContext& ctx) {
35 ctx.OpUnreachable();
36}
37
38void 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;
23Id EmitPhi(EmitContext& ctx, IR::Inst* inst); 23Id EmitPhi(EmitContext& ctx, IR::Inst* inst);
24void EmitVoid(EmitContext& ctx); 24void EmitVoid(EmitContext& ctx);
25Id EmitIdentity(EmitContext& ctx, const IR::Value& value); 25Id EmitIdentity(EmitContext& ctx, const IR::Value& value);
26void EmitBranch(EmitContext& ctx, Id label); 26void EmitBranchConditionRef(EmitContext&);
27void EmitBranchConditional(EmitContext& ctx, Id condition, Id true_label, Id false_label);
28void EmitLoopMerge(EmitContext& ctx, Id merge_label, Id continue_label);
29void EmitSelectionMerge(EmitContext& ctx, Id merge_label);
30void EmitReturn(EmitContext& ctx);
31void EmitJoin(EmitContext& ctx); 27void EmitJoin(EmitContext& ctx);
32void EmitUnreachable(EmitContext& ctx); 28void EmitDemoteToHelperInvocation(EmitContext& ctx);
33void EmitDemoteToHelperInvocation(EmitContext& ctx, Id continue_label);
34void EmitBarrier(EmitContext& ctx); 29void EmitBarrier(EmitContext& ctx);
35void EmitWorkgroupMemoryBarrier(EmitContext& ctx); 30void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
36void EmitDeviceMemoryBarrier(EmitContext& ctx); 31void EmitDeviceMemoryBarrier(EmitContext& ctx);