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