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