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