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