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