summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glasm
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-26 18:32:59 -0300
committerGravatar ameerj2021-07-22 21:51:33 -0400
commitadb591a757ccb289634920d51cf519b515ca32b6 (patch)
tree987c5cd0a346e69633791ad5ec355b6104ab036e /src/shader_recompiler/backend/glasm
parentglasm: Implement Y direction (diff)
downloadyuzu-adb591a757ccb289634920d51cf519b515ca32b6.tar.gz
yuzu-adb591a757ccb289634920d51cf519b515ca32b6.tar.xz
yuzu-adb591a757ccb289634920d51cf519b515ca32b6.zip
glasm: Use storage buffers instead of global memory when possible
Diffstat (limited to 'src/shader_recompiler/backend/glasm')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_context.cpp13
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.h5
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp351
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp380
4 files changed, 380 insertions, 369 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp
index b5b0e2204..e18526816 100644
--- a/src/shader_recompiler/backend/glasm/emit_context.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_context.cpp
@@ -7,6 +7,7 @@
7#include "shader_recompiler/backend/bindings.h" 7#include "shader_recompiler/backend/bindings.h"
8#include "shader_recompiler/backend/glasm/emit_context.h" 8#include "shader_recompiler/backend/glasm/emit_context.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/profile.h"
10 11
11namespace Shader::Backend::GLASM { 12namespace Shader::Backend::GLASM {
12namespace { 13namespace {
@@ -40,13 +41,21 @@ EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile
40 Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index); 41 Add("CBUFFER c{}[]={{program.buffer[{}]}};", desc.index, cbuf_index);
41 ++cbuf_index; 42 ++cbuf_index;
42 } 43 }
44 u32 ssbo_index{};
43 for (const auto& desc : info.storage_buffers_descriptors) { 45 for (const auto& desc : info.storage_buffers_descriptors) {
44 if (desc.count != 1) { 46 if (desc.count != 1) {
45 throw NotImplementedException("Storage buffer descriptor array"); 47 throw NotImplementedException("Storage buffer descriptor array");
46 } 48 }
49 if (runtime_info.glasm_use_storage_buffers) {
50 Add("STORAGE ssbo{}[]={{program.storage[{}]}};", ssbo_index, bindings.storage_buffer);
51 ++bindings.storage_buffer;
52 ++ssbo_index;
53 }
47 } 54 }
48 if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) { 55 if (!runtime_info.glasm_use_storage_buffers) {
49 Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); 56 if (const size_t num = info.storage_buffers_descriptors.size(); num > 0) {
57 Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1);
58 }
50 } 59 }
51 stage = program.stage; 60 stage = program.stage;
52 switch (program.stage) { 61 switch (program.stage) {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.h b/src/shader_recompiler/backend/glasm/emit_glasm.h
index 3d02d873e..3df32a4a6 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.h
@@ -15,9 +15,10 @@ namespace Shader::Backend::GLASM {
15[[nodiscard]] std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, 15[[nodiscard]] std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info,
16 IR::Program& program, Bindings& bindings); 16 IR::Program& program, Bindings& bindings);
17 17
18[[nodiscard]] inline std::string EmitGLASM(const Profile& profile, IR::Program& program) { 18[[nodiscard]] inline std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info,
19 IR::Program& program) {
19 Bindings binding; 20 Bindings binding;
20 return EmitGLASM(profile, {}, program, binding); 21 return EmitGLASM(profile, runtime_info, program, binding);
21} 22}
22 23
23} // namespace Shader::Backend::GLASM 24} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp
deleted file mode 100644
index e72b252a3..000000000
--- a/src/shader_recompiler/backend/glasm/emit_glasm_atomic.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "shader_recompiler/backend/glasm/emit_context.h"
6#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
7#include "shader_recompiler/frontend/ir/value.h"
8
9namespace Shader::Backend::GLASM {
10namespace {
11void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset,
12 std::string_view then_expr, std::string_view else_expr = {}) {
13 // Operate on bindless SSBO, call the expression with bounds checking
14 // address = c[binding].xy
15 // length = c[binding].z
16 const u32 sb_binding{binding.U32()};
17 ctx.Add("PK64.U DC,c[{}];" // pointer = address
18 "CVT.U64.U32 DC.z,{};" // offset = uint64_t(offset)
19 "ADD.U64 DC.x,DC.x,DC.z;" // pointer += offset
20 "SLT.U.CC RC.x,{},c[{}].z;", // cc = offset < length
21 sb_binding, offset, offset, sb_binding);
22 if (else_expr.empty()) {
23 ctx.Add("IF NE.x;{}ENDIF;", then_expr);
24 } else {
25 ctx.Add("IF NE.x;{}ELSE;{}ENDIF;", then_expr, else_expr);
26 }
27}
28
29template <typename ValueType>
30void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset,
31 ValueType value, std::string_view operation, std::string_view size) {
32 const Register ret{ctx.reg_alloc.Define(inst)};
33 StorageOp(ctx, binding, offset,
34 fmt::format("ATOM.{}.{} {},{},DC.x;", operation, size, ret, value));
35}
36} // namespace
37
38void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
39 ScalarU32 value) {
40 ctx.Add("ATOMS.ADD.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
41}
42
43void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
44 ScalarS32 value) {
45 ctx.Add("ATOMS.MIN.S32 {},{},shared_mem[{}];", inst, value, pointer_offset);
46}
47
48void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
49 ScalarU32 value) {
50 ctx.Add("ATOMS.MIN.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
51}
52
53void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
54 ScalarS32 value) {
55 ctx.Add("ATOMS.MAX.S32 {},{},shared_mem[{}];", inst, value, pointer_offset);
56}
57
58void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
59 ScalarU32 value) {
60 ctx.Add("ATOMS.MAX.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
61}
62
63void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
64 ScalarU32 value) {
65 ctx.Add("ATOMS.IWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
66}
67
68void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
69 ScalarU32 value) {
70 ctx.Add("ATOMS.DWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
71}
72
73void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
74 ScalarU32 value) {
75 ctx.Add("ATOMS.AND.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
76}
77
78void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
79 ScalarU32 value) {
80 ctx.Add("ATOMS.OR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
81}
82
83void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
84 ScalarU32 value) {
85 ctx.Add("ATOMS.XOR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
86}
87
88void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
89 ScalarU32 value) {
90 ctx.Add("ATOMS.EXCH.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
91}
92
93void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
94 Register value) {
95 ctx.LongAdd("ATOMS.EXCH.U64 {}.x,{},shared_mem[{}];", inst, value, pointer_offset);
96}
97
98void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
99 ScalarU32 offset, ScalarU32 value) {
100 Atom(ctx, inst, binding, offset, value, "ADD", "U32");
101}
102
103void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
104 ScalarU32 offset, ScalarS32 value) {
105 Atom(ctx, inst, binding, offset, value, "MIN", "S32");
106}
107
108void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
109 ScalarU32 offset, ScalarU32 value) {
110 Atom(ctx, inst, binding, offset, value, "MIN", "U32");
111}
112
113void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
114 ScalarU32 offset, ScalarS32 value) {
115 Atom(ctx, inst, binding, offset, value, "MAX", "S32");
116}
117
118void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
119 ScalarU32 offset, ScalarU32 value) {
120 Atom(ctx, inst, binding, offset, value, "MAX", "U32");
121}
122
123void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
124 ScalarU32 offset, ScalarU32 value) {
125 Atom(ctx, inst, binding, offset, value, "IWRAP", "U32");
126}
127
128void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
129 ScalarU32 offset, ScalarU32 value) {
130 Atom(ctx, inst, binding, offset, value, "DWRAP", "U32");
131}
132
133void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
134 ScalarU32 offset, ScalarU32 value) {
135 Atom(ctx, inst, binding, offset, value, "AND", "U32");
136}
137
138void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
139 ScalarU32 offset, ScalarU32 value) {
140 Atom(ctx, inst, binding, offset, value, "OR", "U32");
141}
142
143void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
144 ScalarU32 offset, ScalarU32 value) {
145 Atom(ctx, inst, binding, offset, value, "XOR", "U32");
146}
147
148void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
149 ScalarU32 offset, ScalarU32 value) {
150 Atom(ctx, inst, binding, offset, value, "EXCH", "U32");
151}
152
153void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
154 ScalarU32 offset, Register value) {
155 Atom(ctx, inst, binding, offset, value, "ADD", "U64");
156}
157
158void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
159 ScalarU32 offset, Register value) {
160 Atom(ctx, inst, binding, offset, value, "MIN", "S64");
161}
162
163void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
164 ScalarU32 offset, Register value) {
165 Atom(ctx, inst, binding, offset, value, "MIN", "U64");
166}
167
168void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
169 ScalarU32 offset, Register value) {
170 Atom(ctx, inst, binding, offset, value, "MAX", "S64");
171}
172
173void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
174 ScalarU32 offset, Register value) {
175 Atom(ctx, inst, binding, offset, value, "MAX", "U64");
176}
177
178void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
179 ScalarU32 offset, Register value) {
180 Atom(ctx, inst, binding, offset, value, "AND", "U64");
181}
182
183void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
184 ScalarU32 offset, Register value) {
185 Atom(ctx, inst, binding, offset, value, "OR", "U64");
186}
187
188void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
189 ScalarU32 offset, Register value) {
190 Atom(ctx, inst, binding, offset, value, "XOR", "U64");
191}
192
193void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
194 ScalarU32 offset, Register value) {
195 Atom(ctx, inst, binding, offset, value, "EXCH", "U64");
196}
197
198void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
199 ScalarU32 offset, ScalarF32 value) {
200 Atom(ctx, inst, binding, offset, value, "ADD", "F32");
201}
202
203void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
204 ScalarU32 offset, Register value) {
205 Atom(ctx, inst, binding, offset, value, "ADD", "F16x2");
206}
207
208void EmitStorageAtomicAddF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
209 [[maybe_unused]] const IR::Value& binding,
210 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
211 throw NotImplementedException("GLASM instruction");
212}
213
214void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
215 ScalarU32 offset, Register value) {
216 Atom(ctx, inst, binding, offset, value, "MIN", "F16x2");
217}
218
219void EmitStorageAtomicMinF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
220 [[maybe_unused]] const IR::Value& binding,
221 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
222 throw NotImplementedException("GLASM instruction");
223}
224
225void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
226 ScalarU32 offset, Register value) {
227 Atom(ctx, inst, binding, offset, value, "MAX", "F16x2");
228}
229
230void EmitStorageAtomicMaxF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
231 [[maybe_unused]] const IR::Value& binding,
232 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
233 throw NotImplementedException("GLASM instruction");
234}
235
236void EmitGlobalAtomicIAdd32(EmitContext&) {
237 throw NotImplementedException("GLASM instruction");
238}
239
240void EmitGlobalAtomicSMin32(EmitContext&) {
241 throw NotImplementedException("GLASM instruction");
242}
243
244void EmitGlobalAtomicUMin32(EmitContext&) {
245 throw NotImplementedException("GLASM instruction");
246}
247
248void EmitGlobalAtomicSMax32(EmitContext&) {
249 throw NotImplementedException("GLASM instruction");
250}
251
252void EmitGlobalAtomicUMax32(EmitContext&) {
253 throw NotImplementedException("GLASM instruction");
254}
255
256void EmitGlobalAtomicInc32(EmitContext&) {
257 throw NotImplementedException("GLASM instruction");
258}
259
260void EmitGlobalAtomicDec32(EmitContext&) {
261 throw NotImplementedException("GLASM instruction");
262}
263
264void EmitGlobalAtomicAnd32(EmitContext&) {
265 throw NotImplementedException("GLASM instruction");
266}
267
268void EmitGlobalAtomicOr32(EmitContext&) {
269 throw NotImplementedException("GLASM instruction");
270}
271
272void EmitGlobalAtomicXor32(EmitContext&) {
273 throw NotImplementedException("GLASM instruction");
274}
275
276void EmitGlobalAtomicExchange32(EmitContext&) {
277 throw NotImplementedException("GLASM instruction");
278}
279
280void EmitGlobalAtomicIAdd64(EmitContext&) {
281 throw NotImplementedException("GLASM instruction");
282}
283
284void EmitGlobalAtomicSMin64(EmitContext&) {
285 throw NotImplementedException("GLASM instruction");
286}
287
288void EmitGlobalAtomicUMin64(EmitContext&) {
289 throw NotImplementedException("GLASM instruction");
290}
291
292void EmitGlobalAtomicSMax64(EmitContext&) {
293 throw NotImplementedException("GLASM instruction");
294}
295
296void EmitGlobalAtomicUMax64(EmitContext&) {
297 throw NotImplementedException("GLASM instruction");
298}
299
300void EmitGlobalAtomicInc64(EmitContext&) {
301 throw NotImplementedException("GLASM instruction");
302}
303
304void EmitGlobalAtomicDec64(EmitContext&) {
305 throw NotImplementedException("GLASM instruction");
306}
307
308void EmitGlobalAtomicAnd64(EmitContext&) {
309 throw NotImplementedException("GLASM instruction");
310}
311
312void EmitGlobalAtomicOr64(EmitContext&) {
313 throw NotImplementedException("GLASM instruction");
314}
315
316void EmitGlobalAtomicXor64(EmitContext&) {
317 throw NotImplementedException("GLASM instruction");
318}
319
320void EmitGlobalAtomicExchange64(EmitContext&) {
321 throw NotImplementedException("GLASM instruction");
322}
323
324void EmitGlobalAtomicAddF32(EmitContext&) {
325 throw NotImplementedException("GLASM instruction");
326}
327
328void EmitGlobalAtomicAddF16x2(EmitContext&) {
329 throw NotImplementedException("GLASM instruction");
330}
331
332void EmitGlobalAtomicAddF32x2(EmitContext&) {
333 throw NotImplementedException("GLASM instruction");
334}
335
336void EmitGlobalAtomicMinF16x2(EmitContext&) {
337 throw NotImplementedException("GLASM instruction");
338}
339
340void EmitGlobalAtomicMinF32x2(EmitContext&) {
341 throw NotImplementedException("GLASM instruction");
342}
343
344void EmitGlobalAtomicMaxF16x2(EmitContext&) {
345 throw NotImplementedException("GLASM instruction");
346}
347
348void EmitGlobalAtomicMaxF32x2(EmitContext&) {
349 throw NotImplementedException("GLASM instruction");
350}
351} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
index 26b03587e..90dbb80d2 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_memory.cpp
@@ -8,6 +8,7 @@
8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" 8#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
9#include "shader_recompiler/frontend/ir/program.h" 9#include "shader_recompiler/frontend/ir/program.h"
10#include "shader_recompiler/frontend/ir/value.h" 10#include "shader_recompiler/frontend/ir/value.h"
11#include "shader_recompiler/profile.h"
11 12
12namespace Shader::Backend::GLASM { 13namespace Shader::Backend::GLASM {
13namespace { 14namespace {
@@ -29,7 +30,7 @@ void StorageOp(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset,
29 } 30 }
30} 31}
31 32
32void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_expr, 33void GlobalStorageOp(EmitContext& ctx, Register address, bool pointer_based, std::string_view expr,
33 std::string_view else_expr = {}) { 34 std::string_view else_expr = {}) {
34 const size_t num_buffers{ctx.info.storage_buffers_descriptors.size()}; 35 const size_t num_buffers{ctx.info.storage_buffers_descriptors.size()};
35 for (size_t index = 0; index < num_buffers; ++index) { 36 for (size_t index = 0; index < num_buffers; ++index) {
@@ -44,14 +45,22 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e
44 "SGE.U64 RC.x,{}.x,DC.x;" // a = input_addr >= ssbo_addr ? -1 : 1 45 "SGE.U64 RC.x,{}.x,DC.x;" // a = input_addr >= ssbo_addr ? -1 : 1
45 "SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 1 46 "SLT.U64 RC.y,{}.x,DC.y;" // b = input_addr < ssbo_end ? -1 : 1
46 "AND.U.CC RC.x,RC.x,RC.y;" 47 "AND.U.CC RC.x,RC.x,RC.y;"
47 "IF NE.x;" // a && b 48 "IF NE.x;" // a && b
48 "SUB.U64 DC.x,{}.x,DC.x;" // offset = input_addr - ssbo_addr 49 "SUB.U64 DC.x,{}.x,DC.x;", // offset = input_addr - ssbo_addr
49 "PK64.U DC.y,c[{}];" // host_ssbo = cbuf
50 "ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset
51 "{}"
52 "ELSE;",
53 ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address, 50 ssbo.cbuf_index, ssbo.cbuf_offset, ssbo.cbuf_index, ssbo.cbuf_offset + 8, address,
54 address, address, index, then_expr); 51 address, address);
52 if (pointer_based) {
53 ctx.Add("PK64.U DC.y,c[{}];" // host_ssbo = cbuf
54 "ADD.U64 DC.x,DC.x,DC.y;" // host_addr = host_ssbo + offset
55 "{}"
56 "ELSE;",
57 index, expr);
58 } else {
59 ctx.Add("CVT.U32.U64 RC.x,DC.x;"
60 "{},ssbo{}[RC.x];"
61 "ELSE;",
62 expr, index);
63 }
55 } 64 }
56 if (!else_expr.empty()) { 65 if (!else_expr.empty()) {
57 ctx.Add("{}", else_expr); 66 ctx.Add("{}", else_expr);
@@ -64,25 +73,54 @@ void GlobalStorageOp(EmitContext& ctx, Register address, std::string_view then_e
64template <typename ValueType> 73template <typename ValueType>
65void Write(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value, 74void Write(EmitContext& ctx, const IR::Value& binding, ScalarU32 offset, ValueType value,
66 std::string_view size) { 75 std::string_view size) {
67 StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, value)); 76 if (ctx.runtime_info.glasm_use_storage_buffers) {
77 ctx.Add("STB.{} {},ssbo{}[{}];", size, value, binding.U32(), offset);
78 } else {
79 StorageOp(ctx, binding, offset, fmt::format("STORE.{} {},DC.x;", size, value));
80 }
68} 81}
69 82
70void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset, 83void Load(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset,
71 std::string_view size) { 84 std::string_view size) {
72 const Register ret{ctx.reg_alloc.Define(inst)}; 85 const Register ret{ctx.reg_alloc.Define(inst)};
73 StorageOp(ctx, binding, offset, fmt::format("LOAD.{} {},DC.x;", size, ret), 86 if (ctx.runtime_info.glasm_use_storage_buffers) {
74 fmt::format("MOV.U {},{{0,0,0,0}};", ret)); 87 ctx.Add("LDB.{} {},ssbo{}[{}];", size, ret, binding.U32(), offset);
88 } else {
89 StorageOp(ctx, binding, offset, fmt::format("LOAD.{} {},DC.x;", size, ret),
90 fmt::format("MOV.U {},{{0,0,0,0}};", ret));
91 }
75} 92}
76 93
77template <typename ValueType> 94template <typename ValueType>
78void GlobalWrite(EmitContext& ctx, Register address, ValueType value, std::string_view size) { 95void GlobalWrite(EmitContext& ctx, Register address, ValueType value, std::string_view size) {
79 GlobalStorageOp(ctx, address, fmt::format("STORE.{} {},DC.x;", size, value)); 96 if (ctx.runtime_info.glasm_use_storage_buffers) {
97 GlobalStorageOp(ctx, address, false, fmt::format("STB.{} {}", size, value));
98 } else {
99 GlobalStorageOp(ctx, address, true, fmt::format("STORE.{} {},DC.x;", size, value));
100 }
80} 101}
81 102
82void GlobalLoad(EmitContext& ctx, IR::Inst& inst, Register address, std::string_view size) { 103void GlobalLoad(EmitContext& ctx, IR::Inst& inst, Register address, std::string_view size) {
83 const Register ret{ctx.reg_alloc.Define(inst)}; 104 const Register ret{ctx.reg_alloc.Define(inst)};
84 GlobalStorageOp(ctx, address, fmt::format("LOAD.{} {},DC.x;", size, ret), 105 if (ctx.runtime_info.glasm_use_storage_buffers) {
85 fmt::format("MOV.S {},0;", ret)); 106 GlobalStorageOp(ctx, address, false, fmt::format("LDB.{} {}", size, ret));
107 } else {
108 GlobalStorageOp(ctx, address, true, fmt::format("LOAD.{} {},DC.x;", size, ret),
109 fmt::format("MOV.S {},0;", ret));
110 }
111}
112
113template <typename ValueType>
114void Atom(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU32 offset,
115 ValueType value, std::string_view operation, std::string_view size) {
116 const Register ret{ctx.reg_alloc.Define(inst)};
117 if (ctx.runtime_info.glasm_use_storage_buffers) {
118 ctx.Add("ATOMB.{}.{} {},{},ssbo{}[{}];", operation, size, ret, value, binding.U32(),
119 offset);
120 } else {
121 StorageOp(ctx, binding, offset,
122 fmt::format("ATOM.{}.{} {},{},DC.x;", operation, size, ret, value));
123 }
86} 124}
87} // Anonymous namespace 125} // Anonymous namespace
88 126
@@ -212,4 +250,318 @@ void EmitWriteStorage128(EmitContext& ctx, const IR::Value& binding, ScalarU32 o
212 Write(ctx, binding, offset, value, "U32X4"); 250 Write(ctx, binding, offset, value, "U32X4");
213} 251}
214 252
253void EmitSharedAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
254 ScalarU32 value) {
255 ctx.Add("ATOMS.ADD.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
256}
257
258void EmitSharedAtomicSMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
259 ScalarS32 value) {
260 ctx.Add("ATOMS.MIN.S32 {},{},shared_mem[{}];", inst, value, pointer_offset);
261}
262
263void EmitSharedAtomicUMin32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
264 ScalarU32 value) {
265 ctx.Add("ATOMS.MIN.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
266}
267
268void EmitSharedAtomicSMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
269 ScalarS32 value) {
270 ctx.Add("ATOMS.MAX.S32 {},{},shared_mem[{}];", inst, value, pointer_offset);
271}
272
273void EmitSharedAtomicUMax32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
274 ScalarU32 value) {
275 ctx.Add("ATOMS.MAX.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
276}
277
278void EmitSharedAtomicInc32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
279 ScalarU32 value) {
280 ctx.Add("ATOMS.IWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
281}
282
283void EmitSharedAtomicDec32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
284 ScalarU32 value) {
285 ctx.Add("ATOMS.DWRAP.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
286}
287
288void EmitSharedAtomicAnd32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
289 ScalarU32 value) {
290 ctx.Add("ATOMS.AND.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
291}
292
293void EmitSharedAtomicOr32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
294 ScalarU32 value) {
295 ctx.Add("ATOMS.OR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
296}
297
298void EmitSharedAtomicXor32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
299 ScalarU32 value) {
300 ctx.Add("ATOMS.XOR.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
301}
302
303void EmitSharedAtomicExchange32(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
304 ScalarU32 value) {
305 ctx.Add("ATOMS.EXCH.U32 {},{},shared_mem[{}];", inst, value, pointer_offset);
306}
307
308void EmitSharedAtomicExchange64(EmitContext& ctx, IR::Inst& inst, ScalarU32 pointer_offset,
309 Register value) {
310 ctx.LongAdd("ATOMS.EXCH.U64 {}.x,{},shared_mem[{}];", inst, value, pointer_offset);
311}
312
313void EmitStorageAtomicIAdd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
314 ScalarU32 offset, ScalarU32 value) {
315 Atom(ctx, inst, binding, offset, value, "ADD", "U32");
316}
317
318void EmitStorageAtomicSMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
319 ScalarU32 offset, ScalarS32 value) {
320 Atom(ctx, inst, binding, offset, value, "MIN", "S32");
321}
322
323void EmitStorageAtomicUMin32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
324 ScalarU32 offset, ScalarU32 value) {
325 Atom(ctx, inst, binding, offset, value, "MIN", "U32");
326}
327
328void EmitStorageAtomicSMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
329 ScalarU32 offset, ScalarS32 value) {
330 Atom(ctx, inst, binding, offset, value, "MAX", "S32");
331}
332
333void EmitStorageAtomicUMax32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
334 ScalarU32 offset, ScalarU32 value) {
335 Atom(ctx, inst, binding, offset, value, "MAX", "U32");
336}
337
338void EmitStorageAtomicInc32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
339 ScalarU32 offset, ScalarU32 value) {
340 Atom(ctx, inst, binding, offset, value, "IWRAP", "U32");
341}
342
343void EmitStorageAtomicDec32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
344 ScalarU32 offset, ScalarU32 value) {
345 Atom(ctx, inst, binding, offset, value, "DWRAP", "U32");
346}
347
348void EmitStorageAtomicAnd32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
349 ScalarU32 offset, ScalarU32 value) {
350 Atom(ctx, inst, binding, offset, value, "AND", "U32");
351}
352
353void EmitStorageAtomicOr32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
354 ScalarU32 offset, ScalarU32 value) {
355 Atom(ctx, inst, binding, offset, value, "OR", "U32");
356}
357
358void EmitStorageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
359 ScalarU32 offset, ScalarU32 value) {
360 Atom(ctx, inst, binding, offset, value, "XOR", "U32");
361}
362
363void EmitStorageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
364 ScalarU32 offset, ScalarU32 value) {
365 Atom(ctx, inst, binding, offset, value, "EXCH", "U32");
366}
367
368void EmitStorageAtomicIAdd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
369 ScalarU32 offset, Register value) {
370 Atom(ctx, inst, binding, offset, value, "ADD", "U64");
371}
372
373void EmitStorageAtomicSMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
374 ScalarU32 offset, Register value) {
375 Atom(ctx, inst, binding, offset, value, "MIN", "S64");
376}
377
378void EmitStorageAtomicUMin64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
379 ScalarU32 offset, Register value) {
380 Atom(ctx, inst, binding, offset, value, "MIN", "U64");
381}
382
383void EmitStorageAtomicSMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
384 ScalarU32 offset, Register value) {
385 Atom(ctx, inst, binding, offset, value, "MAX", "S64");
386}
387
388void EmitStorageAtomicUMax64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
389 ScalarU32 offset, Register value) {
390 Atom(ctx, inst, binding, offset, value, "MAX", "U64");
391}
392
393void EmitStorageAtomicAnd64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
394 ScalarU32 offset, Register value) {
395 Atom(ctx, inst, binding, offset, value, "AND", "U64");
396}
397
398void EmitStorageAtomicOr64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
399 ScalarU32 offset, Register value) {
400 Atom(ctx, inst, binding, offset, value, "OR", "U64");
401}
402
403void EmitStorageAtomicXor64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
404 ScalarU32 offset, Register value) {
405 Atom(ctx, inst, binding, offset, value, "XOR", "U64");
406}
407
408void EmitStorageAtomicExchange64(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
409 ScalarU32 offset, Register value) {
410 Atom(ctx, inst, binding, offset, value, "EXCH", "U64");
411}
412
413void EmitStorageAtomicAddF32(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
414 ScalarU32 offset, ScalarF32 value) {
415 Atom(ctx, inst, binding, offset, value, "ADD", "F32");
416}
417
418void EmitStorageAtomicAddF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
419 ScalarU32 offset, Register value) {
420 Atom(ctx, inst, binding, offset, value, "ADD", "F16x2");
421}
422
423void EmitStorageAtomicAddF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
424 [[maybe_unused]] const IR::Value& binding,
425 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
426 throw NotImplementedException("GLASM instruction");
427}
428
429void EmitStorageAtomicMinF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
430 ScalarU32 offset, Register value) {
431 Atom(ctx, inst, binding, offset, value, "MIN", "F16x2");
432}
433
434void EmitStorageAtomicMinF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
435 [[maybe_unused]] const IR::Value& binding,
436 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
437 throw NotImplementedException("GLASM instruction");
438}
439
440void EmitStorageAtomicMaxF16x2(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding,
441 ScalarU32 offset, Register value) {
442 Atom(ctx, inst, binding, offset, value, "MAX", "F16x2");
443}
444
445void EmitStorageAtomicMaxF32x2([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst,
446 [[maybe_unused]] const IR::Value& binding,
447 [[maybe_unused]] ScalarU32 offset, [[maybe_unused]] Register value) {
448 throw NotImplementedException("GLASM instruction");
449}
450
451void EmitGlobalAtomicIAdd32(EmitContext&) {
452 throw NotImplementedException("GLASM instruction");
453}
454
455void EmitGlobalAtomicSMin32(EmitContext&) {
456 throw NotImplementedException("GLASM instruction");
457}
458
459void EmitGlobalAtomicUMin32(EmitContext&) {
460 throw NotImplementedException("GLASM instruction");
461}
462
463void EmitGlobalAtomicSMax32(EmitContext&) {
464 throw NotImplementedException("GLASM instruction");
465}
466
467void EmitGlobalAtomicUMax32(EmitContext&) {
468 throw NotImplementedException("GLASM instruction");
469}
470
471void EmitGlobalAtomicInc32(EmitContext&) {
472 throw NotImplementedException("GLASM instruction");
473}
474
475void EmitGlobalAtomicDec32(EmitContext&) {
476 throw NotImplementedException("GLASM instruction");
477}
478
479void EmitGlobalAtomicAnd32(EmitContext&) {
480 throw NotImplementedException("GLASM instruction");
481}
482
483void EmitGlobalAtomicOr32(EmitContext&) {
484 throw NotImplementedException("GLASM instruction");
485}
486
487void EmitGlobalAtomicXor32(EmitContext&) {
488 throw NotImplementedException("GLASM instruction");
489}
490
491void EmitGlobalAtomicExchange32(EmitContext&) {
492 throw NotImplementedException("GLASM instruction");
493}
494
495void EmitGlobalAtomicIAdd64(EmitContext&) {
496 throw NotImplementedException("GLASM instruction");
497}
498
499void EmitGlobalAtomicSMin64(EmitContext&) {
500 throw NotImplementedException("GLASM instruction");
501}
502
503void EmitGlobalAtomicUMin64(EmitContext&) {
504 throw NotImplementedException("GLASM instruction");
505}
506
507void EmitGlobalAtomicSMax64(EmitContext&) {
508 throw NotImplementedException("GLASM instruction");
509}
510
511void EmitGlobalAtomicUMax64(EmitContext&) {
512 throw NotImplementedException("GLASM instruction");
513}
514
515void EmitGlobalAtomicInc64(EmitContext&) {
516 throw NotImplementedException("GLASM instruction");
517}
518
519void EmitGlobalAtomicDec64(EmitContext&) {
520 throw NotImplementedException("GLASM instruction");
521}
522
523void EmitGlobalAtomicAnd64(EmitContext&) {
524 throw NotImplementedException("GLASM instruction");
525}
526
527void EmitGlobalAtomicOr64(EmitContext&) {
528 throw NotImplementedException("GLASM instruction");
529}
530
531void EmitGlobalAtomicXor64(EmitContext&) {
532 throw NotImplementedException("GLASM instruction");
533}
534
535void EmitGlobalAtomicExchange64(EmitContext&) {
536 throw NotImplementedException("GLASM instruction");
537}
538
539void EmitGlobalAtomicAddF32(EmitContext&) {
540 throw NotImplementedException("GLASM instruction");
541}
542
543void EmitGlobalAtomicAddF16x2(EmitContext&) {
544 throw NotImplementedException("GLASM instruction");
545}
546
547void EmitGlobalAtomicAddF32x2(EmitContext&) {
548 throw NotImplementedException("GLASM instruction");
549}
550
551void EmitGlobalAtomicMinF16x2(EmitContext&) {
552 throw NotImplementedException("GLASM instruction");
553}
554
555void EmitGlobalAtomicMinF32x2(EmitContext&) {
556 throw NotImplementedException("GLASM instruction");
557}
558
559void EmitGlobalAtomicMaxF16x2(EmitContext&) {
560 throw NotImplementedException("GLASM instruction");
561}
562
563void EmitGlobalAtomicMaxF32x2(EmitContext&) {
564 throw NotImplementedException("GLASM instruction");
565}
566
215} // namespace Shader::Backend::GLASM 567} // namespace Shader::Backend::GLASM