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,const struct spriv_tex_src * src)869 spirv_builder_emit_image_sample(struct spirv_builder *b,
870 SpvId result_type,
871 SpvId sampled_image,
872 const struct spriv_tex_src *src)
873 {
874 SpvId result = spirv_builder_new_id(b);
875
876 bool proj = src->proj != 0;
877
878 int operands = 5;
879 int opcode;
880 if (src->sparse) {
881 opcode = SpvOpImageSparseSampleImplicitLod;
882 if (proj)
883 opcode += SpvOpImageSparseSampleProjImplicitLod - SpvOpImageSparseSampleImplicitLod;
884 if (src->lod || (src->dx && src->dy))
885 opcode += SpvOpImageSparseSampleExplicitLod - SpvOpImageSparseSampleImplicitLod;
886 if (src->dref) {
887 opcode += SpvOpImageSparseSampleDrefImplicitLod - SpvOpImageSparseSampleImplicitLod;
888 operands++;
889 }
890 result_type = sparse_wrap_result_type(b, result_type);
891 } else {
892 opcode = SpvOpImageSampleImplicitLod;
893 if (proj)
894 opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
895 if (src->lod || (src->dx && src->dy))
896 opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
897 if (src->dref) {
898 opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
899 operands++;
900 }
901 }
902
903 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
904 SpvId extra_operands[6];
905 int num_extra_operands = 1;
906 if (src->bias) {
907 extra_operands[num_extra_operands++] = src->bias;
908 operand_mask |= SpvImageOperandsBiasMask;
909 }
910 if (src->lod) {
911 extra_operands[num_extra_operands++] = src->lod;
912 operand_mask |= SpvImageOperandsLodMask;
913 } else if (src->dx && src->dy) {
914 extra_operands[num_extra_operands++] = src->dx;
915 extra_operands[num_extra_operands++] = src->dy;
916 operand_mask |= SpvImageOperandsGradMask;
917 }
918 assert(!(src->const_offset && src->offset));
919 if (src->const_offset) {
920 extra_operands[num_extra_operands++] = src->const_offset;
921 operand_mask |= SpvImageOperandsConstOffsetMask;
922 } else if (src->offset) {
923 extra_operands[num_extra_operands++] = src->offset;
924 operand_mask |= SpvImageOperandsOffsetMask;
925 }
926 if (src->min_lod) {
927 extra_operands[num_extra_operands++] = src->min_lod;
928 operand_mask |= SpvImageOperandsMinLodMask;
929 }
930
931 /* finalize num_extra_operands / extra_operands */
932 extra_operands[0] = operand_mask;
933
934 spirv_buffer_prepare(&b->instructions, b->mem_ctx, operands + num_extra_operands);
935 spirv_buffer_emit_word(&b->instructions, opcode | ((operands + num_extra_operands) << 16));
936 spirv_buffer_emit_word(&b->instructions, result_type);
937 spirv_buffer_emit_word(&b->instructions, result);
938 spirv_buffer_emit_word(&b->instructions, sampled_image);
939 spirv_buffer_emit_word(&b->instructions, src->coord);
940 if (src->dref)
941 spirv_buffer_emit_word(&b->instructions, src->dref);
942 for (int i = 0; i < num_extra_operands; ++i)
943 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
944 return result;
945 }
946
947 SpvId
spirv_builder_emit_image(struct spirv_builder * b,SpvId result_type,SpvId sampled_image)948 spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
949 SpvId sampled_image)
950 {
951 SpvId result = spirv_builder_new_id(b);
952 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
953 spirv_buffer_emit_word(&b->instructions, SpvOpImage | (4 << 16));
954 spirv_buffer_emit_word(&b->instructions, result_type);
955 spirv_buffer_emit_word(&b->instructions, result);
956 spirv_buffer_emit_word(&b->instructions, sampled_image);
957 return result;
958 }
959
960 SpvId
spirv_builder_emit_image_texel_pointer(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId sample)961 spirv_builder_emit_image_texel_pointer(struct spirv_builder *b,
962 SpvId result_type,
963 SpvId image,
964 SpvId coordinate,
965 SpvId sample)
966 {
967 SpvId pointer_type = spirv_builder_type_pointer(b,
968 SpvStorageClassImage,
969 result_type);
970 return spirv_builder_emit_triop(b, SpvOpImageTexelPointer, pointer_type, image, coordinate, sample);
971 }
972
973 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)974 spirv_builder_emit_image_read(struct spirv_builder *b,
975 SpvId result_type,
976 SpvId image,
977 SpvId coordinate,
978 SpvId lod,
979 SpvId sample,
980 SpvId offset,
981 bool sparse)
982 {
983 SpvId result = spirv_builder_new_id(b);
984
985 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
986 SpvId extra_operands[5];
987 int num_extra_operands = 1;
988 if (sparse)
989 result_type = sparse_wrap_result_type(b, result_type);
990 if (lod) {
991 extra_operands[num_extra_operands++] = lod;
992 operand_mask |= SpvImageOperandsLodMask;
993 }
994 if (sample) {
995 extra_operands[num_extra_operands++] = sample;
996 operand_mask |= SpvImageOperandsSampleMask;
997 }
998 if (offset) {
999 extra_operands[num_extra_operands++] = offset;
1000 operand_mask |= SpvImageOperandsOffsetMask;
1001 }
1002 /* finalize num_extra_operands / extra_operands */
1003 extra_operands[0] = operand_mask;
1004
1005 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
1006 spirv_buffer_emit_word(&b->instructions, (sparse ? SpvOpImageSparseRead : SpvOpImageRead) |
1007 ((5 + num_extra_operands) << 16));
1008 spirv_buffer_emit_word(&b->instructions, result_type);
1009 spirv_buffer_emit_word(&b->instructions, result);
1010 spirv_buffer_emit_word(&b->instructions, image);
1011 spirv_buffer_emit_word(&b->instructions, coordinate);
1012 for (int i = 0; i < num_extra_operands; ++i)
1013 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
1014 return result;
1015 }
1016
1017 void
spirv_builder_emit_image_write(struct spirv_builder * b,SpvId image,SpvId coordinate,SpvId texel,SpvId lod,SpvId sample,SpvId offset)1018 spirv_builder_emit_image_write(struct spirv_builder *b,
1019 SpvId image,
1020 SpvId coordinate,
1021 SpvId texel,
1022 SpvId lod,
1023 SpvId sample,
1024 SpvId offset)
1025 {
1026 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
1027 SpvId extra_operands[5];
1028 int num_extra_operands = 1;
1029 if (lod) {
1030 extra_operands[num_extra_operands++] = lod;
1031 operand_mask |= SpvImageOperandsLodMask;
1032 }
1033 if (sample) {
1034 extra_operands[num_extra_operands++] = sample;
1035 operand_mask |= SpvImageOperandsSampleMask;
1036 }
1037 if (offset) {
1038 extra_operands[num_extra_operands++] = offset;
1039 operand_mask |= SpvImageOperandsOffsetMask;
1040 }
1041 /* finalize num_extra_operands / extra_operands */
1042 extra_operands[0] = operand_mask;
1043
1044 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4 + num_extra_operands);
1045 spirv_buffer_emit_word(&b->instructions, SpvOpImageWrite |
1046 ((4 + num_extra_operands) << 16));
1047 spirv_buffer_emit_word(&b->instructions, image);
1048 spirv_buffer_emit_word(&b->instructions, coordinate);
1049 spirv_buffer_emit_word(&b->instructions, texel);
1050 for (int i = 0; i < num_extra_operands; ++i)
1051 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
1052 }
1053
1054 SpvId
spirv_builder_emit_image_gather(struct spirv_builder * b,SpvId result_type,SpvId image,const struct spriv_tex_src * src,SpvId component)1055 spirv_builder_emit_image_gather(struct spirv_builder *b,
1056 SpvId result_type,
1057 SpvId image,
1058 const struct spriv_tex_src *src,
1059 SpvId component)
1060 {
1061 SpvId result = spirv_builder_new_id(b);
1062 SpvId op = src->sparse ? SpvOpImageSparseGather : SpvOpImageGather;
1063
1064 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
1065 SpvId extra_operands[4];
1066 int num_extra_operands = 1;
1067 if (src->lod) {
1068 extra_operands[num_extra_operands++] = src->lod;
1069 operand_mask |= SpvImageOperandsLodMask;
1070 }
1071 if (src->sample) {
1072 extra_operands[num_extra_operands++] = src->sample;
1073 operand_mask |= SpvImageOperandsSampleMask;
1074 }
1075 assert(!(src->const_offset && src->offset));
1076 if (src->const_offset) {
1077 extra_operands[num_extra_operands++] = src->const_offset;
1078 operand_mask |= SpvImageOperandsConstOffsetMask;
1079 } else if (src->offset) {
1080 extra_operands[num_extra_operands++] = src->offset;
1081 operand_mask |= SpvImageOperandsOffsetMask;
1082 }
1083 if (src->dref)
1084 op = src->sparse ? SpvOpImageSparseDrefGather : SpvOpImageDrefGather;
1085 if (src->sparse)
1086 result_type = sparse_wrap_result_type(b, result_type);
1087 /* finalize num_extra_operands / extra_operands */
1088 extra_operands[0] = operand_mask;
1089
1090 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6 + num_extra_operands);
1091 spirv_buffer_emit_word(&b->instructions, op |
1092 ((6 + num_extra_operands) << 16));
1093 spirv_buffer_emit_word(&b->instructions, result_type);
1094 spirv_buffer_emit_word(&b->instructions, result);
1095 spirv_buffer_emit_word(&b->instructions, image);
1096 spirv_buffer_emit_word(&b->instructions, src->coord);
1097 if (src->dref)
1098 spirv_buffer_emit_word(&b->instructions, src->dref);
1099 else
1100 spirv_buffer_emit_word(&b->instructions, component);
1101 for (int i = 0; i < num_extra_operands; ++i)
1102 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
1103 return result;
1104 }
1105
1106 SpvId
spirv_builder_emit_image_fetch(struct spirv_builder * b,SpvId result_type,SpvId image,const struct spriv_tex_src * src)1107 spirv_builder_emit_image_fetch(struct spirv_builder *b,
1108 SpvId result_type,
1109 SpvId image,
1110 const struct spriv_tex_src *src)
1111 {
1112 SpvId result = spirv_builder_new_id(b);
1113
1114 SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
1115 SpvId extra_operands[4];
1116 int num_extra_operands = 1;
1117 if (src->lod) {
1118 extra_operands[num_extra_operands++] = src->lod;
1119 operand_mask |= SpvImageOperandsLodMask;
1120 }
1121 if (src->sample) {
1122 extra_operands[num_extra_operands++] = src->sample;
1123 operand_mask |= SpvImageOperandsSampleMask;
1124 }
1125 assert(!(src->const_offset && src->offset));
1126 if (src->const_offset) {
1127 extra_operands[num_extra_operands++] = src->const_offset;
1128 operand_mask |= SpvImageOperandsConstOffsetMask;
1129 } else if (src->offset) {
1130 extra_operands[num_extra_operands++] = src->offset;
1131 operand_mask |= SpvImageOperandsOffsetMask;
1132 }
1133 if (src->sparse)
1134 result_type = sparse_wrap_result_type(b, result_type);
1135
1136 /* finalize num_extra_operands / extra_operands */
1137 extra_operands[0] = operand_mask;
1138
1139 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
1140 spirv_buffer_emit_word(&b->instructions, (src->sparse ? SpvOpImageSparseFetch : SpvOpImageFetch) |
1141 ((5 + num_extra_operands) << 16));
1142 spirv_buffer_emit_word(&b->instructions, result_type);
1143 spirv_buffer_emit_word(&b->instructions, result);
1144 spirv_buffer_emit_word(&b->instructions, image);
1145 spirv_buffer_emit_word(&b->instructions, src->coord);
1146 for (int i = 0; i < num_extra_operands; ++i)
1147 spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
1148 return result;
1149 }
1150
1151 SpvId
spirv_builder_emit_image_query_size(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId lod)1152 spirv_builder_emit_image_query_size(struct spirv_builder *b,
1153 SpvId result_type,
1154 SpvId image,
1155 SpvId lod)
1156 {
1157 int opcode = SpvOpImageQuerySize;
1158 int words = 4;
1159 if (lod) {
1160 words++;
1161 opcode = SpvOpImageQuerySizeLod;
1162 }
1163
1164 SpvId result = spirv_builder_new_id(b);
1165 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1166 spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
1167 spirv_buffer_emit_word(&b->instructions, result_type);
1168 spirv_buffer_emit_word(&b->instructions, result);
1169 spirv_buffer_emit_word(&b->instructions, image);
1170
1171 if (lod)
1172 spirv_buffer_emit_word(&b->instructions, lod);
1173
1174 return result;
1175 }
1176
1177 SpvId
spirv_builder_emit_image_query_levels(struct spirv_builder * b,SpvId result_type,SpvId image)1178 spirv_builder_emit_image_query_levels(struct spirv_builder *b,
1179 SpvId result_type,
1180 SpvId image)
1181 {
1182 return spirv_builder_emit_unop(b, SpvOpImageQueryLevels, result_type, image);
1183 }
1184
1185 SpvId
spirv_builder_emit_image_query_lod(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coords)1186 spirv_builder_emit_image_query_lod(struct spirv_builder *b,
1187 SpvId result_type,
1188 SpvId image,
1189 SpvId coords)
1190 {
1191 int opcode = SpvOpImageQueryLod;
1192 int words = 5;
1193
1194 SpvId result = spirv_builder_new_id(b);
1195 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1196 spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
1197 spirv_buffer_emit_word(&b->instructions, result_type);
1198 spirv_buffer_emit_word(&b->instructions, result);
1199 spirv_buffer_emit_word(&b->instructions, image);
1200 spirv_buffer_emit_word(&b->instructions, coords);
1201
1202 return result;
1203 }
1204
1205 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)1206 spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
1207 SpvId set, uint32_t instruction,
1208 const SpvId *args, size_t num_args)
1209 {
1210 SpvId result = spirv_builder_new_id(b);
1211
1212 int words = 5 + num_args;
1213 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1214 spirv_buffer_emit_word(&b->instructions, SpvOpExtInst | (words << 16));
1215 spirv_buffer_emit_word(&b->instructions, result_type);
1216 spirv_buffer_emit_word(&b->instructions, result);
1217 spirv_buffer_emit_word(&b->instructions, set);
1218 spirv_buffer_emit_word(&b->instructions, instruction);
1219 for (int i = 0; i < num_args; ++i)
1220 spirv_buffer_emit_word(&b->instructions, args[i]);
1221 return result;
1222 }
1223
1224 struct spirv_type {
1225 SpvOp op;
1226 uint32_t args[8];
1227 size_t num_args;
1228
1229 SpvId type;
1230 };
1231
1232 static uint32_t
non_aggregate_type_hash(const void * arg)1233 non_aggregate_type_hash(const void *arg)
1234 {
1235 const struct spirv_type *type = arg;
1236
1237 uint32_t hash = 0;
1238 hash = XXH32(&type->op, sizeof(type->op), hash);
1239 hash = XXH32(type->args, sizeof(uint32_t) * type->num_args, hash);
1240 return hash;
1241 }
1242
1243 static bool
non_aggregate_type_equals(const void * a,const void * b)1244 non_aggregate_type_equals(const void *a, const void *b)
1245 {
1246 const struct spirv_type *ta = a, *tb = b;
1247
1248 if (ta->op != tb->op)
1249 return false;
1250
1251 assert(ta->num_args == tb->num_args);
1252 return memcmp(ta->args, tb->args, sizeof(uint32_t) * ta->num_args) == 0;
1253 }
1254
1255 static SpvId
get_type_def(struct spirv_builder * b,SpvOp op,const uint32_t args[],size_t num_args)1256 get_type_def(struct spirv_builder *b, SpvOp op, const uint32_t args[],
1257 size_t num_args)
1258 {
1259 /* According to the SPIR-V specification:
1260 *
1261 * "Two different type <id>s form, by definition, two different types. It
1262 * is valid to declare multiple aggregate type <id>s having the same
1263 * opcode and operands. This is to allow multiple instances of aggregate
1264 * types with the same structure to be decorated differently. (Different
1265 * decorations are not required; two different aggregate type <id>s are
1266 * allowed to have identical declarations and decorations, and will still
1267 * be two different types.) Non-aggregate types are different: It is
1268 * invalid to declare multiple type <id>s for the same scalar, vector, or
1269 * matrix type. That is, non-aggregate type declarations must all have
1270 * different opcodes or operands. (Note that non-aggregate types cannot
1271 * be decorated in ways that affect their type.)"
1272 *
1273 * ..so, we need to prevent the same non-aggregate type to be re-defined
1274 * with a new <id>. We do this by putting the definitions in a hash-map, so
1275 * we can easily look up and reuse them.
1276 */
1277
1278 struct spirv_type key;
1279 assert(num_args <= ARRAY_SIZE(key.args));
1280 key.op = op;
1281 memcpy(&key.args, args, sizeof(uint32_t) * num_args);
1282 key.num_args = num_args;
1283
1284 struct hash_entry *entry;
1285 if (b->types) {
1286 entry = _mesa_hash_table_search(b->types, &key);
1287 if (entry)
1288 return ((struct spirv_type *)entry->data)->type;
1289 } else {
1290 b->types = _mesa_hash_table_create(b->mem_ctx,
1291 non_aggregate_type_hash,
1292 non_aggregate_type_equals);
1293 assert(b->types);
1294 }
1295
1296 struct spirv_type *type = rzalloc(b->mem_ctx, struct spirv_type);
1297 if (!type)
1298 return 0;
1299
1300 type->op = op;
1301 memcpy(&type->args, args, sizeof(uint32_t) * num_args);
1302 type->num_args = num_args;
1303
1304 type->type = spirv_builder_new_id(b);
1305 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 2 + num_args);
1306 spirv_buffer_emit_word(&b->types_const_defs, op | ((2 + num_args) << 16));
1307 spirv_buffer_emit_word(&b->types_const_defs, type->type);
1308 for (int i = 0; i < num_args; ++i)
1309 spirv_buffer_emit_word(&b->types_const_defs, args[i]);
1310
1311 entry = _mesa_hash_table_insert(b->types, type, type);
1312 assert(entry);
1313
1314 return ((struct spirv_type *)entry->data)->type;
1315 }
1316
1317 SpvId
spirv_builder_type_void(struct spirv_builder * b)1318 spirv_builder_type_void(struct spirv_builder *b)
1319 {
1320 return get_type_def(b, SpvOpTypeVoid, NULL, 0);
1321 }
1322
1323 SpvId
spirv_builder_type_bool(struct spirv_builder * b)1324 spirv_builder_type_bool(struct spirv_builder *b)
1325 {
1326 return get_type_def(b, SpvOpTypeBool, NULL, 0);
1327 }
1328
1329 SpvId
spirv_builder_type_int(struct spirv_builder * b,unsigned width)1330 spirv_builder_type_int(struct spirv_builder *b, unsigned width)
1331 {
1332 uint32_t args[] = { width, 1 };
1333 if (width == 8)
1334 spirv_builder_emit_cap(b, SpvCapabilityInt8);
1335 else if (width == 16)
1336 spirv_builder_emit_cap(b, SpvCapabilityInt16);
1337 else if (width == 64)
1338 spirv_builder_emit_cap(b, SpvCapabilityInt64);
1339 return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
1340 }
1341
1342 SpvId
spirv_builder_type_uint(struct spirv_builder * b,unsigned width)1343 spirv_builder_type_uint(struct spirv_builder *b, unsigned width)
1344 {
1345 uint32_t args[] = { width, 0 };
1346 if (width == 8)
1347 spirv_builder_emit_cap(b, SpvCapabilityInt8);
1348 else if (width == 16)
1349 spirv_builder_emit_cap(b, SpvCapabilityInt16);
1350 else if (width == 64)
1351 spirv_builder_emit_cap(b, SpvCapabilityInt64);
1352 return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
1353 }
1354
1355 SpvId
spirv_builder_type_float(struct spirv_builder * b,unsigned width)1356 spirv_builder_type_float(struct spirv_builder *b, unsigned width)
1357 {
1358 uint32_t args[] = { width };
1359 if (width == 16)
1360 spirv_builder_emit_cap(b, SpvCapabilityFloat16);
1361 else if (width == 64)
1362 spirv_builder_emit_cap(b, SpvCapabilityFloat64);
1363 return get_type_def(b, SpvOpTypeFloat, args, ARRAY_SIZE(args));
1364 }
1365
1366 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)1367 spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,
1368 SpvDim dim, bool depth, bool arrayed, bool ms,
1369 unsigned sampled, SpvImageFormat image_format)
1370 {
1371 assert(sampled < 3);
1372 uint32_t args[] = {
1373 sampled_type, dim, depth ? 1 : 0, arrayed ? 1 : 0, ms ? 1 : 0, sampled,
1374 image_format
1375 };
1376 if (sampled == 2 && ms && dim != SpvDimSubpassData)
1377 spirv_builder_emit_cap(b, SpvCapabilityStorageImageMultisample);
1378 return get_type_def(b, SpvOpTypeImage, args, ARRAY_SIZE(args));
1379 }
1380
1381 SpvId
spirv_builder_emit_sampled_image(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId sampler)1382 spirv_builder_emit_sampled_image(struct spirv_builder *b, SpvId result_type, SpvId image, SpvId sampler)
1383 {
1384 return spirv_builder_emit_binop(b, SpvOpSampledImage, result_type, image, sampler);
1385 }
1386
1387 SpvId
spirv_builder_type_sampled_image(struct spirv_builder * b,SpvId image_type)1388 spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type)
1389 {
1390 uint32_t args[] = { image_type };
1391 return get_type_def(b, SpvOpTypeSampledImage, args, ARRAY_SIZE(args));
1392 }
1393
1394 SpvId
spirv_builder_type_sampler(struct spirv_builder * b)1395 spirv_builder_type_sampler(struct spirv_builder *b)
1396 {
1397 uint32_t args[1] = {0};
1398 return get_type_def(b, SpvOpTypeSampler, args, 0);
1399 }
1400
1401 SpvId
spirv_builder_type_pointer(struct spirv_builder * b,SpvStorageClass storage_class,SpvId type)1402 spirv_builder_type_pointer(struct spirv_builder *b,
1403 SpvStorageClass storage_class, SpvId type)
1404 {
1405 uint32_t args[] = { storage_class, type };
1406 return get_type_def(b, SpvOpTypePointer, args, ARRAY_SIZE(args));
1407 }
1408
1409 SpvId
spirv_builder_type_vector(struct spirv_builder * b,SpvId component_type,unsigned component_count)1410 spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,
1411 unsigned component_count)
1412 {
1413 assert(component_count > 1);
1414 uint32_t args[] = { component_type, component_count };
1415 return get_type_def(b, SpvOpTypeVector, args, ARRAY_SIZE(args));
1416 }
1417
1418 SpvId
spirv_builder_type_matrix(struct spirv_builder * b,SpvId component_type,unsigned component_count)1419 spirv_builder_type_matrix(struct spirv_builder *b, SpvId component_type,
1420 unsigned component_count)
1421 {
1422 assert(component_count > 1);
1423 uint32_t args[] = { component_type, component_count };
1424 return get_type_def(b, SpvOpTypeMatrix, args, ARRAY_SIZE(args));
1425 }
1426
1427 SpvId
spirv_builder_type_runtime_array(struct spirv_builder * b,SpvId component_type)1428 spirv_builder_type_runtime_array(struct spirv_builder *b, SpvId component_type)
1429 {
1430 SpvId type = spirv_builder_new_id(b);
1431 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3);
1432 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeRuntimeArray | (3 << 16));
1433 spirv_buffer_emit_word(&b->types_const_defs, type);
1434 spirv_buffer_emit_word(&b->types_const_defs, component_type);
1435 return type;
1436 }
1437
1438 SpvId
spirv_builder_type_array(struct spirv_builder * b,SpvId component_type,SpvId length)1439 spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,
1440 SpvId length)
1441 {
1442 SpvId type = spirv_builder_new_id(b);
1443 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 4);
1444 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeArray | (4 << 16));
1445 spirv_buffer_emit_word(&b->types_const_defs, type);
1446 spirv_buffer_emit_word(&b->types_const_defs, component_type);
1447 spirv_buffer_emit_word(&b->types_const_defs, length);
1448 return type;
1449 }
1450
1451 SpvId
spirv_builder_type_struct(struct spirv_builder * b,const SpvId member_types[],size_t num_member_types)1452 spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],
1453 size_t num_member_types)
1454 {
1455 int words = 2 + num_member_types;
1456 SpvId type = spirv_builder_new_id(b);
1457 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1458 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeStruct | (words << 16));
1459 spirv_buffer_emit_word(&b->types_const_defs, type);
1460 for (int i = 0; i < num_member_types; ++i)
1461 spirv_buffer_emit_word(&b->types_const_defs, member_types[i]);
1462 return type;
1463 }
1464
1465 SpvId
spirv_builder_type_function(struct spirv_builder * b,SpvId return_type,const SpvId parameter_types[],size_t num_parameter_types)1466 spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,
1467 const SpvId parameter_types[],
1468 size_t num_parameter_types)
1469 {
1470 int words = 3 + num_parameter_types;
1471 SpvId type = spirv_builder_new_id(b);
1472 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1473 spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeFunction | (words << 16));
1474 spirv_buffer_emit_word(&b->types_const_defs, type);
1475 spirv_buffer_emit_word(&b->types_const_defs, return_type);
1476 for (int i = 0; i < num_parameter_types; ++i)
1477 spirv_buffer_emit_word(&b->types_const_defs, parameter_types[i]);
1478 return type;
1479 }
1480
1481 struct spirv_const {
1482 SpvOp op, type;
1483 uint32_t args[8];
1484 size_t num_args;
1485
1486 SpvId result;
1487 };
1488
1489 static uint32_t
const_hash(const void * arg)1490 const_hash(const void *arg)
1491 {
1492 const struct spirv_const *key = arg;
1493
1494 uint32_t hash = 0;
1495 hash = XXH32(&key->op, sizeof(key->op), hash);
1496 hash = XXH32(&key->type, sizeof(key->type), hash);
1497 hash = XXH32(key->args, sizeof(uint32_t) * key->num_args, hash);
1498 return hash;
1499 }
1500
1501 static bool
const_equals(const void * a,const void * b)1502 const_equals(const void *a, const void *b)
1503 {
1504 const struct spirv_const *ca = a, *cb = b;
1505
1506 if (ca->op != cb->op ||
1507 ca->type != cb->type)
1508 return false;
1509
1510 assert(ca->num_args == cb->num_args);
1511 return memcmp(ca->args, cb->args, sizeof(uint32_t) * ca->num_args) == 0;
1512 }
1513
1514 static SpvId
get_const_def(struct spirv_builder * b,SpvOp op,SpvId type,const uint32_t args[],size_t num_args)1515 get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,
1516 const uint32_t args[], size_t num_args)
1517 {
1518 struct spirv_const key;
1519 assert(num_args <= ARRAY_SIZE(key.args));
1520 key.op = op;
1521 key.type = type;
1522 memcpy(&key.args, args, sizeof(uint32_t) * num_args);
1523 key.num_args = num_args;
1524
1525 struct hash_entry *entry;
1526 if (b->consts) {
1527 entry = _mesa_hash_table_search(b->consts, &key);
1528 if (entry)
1529 return ((struct spirv_const *)entry->data)->result;
1530 } else {
1531 b->consts = _mesa_hash_table_create(b->mem_ctx, const_hash,
1532 const_equals);
1533 assert(b->consts);
1534 }
1535
1536 struct spirv_const *cnst = rzalloc(b->mem_ctx, struct spirv_const);
1537 if (!cnst)
1538 return 0;
1539
1540 cnst->op = op;
1541 cnst->type = type;
1542 memcpy(&cnst->args, args, sizeof(uint32_t) * num_args);
1543 cnst->num_args = num_args;
1544
1545 cnst->result = spirv_builder_new_id(b);
1546 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3 + num_args);
1547 spirv_buffer_emit_word(&b->types_const_defs, op | ((3 + num_args) << 16));
1548 spirv_buffer_emit_word(&b->types_const_defs, type);
1549 spirv_buffer_emit_word(&b->types_const_defs, cnst->result);
1550 for (int i = 0; i < num_args; ++i)
1551 spirv_buffer_emit_word(&b->types_const_defs, args[i]);
1552
1553 entry = _mesa_hash_table_insert(b->consts, cnst, cnst);
1554 assert(entry);
1555
1556 return ((struct spirv_const *)entry->data)->result;
1557 }
1558
1559 static SpvId
emit_constant_32(struct spirv_builder * b,SpvId type,uint32_t val)1560 emit_constant_32(struct spirv_builder *b, SpvId type, uint32_t val)
1561 {
1562 uint32_t args[] = { val };
1563 return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));
1564 }
1565
1566 static SpvId
emit_constant_64(struct spirv_builder * b,SpvId type,uint64_t val)1567 emit_constant_64(struct spirv_builder *b, SpvId type, uint64_t val)
1568 {
1569 uint32_t args[] = { val & UINT32_MAX, val >> 32 };
1570 return get_const_def(b, SpvOpConstant, type, args, ARRAY_SIZE(args));
1571 }
1572
1573 SpvId
spirv_builder_const_bool(struct spirv_builder * b,bool val)1574 spirv_builder_const_bool(struct spirv_builder *b, bool val)
1575 {
1576 return get_const_def(b, val ? SpvOpConstantTrue : SpvOpConstantFalse,
1577 spirv_builder_type_bool(b), NULL, 0);
1578 }
1579
1580 SpvId
spirv_builder_const_int(struct spirv_builder * b,int width,int64_t val)1581 spirv_builder_const_int(struct spirv_builder *b, int width, int64_t val)
1582 {
1583 assert(width >= 8);
1584 SpvId type = spirv_builder_type_int(b, width);
1585 if (width <= 32)
1586 return emit_constant_32(b, type, val);
1587 else
1588 return emit_constant_64(b, type, val);
1589 }
1590
1591 SpvId
spirv_builder_const_uint(struct spirv_builder * b,int width,uint64_t val)1592 spirv_builder_const_uint(struct spirv_builder *b, int width, uint64_t val)
1593 {
1594 assert(width >= 8);
1595 if (width == 8)
1596 spirv_builder_emit_cap(b, SpvCapabilityInt8);
1597 else if (width == 16)
1598 spirv_builder_emit_cap(b, SpvCapabilityInt16);
1599 else if (width == 64)
1600 spirv_builder_emit_cap(b, SpvCapabilityInt64);
1601 SpvId type = spirv_builder_type_uint(b, width);
1602 if (width <= 32)
1603 return emit_constant_32(b, type, val);
1604 else
1605 return emit_constant_64(b, type, val);
1606 }
1607
1608 SpvId
spirv_builder_spec_const_uint(struct spirv_builder * b,int width)1609 spirv_builder_spec_const_uint(struct spirv_builder *b, int width)
1610 {
1611 assert(width <= 32);
1612 SpvId const_type = spirv_builder_type_uint(b, width);
1613 SpvId result = spirv_builder_new_id(b);
1614 spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 4);
1615 spirv_buffer_emit_word(&b->types_const_defs, SpvOpSpecConstant | (4 << 16));
1616 spirv_buffer_emit_word(&b->types_const_defs, const_type);
1617 spirv_buffer_emit_word(&b->types_const_defs, result);
1618 /* this is the default value for spec constants;
1619 * if any users need a different default, add a param to pass for it
1620 */
1621 spirv_buffer_emit_word(&b->types_const_defs, 1);
1622 return result;
1623 }
1624
1625 SpvId
spirv_builder_const_float(struct spirv_builder * b,int width,double val)1626 spirv_builder_const_float(struct spirv_builder *b, int width, double val)
1627 {
1628 assert(width >= 16);
1629 SpvId type = spirv_builder_type_float(b, width);
1630 if (width == 16) {
1631 spirv_builder_emit_cap(b, SpvCapabilityFloat16);
1632 return emit_constant_32(b, type, _mesa_float_to_half(val));
1633 } else if (width == 32)
1634 return emit_constant_32(b, type, u_bitcast_f2u(val));
1635 else if (width == 64) {
1636 spirv_builder_emit_cap(b, SpvCapabilityFloat64);
1637 return emit_constant_64(b, type, u_bitcast_d2u(val));
1638 }
1639
1640 unreachable("unhandled float-width");
1641 }
1642
1643 SpvId
spirv_builder_const_composite(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)1644 spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,
1645 const SpvId constituents[],
1646 size_t num_constituents)
1647 {
1648 return get_const_def(b, SpvOpConstantComposite, result_type,
1649 (const uint32_t *)constituents,
1650 num_constituents);
1651 }
1652
1653 SpvId
spirv_builder_spec_const_composite(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)1654 spirv_builder_spec_const_composite(struct spirv_builder *b, SpvId result_type,
1655 const SpvId constituents[],
1656 size_t num_constituents)
1657 {
1658 SpvId result = spirv_builder_new_id(b);
1659
1660 assert(num_constituents > 0);
1661 int words = 3 + num_constituents;
1662 spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
1663 spirv_buffer_emit_word(&b->instructions,
1664 SpvOpSpecConstantComposite | (words << 16));
1665 spirv_buffer_emit_word(&b->instructions, result_type);
1666 spirv_buffer_emit_word(&b->instructions, result);
1667 for (int i = 0; i < num_constituents; ++i)
1668 spirv_buffer_emit_word(&b->instructions, constituents[i]);
1669 return result;
1670 }
1671
1672 SpvId
spirv_builder_emit_var(struct spirv_builder * b,SpvId type,SpvStorageClass storage_class)1673 spirv_builder_emit_var(struct spirv_builder *b, SpvId type,
1674 SpvStorageClass storage_class)
1675 {
1676 assert(storage_class != SpvStorageClassGeneric);
1677 struct spirv_buffer *buf = storage_class != SpvStorageClassFunction ?
1678 &b->types_const_defs : &b->local_vars;
1679
1680 SpvId ret = spirv_builder_new_id(b);
1681 spirv_buffer_prepare(buf, b->mem_ctx, 4);
1682 spirv_buffer_emit_word(buf, SpvOpVariable | (4 << 16));
1683 spirv_buffer_emit_word(buf, type);
1684 spirv_buffer_emit_word(buf, ret);
1685 spirv_buffer_emit_word(buf, storage_class);
1686 return ret;
1687 }
1688
1689 void
spirv_builder_emit_memory_barrier(struct spirv_builder * b,SpvScope scope,SpvMemorySemanticsMask semantics)1690 spirv_builder_emit_memory_barrier(struct spirv_builder *b, SpvScope scope, SpvMemorySemanticsMask semantics)
1691 {
1692 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
1693 spirv_buffer_emit_word(&b->instructions, SpvOpMemoryBarrier | (3 << 16));
1694 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1695 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1696 }
1697
1698 void
spirv_builder_emit_control_barrier(struct spirv_builder * b,SpvScope scope,SpvScope mem_scope,SpvMemorySemanticsMask semantics)1699 spirv_builder_emit_control_barrier(struct spirv_builder *b, SpvScope scope, SpvScope mem_scope, SpvMemorySemanticsMask semantics)
1700 {
1701 spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
1702 spirv_buffer_emit_word(&b->instructions, SpvOpControlBarrier | (4 << 16));
1703 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1704 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, mem_scope));
1705 spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1706 }
1707
1708 SpvId
spirv_builder_import(struct spirv_builder * b,const char * name)1709 spirv_builder_import(struct spirv_builder *b, const char *name)
1710 {
1711 SpvId result = spirv_builder_new_id(b);
1712 size_t pos = b->imports.num_words;
1713 spirv_buffer_prepare(&b->imports, b->mem_ctx, 2);
1714 spirv_buffer_emit_word(&b->imports, SpvOpExtInstImport);
1715 spirv_buffer_emit_word(&b->imports, result);
1716 int len = spirv_buffer_emit_string(&b->imports, b->mem_ctx, name);
1717 b->imports.words[pos] |= (2 + len) << 16;
1718 return result;
1719 }
1720
1721 size_t
spirv_builder_get_num_words(struct spirv_builder * b)1722 spirv_builder_get_num_words(struct spirv_builder *b)
1723 {
1724 const size_t header_size = 5;
1725 const size_t caps_size = b->caps ? b->caps->entries * 2 : 0;
1726 return header_size + caps_size +
1727 b->extensions.num_words +
1728 b->imports.num_words +
1729 b->memory_model.num_words +
1730 b->entry_points.num_words +
1731 b->exec_modes.num_words +
1732 b->debug_names.num_words +
1733 b->decorations.num_words +
1734 b->types_const_defs.num_words +
1735 b->local_vars.num_words +
1736 b->instructions.num_words;
1737 }
1738
1739 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)1740 spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
1741 size_t num_words, uint32_t spirv_version,
1742 uint32_t *tcs_vertices_out_word)
1743 {
1744 assert(num_words >= spirv_builder_get_num_words(b));
1745
1746 size_t written = 0;
1747 words[written++] = SpvMagicNumber;
1748 words[written++] = spirv_version;
1749 words[written++] = 0;
1750 words[written++] = b->prev_id + 1;
1751 words[written++] = 0;
1752
1753 if (b->caps) {
1754 set_foreach(b->caps, entry) {
1755 words[written++] = SpvOpCapability | (2 << 16);
1756 words[written++] = (uintptr_t)entry->key;
1757 }
1758 }
1759
1760 const struct spirv_buffer *buffers[] = {
1761 &b->extensions,
1762 &b->imports,
1763 &b->memory_model,
1764 &b->entry_points,
1765 &b->exec_modes,
1766 &b->debug_names,
1767 &b->decorations,
1768 &b->types_const_defs,
1769 };
1770
1771 for (int i = 0; i < ARRAY_SIZE(buffers); ++i) {
1772 const struct spirv_buffer *buffer = buffers[i];
1773
1774 if (buffer == &b->exec_modes && *tcs_vertices_out_word > 0)
1775 *tcs_vertices_out_word += written;
1776
1777 memcpy(words + written, buffer->words,
1778 buffer->num_words * sizeof(uint32_t));
1779 written += buffer->num_words;
1780 }
1781 typed_memcpy(&words[written], b->instructions.words, b->local_vars_begin);
1782 written += b->local_vars_begin;
1783 typed_memcpy(&words[written], b->local_vars.words, b->local_vars.num_words);
1784 written += b->local_vars.num_words;
1785 typed_memcpy(&words[written], &b->instructions.words[b->local_vars_begin], (b->instructions.num_words - b->local_vars_begin));
1786 written += b->instructions.num_words - b->local_vars_begin;
1787
1788 assert(written == spirv_builder_get_num_words(b));
1789 return written;
1790 }
1791
1792 void
spirv_builder_begin_local_vars(struct spirv_builder * b)1793 spirv_builder_begin_local_vars(struct spirv_builder *b)
1794 {
1795 b->local_vars_begin = b->instructions.num_words;
1796 }
1797