1 /*
2 * Copyright 2018 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "spirv_builder.h"
25
26 #include "util/macros.h"
27 #include "util/set.h"
28 #include "util/ralloc.h"
29 #include "util/u_bitcast.h"
30 #include "util/u_memory.h"
31 #include "util/half_float.h"
32 #include "util/hash_table.h"
33 #define XXH_INLINE_ALL
34 #include "util/xxhash.h"
35
36 #include <stdbool.h>
37 #include <inttypes.h>
38 #include <string.h>
39
40 static bool
spirv_buffer_grow(struct spirv_buffer * b,void * mem_ctx,size_t needed)41 spirv_buffer_grow(struct spirv_buffer *b, void *mem_ctx, size_t needed)
42 {
43 size_t new_room = MAX3(64, (b->room * 3) / 2, needed);
44
45 uint32_t *new_words = reralloc_size(mem_ctx, b->words,
46 new_room * sizeof(uint32_t));
47 if (!new_words)
48 return false;
49
50 b->words = new_words;
51 b->room = new_room;
52 return true;
53 }
54
55 static inline bool
spirv_buffer_prepare(struct spirv_buffer * b,void * mem_ctx,size_t needed)56 spirv_buffer_prepare(struct spirv_buffer *b, void *mem_ctx, size_t needed)
57 {
58 needed += b->num_words;
59 if (b->room >= b->num_words + needed)
60 return true;
61
62 return spirv_buffer_grow(b, mem_ctx, needed);
63 }
64
65 static inline void
spirv_buffer_emit_word(struct spirv_buffer * b,uint32_t word)66 spirv_buffer_emit_word(struct spirv_buffer *b, uint32_t word)
67 {
68 assert(b->num_words < b->room);
69 b->words[b->num_words++] = word;
70 }
71
72 static int
spirv_buffer_emit_string(struct spirv_buffer * b,void * mem_ctx,const char * str)73 spirv_buffer_emit_string(struct spirv_buffer *b, void *mem_ctx,
74 const char *str)
75 {
76 int pos = 0;
77 uint32_t word = 0;
78 while (str[pos] != '\0') {
79 word |= str[pos] << (8 * (pos % 4));
80 if (++pos % 4 == 0) {
81 spirv_buffer_prepare(b, mem_ctx, 1);
82 spirv_buffer_emit_word(b, word);
83 word = 0;
84 }
85 }
86
87 spirv_buffer_prepare(b, mem_ctx, 1);
88 spirv_buffer_emit_word(b, word);
89
90 return 1 + pos / 4;
91 }
92
93 void
spirv_builder_emit_cap(struct spirv_builder * b,SpvCapability cap)94 spirv_builder_emit_cap(struct spirv_builder *b, SpvCapability cap)
95 {
96 if (!b->caps)
97 b->caps = _mesa_set_create_u32_keys(b->mem_ctx);
98
99 assert(b->caps);
100 _mesa_set_add(b->caps, (void*)(uintptr_t)cap);
101 }
102
103 void
spirv_builder_emit_extension(struct spirv_builder * b,const char * name)104 spirv_builder_emit_extension(struct spirv_builder *b, const char *name)
105 {
106 size_t pos = b->extensions.num_words;
107 spirv_buffer_prepare(&b->extensions, b->mem_ctx, 1);
108 spirv_buffer_emit_word(&b->extensions, SpvOpExtension);
109 int len = spirv_buffer_emit_string(&b->extensions, b->mem_ctx, name);
110 b->extensions.words[pos] |= (1 + len) << 16;
111 }
112
113 void
spirv_builder_emit_source(struct spirv_builder * b,SpvSourceLanguage lang,uint32_t version)114 spirv_builder_emit_source(struct spirv_builder *b, SpvSourceLanguage lang,
115 uint32_t version)
116 {
117 spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 3);
118 spirv_buffer_emit_word(&b->debug_names, SpvOpSource | (3 << 16));
119 spirv_buffer_emit_word(&b->debug_names, lang);
120 spirv_buffer_emit_word(&b->debug_names, version);
121 }
122
123 void
spirv_builder_emit_mem_model(struct spirv_builder * b,SpvAddressingModel addr_model,SpvMemoryModel mem_model)124 spirv_builder_emit_mem_model(struct spirv_builder *b,
125 SpvAddressingModel addr_model,
126 SpvMemoryModel mem_model)
127 {
128 spirv_buffer_prepare(&b->memory_model, b->mem_ctx, 3);
129 spirv_buffer_emit_word(&b->memory_model, SpvOpMemoryModel | (3 << 16));
130 spirv_buffer_emit_word(&b->memory_model, addr_model);
131 spirv_buffer_emit_word(&b->memory_model, mem_model);
132 }
133
134 void
spirv_builder_emit_entry_point(struct spirv_builder * b,SpvExecutionModel exec_model,SpvId entry_point,const char * name,const SpvId interfaces[],size_t num_interfaces)135 spirv_builder_emit_entry_point(struct spirv_builder *b,
136 SpvExecutionModel exec_model, SpvId entry_point,
137 const char *name, const SpvId interfaces[],
138 size_t num_interfaces)
139 {
140 size_t pos = b->entry_points.num_words;
141 spirv_buffer_prepare(&b->entry_points, b->mem_ctx, 3);
142 spirv_buffer_emit_word(&b->entry_points, SpvOpEntryPoint);
143 spirv_buffer_emit_word(&b->entry_points, exec_model);
144 spirv_buffer_emit_word(&b->entry_points, entry_point);
145 int len = spirv_buffer_emit_string(&b->entry_points, b->mem_ctx, name);
146 b->entry_points.words[pos] |= (3 + len + num_interfaces) << 16;
147 spirv_buffer_prepare(&b->entry_points, b->mem_ctx, num_interfaces);
148 for (int i = 0; i < num_interfaces; ++i)
149 spirv_buffer_emit_word(&b->entry_points, interfaces[i]);
150 }
151
152 void
spirv_builder_emit_exec_mode_literal(struct spirv_builder * b,SpvId entry_point,SpvExecutionMode exec_mode,uint32_t param)153 spirv_builder_emit_exec_mode_literal(struct spirv_builder *b, SpvId entry_point,
154 SpvExecutionMode exec_mode, uint32_t param)
155 {
156 spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 4);
157 spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (4 << 16));
158 spirv_buffer_emit_word(&b->exec_modes, entry_point);
159 spirv_buffer_emit_word(&b->exec_modes, exec_mode);
160 spirv_buffer_emit_word(&b->exec_modes, param);
161 }
162
163 void
spirv_builder_emit_exec_mode_literal3(struct spirv_builder * b,SpvId entry_point,SpvExecutionMode exec_mode,uint32_t param[3])164 spirv_builder_emit_exec_mode_literal3(struct spirv_builder *b, SpvId entry_point,
165 SpvExecutionMode exec_mode, uint32_t param[3])
166 {
167 spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 6);
168 spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (6 << 16));
169 spirv_buffer_emit_word(&b->exec_modes, entry_point);
170 spirv_buffer_emit_word(&b->exec_modes, exec_mode);
171 for (unsigned i = 0; i < 3; i++)
172 spirv_buffer_emit_word(&b->exec_modes, param[i]);
173 }
174
175 void
spirv_builder_emit_exec_mode(struct spirv_builder * b,SpvId entry_point,SpvExecutionMode exec_mode)176 spirv_builder_emit_exec_mode(struct spirv_builder *b, SpvId entry_point,
177 SpvExecutionMode exec_mode)
178 {
179 spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 3);
180 spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (3 << 16));
181 spirv_buffer_emit_word(&b->exec_modes, entry_point);
182 spirv_buffer_emit_word(&b->exec_modes, exec_mode);
183 }
184
185 void
spirv_builder_emit_name(struct spirv_builder * b,SpvId target,const char * name)186 spirv_builder_emit_name(struct spirv_builder *b, SpvId target,
187 const char *name)
188 {
189 size_t pos = b->debug_names.num_words;
190 spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 2);
191 spirv_buffer_emit_word(&b->debug_names, SpvOpName);
192 spirv_buffer_emit_word(&b->debug_names, target);
193 int len = spirv_buffer_emit_string(&b->debug_names, b->mem_ctx, name);
194 b->debug_names.words[pos] |= (2 + len) << 16;
195 }
196
197 static void
emit_decoration(struct spirv_builder * b,SpvId target,SpvDecoration decoration,const uint32_t extra_operands[],size_t num_extra_operands)198 emit_decoration(struct spirv_builder *b, SpvId target,
199 SpvDecoration decoration, const uint32_t extra_operands[],
200 size_t num_extra_operands)
201 {
202 int words = 3 + num_extra_operands;
203 spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);
204 spirv_buffer_emit_word(&b->decorations, SpvOpDecorate | (words << 16));
205 spirv_buffer_emit_word(&b->decorations, target);
206 spirv_buffer_emit_word(&b->decorations, decoration);
207 for (int i = 0; i < num_extra_operands; ++i)
208 spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
209 }
210
211 void
spirv_builder_emit_decoration(struct spirv_builder * b,SpvId target,SpvDecoration decoration)212 spirv_builder_emit_decoration(struct spirv_builder *b, SpvId target,
213 SpvDecoration decoration)
214 {
215 emit_decoration(b, target, decoration, NULL, 0);
216 }
217
218 void
spirv_builder_emit_input_attachment_index(struct spirv_builder * b,SpvId target,uint32_t id)219 spirv_builder_emit_input_attachment_index(struct spirv_builder *b, SpvId target, uint32_t id)
220 {
221 uint32_t args[] = { id };
222 emit_decoration(b, target, SpvDecorationInputAttachmentIndex, args, ARRAY_SIZE(args));
223 }
224
225 void
spirv_builder_emit_specid(struct spirv_builder * b,SpvId target,uint32_t id)226 spirv_builder_emit_specid(struct spirv_builder *b, SpvId target, uint32_t id)
227 {
228 uint32_t args[] = { id };
229 emit_decoration(b, target, SpvDecorationSpecId, args, ARRAY_SIZE(args));
230 }
231
232 void
spirv_builder_emit_location(struct spirv_builder * b,SpvId target,uint32_t location)233 spirv_builder_emit_location(struct spirv_builder *b, SpvId target,
234 uint32_t location)
235 {
236 uint32_t args[] = { location };
237 emit_decoration(b, target, SpvDecorationLocation, args, ARRAY_SIZE(args));
238 }
239
240 void
spirv_builder_emit_component(struct spirv_builder * b,SpvId target,uint32_t component)241 spirv_builder_emit_component(struct spirv_builder *b, SpvId target,
242 uint32_t component)
243 {
244 uint32_t args[] = { component };
245 emit_decoration(b, target, SpvDecorationComponent, args, ARRAY_SIZE(args));
246 }
247
248 void
spirv_builder_emit_builtin(struct spirv_builder * b,SpvId target,SpvBuiltIn builtin)249 spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,
250 SpvBuiltIn builtin)
251 {
252 uint32_t args[] = { builtin };
253 emit_decoration(b, target, SpvDecorationBuiltIn, args, ARRAY_SIZE(args));
254 }
255
256 void
spirv_builder_emit_vertex(struct spirv_builder * b,uint32_t stream)257 spirv_builder_emit_vertex(struct spirv_builder *b, uint32_t stream)
258 {
259 unsigned words = 1;
260 SpvOp op = SpvOpEmitVertex;
261 if (stream > 0) {
262 op = SpvOpEmitStreamVertex;
263 words++;
264 }
265 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
266 spirv_buffer_emit_word(&b->instructions, op | (words << 16));
267 if (stream)
268 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));
269 }
270
271 void
spirv_builder_end_primitive(struct spirv_builder * b,uint32_t stream)272 spirv_builder_end_primitive(struct spirv_builder *b, uint32_t stream)
273 {
274 unsigned words = 1;
275 SpvOp op = SpvOpEndPrimitive;
276 if (stream > 0) {
277 op = SpvOpEndStreamPrimitive;
278 words++;
279 }
280 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
281 spirv_buffer_emit_word(&b->instructions, op | (words << 16));
282 if (stream)
283 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, stream));
284 }
285
286 void
spirv_builder_emit_descriptor_set(struct spirv_builder * b,SpvId target,uint32_t descriptor_set)287 spirv_builder_emit_descriptor_set(struct spirv_builder *b, SpvId target,
288 uint32_t descriptor_set)
289 {
290 uint32_t args[] = { descriptor_set };
291 emit_decoration(b, target, SpvDecorationDescriptorSet, args,
292 ARRAY_SIZE(args));
293 }
294
295 void
spirv_builder_emit_binding(struct spirv_builder * b,SpvId target,uint32_t binding)296 spirv_builder_emit_binding(struct spirv_builder *b, SpvId target,
297 uint32_t binding)
298 {
299 uint32_t args[] = { binding };
300 emit_decoration(b, target, SpvDecorationBinding, args, ARRAY_SIZE(args));
301 }
302
303 void
spirv_builder_emit_array_stride(struct spirv_builder * b,SpvId target,uint32_t stride)304 spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,
305 uint32_t stride)
306 {
307 uint32_t args[] = { stride };
308 emit_decoration(b, target, SpvDecorationArrayStride, args, ARRAY_SIZE(args));
309 }
310
311 void
spirv_builder_emit_offset(struct spirv_builder * b,SpvId target,uint32_t offset)312 spirv_builder_emit_offset(struct spirv_builder *b, SpvId target,
313 uint32_t offset)
314 {
315 uint32_t args[] = { offset };
316 emit_decoration(b, target, SpvDecorationOffset, args, ARRAY_SIZE(args));
317 }
318
319 void
spirv_builder_emit_xfb_buffer(struct spirv_builder * b,SpvId target,uint32_t buffer)320 spirv_builder_emit_xfb_buffer(struct spirv_builder *b, SpvId target,
321 uint32_t buffer)
322 {
323 uint32_t args[] = { buffer };
324 emit_decoration(b, target, SpvDecorationXfbBuffer, args, ARRAY_SIZE(args));
325 }
326
327 void
spirv_builder_emit_xfb_stride(struct spirv_builder * b,SpvId target,uint32_t stride)328 spirv_builder_emit_xfb_stride(struct spirv_builder *b, SpvId target,
329 uint32_t stride)
330 {
331 uint32_t args[] = { stride };
332 emit_decoration(b, target, SpvDecorationXfbStride, args, ARRAY_SIZE(args));
333 }
334
335 void
spirv_builder_emit_index(struct spirv_builder * b,SpvId target,int index)336 spirv_builder_emit_index(struct spirv_builder *b, SpvId target, int index)
337 {
338 uint32_t args[] = { index };
339 emit_decoration(b, target, SpvDecorationIndex, args, ARRAY_SIZE(args));
340 }
341
342 void
spirv_builder_emit_stream(struct spirv_builder * b,SpvId target,int stream)343 spirv_builder_emit_stream(struct spirv_builder *b, SpvId target, int stream)
344 {
345 uint32_t args[] = { stream };
346 emit_decoration(b, target, SpvDecorationStream, args, ARRAY_SIZE(args));
347 }
348
349 static void
emit_member_decoration(struct spirv_builder * b,SpvId target,uint32_t member,SpvDecoration decoration,const uint32_t extra_operands[],size_t num_extra_operands)350 emit_member_decoration(struct spirv_builder *b, SpvId target, uint32_t member,
351 SpvDecoration decoration, const uint32_t extra_operands[],
352 size_t num_extra_operands)
353 {
354 int words = 4 + num_extra_operands;
355 spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);
356 spirv_buffer_emit_word(&b->decorations,
357 SpvOpMemberDecorate | (words << 16));
358 spirv_buffer_emit_word(&b->decorations, target);
359 spirv_buffer_emit_word(&b->decorations, member);
360 spirv_buffer_emit_word(&b->decorations, decoration);
361 for (int i = 0; i < num_extra_operands; ++i)
362 spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
363 }
364
365 void
spirv_builder_emit_member_offset(struct spirv_builder * b,SpvId target,uint32_t member,uint32_t offset)366 spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target,
367 uint32_t member, uint32_t offset)
368 {
369 uint32_t args[] = { offset };
370 emit_member_decoration(b, target, member, SpvDecorationOffset,
371 args, ARRAY_SIZE(args));
372 }
373
374 SpvId
spirv_builder_emit_undef(struct spirv_builder * b,SpvId result_type)375 spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type)
376 {
377 SpvId result = spirv_builder_new_id(b);
378 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
379 spirv_buffer_emit_word(&b->instructions, SpvOpUndef | (3 << 16));
380 spirv_buffer_emit_word(&b->instructions, result_type);
381 spirv_buffer_emit_word(&b->instructions, result);
382 return result;
383 }
384
385 void
spirv_builder_function(struct spirv_builder * b,SpvId result,SpvId return_type,SpvFunctionControlMask function_control,SpvId function_type)386 spirv_builder_function(struct spirv_builder *b, SpvId result,
387 SpvId return_type,
388 SpvFunctionControlMask function_control,
389 SpvId function_type)
390 {
391 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);
392 spirv_buffer_emit_word(&b->instructions, SpvOpFunction | (5 << 16));
393 spirv_buffer_emit_word(&b->instructions, return_type);
394 spirv_buffer_emit_word(&b->instructions, result);
395 spirv_buffer_emit_word(&b->instructions, function_control);
396 spirv_buffer_emit_word(&b->instructions, function_type);
397 }
398
399 void
spirv_builder_function_end(struct spirv_builder * b)400 spirv_builder_function_end(struct spirv_builder *b)
401 {
402 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
403 spirv_buffer_emit_word(&b->instructions, SpvOpFunctionEnd | (1 << 16));
404 }
405
406 void
spirv_builder_label(struct spirv_builder * b,SpvId label)407 spirv_builder_label(struct spirv_builder *b, SpvId label)
408 {
409 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);
410 spirv_buffer_emit_word(&b->instructions, SpvOpLabel | (2 << 16));
411 spirv_buffer_emit_word(&b->instructions, label);
412 }
413
414 void
spirv_builder_return(struct spirv_builder * b)415 spirv_builder_return(struct spirv_builder *b)
416 {
417 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
418 spirv_buffer_emit_word(&b->instructions, SpvOpReturn | (1 << 16));
419 }
420
421 SpvId
spirv_builder_emit_load(struct spirv_builder * b,SpvId result_type,SpvId pointer)422 spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type,
423 SpvId pointer)
424 {
425 return spirv_builder_emit_unop(b, SpvOpLoad, result_type, pointer);
426 }
427
428 void
spirv_builder_emit_store(struct spirv_builder * b,SpvId pointer,SpvId object)429 spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object)
430 {
431 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
432 spirv_buffer_emit_word(&b->instructions, SpvOpStore | (3 << 16));
433 spirv_buffer_emit_word(&b->instructions, pointer);
434 spirv_buffer_emit_word(&b->instructions, object);
435 }
436
437 void
spirv_builder_emit_atomic_store(struct spirv_builder * b,SpvId pointer,SpvScope scope,SpvMemorySemanticsMask semantics,SpvId object)438 spirv_builder_emit_atomic_store(struct spirv_builder *b, SpvId pointer, SpvScope scope,
439 SpvMemorySemanticsMask semantics, SpvId object)
440 {
441 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);
442 spirv_buffer_emit_word(&b->instructions, SpvOpAtomicStore | (5 << 16));
443 spirv_buffer_emit_word(&b->instructions, pointer);
444 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
445 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
446 spirv_buffer_emit_word(&b->instructions, object);
447 }
448
449 SpvId
spirv_builder_emit_access_chain(struct spirv_builder * b,SpvId result_type,SpvId base,const SpvId indexes[],size_t num_indexes)450 spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,
451 SpvId base, const SpvId indexes[],
452 size_t num_indexes)
453 {
454 assert(base);
455 assert(result_type);
456 SpvId result = spirv_builder_new_id(b);
457
458 int words = 4 + num_indexes;
459 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
460 spirv_buffer_emit_word(&b->instructions, SpvOpAccessChain | (words << 16));
461 spirv_buffer_emit_word(&b->instructions, result_type);
462 spirv_buffer_emit_word(&b->instructions, result);
463 spirv_buffer_emit_word(&b->instructions, base);
464 for (int i = 0; i < num_indexes; ++i) {
465 assert(indexes[i]);
466 spirv_buffer_emit_word(&b->instructions, indexes[i]);
467 }
468 return result;
469 }
470
471 void
spirv_builder_emit_interlock(struct spirv_builder * b,bool end)472 spirv_builder_emit_interlock(struct spirv_builder *b, bool end)
473 {
474 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
475 spirv_buffer_emit_word(&b->instructions, (end ? SpvOpEndInvocationInterlockEXT : SpvOpBeginInvocationInterlockEXT) | (1 << 16));
476 }
477
478
479 SpvId
spirv_builder_emit_unop_const(struct spirv_builder * b,SpvOp op,SpvId result_type,uint64_t operand)480 spirv_builder_emit_unop_const(struct spirv_builder *b, SpvOp op, SpvId result_type, uint64_t operand)
481 {
482 SpvId result = spirv_builder_new_id(b);
483 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
484 spirv_buffer_emit_word(&b->instructions, op | (4 << 16));
485 spirv_buffer_emit_word(&b->instructions, result_type);
486 spirv_buffer_emit_word(&b->instructions, result);
487 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, operand));
488 return result;
489 }
490
491 SpvId
spirv_builder_emit_unop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand)492 spirv_builder_emit_unop(struct spirv_builder *b, SpvOp op, SpvId result_type,
493 SpvId operand)
494 {
495 SpvId result = spirv_builder_new_id(b);
496 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
497 spirv_buffer_emit_word(&b->instructions, op | (4 << 16));
498 spirv_buffer_emit_word(&b->instructions, result_type);
499 spirv_buffer_emit_word(&b->instructions, result);
500 spirv_buffer_emit_word(&b->instructions, operand);
501 return result;
502 }
503
504 SpvId
spirv_builder_emit_binop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1)505 spirv_builder_emit_binop(struct spirv_builder *b, SpvOp op, SpvId result_type,
506 SpvId operand0, SpvId operand1)
507 {
508 SpvId result = spirv_builder_new_id(b);
509 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);
510 spirv_buffer_emit_word(&b->instructions, op | (5 << 16));
511 spirv_buffer_emit_word(&b->instructions, result_type);
512 spirv_buffer_emit_word(&b->instructions, result);
513 spirv_buffer_emit_word(&b->instructions, operand0);
514 spirv_buffer_emit_word(&b->instructions, operand1);
515 return result;
516 }
517
518 SpvId
spirv_builder_emit_triop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1,SpvId operand2)519 spirv_builder_emit_triop(struct spirv_builder *b, SpvOp op, SpvId result_type,
520 SpvId operand0, SpvId operand1, SpvId operand2)
521 {
522 SpvId result = spirv_builder_new_id(b);
523 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6);
524 spirv_buffer_emit_word(&b->instructions, op | (6 << 16));
525 spirv_buffer_emit_word(&b->instructions, result_type);
526 spirv_buffer_emit_word(&b->instructions, result);
527 spirv_buffer_emit_word(&b->instructions, operand0);
528 spirv_buffer_emit_word(&b->instructions, operand1);
529 spirv_buffer_emit_word(&b->instructions, operand2);
530 return result;
531 }
532
533 SpvId
spirv_builder_emit_quadop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1,SpvId operand2,SpvId operand3)534 spirv_builder_emit_quadop(struct spirv_builder *b, SpvOp op, SpvId result_type,
535 SpvId operand0, SpvId operand1, SpvId operand2, SpvId operand3)
536 {
537 SpvId result = spirv_builder_new_id(b);
538 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 7);
539 spirv_buffer_emit_word(&b->instructions, op | (7 << 16));
540 spirv_buffer_emit_word(&b->instructions, result_type);
541 spirv_buffer_emit_word(&b->instructions, result);
542 spirv_buffer_emit_word(&b->instructions, operand0);
543 spirv_buffer_emit_word(&b->instructions, operand1);
544 spirv_buffer_emit_word(&b->instructions, operand2);
545 spirv_buffer_emit_word(&b->instructions, operand3);
546 return result;
547 }
548
549 SpvId
spirv_builder_emit_hexop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1,SpvId operand2,SpvId operand3,SpvId operand4,SpvId operand5)550 spirv_builder_emit_hexop(struct spirv_builder *b, SpvOp op, SpvId result_type,
551 SpvId operand0, SpvId operand1, SpvId operand2, SpvId operand3,
552 SpvId operand4, SpvId operand5)
553 {
554 SpvId result = spirv_builder_new_id(b);
555 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 9);
556 spirv_buffer_emit_word(&b->instructions, op | (9 << 16));
557 spirv_buffer_emit_word(&b->instructions, result_type);
558 spirv_buffer_emit_word(&b->instructions, result);
559 spirv_buffer_emit_word(&b->instructions, operand0);
560 spirv_buffer_emit_word(&b->instructions, operand1);
561 spirv_buffer_emit_word(&b->instructions, operand2);
562 spirv_buffer_emit_word(&b->instructions, operand3);
563 spirv_buffer_emit_word(&b->instructions, operand4);
564 spirv_buffer_emit_word(&b->instructions, operand5);
565 return result;
566 }
567
568 SpvId
spirv_builder_emit_composite_extract(struct spirv_builder * b,SpvId result_type,SpvId composite,const uint32_t indexes[],size_t num_indexes)569 spirv_builder_emit_composite_extract(struct spirv_builder *b, SpvId result_type,
570 SpvId composite, const uint32_t indexes[],
571 size_t num_indexes)
572 {
573 SpvId result = spirv_builder_new_id(b);
574
575 assert(num_indexes > 0);
576 int words = 4 + num_indexes;
577 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
578 spirv_buffer_emit_word(&b->instructions,
579 SpvOpCompositeExtract | (words << 16));
580 spirv_buffer_emit_word(&b->instructions, result_type);
581 spirv_buffer_emit_word(&b->instructions, result);
582 spirv_buffer_emit_word(&b->instructions, composite);
583 for (int i = 0; i < num_indexes; ++i)
584 spirv_buffer_emit_word(&b->instructions, indexes[i]);
585 return result;
586 }
587
588 SpvId
spirv_builder_emit_composite_construct(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)589 spirv_builder_emit_composite_construct(struct spirv_builder *b,
590 SpvId result_type,
591 const SpvId constituents[],
592 size_t num_constituents)
593 {
594 SpvId result = spirv_builder_new_id(b);
595
596 assert(num_constituents > 0);
597 int words = 3 + num_constituents;
598 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
599 spirv_buffer_emit_word(&b->instructions,
600 SpvOpCompositeConstruct | (words << 16));
601 spirv_buffer_emit_word(&b->instructions, result_type);
602 spirv_buffer_emit_word(&b->instructions, result);
603 for (int i = 0; i < num_constituents; ++i)
604 spirv_buffer_emit_word(&b->instructions, constituents[i]);
605 return result;
606 }
607
608 SpvId
spirv_builder_emit_vector_shuffle(struct spirv_builder * b,SpvId result_type,SpvId vector_1,SpvId vector_2,const uint32_t components[],size_t num_components)609 spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
610 SpvId vector_1, SpvId vector_2,
611 const uint32_t components[],
612 size_t num_components)
613 {
614 SpvId result = spirv_builder_new_id(b);
615
616 assert(num_components > 0);
617 int words = 5 + num_components;
618 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
619 spirv_buffer_emit_word(&b->instructions, SpvOpVectorShuffle | (words << 16));
620 spirv_buffer_emit_word(&b->instructions, result_type);
621 spirv_buffer_emit_word(&b->instructions, result);
622 spirv_buffer_emit_word(&b->instructions, vector_1);
623 spirv_buffer_emit_word(&b->instructions, vector_2);
624 for (int i = 0; i < num_components; ++i)
625 spirv_buffer_emit_word(&b->instructions, components[i]);
626 return result;
627 }
628
629 SpvId
spirv_builder_emit_vector_extract(struct spirv_builder * b,SpvId result_type,SpvId vector_1,uint32_t component)630 spirv_builder_emit_vector_extract(struct spirv_builder *b, SpvId result_type,
631 SpvId vector_1,
632 uint32_t component)
633 {
634 SpvId result = spirv_builder_new_id(b);
635
636 int words = 5;
637 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
638 spirv_buffer_emit_word(&b->instructions, SpvOpVectorExtractDynamic | (words << 16));
639 spirv_buffer_emit_word(&b->instructions, result_type);
640 spirv_buffer_emit_word(&b->instructions, result);
641 spirv_buffer_emit_word(&b->instructions, vector_1);
642 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, component));
643 return result;
644 }
645
646 SpvId
spirv_builder_emit_vector_insert(struct spirv_builder * b,SpvId result_type,SpvId vector_1,SpvId component,uint32_t index)647 spirv_builder_emit_vector_insert(struct spirv_builder *b, SpvId result_type,
648 SpvId vector_1,
649 SpvId component,
650 uint32_t index)
651 {
652 SpvId result = spirv_builder_new_id(b);
653
654 int words = 6;
655 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
656 spirv_buffer_emit_word(&b->instructions, SpvOpVectorInsertDynamic | (words << 16));
657 spirv_buffer_emit_word(&b->instructions, result_type);
658 spirv_buffer_emit_word(&b->instructions, result);
659 spirv_buffer_emit_word(&b->instructions, vector_1);
660 spirv_buffer_emit_word(&b->instructions, component);
661 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, index));
662 return result;
663 }
664
665 void
spirv_builder_emit_branch(struct spirv_builder * b,SpvId label)666 spirv_builder_emit_branch(struct spirv_builder *b, SpvId label)
667 {
668 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);
669 spirv_buffer_emit_word(&b->instructions, SpvOpBranch | (2 << 16));
670 spirv_buffer_emit_word(&b->instructions, label);
671 }
672
673 void
spirv_builder_emit_selection_merge(struct spirv_builder * b,SpvId merge_block,SpvSelectionControlMask selection_control)674 spirv_builder_emit_selection_merge(struct spirv_builder *b, SpvId merge_block,
675 SpvSelectionControlMask selection_control)
676 {
677 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
678 spirv_buffer_emit_word(&b->instructions, SpvOpSelectionMerge | (3 << 16));
679 spirv_buffer_emit_word(&b->instructions, merge_block);
680 spirv_buffer_emit_word(&b->instructions, selection_control);
681 }
682
683 void
spirv_builder_loop_merge(struct spirv_builder * b,SpvId merge_block,SpvId cont_target,SpvLoopControlMask loop_control)684 spirv_builder_loop_merge(struct spirv_builder *b, SpvId merge_block,
685 SpvId cont_target, SpvLoopControlMask loop_control)
686 {
687 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
688 spirv_buffer_emit_word(&b->instructions, SpvOpLoopMerge | (4 << 16));
689 spirv_buffer_emit_word(&b->instructions, merge_block);
690 spirv_buffer_emit_word(&b->instructions, cont_target);
691 spirv_buffer_emit_word(&b->instructions, loop_control);
692 }
693
694 void
spirv_builder_emit_branch_conditional(struct spirv_builder * b,SpvId condition,SpvId true_label,SpvId false_label)695 spirv_builder_emit_branch_conditional(struct spirv_builder *b, SpvId condition,
696 SpvId true_label, SpvId false_label)
697 {
698 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
699 spirv_buffer_emit_word(&b->instructions, SpvOpBranchConditional | (4 << 16));
700 spirv_buffer_emit_word(&b->instructions, condition);
701 spirv_buffer_emit_word(&b->instructions, true_label);
702 spirv_buffer_emit_word(&b->instructions, false_label);
703 }
704
705 SpvId
spirv_builder_emit_phi(struct spirv_builder * b,SpvId result_type,size_t num_vars,size_t * position)706 spirv_builder_emit_phi(struct spirv_builder *b, SpvId result_type,
707 size_t num_vars, size_t *position)
708 {
709 SpvId result = spirv_builder_new_id(b);
710
711 assert(num_vars > 0);
712 int words = 3 + 2 * num_vars;
713 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
714 spirv_buffer_emit_word(&b->instructions, SpvOpPhi | (words << 16));
715 spirv_buffer_emit_word(&b->instructions, result_type);
716 spirv_buffer_emit_word(&b->instructions, result);
717 *position = b->instructions.num_words;
718 for (int i = 0; i < 2 * num_vars; ++i)
719 spirv_buffer_emit_word(&b->instructions, 0);
720 return result;
721 }
722
723 void
spirv_builder_set_phi_operand(struct spirv_builder * b,size_t position,size_t index,SpvId variable,SpvId parent)724 spirv_builder_set_phi_operand(struct spirv_builder *b, size_t position,
725 size_t index, SpvId variable, SpvId parent)
726 {
727 b->instructions.words[position + index * 2 + 0] = variable;
728 b->instructions.words[position + index * 2 + 1] = parent;
729 }
730
731 void
spirv_builder_emit_kill(struct spirv_builder * b)732 spirv_builder_emit_kill(struct spirv_builder *b)
733 {
734 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
735 spirv_buffer_emit_word(&b->instructions, SpvOpKill | (1 << 16));
736 }
737
738 SpvId
spirv_builder_emit_vote(struct spirv_builder * b,SpvOp op,SpvId src)739 spirv_builder_emit_vote(struct spirv_builder *b, SpvOp op, SpvId src)
740 {
741 return spirv_builder_emit_binop(b, op, spirv_builder_type_bool(b),
742 spirv_builder_const_uint(b, 32, SpvScopeWorkgroup), src);
743 }
744
745 SpvId
spirv_builder_emit_image_sample(struct spirv_builder * b,SpvId result_type,SpvId sampled_image,SpvId coordinate,bool proj,SpvId lod,SpvId bias,SpvId dref,SpvId dx,SpvId dy,SpvId const_offset,SpvId offset)746 spirv_builder_emit_image_sample(struct spirv_builder *b,
747 SpvId result_type,
748 SpvId sampled_image,
749 SpvId coordinate,
750 bool proj,
751 SpvId lod,
752 SpvId bias,
753 SpvId dref,
754 SpvId dx,
755 SpvId dy,
756 SpvId const_offset,
757 SpvId offset)
758 {
759 SpvId result = spirv_builder_new_id(b);
760
761 int opcode = SpvOpImageSampleImplicitLod;
762 int operands = 5;
763 if (proj)
764 opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
765 if (lod || (dx && dy))
766 opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
767 if (dref) {
768 opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
769 operands++;
770 }
771
772 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
773 SpvId extra_operands[5];
774 int num_extra_operands = 1;
775 if (bias) {
776 extra_operands[num_extra_operands++] = bias;
777 operand_mask |= SpvImageOperandsBiasMask;
778 }
779 if (lod) {
780 extra_operands[num_extra_operands++] = lod;
781 operand_mask |= SpvImageOperandsLodMask;
782 } else if (dx && dy) {
783 extra_operands[num_extra_operands++] = dx;
784 extra_operands[num_extra_operands++] = dy;
785 operand_mask |= SpvImageOperandsGradMask;
786 }
787 assert(!(const_offset && offset));
788 if (const_offset) {
789 extra_operands[num_extra_operands++] = const_offset;
790 operand_mask |= SpvImageOperandsConstOffsetMask;
791 } else if (offset) {
792 extra_operands[num_extra_operands++] = offset;
793 operand_mask |= SpvImageOperandsOffsetMask;
794 }
795
796 /* finalize num_extra_operands / extra_operands */
797 extra_operands[0] = operand_mask;
798
799 spirv_buffer_prepare(&b->instructions, b->mem_ctx, operands + num_extra_operands);
800 spirv_buffer_emit_word(&b->instructions, opcode | ((operands + num_extra_operands) << 16));
801 spirv_buffer_emit_word(&b->instructions, result_type);
802 spirv_buffer_emit_word(&b->instructions, result);
803 spirv_buffer_emit_word(&b->instructions, sampled_image);
804 spirv_buffer_emit_word(&b->instructions, coordinate);
805 if (dref)
806 spirv_buffer_emit_word(&b->instructions, dref);
807 for (int i = 0; i < num_extra_operands; ++i)
808 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
809 return result;
810 }
811
812 SpvId
spirv_builder_emit_image(struct spirv_builder * b,SpvId result_type,SpvId sampled_image)813 spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
814 SpvId sampled_image)
815 {
816 SpvId result = spirv_builder_new_id(b);
817 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
818 spirv_buffer_emit_word(&b->instructions, SpvOpImage | (4 << 16));
819 spirv_buffer_emit_word(&b->instructions, result_type);
820 spirv_buffer_emit_word(&b->instructions, result);
821 spirv_buffer_emit_word(&b->instructions, sampled_image);
822 return result;
823 }
824
825 SpvId
spirv_builder_emit_image_texel_pointer(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId sample)826 spirv_builder_emit_image_texel_pointer(struct spirv_builder *b,
827 SpvId result_type,
828 SpvId image,
829 SpvId coordinate,
830 SpvId sample)
831 {
832 SpvId pointer_type = spirv_builder_type_pointer(b,
833 SpvStorageClassImage,
834 result_type);
835 return spirv_builder_emit_triop(b, SpvOpImageTexelPointer, pointer_type, image, coordinate, sample);
836 }
837
838 SpvId
spirv_builder_emit_image_read(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId lod,SpvId sample,SpvId offset)839 spirv_builder_emit_image_read(struct spirv_builder *b,
840 SpvId result_type,
841 SpvId image,
842 SpvId coordinate,
843 SpvId lod,
844 SpvId sample,
845 SpvId offset)
846 {
847 SpvId result = spirv_builder_new_id(b);
848
849 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
850 SpvId extra_operands[5];
851 int num_extra_operands = 1;
852 if (lod) {
853 extra_operands[num_extra_operands++] = lod;
854 operand_mask |= SpvImageOperandsLodMask;
855 }
856 if (sample) {
857 extra_operands[num_extra_operands++] = sample;
858 operand_mask |= SpvImageOperandsSampleMask;
859 }
860 if (offset) {
861 extra_operands[num_extra_operands++] = offset;
862 operand_mask |= SpvImageOperandsOffsetMask;
863 }
864 /* finalize num_extra_operands / extra_operands */
865 extra_operands[0] = operand_mask;
866
867 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
868 spirv_buffer_emit_word(&b->instructions, SpvOpImageRead |
869 ((5 + num_extra_operands) << 16));
870 spirv_buffer_emit_word(&b->instructions, result_type);
871 spirv_buffer_emit_word(&b->instructions, result);
872 spirv_buffer_emit_word(&b->instructions, image);
873 spirv_buffer_emit_word(&b->instructions, coordinate);
874 for (int i = 0; i < num_extra_operands; ++i)
875 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
876 return result;
877 }
878
879 void
spirv_builder_emit_image_write(struct spirv_builder * b,SpvId image,SpvId coordinate,SpvId texel,SpvId lod,SpvId sample,SpvId offset)880 spirv_builder_emit_image_write(struct spirv_builder *b,
881 SpvId image,
882 SpvId coordinate,
883 SpvId texel,
884 SpvId lod,
885 SpvId sample,
886 SpvId offset)
887 {
888 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
889 SpvId extra_operands[5];
890 int num_extra_operands = 1;
891 if (lod) {
892 extra_operands[num_extra_operands++] = lod;
893 operand_mask |= SpvImageOperandsLodMask;
894 }
895 if (sample) {
896 extra_operands[num_extra_operands++] = sample;
897 operand_mask |= SpvImageOperandsSampleMask;
898 }
899 if (offset) {
900 extra_operands[num_extra_operands++] = offset;
901 operand_mask |= SpvImageOperandsOffsetMask;
902 }
903 /* finalize num_extra_operands / extra_operands */
904 extra_operands[0] = operand_mask;
905
906 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4 + num_extra_operands);
907 spirv_buffer_emit_word(&b->instructions, SpvOpImageWrite |
908 ((4 + num_extra_operands) << 16));
909 spirv_buffer_emit_word(&b->instructions, image);
910 spirv_buffer_emit_word(&b->instructions, coordinate);
911 spirv_buffer_emit_word(&b->instructions, texel);
912 for (int i = 0; i < num_extra_operands; ++i)
913 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
914 }
915
916 SpvId
spirv_builder_emit_image_gather(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId component,SpvId lod,SpvId sample,SpvId const_offset,SpvId offset,SpvId dref)917 spirv_builder_emit_image_gather(struct spirv_builder *b,
918 SpvId result_type,
919 SpvId image,
920 SpvId coordinate,
921 SpvId component,
922 SpvId lod,
923 SpvId sample,
924 SpvId const_offset,
925 SpvId offset,
926 SpvId dref)
927 {
928 SpvId result = spirv_builder_new_id(b);
929 SpvId op = SpvOpImageGather;
930
931 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
932 SpvId extra_operands[4];
933 int num_extra_operands = 1;
934 if (lod) {
935 extra_operands[num_extra_operands++] = lod;
936 operand_mask |= SpvImageOperandsLodMask;
937 }
938 if (sample) {
939 extra_operands[num_extra_operands++] = sample;
940 operand_mask |= SpvImageOperandsSampleMask;
941 }
942 assert(!(const_offset && offset));
943 if (const_offset) {
944 extra_operands[num_extra_operands++] = const_offset;
945 operand_mask |= SpvImageOperandsConstOffsetMask;
946 } else if (offset) {
947 extra_operands[num_extra_operands++] = offset;
948 operand_mask |= SpvImageOperandsOffsetMask;
949 }
950 if (dref)
951 op = SpvOpImageDrefGather;
952 /* finalize num_extra_operands / extra_operands */
953 extra_operands[0] = operand_mask;
954
955 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6 + num_extra_operands);
956 spirv_buffer_emit_word(&b->instructions, op |
957 ((6 + num_extra_operands) << 16));
958 spirv_buffer_emit_word(&b->instructions, result_type);
959 spirv_buffer_emit_word(&b->instructions, result);
960 spirv_buffer_emit_word(&b->instructions, image);
961 spirv_buffer_emit_word(&b->instructions, coordinate);
962 if (dref)
963 spirv_buffer_emit_word(&b->instructions, dref);
964 else
965 spirv_buffer_emit_word(&b->instructions, component);
966 for (int i = 0; i < num_extra_operands; ++i)
967 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
968 return result;
969 }
970
971 SpvId
spirv_builder_emit_image_fetch(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId lod,SpvId sample,SpvId const_offset,SpvId offset)972 spirv_builder_emit_image_fetch(struct spirv_builder *b,
973 SpvId result_type,
974 SpvId image,
975 SpvId coordinate,
976 SpvId lod,
977 SpvId sample,
978 SpvId const_offset,
979 SpvId offset)
980 {
981 SpvId result = spirv_builder_new_id(b);
982
983 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
984 SpvId extra_operands[4];
985 int num_extra_operands = 1;
986 if (lod) {
987 extra_operands[num_extra_operands++] = lod;
988 operand_mask |= SpvImageOperandsLodMask;
989 }
990 if (sample) {
991 extra_operands[num_extra_operands++] = sample;
992 operand_mask |= SpvImageOperandsSampleMask;
993 }
994 assert(!(const_offset && offset));
995 if (const_offset) {
996 extra_operands[num_extra_operands++] = const_offset;
997 operand_mask |= SpvImageOperandsConstOffsetMask;
998 } else if (offset) {
999 extra_operands[num_extra_operands++] = offset;
1000 operand_mask |= SpvImageOperandsOffsetMask;
1001 }
1002
1003 /* finalize num_extra_operands / extra_operands */
1004 extra_operands[0] = operand_mask;
1005
1006 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
1007 spirv_buffer_emit_word(&b->instructions, SpvOpImageFetch |
1008 ((5 + num_extra_operands) << 16));
1009 spirv_buffer_emit_word(&b->instructions, result_type);
1010 spirv_buffer_emit_word(&b->instructions, result);
1011 spirv_buffer_emit_word(&b->instructions, image);
1012 spirv_buffer_emit_word(&b->instructions, coordinate);
1013 for (int i = 0; i < num_extra_operands; ++i)
1014 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
1015 return result;
1016 }
1017
1018 SpvId
spirv_builder_emit_image_query_size(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId lod)1019 spirv_builder_emit_image_query_size(struct spirv_builder *b,
1020 SpvId result_type,
1021 SpvId image,
1022 SpvId lod)
1023 {
1024 int opcode = SpvOpImageQuerySize;
1025 int words = 4;
1026 if (lod) {
1027 words++;
1028 opcode = SpvOpImageQuerySizeLod;
1029 }
1030
1031 SpvId result = spirv_builder_new_id(b);
1032 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1033 spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
1034 spirv_buffer_emit_word(&b->instructions, result_type);
1035 spirv_buffer_emit_word(&b->instructions, result);
1036 spirv_buffer_emit_word(&b->instructions, image);
1037
1038 if (lod)
1039 spirv_buffer_emit_word(&b->instructions, lod);
1040
1041 return result;
1042 }
1043
1044 SpvId
spirv_builder_emit_image_query_levels(struct spirv_builder * b,SpvId result_type,SpvId image)1045 spirv_builder_emit_image_query_levels(struct spirv_builder *b,
1046 SpvId result_type,
1047 SpvId image)
1048 {
1049 return spirv_builder_emit_unop(b, SpvOpImageQueryLevels, result_type, image);
1050 }
1051
1052 SpvId
spirv_builder_emit_image_query_lod(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coords)1053 spirv_builder_emit_image_query_lod(struct spirv_builder *b,
1054 SpvId result_type,
1055 SpvId image,
1056 SpvId coords)
1057 {
1058 int opcode = SpvOpImageQueryLod;
1059 int words = 5;
1060
1061 SpvId result = spirv_builder_new_id(b);
1062 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1063 spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
1064 spirv_buffer_emit_word(&b->instructions, result_type);
1065 spirv_buffer_emit_word(&b->instructions, result);
1066 spirv_buffer_emit_word(&b->instructions, image);
1067 spirv_buffer_emit_word(&b->instructions, coords);
1068
1069 return result;
1070 }
1071
1072 SpvId
spirv_builder_emit_ext_inst(struct spirv_builder * b,SpvId result_type,SpvId set,uint32_t instruction,const SpvId * args,size_t num_args)1073 spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
1074 SpvId set, uint32_t instruction,
1075 const SpvId *args, size_t num_args)
1076 {
1077 SpvId result = spirv_builder_new_id(b);
1078
1079 int words = 5 + num_args;
1080 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1081 spirv_buffer_emit_word(&b->instructions, SpvOpExtInst | (words << 16));
1082 spirv_buffer_emit_word(&b->instructions, result_type);
1083 spirv_buffer_emit_word(&b->instructions, result);
1084 spirv_buffer_emit_word(&b->instructions, set);
1085 spirv_buffer_emit_word(&b->instructions, instruction);
1086 for (int i = 0; i < num_args; ++i)
1087 spirv_buffer_emit_word(&b->instructions, args[i]);
1088 return result;
1089 }
1090
1091 struct spirv_type {
1092 SpvOp op;
1093 uint32_t args[8];
1094 size_t num_args;
1095
1096 SpvId type;
1097 };
1098
1099 static uint32_t
non_aggregate_type_hash(const void * arg)1100 non_aggregate_type_hash(const void *arg)
1101 {
1102 const struct spirv_type *type = arg;
1103
1104 uint32_t hash = 0;
1105 hash = XXH32(&type->op, sizeof(type->op), hash);
1106 hash = XXH32(type->args, sizeof(uint32_t) * type->num_args, hash);
1107 return hash;
1108 }
1109
1110 static bool
non_aggregate_type_equals(const void * a,const void * b)1111 non_aggregate_type_equals(const void *a, const void *b)
1112 {
1113 const struct spirv_type *ta = a, *tb = b;
1114
1115 if (ta->op != tb->op)
1116 return false;
1117
1118 assert(ta->num_args == tb->num_args);
1119 return memcmp(ta->args, tb->args, sizeof(uint32_t) * ta->num_args) == 0;
1120 }
1121
1122 static SpvId
get_type_def(struct spirv_builder * b,SpvOp op,const uint32_t args[],size_t num_args)1123 get_type_def(struct spirv_builder *b, SpvOp op, const uint32_t args[],
1124 size_t num_args)
1125 {
1126 /* According to the SPIR-V specification:
1127 *
1128 * "Two different type <id>s form, by definition, two different types. It
1129 * is valid to declare multiple aggregate type <id>s having the same
1130 * opcode and operands. This is to allow multiple instances of aggregate
1131 * types with the same structure to be decorated differently. (Different
1132 * decorations are not required; two different aggregate type <id>s are
1133 * allowed to have identical declarations and decorations, and will still
1134 * be two different types.) Non-aggregate types are different: It is
1135 * invalid to declare multiple type <id>s for the same scalar, vector, or
1136 * matrix type. That is, non-aggregate type declarations must all have
1137 * different opcodes or operands. (Note that non-aggregate types cannot
1138 * be decorated in ways that affect their type.)"
1139 *
1140 * ..so, we need to prevent the same non-aggregate type to be re-defined
1141 * with a new <id>. We do this by putting the definitions in a hash-map, so
1142 * we can easily look up and reuse them.
1143 */
1144
1145 struct spirv_type key;
1146 assert(num_args <= ARRAY_SIZE(key.args));
1147 key.op = op;
1148 memcpy(&key.args, args, sizeof(uint32_t) * num_args);
1149 key.num_args = num_args;
1150
1151 struct hash_entry *entry;
1152 if (b->types) {
1153 entry = _mesa_hash_table_search(b->types, &key);
1154 if (entry)
1155 return ((struct spirv_type *)entry->data)->type;
1156 } else {
1157 b->types = _mesa_hash_table_create(b->mem_ctx,
1158 non_aggregate_type_hash,
1159 non_aggregate_type_equals);
1160 assert(b->types);
1161 }
1162
1163 struct spirv_type *type = rzalloc(b->mem_ctx, struct spirv_type);
1164 if (!type)
1165 return 0;
1166
1167 type->op = op;
1168 memcpy(&type->args, args, sizeof(uint32_t) * num_args);
1169 type->num_args = num_args;
1170
1171 type->type = spirv_builder_new_id(b);
1172 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 2 + num_args);
1173 spirv_buffer_emit_word(&b->types_const_defs, op | ((2 + num_args) << 16));
1174 spirv_buffer_emit_word(&b->types_const_defs, type->type);
1175 for (int i = 0; i < num_args; ++i)
1176 spirv_buffer_emit_word(&b->types_const_defs, args[i]);
1177
1178 entry = _mesa_hash_table_insert(b->types, type, type);
1179 assert(entry);
1180
1181 return ((struct spirv_type *)entry->data)->type;
1182 }
1183
1184 SpvId
spirv_builder_type_void(struct spirv_builder * b)1185 spirv_builder_type_void(struct spirv_builder *b)
1186 {
1187 return get_type_def(b, SpvOpTypeVoid, NULL, 0);
1188 }
1189
1190 SpvId
spirv_builder_type_bool(struct spirv_builder * b)1191 spirv_builder_type_bool(struct spirv_builder *b)
1192 {
1193 return get_type_def(b, SpvOpTypeBool, NULL, 0);
1194 }
1195
1196 SpvId
spirv_builder_type_int(struct spirv_builder * b,unsigned width)1197 spirv_builder_type_int(struct spirv_builder *b, unsigned width)
1198 {
1199 uint32_t args[] = { width, 1 };
1200 return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
1201 }
1202
1203 SpvId
spirv_builder_type_uint(struct spirv_builder * b,unsigned width)1204 spirv_builder_type_uint(struct spirv_builder *b, unsigned width)
1205 {
1206 uint32_t args[] = { width, 0 };
1207 return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
1208 }
1209
1210 SpvId
spirv_builder_type_float(struct spirv_builder * b,unsigned width)1211 spirv_builder_type_float(struct spirv_builder *b, unsigned width)
1212 {
1213 uint32_t args[] = { width };
1214 return get_type_def(b, SpvOpTypeFloat, args, ARRAY_SIZE(args));
1215 }
1216
1217 SpvId
spirv_builder_type_image(struct spirv_builder * b,SpvId sampled_type,SpvDim dim,bool depth,bool arrayed,bool ms,unsigned sampled,SpvImageFormat image_format)1218 spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,
1219 SpvDim dim, bool depth, bool arrayed, bool ms,
1220 unsigned sampled, SpvImageFormat image_format)
1221 {
1222 assert(sampled < 3);
1223 uint32_t args[] = {
1224 sampled_type, dim, depth ? 1 : 0, arrayed ? 1 : 0, ms ? 1 : 0, sampled,
1225 image_format
1226 };
1227 if (sampled == 2 && ms)
1228 spirv_builder_emit_cap(b, SpvCapabilityStorageImageMultisample);
1229 return get_type_def(b, SpvOpTypeImage, args, ARRAY_SIZE(args));
1230 }
1231
1232 SpvId
spirv_builder_type_sampled_image(struct spirv_builder * b,SpvId image_type)1233 spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type)
1234 {
1235 uint32_t args[] = { image_type };
1236 return get_type_def(b, SpvOpTypeSampledImage, args, ARRAY_SIZE(args));
1237 }
1238
1239 SpvId
spirv_builder_type_pointer(struct spirv_builder * b,SpvStorageClass storage_class,SpvId type)1240 spirv_builder_type_pointer(struct spirv_builder *b,
1241 SpvStorageClass storage_class, SpvId type)
1242 {
1243 uint32_t args[] = { storage_class, type };
1244 return get_type_def(b, SpvOpTypePointer, args, ARRAY_SIZE(args));
1245 }
1246
1247 SpvId
spirv_builder_type_vector(struct spirv_builder * b,SpvId component_type,unsigned component_count)1248 spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,
1249 unsigned component_count)
1250 {
1251 assert(component_count > 1);
1252 uint32_t args[] = { component_type, component_count };
1253 return get_type_def(b, SpvOpTypeVector, args, ARRAY_SIZE(args));
1254 }
1255
1256 SpvId
spirv_builder_type_matrix(struct spirv_builder * b,SpvId component_type,unsigned component_count)1257 spirv_builder_type_matrix(struct spirv_builder *b, SpvId component_type,
1258 unsigned component_count)
1259 {
1260 assert(component_count > 1);
1261 uint32_t args[] = { component_type, component_count };
1262 return get_type_def(b, SpvOpTypeMatrix, args, ARRAY_SIZE(args));
1263 }
1264
1265 SpvId
spirv_builder_type_runtime_array(struct spirv_builder * b,SpvId component_type)1266 spirv_builder_type_runtime_array(struct spirv_builder *b, SpvId component_type)
1267 {
1268 SpvId type = spirv_builder_new_id(b);
1269 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3);
1270 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeRuntimeArray | (3 << 16));
1271 spirv_buffer_emit_word(&b->types_const_defs, type);
1272 spirv_buffer_emit_word(&b->types_const_defs, component_type);
1273 return type;
1274 }
1275
1276 SpvId
spirv_builder_type_array(struct spirv_builder * b,SpvId component_type,SpvId length)1277 spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,
1278 SpvId length)
1279 {
1280 SpvId type = spirv_builder_new_id(b);
1281 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 4);
1282 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeArray | (4 << 16));
1283 spirv_buffer_emit_word(&b->types_const_defs, type);
1284 spirv_buffer_emit_word(&b->types_const_defs, component_type);
1285 spirv_buffer_emit_word(&b->types_const_defs, length);
1286 return type;
1287 }
1288
1289 SpvId
spirv_builder_type_struct(struct spirv_builder * b,const SpvId member_types[],size_t num_member_types)1290 spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],
1291 size_t num_member_types)
1292 {
1293 int words = 2 + num_member_types;
1294 SpvId type = spirv_builder_new_id(b);
1295 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1296 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeStruct | (words << 16));
1297 spirv_buffer_emit_word(&b->types_const_defs, type);
1298 for (int i = 0; i < num_member_types; ++i)
1299 spirv_buffer_emit_word(&b->types_const_defs, member_types[i]);
1300 return type;
1301 }
1302
1303 SpvId
spirv_builder_type_function(struct spirv_builder * b,SpvId return_type,const SpvId parameter_types[],size_t num_parameter_types)1304 spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,
1305 const SpvId parameter_types[],
1306 size_t num_parameter_types)
1307 {
1308 int words = 3 + num_parameter_types;
1309 SpvId type = spirv_builder_new_id(b);
1310 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1311 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeFunction | (words << 16));
1312 spirv_buffer_emit_word(&b->types_const_defs, type);
1313 spirv_buffer_emit_word(&b->types_const_defs, return_type);
1314 for (int i = 0; i < num_parameter_types; ++i)
1315 spirv_buffer_emit_word(&b->types_const_defs, parameter_types[i]);
1316 return type;
1317 }
1318
1319 struct spirv_const {
1320 SpvOp op, type;
1321 uint32_t args[8];
1322 size_t num_args;
1323
1324 SpvId result;
1325 };
1326
1327 static uint32_t
const_hash(const void * arg)1328 const_hash(const void *arg)
1329 {
1330 const struct spirv_const *key = arg;
1331
1332 uint32_t hash = 0;
1333 hash = XXH32(&key->op, sizeof(key->op), hash);
1334 hash = XXH32(&key->type, sizeof(key->type), hash);
1335 hash = XXH32(key->args, sizeof(uint32_t) * key->num_args, hash);
1336 return hash;
1337 }
1338
1339 static bool
const_equals(const void * a,const void * b)1340 const_equals(const void *a, const void *b)
1341 {
1342 const struct spirv_const *ca = a, *cb = b;
1343
1344 if (ca->op != cb->op ||
1345 ca->type != cb->type)
1346 return false;
1347
1348 assert(ca->num_args == cb->num_args);
1349 return memcmp(ca->args, cb->args, sizeof(uint32_t) * ca->num_args) == 0;
1350 }
1351
1352 static SpvId
get_const_def(struct spirv_builder * b,SpvOp op,SpvId type,const uint32_t args[],size_t num_args)1353 get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,
1354 const uint32_t args[], size_t num_args)
1355 {
1356 struct spirv_const key;
1357 assert(num_args <= ARRAY_SIZE(key.args));
1358 key.op = op;
1359 key.type = type;
1360 memcpy(&key.args, args, sizeof(uint32_t) * num_args);
1361 key.num_args = num_args;
1362
1363 struct hash_entry *entry;
1364 if (b->consts) {
1365 entry = _mesa_hash_table_search(b->consts, &key);
1366 if (entry)
1367 return ((struct spirv_const *)entry->data)->result;
1368 } else {
1369 b->consts = _mesa_hash_table_create(b->mem_ctx, const_hash,
1370 const_equals);
1371 assert(b->consts);
1372 }
1373
1374 struct spirv_const *cnst = rzalloc(b->mem_ctx, struct spirv_const);
1375 if (!cnst)
1376 return 0;
1377
1378 cnst->op = op;
1379 cnst->type = type;
1380 memcpy(&cnst->args, args, sizeof(uint32_t) * num_args);
1381 cnst->num_args = num_args;
1382
1383 cnst->result = spirv_builder_new_id(b);
1384 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3 + num_args);
1385 spirv_buffer_emit_word(&b->types_const_defs, op | ((3 + num_args) << 16));
1386 spirv_buffer_emit_word(&b->types_const_defs, type);
1387 spirv_buffer_emit_word(&b->types_const_defs, cnst->result);
1388 for (int i = 0; i < num_args; ++i)
1389 spirv_buffer_emit_word(&b->types_const_defs, args[i]);
1390
1391 entry = _mesa_hash_table_insert(b->consts, cnst, cnst);
1392 assert(entry);
1393
1394 return ((struct spirv_const *)entry->data)->result;
1395 }
1396
1397 static SpvId
emit_constant_32(struct spirv_builder * b,SpvId type,uint32_t val)1398 emit_constant_32(struct spirv_builder *b, SpvId type, uint32_t val)
1399 {
1400 uint32_t args[] = { val };
1401 return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));
1402 }
1403
1404 static SpvId
emit_constant_64(struct spirv_builder * b,SpvId type,uint64_t val)1405 emit_constant_64(struct spirv_builder *b, SpvId type, uint64_t val)
1406 {
1407 uint32_t args[] = { val & UINT32_MAX, val >> 32 };
1408 return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));
1409 }
1410
1411 SpvId
spirv_builder_const_bool(struct spirv_builder * b,bool val)1412 spirv_builder_const_bool(struct spirv_builder *b, bool val)
1413 {
1414 return get_const_def(b, val ? SpvOpConstantTrue : SpvOpConstantFalse,
1415 spirv_builder_type_bool(b), NULL, 0);
1416 }
1417
1418 SpvId
spirv_builder_const_int(struct spirv_builder * b,int width,int64_t val)1419 spirv_builder_const_int(struct spirv_builder *b, int width, int64_t val)
1420 {
1421 assert(width >= 16);
1422 SpvId type = spirv_builder_type_int(b, width);
1423 if (width <= 32)
1424 return emit_constant_32(b, type, val);
1425 else
1426 return emit_constant_64(b, type, val);
1427 }
1428
1429 SpvId
spirv_builder_const_uint(struct spirv_builder * b,int width,uint64_t val)1430 spirv_builder_const_uint(struct spirv_builder *b, int width, uint64_t val)
1431 {
1432 assert(width >= 8);
1433 SpvId type = spirv_builder_type_uint(b, width);
1434 if (width <= 32)
1435 return emit_constant_32(b, type, val);
1436 else
1437 return emit_constant_64(b, type, val);
1438 }
1439
1440 SpvId
spirv_builder_spec_const_uint(struct spirv_builder * b,int width)1441 spirv_builder_spec_const_uint(struct spirv_builder *b, int width)
1442 {
1443 assert(width <= 32);
1444 return spirv_builder_emit_unop(b, SpvOpSpecConstant, spirv_builder_type_uint(b, width), 0);
1445 }
1446
1447 SpvId
spirv_builder_const_float(struct spirv_builder * b,int width,double val)1448 spirv_builder_const_float(struct spirv_builder *b, int width, double val)
1449 {
1450 assert(width >= 16);
1451 SpvId type = spirv_builder_type_float(b, width);
1452 if (width == 16)
1453 return emit_constant_32(b, type, _mesa_float_to_half(val));
1454 else if (width == 32)
1455 return emit_constant_32(b, type, u_bitcast_f2u(val));
1456 else if (width == 64)
1457 return emit_constant_64(b, type, u_bitcast_d2u(val));
1458
1459 unreachable("unhandled float-width");
1460 }
1461
1462 SpvId
spirv_builder_const_composite(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)1463 spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,
1464 const SpvId constituents[],
1465 size_t num_constituents)
1466 {
1467 return get_const_def(b, SpvOpConstantComposite, result_type,
1468 (const uint32_t *)constituents,
1469 num_constituents);
1470 }
1471
1472 SpvId
spirv_builder_spec_const_composite(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)1473 spirv_builder_spec_const_composite(struct spirv_builder *b, SpvId result_type,
1474 const SpvId constituents[],
1475 size_t num_constituents)
1476 {
1477 SpvId result = spirv_builder_new_id(b);
1478
1479 assert(num_constituents > 0);
1480 int words = 3 + num_constituents;
1481 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1482 spirv_buffer_emit_word(&b->instructions,
1483 SpvOpSpecConstantComposite | (words << 16));
1484 spirv_buffer_emit_word(&b->instructions, result_type);
1485 spirv_buffer_emit_word(&b->instructions, result);
1486 for (int i = 0; i < num_constituents; ++i)
1487 spirv_buffer_emit_word(&b->instructions, constituents[i]);
1488 return result;
1489 }
1490
1491 SpvId
spirv_builder_emit_var(struct spirv_builder * b,SpvId type,SpvStorageClass storage_class)1492 spirv_builder_emit_var(struct spirv_builder *b, SpvId type,
1493 SpvStorageClass storage_class)
1494 {
1495 assert(storage_class != SpvStorageClassGeneric);
1496 struct spirv_buffer *buf = storage_class != SpvStorageClassFunction ?
1497 &b->types_const_defs : &b->instructions;
1498
1499 SpvId ret = spirv_builder_new_id(b);
1500 spirv_buffer_prepare(buf, b->mem_ctx, 4);
1501 spirv_buffer_emit_word(buf, SpvOpVariable | (4 << 16));
1502 spirv_buffer_emit_word(buf, type);
1503 spirv_buffer_emit_word(buf, ret);
1504 spirv_buffer_emit_word(buf, storage_class);
1505 return ret;
1506 }
1507
1508 void
spirv_builder_emit_memory_barrier(struct spirv_builder * b,SpvScope scope,SpvMemorySemanticsMask semantics)1509 spirv_builder_emit_memory_barrier(struct spirv_builder *b, SpvScope scope, SpvMemorySemanticsMask semantics)
1510 {
1511 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
1512 spirv_buffer_emit_word(&b->instructions, SpvOpMemoryBarrier | (3 << 16));
1513 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1514 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1515 }
1516
1517 void
spirv_builder_emit_control_barrier(struct spirv_builder * b,SpvScope scope,SpvScope mem_scope,SpvMemorySemanticsMask semantics)1518 spirv_builder_emit_control_barrier(struct spirv_builder *b, SpvScope scope, SpvScope mem_scope, SpvMemorySemanticsMask semantics)
1519 {
1520 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
1521 spirv_buffer_emit_word(&b->instructions, SpvOpControlBarrier | (4 << 16));
1522 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1523 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, mem_scope));
1524 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1525 }
1526
1527 SpvId
spirv_builder_import(struct spirv_builder * b,const char * name)1528 spirv_builder_import(struct spirv_builder *b, const char *name)
1529 {
1530 SpvId result = spirv_builder_new_id(b);
1531 size_t pos = b->imports.num_words;
1532 spirv_buffer_prepare(&b->imports, b->mem_ctx, 2);
1533 spirv_buffer_emit_word(&b->imports, SpvOpExtInstImport);
1534 spirv_buffer_emit_word(&b->imports, result);
1535 int len = spirv_buffer_emit_string(&b->imports, b->mem_ctx, name);
1536 b->imports.words[pos] |= (2 + len) << 16;
1537 return result;
1538 }
1539
1540 size_t
spirv_builder_get_num_words(struct spirv_builder * b)1541 spirv_builder_get_num_words(struct spirv_builder *b)
1542 {
1543 const size_t header_size = 5;
1544 const size_t caps_size = b->caps ? b->caps->entries * 2 : 0;
1545 return header_size + caps_size +
1546 b->extensions.num_words +
1547 b->imports.num_words +
1548 b->memory_model.num_words +
1549 b->entry_points.num_words +
1550 b->exec_modes.num_words +
1551 b->debug_names.num_words +
1552 b->decorations.num_words +
1553 b->types_const_defs.num_words +
1554 b->instructions.num_words;
1555 }
1556
1557 size_t
spirv_builder_get_words(struct spirv_builder * b,uint32_t * words,size_t num_words,uint32_t spirv_version)1558 spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
1559 size_t num_words, uint32_t spirv_version)
1560 {
1561 assert(num_words >= spirv_builder_get_num_words(b));
1562
1563 size_t written = 0;
1564 words[written++] = SpvMagicNumber;
1565 words[written++] = spirv_version;
1566 words[written++] = 0;
1567 words[written++] = b->prev_id + 1;
1568 words[written++] = 0;
1569
1570 if (b->caps) {
1571 set_foreach(b->caps, entry) {
1572 words[written++] = SpvOpCapability | (2 << 16);
1573 words[written++] = (uintptr_t)entry->key;
1574 }
1575 }
1576
1577 const struct spirv_buffer *buffers[] = {
1578 &b->extensions,
1579 &b->imports,
1580 &b->memory_model,
1581 &b->entry_points,
1582 &b->exec_modes,
1583 &b->debug_names,
1584 &b->decorations,
1585 &b->types_const_defs,
1586 &b->instructions
1587 };
1588
1589 for (int i = 0; i < ARRAY_SIZE(buffers); ++i) {
1590 const struct spirv_buffer *buffer = buffers[i];
1591 for (int j = 0; j < buffer->num_words; ++j)
1592 words[written++] = buffer->words[j];
1593 }
1594
1595 assert(written == spirv_builder_get_num_words(b));
1596 return written;
1597 }
1598