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