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