• 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/ralloc.h"
28 #include "util/u_bitcast.h"
29 #include "util/u_memory.h"
30 #include "util/hash_table.h"
31 #define XXH_INLINE_ALL
32 #include "util/xxhash.h"
33 
34 #include <stdbool.h>
35 #include <inttypes.h>
36 #include <string.h>
37 
38 static bool
spirv_buffer_grow(struct spirv_buffer * b,void * mem_ctx,size_t needed)39 spirv_buffer_grow(struct spirv_buffer *b, void *mem_ctx, size_t needed)
40 {
41    size_t new_room = MAX3(64, (b->room * 3) / 2, needed);
42 
43    uint32_t *new_words = reralloc_size(mem_ctx, b->words,
44                                        new_room * sizeof(uint32_t));
45    if (!new_words)
46       return false;
47 
48    b->words = new_words;
49    b->room = new_room;
50    return true;
51 }
52 
53 static inline bool
spirv_buffer_prepare(struct spirv_buffer * b,void * mem_ctx,size_t needed)54 spirv_buffer_prepare(struct spirv_buffer *b, void *mem_ctx, size_t needed)
55 {
56    needed += b->num_words;
57    if (b->room >= b->num_words + needed)
58       return true;
59 
60    return spirv_buffer_grow(b, mem_ctx, needed);
61 }
62 
63 static inline void
spirv_buffer_emit_word(struct spirv_buffer * b,uint32_t word)64 spirv_buffer_emit_word(struct spirv_buffer *b, uint32_t word)
65 {
66    assert(b->num_words < b->room);
67    b->words[b->num_words++] = word;
68 }
69 
70 static int
spirv_buffer_emit_string(struct spirv_buffer * b,void * mem_ctx,const char * str)71 spirv_buffer_emit_string(struct spirv_buffer *b, void *mem_ctx,
72                          const char *str)
73 {
74    int pos = 0;
75    uint32_t word = 0;
76    while (str[pos] != '\0') {
77       word |= str[pos] << (8 * (pos % 4));
78       if (++pos % 4 == 0) {
79          spirv_buffer_prepare(b, mem_ctx, 1);
80          spirv_buffer_emit_word(b, word);
81          word = 0;
82       }
83    }
84 
85    spirv_buffer_prepare(b, mem_ctx, 1);
86    spirv_buffer_emit_word(b, word);
87 
88    return 1 + pos / 4;
89 }
90 
91 void
spirv_builder_emit_cap(struct spirv_builder * b,SpvCapability cap)92 spirv_builder_emit_cap(struct spirv_builder *b, SpvCapability cap)
93 {
94    spirv_buffer_prepare(&b->capabilities, b->mem_ctx, 2);
95    spirv_buffer_emit_word(&b->capabilities, SpvOpCapability | (2 << 16));
96    spirv_buffer_emit_word(&b->capabilities, cap);
97 }
98 
99 void
spirv_builder_emit_extension(struct spirv_builder * b,const char * name)100 spirv_builder_emit_extension(struct spirv_builder *b, const char *name)
101 {
102    size_t pos = b->extensions.num_words;
103    spirv_buffer_prepare(&b->extensions, b->mem_ctx, 1);
104    spirv_buffer_emit_word(&b->extensions, SpvOpExtension);
105    int len = spirv_buffer_emit_string(&b->extensions, b->mem_ctx, name);
106    b->extensions.words[pos] |= (1 + len) << 16;
107 }
108 
109 void
spirv_builder_emit_source(struct spirv_builder * b,SpvSourceLanguage lang,uint32_t version)110 spirv_builder_emit_source(struct spirv_builder *b, SpvSourceLanguage lang,
111                           uint32_t version)
112 {
113    spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 3);
114    spirv_buffer_emit_word(&b->debug_names, SpvOpSource | (3 << 16));
115    spirv_buffer_emit_word(&b->debug_names, lang);
116    spirv_buffer_emit_word(&b->debug_names, version);
117 }
118 
119 void
spirv_builder_emit_mem_model(struct spirv_builder * b,SpvAddressingModel addr_model,SpvMemoryModel mem_model)120 spirv_builder_emit_mem_model(struct spirv_builder *b,
121                              SpvAddressingModel addr_model,
122                              SpvMemoryModel mem_model)
123 {
124    spirv_buffer_prepare(&b->memory_model, b->mem_ctx, 3);
125    spirv_buffer_emit_word(&b->memory_model, SpvOpMemoryModel | (3 << 16));
126    spirv_buffer_emit_word(&b->memory_model, addr_model);
127    spirv_buffer_emit_word(&b->memory_model, mem_model);
128 }
129 
130 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)131 spirv_builder_emit_entry_point(struct spirv_builder *b,
132                                SpvExecutionModel exec_model, SpvId entry_point,
133                                const char *name, const SpvId interfaces[],
134                                size_t num_interfaces)
135 {
136    size_t pos = b->entry_points.num_words;
137    spirv_buffer_prepare(&b->entry_points, b->mem_ctx, 3);
138    spirv_buffer_emit_word(&b->entry_points, SpvOpEntryPoint);
139    spirv_buffer_emit_word(&b->entry_points, exec_model);
140    spirv_buffer_emit_word(&b->entry_points, entry_point);
141    int len = spirv_buffer_emit_string(&b->entry_points, b->mem_ctx, name);
142    b->entry_points.words[pos] |= (3 + len + num_interfaces) << 16;
143    spirv_buffer_prepare(&b->entry_points, b->mem_ctx, num_interfaces);
144    for (int i = 0; i < num_interfaces; ++i)
145         spirv_buffer_emit_word(&b->entry_points, interfaces[i]);
146 }
147 
148 void
spirv_builder_emit_exec_mode_literal(struct spirv_builder * b,SpvId entry_point,SpvExecutionMode exec_mode,uint32_t param)149 spirv_builder_emit_exec_mode_literal(struct spirv_builder *b, SpvId entry_point,
150                                      SpvExecutionMode exec_mode, uint32_t param)
151 {
152    spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 4);
153    spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (4 << 16));
154    spirv_buffer_emit_word(&b->exec_modes, entry_point);
155    spirv_buffer_emit_word(&b->exec_modes, exec_mode);
156    spirv_buffer_emit_word(&b->exec_modes, param);
157 }
158 
159 void
spirv_builder_emit_exec_mode(struct spirv_builder * b,SpvId entry_point,SpvExecutionMode exec_mode)160 spirv_builder_emit_exec_mode(struct spirv_builder *b, SpvId entry_point,
161                              SpvExecutionMode exec_mode)
162 {
163    spirv_buffer_prepare(&b->exec_modes, b->mem_ctx, 3);
164    spirv_buffer_emit_word(&b->exec_modes, SpvOpExecutionMode | (3 << 16));
165    spirv_buffer_emit_word(&b->exec_modes, entry_point);
166    spirv_buffer_emit_word(&b->exec_modes, exec_mode);
167 }
168 
169 void
spirv_builder_emit_name(struct spirv_builder * b,SpvId target,const char * name)170 spirv_builder_emit_name(struct spirv_builder *b, SpvId target,
171                         const char *name)
172 {
173    size_t pos = b->debug_names.num_words;
174    spirv_buffer_prepare(&b->debug_names, b->mem_ctx, 2);
175    spirv_buffer_emit_word(&b->debug_names, SpvOpName);
176    spirv_buffer_emit_word(&b->debug_names, target);
177    int len = spirv_buffer_emit_string(&b->debug_names, b->mem_ctx, name);
178    b->debug_names.words[pos] |= (2 + len) << 16;
179 }
180 
181 static void
emit_decoration(struct spirv_builder * b,SpvId target,SpvDecoration decoration,const uint32_t extra_operands[],size_t num_extra_operands)182 emit_decoration(struct spirv_builder *b, SpvId target,
183                 SpvDecoration decoration, const uint32_t extra_operands[],
184                 size_t num_extra_operands)
185 {
186    int words = 3 + num_extra_operands;
187    spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);
188    spirv_buffer_emit_word(&b->decorations, SpvOpDecorate | (words << 16));
189    spirv_buffer_emit_word(&b->decorations, target);
190    spirv_buffer_emit_word(&b->decorations, decoration);
191    for (int i = 0; i < num_extra_operands; ++i)
192       spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
193 }
194 
195 void
spirv_builder_emit_decoration(struct spirv_builder * b,SpvId target,SpvDecoration decoration)196 spirv_builder_emit_decoration(struct spirv_builder *b, SpvId target,
197                               SpvDecoration decoration)
198 {
199    emit_decoration(b, target, decoration, NULL, 0);
200 }
201 
202 void
spirv_builder_emit_location(struct spirv_builder * b,SpvId target,uint32_t location)203 spirv_builder_emit_location(struct spirv_builder *b, SpvId target,
204                             uint32_t location)
205 {
206    uint32_t args[] = { location };
207    emit_decoration(b, target, SpvDecorationLocation, args, ARRAY_SIZE(args));
208 }
209 
210 void
spirv_builder_emit_component(struct spirv_builder * b,SpvId target,uint32_t component)211 spirv_builder_emit_component(struct spirv_builder *b, SpvId target,
212                              uint32_t component)
213 {
214    uint32_t args[] = { component };
215    emit_decoration(b, target, SpvDecorationComponent, args, ARRAY_SIZE(args));
216 }
217 
218 void
spirv_builder_emit_builtin(struct spirv_builder * b,SpvId target,SpvBuiltIn builtin)219 spirv_builder_emit_builtin(struct spirv_builder *b, SpvId target,
220                            SpvBuiltIn builtin)
221 {
222    uint32_t args[] = { builtin };
223    emit_decoration(b, target, SpvDecorationBuiltIn, args, ARRAY_SIZE(args));
224 }
225 
226 void
spirv_builder_emit_vertex(struct spirv_builder * b)227 spirv_builder_emit_vertex(struct spirv_builder *b)
228 {
229    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
230    spirv_buffer_emit_word(&b->instructions, SpvOpEmitVertex | (1 << 16));
231 }
232 
233 void
spirv_builder_end_primitive(struct spirv_builder * b)234 spirv_builder_end_primitive(struct spirv_builder *b)
235 {
236    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
237    spirv_buffer_emit_word(&b->instructions, SpvOpEndPrimitive | (1 << 16));
238 }
239 
240 void
spirv_builder_emit_descriptor_set(struct spirv_builder * b,SpvId target,uint32_t descriptor_set)241 spirv_builder_emit_descriptor_set(struct spirv_builder *b, SpvId target,
242                                   uint32_t descriptor_set)
243 {
244    uint32_t args[] = { descriptor_set };
245    emit_decoration(b, target, SpvDecorationDescriptorSet, args,
246                    ARRAY_SIZE(args));
247 }
248 
249 void
spirv_builder_emit_binding(struct spirv_builder * b,SpvId target,uint32_t binding)250 spirv_builder_emit_binding(struct spirv_builder *b, SpvId target,
251                            uint32_t binding)
252 {
253    uint32_t args[] = { binding };
254    emit_decoration(b, target, SpvDecorationBinding, args, ARRAY_SIZE(args));
255 }
256 
257 void
spirv_builder_emit_array_stride(struct spirv_builder * b,SpvId target,uint32_t stride)258 spirv_builder_emit_array_stride(struct spirv_builder *b, SpvId target,
259                                 uint32_t stride)
260 {
261    uint32_t args[] = { stride };
262    emit_decoration(b, target, SpvDecorationArrayStride, args, ARRAY_SIZE(args));
263 }
264 
265 void
spirv_builder_emit_offset(struct spirv_builder * b,SpvId target,uint32_t offset)266 spirv_builder_emit_offset(struct spirv_builder *b, SpvId target,
267                           uint32_t offset)
268 {
269    uint32_t args[] = { offset };
270    emit_decoration(b, target, SpvDecorationOffset, args, ARRAY_SIZE(args));
271 }
272 
273 void
spirv_builder_emit_xfb_buffer(struct spirv_builder * b,SpvId target,uint32_t buffer)274 spirv_builder_emit_xfb_buffer(struct spirv_builder *b, SpvId target,
275                               uint32_t buffer)
276 {
277    uint32_t args[] = { buffer };
278    emit_decoration(b, target, SpvDecorationXfbBuffer, args, ARRAY_SIZE(args));
279 }
280 
281 void
spirv_builder_emit_xfb_stride(struct spirv_builder * b,SpvId target,uint32_t stride)282 spirv_builder_emit_xfb_stride(struct spirv_builder *b, SpvId target,
283                               uint32_t stride)
284 {
285    uint32_t args[] = { stride };
286    emit_decoration(b, target, SpvDecorationXfbStride, args, ARRAY_SIZE(args));
287 }
288 
289 void
spirv_builder_emit_index(struct spirv_builder * b,SpvId target,int index)290 spirv_builder_emit_index(struct spirv_builder *b, SpvId target, int index)
291 {
292    uint32_t args[] = { index };
293    emit_decoration(b, target, SpvDecorationIndex, args, ARRAY_SIZE(args));
294 }
295 
296 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)297 emit_member_decoration(struct spirv_builder *b, SpvId target, uint32_t member,
298                        SpvDecoration decoration, const uint32_t extra_operands[],
299                        size_t num_extra_operands)
300 {
301    int words = 4 + num_extra_operands;
302    spirv_buffer_prepare(&b->decorations, b->mem_ctx, words);
303    spirv_buffer_emit_word(&b->decorations,
304                           SpvOpMemberDecorate | (words << 16));
305    spirv_buffer_emit_word(&b->decorations, target);
306    spirv_buffer_emit_word(&b->decorations, member);
307    spirv_buffer_emit_word(&b->decorations, decoration);
308    for (int i = 0; i < num_extra_operands; ++i)
309       spirv_buffer_emit_word(&b->decorations, extra_operands[i]);
310 }
311 
312 void
spirv_builder_emit_member_offset(struct spirv_builder * b,SpvId target,uint32_t member,uint32_t offset)313 spirv_builder_emit_member_offset(struct spirv_builder *b, SpvId target,
314                           uint32_t member, uint32_t offset)
315 {
316    uint32_t args[] = { offset };
317    emit_member_decoration(b, target, member, SpvDecorationOffset,
318                           args, ARRAY_SIZE(args));
319 }
320 
321 SpvId
spirv_builder_emit_undef(struct spirv_builder * b,SpvId result_type)322 spirv_builder_emit_undef(struct spirv_builder *b, SpvId result_type)
323 {
324    SpvId result = spirv_builder_new_id(b);
325    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
326    spirv_buffer_emit_word(&b->instructions, SpvOpUndef | (3 << 16));
327    spirv_buffer_emit_word(&b->instructions, result_type);
328    spirv_buffer_emit_word(&b->instructions, result);
329    return result;
330 }
331 
332 void
spirv_builder_function(struct spirv_builder * b,SpvId result,SpvId return_type,SpvFunctionControlMask function_control,SpvId function_type)333 spirv_builder_function(struct spirv_builder *b, SpvId result,
334                        SpvId return_type,
335                        SpvFunctionControlMask function_control,
336                        SpvId function_type)
337 {
338    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);
339    spirv_buffer_emit_word(&b->instructions, SpvOpFunction | (5 << 16));
340    spirv_buffer_emit_word(&b->instructions, return_type);
341    spirv_buffer_emit_word(&b->instructions, result);
342    spirv_buffer_emit_word(&b->instructions, function_control);
343    spirv_buffer_emit_word(&b->instructions, function_type);
344 }
345 
346 void
spirv_builder_function_end(struct spirv_builder * b)347 spirv_builder_function_end(struct spirv_builder *b)
348 {
349    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
350    spirv_buffer_emit_word(&b->instructions, SpvOpFunctionEnd | (1 << 16));
351 }
352 
353 void
spirv_builder_label(struct spirv_builder * b,SpvId label)354 spirv_builder_label(struct spirv_builder *b, SpvId label)
355 {
356    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);
357    spirv_buffer_emit_word(&b->instructions, SpvOpLabel | (2 << 16));
358    spirv_buffer_emit_word(&b->instructions, label);
359 }
360 
361 void
spirv_builder_return(struct spirv_builder * b)362 spirv_builder_return(struct spirv_builder *b)
363 {
364    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
365    spirv_buffer_emit_word(&b->instructions, SpvOpReturn | (1 << 16));
366 }
367 
368 SpvId
spirv_builder_emit_load(struct spirv_builder * b,SpvId result_type,SpvId pointer)369 spirv_builder_emit_load(struct spirv_builder *b, SpvId result_type,
370                         SpvId pointer)
371 {
372    return spirv_builder_emit_unop(b, SpvOpLoad, result_type, pointer);
373 }
374 
375 void
spirv_builder_emit_store(struct spirv_builder * b,SpvId pointer,SpvId object)376 spirv_builder_emit_store(struct spirv_builder *b, SpvId pointer, SpvId object)
377 {
378    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
379    spirv_buffer_emit_word(&b->instructions, SpvOpStore | (3 << 16));
380    spirv_buffer_emit_word(&b->instructions, pointer);
381    spirv_buffer_emit_word(&b->instructions, object);
382 }
383 
384 SpvId
spirv_builder_emit_access_chain(struct spirv_builder * b,SpvId result_type,SpvId base,const SpvId indexes[],size_t num_indexes)385 spirv_builder_emit_access_chain(struct spirv_builder *b, SpvId result_type,
386                                 SpvId base, const SpvId indexes[],
387                                 size_t num_indexes)
388 {
389    assert(base);
390    assert(result_type);
391    SpvId result = spirv_builder_new_id(b);
392 
393    int words = 4 + num_indexes;
394    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
395    spirv_buffer_emit_word(&b->instructions, SpvOpAccessChain | (words << 16));
396    spirv_buffer_emit_word(&b->instructions, result_type);
397    spirv_buffer_emit_word(&b->instructions, result);
398    spirv_buffer_emit_word(&b->instructions, base);
399    for (int i = 0; i < num_indexes; ++i)
400       spirv_buffer_emit_word(&b->instructions, indexes[i]);
401    return result;
402 }
403 
404 
405 SpvId
spirv_builder_emit_unop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand)406 spirv_builder_emit_unop(struct spirv_builder *b, SpvOp op, SpvId result_type,
407                         SpvId operand)
408 {
409    SpvId result = spirv_builder_new_id(b);
410    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
411    spirv_buffer_emit_word(&b->instructions, op | (4 << 16));
412    spirv_buffer_emit_word(&b->instructions, result_type);
413    spirv_buffer_emit_word(&b->instructions, result);
414    spirv_buffer_emit_word(&b->instructions, operand);
415    return result;
416 }
417 
418 SpvId
spirv_builder_emit_binop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1)419 spirv_builder_emit_binop(struct spirv_builder *b, SpvOp op, SpvId result_type,
420                          SpvId operand0, SpvId operand1)
421 {
422    SpvId result = spirv_builder_new_id(b);
423    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5);
424    spirv_buffer_emit_word(&b->instructions, op | (5 << 16));
425    spirv_buffer_emit_word(&b->instructions, result_type);
426    spirv_buffer_emit_word(&b->instructions, result);
427    spirv_buffer_emit_word(&b->instructions, operand0);
428    spirv_buffer_emit_word(&b->instructions, operand1);
429    return result;
430 }
431 
432 SpvId
spirv_builder_emit_triop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1,SpvId operand2)433 spirv_builder_emit_triop(struct spirv_builder *b, SpvOp op, SpvId result_type,
434                          SpvId operand0, SpvId operand1, SpvId operand2)
435 {
436    SpvId result = spirv_builder_new_id(b);
437    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 6);
438    spirv_buffer_emit_word(&b->instructions, op | (6 << 16));
439    spirv_buffer_emit_word(&b->instructions, result_type);
440    spirv_buffer_emit_word(&b->instructions, result);
441    spirv_buffer_emit_word(&b->instructions, operand0);
442    spirv_buffer_emit_word(&b->instructions, operand1);
443    spirv_buffer_emit_word(&b->instructions, operand2);
444    return result;
445 }
446 
447 SpvId
spirv_builder_emit_quadop(struct spirv_builder * b,SpvOp op,SpvId result_type,SpvId operand0,SpvId operand1,SpvId operand2,SpvId operand3)448 spirv_builder_emit_quadop(struct spirv_builder *b, SpvOp op, SpvId result_type,
449                          SpvId operand0, SpvId operand1, SpvId operand2, SpvId operand3)
450 {
451    SpvId result = spirv_builder_new_id(b);
452    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 7);
453    spirv_buffer_emit_word(&b->instructions, op | (7 << 16));
454    spirv_buffer_emit_word(&b->instructions, result_type);
455    spirv_buffer_emit_word(&b->instructions, result);
456    spirv_buffer_emit_word(&b->instructions, operand0);
457    spirv_buffer_emit_word(&b->instructions, operand1);
458    spirv_buffer_emit_word(&b->instructions, operand2);
459    spirv_buffer_emit_word(&b->instructions, operand3);
460    return result;
461 }
462 
463 SpvId
spirv_builder_emit_composite_extract(struct spirv_builder * b,SpvId result_type,SpvId composite,const uint32_t indexes[],size_t num_indexes)464 spirv_builder_emit_composite_extract(struct spirv_builder *b, SpvId result_type,
465                                      SpvId composite, const uint32_t indexes[],
466                                      size_t num_indexes)
467 {
468    SpvId result = spirv_builder_new_id(b);
469 
470    assert(num_indexes > 0);
471    int words = 4 + num_indexes;
472    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
473    spirv_buffer_emit_word(&b->instructions,
474                           SpvOpCompositeExtract | (words << 16));
475    spirv_buffer_emit_word(&b->instructions, result_type);
476    spirv_buffer_emit_word(&b->instructions, result);
477    spirv_buffer_emit_word(&b->instructions, composite);
478    for (int i = 0; i < num_indexes; ++i)
479       spirv_buffer_emit_word(&b->instructions, indexes[i]);
480    return result;
481 }
482 
483 SpvId
spirv_builder_emit_composite_construct(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)484 spirv_builder_emit_composite_construct(struct spirv_builder *b,
485                                        SpvId result_type,
486                                        const SpvId constituents[],
487                                        size_t num_constituents)
488 {
489    SpvId result = spirv_builder_new_id(b);
490 
491    assert(num_constituents > 0);
492    int words = 3 + num_constituents;
493    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
494    spirv_buffer_emit_word(&b->instructions,
495                           SpvOpCompositeConstruct | (words << 16));
496    spirv_buffer_emit_word(&b->instructions, result_type);
497    spirv_buffer_emit_word(&b->instructions, result);
498    for (int i = 0; i < num_constituents; ++i)
499       spirv_buffer_emit_word(&b->instructions, constituents[i]);
500    return result;
501 }
502 
503 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)504 spirv_builder_emit_vector_shuffle(struct spirv_builder *b, SpvId result_type,
505                                   SpvId vector_1, SpvId vector_2,
506                                   const uint32_t components[],
507                                   size_t num_components)
508 {
509    SpvId result = spirv_builder_new_id(b);
510 
511    assert(num_components > 0);
512    int words = 5 + num_components;
513    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
514    spirv_buffer_emit_word(&b->instructions, SpvOpVectorShuffle | (words << 16));
515    spirv_buffer_emit_word(&b->instructions, result_type);
516    spirv_buffer_emit_word(&b->instructions, result);
517    spirv_buffer_emit_word(&b->instructions, vector_1);
518    spirv_buffer_emit_word(&b->instructions, vector_2);
519    for (int i = 0; i < num_components; ++i)
520       spirv_buffer_emit_word(&b->instructions, components[i]);
521    return result;
522 }
523 
524 SpvId
spirv_builder_emit_vector_extract(struct spirv_builder * b,SpvId result_type,SpvId vector_1,uint32_t component)525 spirv_builder_emit_vector_extract(struct spirv_builder *b, SpvId result_type,
526                                   SpvId vector_1,
527                                   uint32_t component)
528 {
529    SpvId result = spirv_builder_new_id(b);
530 
531    int words = 5;
532    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
533    spirv_buffer_emit_word(&b->instructions, SpvOpVectorExtractDynamic | (words << 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, vector_1);
537    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, component));
538    return result;
539 }
540 
541 SpvId
spirv_builder_emit_vector_insert(struct spirv_builder * b,SpvId result_type,SpvId vector_1,SpvId component,uint32_t index)542 spirv_builder_emit_vector_insert(struct spirv_builder *b, SpvId result_type,
543                                   SpvId vector_1,
544                                   SpvId component,
545                                   uint32_t index)
546 {
547    SpvId result = spirv_builder_new_id(b);
548 
549    int words = 6;
550    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
551    spirv_buffer_emit_word(&b->instructions, SpvOpVectorInsertDynamic | (words << 16));
552    spirv_buffer_emit_word(&b->instructions, result_type);
553    spirv_buffer_emit_word(&b->instructions, result);
554    spirv_buffer_emit_word(&b->instructions, vector_1);
555    spirv_buffer_emit_word(&b->instructions, component);
556    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, index));
557    return result;
558 }
559 
560 void
spirv_builder_emit_branch(struct spirv_builder * b,SpvId label)561 spirv_builder_emit_branch(struct spirv_builder *b, SpvId label)
562 {
563    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 2);
564    spirv_buffer_emit_word(&b->instructions, SpvOpBranch | (2 << 16));
565    spirv_buffer_emit_word(&b->instructions, label);
566 }
567 
568 void
spirv_builder_emit_selection_merge(struct spirv_builder * b,SpvId merge_block,SpvSelectionControlMask selection_control)569 spirv_builder_emit_selection_merge(struct spirv_builder *b, SpvId merge_block,
570                                    SpvSelectionControlMask selection_control)
571 {
572    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
573    spirv_buffer_emit_word(&b->instructions, SpvOpSelectionMerge | (3 << 16));
574    spirv_buffer_emit_word(&b->instructions, merge_block);
575    spirv_buffer_emit_word(&b->instructions, selection_control);
576 }
577 
578 void
spirv_builder_loop_merge(struct spirv_builder * b,SpvId merge_block,SpvId cont_target,SpvLoopControlMask loop_control)579 spirv_builder_loop_merge(struct spirv_builder *b, SpvId merge_block,
580                          SpvId cont_target, SpvLoopControlMask loop_control)
581 {
582    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
583    spirv_buffer_emit_word(&b->instructions, SpvOpLoopMerge | (4 << 16));
584    spirv_buffer_emit_word(&b->instructions, merge_block);
585    spirv_buffer_emit_word(&b->instructions, cont_target);
586    spirv_buffer_emit_word(&b->instructions, loop_control);
587 }
588 
589 void
spirv_builder_emit_branch_conditional(struct spirv_builder * b,SpvId condition,SpvId true_label,SpvId false_label)590 spirv_builder_emit_branch_conditional(struct spirv_builder *b, SpvId condition,
591                                       SpvId true_label, SpvId false_label)
592 {
593    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
594    spirv_buffer_emit_word(&b->instructions, SpvOpBranchConditional | (4 << 16));
595    spirv_buffer_emit_word(&b->instructions, condition);
596    spirv_buffer_emit_word(&b->instructions, true_label);
597    spirv_buffer_emit_word(&b->instructions, false_label);
598 }
599 
600 SpvId
spirv_builder_emit_phi(struct spirv_builder * b,SpvId result_type,size_t num_vars,size_t * position)601 spirv_builder_emit_phi(struct spirv_builder *b, SpvId result_type,
602                        size_t num_vars, size_t *position)
603 {
604    SpvId result = spirv_builder_new_id(b);
605 
606    assert(num_vars > 0);
607    int words = 3 + 2 * num_vars;
608    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
609    spirv_buffer_emit_word(&b->instructions, SpvOpPhi | (words << 16));
610    spirv_buffer_emit_word(&b->instructions, result_type);
611    spirv_buffer_emit_word(&b->instructions, result);
612    *position = b->instructions.num_words;
613    for (int i = 0; i < 2 * num_vars; ++i)
614       spirv_buffer_emit_word(&b->instructions, 0);
615    return result;
616 }
617 
618 void
spirv_builder_set_phi_operand(struct spirv_builder * b,size_t position,size_t index,SpvId variable,SpvId parent)619 spirv_builder_set_phi_operand(struct spirv_builder *b, size_t position,
620                               size_t index, SpvId variable, SpvId parent)
621 {
622    b->instructions.words[position + index * 2 + 0] = variable;
623    b->instructions.words[position + index * 2 + 1] = parent;
624 }
625 
626 void
spirv_builder_emit_kill(struct spirv_builder * b)627 spirv_builder_emit_kill(struct spirv_builder *b)
628 {
629    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 1);
630    spirv_buffer_emit_word(&b->instructions, SpvOpKill | (1 << 16));
631 }
632 
633 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 offset)634 spirv_builder_emit_image_sample(struct spirv_builder *b,
635                                 SpvId result_type,
636                                 SpvId sampled_image,
637                                 SpvId coordinate,
638                                 bool proj,
639                                 SpvId lod,
640                                 SpvId bias,
641                                 SpvId dref,
642                                 SpvId dx,
643                                 SpvId dy,
644                                 SpvId offset)
645 {
646    SpvId result = spirv_builder_new_id(b);
647 
648    int opcode = SpvOpImageSampleImplicitLod;
649    int operands = 5;
650    if (proj)
651       opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
652    if (lod || (dx && dy))
653       opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
654    if (dref) {
655       opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
656       operands++;
657    }
658 
659    SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
660    SpvId extra_operands[5];
661    int num_extra_operands = 0;
662    if (bias) {
663       extra_operands[++num_extra_operands] = bias;
664       operand_mask |= SpvImageOperandsBiasMask;
665    }
666    if (lod) {
667       extra_operands[++num_extra_operands] = lod;
668       operand_mask |= SpvImageOperandsLodMask;
669    } else if (dx && dy) {
670       extra_operands[++num_extra_operands] = dx;
671       extra_operands[++num_extra_operands] = dy;
672       operand_mask |= SpvImageOperandsGradMask;
673    }
674    if (offset) {
675       extra_operands[++num_extra_operands] = offset;
676       operand_mask |= SpvImageOperandsOffsetMask;
677    }
678 
679    /* finalize num_extra_operands / extra_operands */
680    if (num_extra_operands > 0) {
681       extra_operands[0] = operand_mask;
682       num_extra_operands++;
683    }
684 
685    spirv_buffer_prepare(&b->instructions, b->mem_ctx, operands + num_extra_operands);
686    spirv_buffer_emit_word(&b->instructions, opcode | ((operands + num_extra_operands) << 16));
687    spirv_buffer_emit_word(&b->instructions, result_type);
688    spirv_buffer_emit_word(&b->instructions, result);
689    spirv_buffer_emit_word(&b->instructions, sampled_image);
690    spirv_buffer_emit_word(&b->instructions, coordinate);
691    if (dref)
692       spirv_buffer_emit_word(&b->instructions, dref);
693    for (int i = 0; i < num_extra_operands; ++i)
694       spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
695    return result;
696 }
697 
698 SpvId
spirv_builder_emit_image(struct spirv_builder * b,SpvId result_type,SpvId sampled_image)699 spirv_builder_emit_image(struct spirv_builder *b, SpvId result_type,
700                          SpvId sampled_image)
701 {
702    SpvId result = spirv_builder_new_id(b);
703    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
704    spirv_buffer_emit_word(&b->instructions, SpvOpImage | (4 << 16));
705    spirv_buffer_emit_word(&b->instructions, result_type);
706    spirv_buffer_emit_word(&b->instructions, result);
707    spirv_buffer_emit_word(&b->instructions, sampled_image);
708    return result;
709 }
710 
711 SpvId
spirv_builder_emit_image_fetch(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coordinate,SpvId lod,SpvId sample)712 spirv_builder_emit_image_fetch(struct spirv_builder *b,
713                                SpvId result_type,
714                                SpvId image,
715                                SpvId coordinate,
716                                SpvId lod,
717                                SpvId sample)
718 {
719    SpvId result = spirv_builder_new_id(b);
720 
721    SpvImageOperandsMask operand_mask = SpvImageOperandsMaskNone;
722    SpvId extra_operands[3];
723    int num_extra_operands = 0;
724    if (lod) {
725       extra_operands[++num_extra_operands] = lod;
726       operand_mask |= SpvImageOperandsLodMask;
727    }
728    if (sample) {
729       extra_operands[++num_extra_operands] = sample;
730       operand_mask |= SpvImageOperandsSampleMask;
731    }
732 
733    /* finalize num_extra_operands / extra_operands */
734    if (num_extra_operands > 0) {
735       extra_operands[0] = operand_mask;
736       num_extra_operands++;
737    }
738 
739    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 5 + num_extra_operands);
740    spirv_buffer_emit_word(&b->instructions, SpvOpImageFetch |
741                           ((5 + num_extra_operands) << 16));
742    spirv_buffer_emit_word(&b->instructions, result_type);
743    spirv_buffer_emit_word(&b->instructions, result);
744    spirv_buffer_emit_word(&b->instructions, image);
745    spirv_buffer_emit_word(&b->instructions, coordinate);
746    for (int i = 0; i < num_extra_operands; ++i)
747       spirv_buffer_emit_word(&b->instructions, extra_operands[i]);
748    return result;
749 }
750 
751 SpvId
spirv_builder_emit_image_query_size(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId lod)752 spirv_builder_emit_image_query_size(struct spirv_builder *b,
753                                     SpvId result_type,
754                                     SpvId image,
755                                     SpvId lod)
756 {
757    int opcode = SpvOpImageQuerySize;
758    int words = 4;
759    if (lod) {
760       words++;
761       opcode = SpvOpImageQuerySizeLod;
762    }
763 
764    SpvId result = spirv_builder_new_id(b);
765    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
766    spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
767    spirv_buffer_emit_word(&b->instructions, result_type);
768    spirv_buffer_emit_word(&b->instructions, result);
769    spirv_buffer_emit_word(&b->instructions, image);
770 
771    if (lod)
772       spirv_buffer_emit_word(&b->instructions, lod);
773 
774    return result;
775 }
776 
777 SpvId
spirv_builder_emit_image_query_lod(struct spirv_builder * b,SpvId result_type,SpvId image,SpvId coords)778 spirv_builder_emit_image_query_lod(struct spirv_builder *b,
779                                     SpvId result_type,
780                                     SpvId image,
781                                     SpvId coords)
782 {
783    int opcode = SpvOpImageQueryLod;
784    int words = 5;
785 
786    SpvId result = spirv_builder_new_id(b);
787    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
788    spirv_buffer_emit_word(&b->instructions, opcode | (words << 16));
789    spirv_buffer_emit_word(&b->instructions, result_type);
790    spirv_buffer_emit_word(&b->instructions, result);
791    spirv_buffer_emit_word(&b->instructions, image);
792    spirv_buffer_emit_word(&b->instructions, coords);
793 
794    return result;
795 }
796 
797 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)798 spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
799                             SpvId set, uint32_t instruction,
800                             const SpvId *args, size_t num_args)
801 {
802    SpvId result = spirv_builder_new_id(b);
803 
804    int words = 5 + num_args;
805    spirv_buffer_prepare(&b->instructions, b->mem_ctx, words);
806    spirv_buffer_emit_word(&b->instructions, SpvOpExtInst | (words << 16));
807    spirv_buffer_emit_word(&b->instructions, result_type);
808    spirv_buffer_emit_word(&b->instructions, result);
809    spirv_buffer_emit_word(&b->instructions, set);
810    spirv_buffer_emit_word(&b->instructions, instruction);
811    for (int i = 0; i < num_args; ++i)
812       spirv_buffer_emit_word(&b->instructions, args[i]);
813    return result;
814 }
815 
816 struct spirv_type {
817    SpvOp op;
818    uint32_t args[8];
819    size_t num_args;
820 
821    SpvId type;
822 };
823 
824 static uint32_t
non_aggregate_type_hash(const void * arg)825 non_aggregate_type_hash(const void *arg)
826 {
827    const struct spirv_type *type = arg;
828 
829    uint32_t hash = 0;
830    hash = XXH32(&type->op, sizeof(type->op), hash);
831    hash = XXH32(type->args, sizeof(uint32_t) * type->num_args, hash);
832    return hash;
833 }
834 
835 static bool
non_aggregate_type_equals(const void * a,const void * b)836 non_aggregate_type_equals(const void *a, const void *b)
837 {
838    const struct spirv_type *ta = a, *tb = b;
839 
840    if (ta->op != tb->op)
841       return false;
842 
843    assert(ta->num_args == tb->num_args);
844    return memcmp(ta->args, tb->args, sizeof(uint32_t) * ta->num_args) == 0;
845 }
846 
847 static SpvId
get_type_def(struct spirv_builder * b,SpvOp op,const uint32_t args[],size_t num_args)848 get_type_def(struct spirv_builder *b, SpvOp op, const uint32_t args[],
849              size_t num_args)
850 {
851    /* According to the SPIR-V specification:
852     *
853     *   "Two different type <id>s form, by definition, two different types. It
854     *    is valid to declare multiple aggregate type <id>s having the same
855     *    opcode and operands. This is to allow multiple instances of aggregate
856     *    types with the same structure to be decorated differently. (Different
857     *    decorations are not required; two different aggregate type <id>s are
858     *    allowed to have identical declarations and decorations, and will still
859     *    be two different types.) Non-aggregate types are different: It is
860     *    invalid to declare multiple type <id>s for the same scalar, vector, or
861     *    matrix type. That is, non-aggregate type declarations must all have
862     *    different opcodes or operands. (Note that non-aggregate types cannot
863     *    be decorated in ways that affect their type.)"
864     *
865     *  ..so, we need to prevent the same non-aggregate type to be re-defined
866     *  with a new <id>. We do this by putting the definitions in a hash-map, so
867     *  we can easily look up and reuse them.
868     */
869 
870    struct spirv_type key;
871    assert(num_args <= ARRAY_SIZE(key.args));
872    key.op = op;
873    memcpy(&key.args, args, sizeof(uint32_t) * num_args);
874    key.num_args = num_args;
875 
876    struct hash_entry *entry;
877    if (b->types) {
878       entry = _mesa_hash_table_search(b->types, &key);
879       if (entry)
880          return ((struct spirv_type *)entry->data)->type;
881    } else {
882       b->types = _mesa_hash_table_create(b->mem_ctx,
883                                          non_aggregate_type_hash,
884                                          non_aggregate_type_equals);
885       assert(b->types);
886    }
887 
888    struct spirv_type *type = rzalloc(b->mem_ctx, struct spirv_type);
889    if (!type)
890       return 0;
891 
892    type->op = op;
893    memcpy(&type->args, args, sizeof(uint32_t) * num_args);
894    type->num_args = num_args;
895 
896    type->type = spirv_builder_new_id(b);
897    spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 2 + num_args);
898    spirv_buffer_emit_word(&b->types_const_defs, op | ((2 + num_args) << 16));
899    spirv_buffer_emit_word(&b->types_const_defs, type->type);
900    for (int i = 0; i < num_args; ++i)
901       spirv_buffer_emit_word(&b->types_const_defs, args[i]);
902 
903    entry = _mesa_hash_table_insert(b->types, type, type);
904    assert(entry);
905 
906    return ((struct spirv_type *)entry->data)->type;
907 }
908 
909 SpvId
spirv_builder_type_void(struct spirv_builder * b)910 spirv_builder_type_void(struct spirv_builder *b)
911 {
912    return get_type_def(b, SpvOpTypeVoid, NULL, 0);
913 }
914 
915 SpvId
spirv_builder_type_bool(struct spirv_builder * b)916 spirv_builder_type_bool(struct spirv_builder *b)
917 {
918    return get_type_def(b, SpvOpTypeBool, NULL, 0);
919 }
920 
921 SpvId
spirv_builder_type_int(struct spirv_builder * b,unsigned width)922 spirv_builder_type_int(struct spirv_builder *b, unsigned width)
923 {
924    uint32_t args[] = { width, 1 };
925    return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
926 }
927 
928 SpvId
spirv_builder_type_uint(struct spirv_builder * b,unsigned width)929 spirv_builder_type_uint(struct spirv_builder *b, unsigned width)
930 {
931    uint32_t args[] = { width, 0 };
932    return get_type_def(b, SpvOpTypeInt, args, ARRAY_SIZE(args));
933 }
934 
935 SpvId
spirv_builder_type_float(struct spirv_builder * b,unsigned width)936 spirv_builder_type_float(struct spirv_builder *b, unsigned width)
937 {
938    uint32_t args[] = { width };
939    return get_type_def(b, SpvOpTypeFloat, args, ARRAY_SIZE(args));
940 }
941 
942 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)943 spirv_builder_type_image(struct spirv_builder *b, SpvId sampled_type,
944                          SpvDim dim, bool depth, bool arrayed, bool ms,
945                          unsigned sampled, SpvImageFormat image_format)
946 {
947    assert(sampled < 3);
948    uint32_t args[] = {
949       sampled_type, dim, depth ? 1 : 0, arrayed ? 1 : 0, ms ? 1 : 0, sampled,
950       image_format
951    };
952    return get_type_def(b, SpvOpTypeImage, args, ARRAY_SIZE(args));
953 }
954 
955 SpvId
spirv_builder_type_sampled_image(struct spirv_builder * b,SpvId image_type)956 spirv_builder_type_sampled_image(struct spirv_builder *b, SpvId image_type)
957 {
958    uint32_t args[] = { image_type };
959    return get_type_def(b, SpvOpTypeSampledImage, args, ARRAY_SIZE(args));
960 }
961 
962 SpvId
spirv_builder_type_pointer(struct spirv_builder * b,SpvStorageClass storage_class,SpvId type)963 spirv_builder_type_pointer(struct spirv_builder *b,
964                            SpvStorageClass storage_class, SpvId type)
965 {
966    uint32_t args[] = { storage_class, type };
967    return get_type_def(b, SpvOpTypePointer, args, ARRAY_SIZE(args));
968 }
969 
970 SpvId
spirv_builder_type_vector(struct spirv_builder * b,SpvId component_type,unsigned component_count)971 spirv_builder_type_vector(struct spirv_builder *b, SpvId component_type,
972                           unsigned component_count)
973 {
974    assert(component_count > 1);
975    uint32_t args[] = { component_type, component_count };
976    return get_type_def(b, SpvOpTypeVector, args, ARRAY_SIZE(args));
977 }
978 
979 SpvId
spirv_builder_type_matrix(struct spirv_builder * b,SpvId component_type,unsigned component_count)980 spirv_builder_type_matrix(struct spirv_builder *b, SpvId component_type,
981                           unsigned component_count)
982 {
983    assert(component_count > 1);
984    uint32_t args[] = { component_type, component_count };
985    return get_type_def(b, SpvOpTypeMatrix, args, ARRAY_SIZE(args));
986 }
987 
988 SpvId
spirv_builder_type_array(struct spirv_builder * b,SpvId component_type,SpvId length)989 spirv_builder_type_array(struct spirv_builder *b, SpvId component_type,
990                          SpvId length)
991 {
992    SpvId type = spirv_builder_new_id(b);
993    spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 4);
994    spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeArray | (4 << 16));
995    spirv_buffer_emit_word(&b->types_const_defs, type);
996    spirv_buffer_emit_word(&b->types_const_defs, component_type);
997    spirv_buffer_emit_word(&b->types_const_defs, length);
998    return type;
999 }
1000 
1001 SpvId
spirv_builder_type_struct(struct spirv_builder * b,const SpvId member_types[],size_t num_member_types)1002 spirv_builder_type_struct(struct spirv_builder *b, const SpvId member_types[],
1003                           size_t num_member_types)
1004 {
1005    int words = 2 + num_member_types;
1006    SpvId type = spirv_builder_new_id(b);
1007    spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1008    spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeStruct | (words << 16));
1009    spirv_buffer_emit_word(&b->types_const_defs, type);
1010    for (int i = 0; i < num_member_types; ++i)
1011       spirv_buffer_emit_word(&b->types_const_defs, member_types[i]);
1012    return type;
1013 }
1014 
1015 SpvId
spirv_builder_type_function(struct spirv_builder * b,SpvId return_type,const SpvId parameter_types[],size_t num_parameter_types)1016 spirv_builder_type_function(struct spirv_builder *b, SpvId return_type,
1017                             const SpvId parameter_types[],
1018                             size_t num_parameter_types)
1019 {
1020    int words = 3 + num_parameter_types;
1021    SpvId type = spirv_builder_new_id(b);
1022    spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, words);
1023    spirv_buffer_emit_word(&b->types_const_defs, SpvOpTypeFunction | (words << 16));
1024    spirv_buffer_emit_word(&b->types_const_defs, type);
1025    spirv_buffer_emit_word(&b->types_const_defs, return_type);
1026    for (int i = 0; i < num_parameter_types; ++i)
1027       spirv_buffer_emit_word(&b->types_const_defs, parameter_types[i]);
1028    return type;
1029 }
1030 
1031 struct spirv_const {
1032    SpvOp op, type;
1033    uint32_t args[8];
1034    size_t num_args;
1035 
1036    SpvId result;
1037 };
1038 
1039 static uint32_t
const_hash(const void * arg)1040 const_hash(const void *arg)
1041 {
1042    const struct spirv_const *key = arg;
1043 
1044    uint32_t hash = 0;
1045    hash = XXH32(&key->op, sizeof(key->op), hash);
1046    hash = XXH32(&key->type, sizeof(key->type), hash);
1047    hash = XXH32(key->args, sizeof(uint32_t) * key->num_args, hash);
1048    return hash;
1049 }
1050 
1051 static bool
const_equals(const void * a,const void * b)1052 const_equals(const void *a, const void *b)
1053 {
1054    const struct spirv_const *ca = a, *cb = b;
1055 
1056    if (ca->op != cb->op ||
1057        ca->type != cb->type)
1058       return false;
1059 
1060    assert(ca->num_args == cb->num_args);
1061    return memcmp(ca->args, cb->args, sizeof(uint32_t) * ca->num_args) == 0;
1062 }
1063 
1064 static SpvId
get_const_def(struct spirv_builder * b,SpvOp op,SpvId type,const uint32_t args[],size_t num_args)1065 get_const_def(struct spirv_builder *b, SpvOp op, SpvId type,
1066               const uint32_t args[], size_t num_args)
1067 {
1068    struct spirv_const key;
1069    assert(num_args <= ARRAY_SIZE(key.args));
1070    key.op = op;
1071    key.type = type;
1072    memcpy(&key.args, args, sizeof(uint32_t) * num_args);
1073    key.num_args = num_args;
1074 
1075    struct hash_entry *entry;
1076    if (b->consts) {
1077       entry = _mesa_hash_table_search(b->consts, &key);
1078       if (entry)
1079          return ((struct spirv_const *)entry->data)->result;
1080    } else {
1081       b->consts = _mesa_hash_table_create(b->mem_ctx, const_hash,
1082                                           const_equals);
1083       assert(b->consts);
1084    }
1085 
1086    struct spirv_const *cnst = rzalloc(b->mem_ctx, struct spirv_const);
1087    if (!cnst)
1088       return 0;
1089 
1090    cnst->op = op;
1091    cnst->type = type;
1092    memcpy(&cnst->args, args, sizeof(uint32_t) * num_args);
1093    cnst->num_args = num_args;
1094 
1095    cnst->result = spirv_builder_new_id(b);
1096    spirv_buffer_prepare(&b->types_const_defs, b->mem_ctx, 3 + num_args);
1097    spirv_buffer_emit_word(&b->types_const_defs, op | ((3 + num_args) << 16));
1098    spirv_buffer_emit_word(&b->types_const_defs, type);
1099    spirv_buffer_emit_word(&b->types_const_defs, cnst->result);
1100    for (int i = 0; i < num_args; ++i)
1101       spirv_buffer_emit_word(&b->types_const_defs, args[i]);
1102 
1103    entry = _mesa_hash_table_insert(b->consts, cnst, cnst);
1104    assert(entry);
1105 
1106    return ((struct spirv_const *)entry->data)->result;
1107 }
1108 
1109 SpvId
spirv_builder_const_bool(struct spirv_builder * b,bool val)1110 spirv_builder_const_bool(struct spirv_builder *b, bool val)
1111 {
1112    return get_const_def(b, val ? SpvOpConstantTrue : SpvOpConstantFalse,
1113                         spirv_builder_type_bool(b), NULL, 0);
1114 }
1115 
1116 SpvId
spirv_builder_const_int(struct spirv_builder * b,int width,int32_t val)1117 spirv_builder_const_int(struct spirv_builder *b, int width, int32_t val)
1118 {
1119    assert(width <= 32);
1120    uint32_t args[] = { val };
1121    return get_const_def(b, SpvOpConstant, spirv_builder_type_int(b, width),
1122                         args, ARRAY_SIZE(args));
1123 }
1124 
1125 SpvId
spirv_builder_const_uint(struct spirv_builder * b,int width,uint32_t val)1126 spirv_builder_const_uint(struct spirv_builder *b, int width, uint32_t val)
1127 {
1128    assert(width <= 32);
1129    uint32_t args[] = { val };
1130    return get_const_def(b, SpvOpConstant, spirv_builder_type_uint(b, width),
1131                         args, ARRAY_SIZE(args));
1132 }
1133 
1134 SpvId
spirv_builder_const_float(struct spirv_builder * b,int width,float val)1135 spirv_builder_const_float(struct spirv_builder *b, int width, float val)
1136 {
1137    assert(width <= 32);
1138    uint32_t args[] = { u_bitcast_f2u(val) };
1139    return get_const_def(b, SpvOpConstant, spirv_builder_type_float(b, width),
1140                         args, ARRAY_SIZE(args));
1141 }
1142 
1143 SpvId
spirv_builder_const_composite(struct spirv_builder * b,SpvId result_type,const SpvId constituents[],size_t num_constituents)1144 spirv_builder_const_composite(struct spirv_builder *b, SpvId result_type,
1145                               const SpvId constituents[],
1146                               size_t num_constituents)
1147 {
1148    return get_const_def(b, SpvOpConstantComposite, result_type,
1149                         (const uint32_t *)constituents,
1150                         num_constituents);
1151 }
1152 
1153 SpvId
spirv_builder_emit_var(struct spirv_builder * b,SpvId type,SpvStorageClass storage_class)1154 spirv_builder_emit_var(struct spirv_builder *b, SpvId type,
1155                        SpvStorageClass storage_class)
1156 {
1157    assert(storage_class != SpvStorageClassGeneric);
1158    struct spirv_buffer *buf = storage_class != SpvStorageClassFunction ?
1159                               &b->types_const_defs : &b->instructions;
1160 
1161    SpvId ret = spirv_builder_new_id(b);
1162    spirv_buffer_prepare(buf, b->mem_ctx, 4);
1163    spirv_buffer_emit_word(buf, SpvOpVariable | (4 << 16));
1164    spirv_buffer_emit_word(buf, type);
1165    spirv_buffer_emit_word(buf, ret);
1166    spirv_buffer_emit_word(buf, storage_class);
1167    return ret;
1168 }
1169 
1170 void
spirv_builder_emit_memory_barrier(struct spirv_builder * b,SpvScope scope,SpvMemorySemanticsMask semantics)1171 spirv_builder_emit_memory_barrier(struct spirv_builder *b, SpvScope scope, SpvMemorySemanticsMask semantics)
1172 {
1173    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 3);
1174    spirv_buffer_emit_word(&b->instructions, SpvOpMemoryBarrier | (3 << 16));
1175    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1176    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1177 }
1178 
1179 void
spirv_builder_emit_control_barrier(struct spirv_builder * b,SpvScope scope,SpvScope mem_scope,SpvMemorySemanticsMask semantics)1180 spirv_builder_emit_control_barrier(struct spirv_builder *b, SpvScope scope, SpvScope mem_scope, SpvMemorySemanticsMask semantics)
1181 {
1182    spirv_buffer_prepare(&b->instructions, b->mem_ctx, 4);
1183    spirv_buffer_emit_word(&b->instructions, SpvOpControlBarrier | (4 << 16));
1184    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, scope));
1185    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, mem_scope));
1186    spirv_buffer_emit_word(&b->instructions, spirv_builder_const_uint(b, 32, semantics));
1187 }
1188 
1189 SpvId
spirv_builder_import(struct spirv_builder * b,const char * name)1190 spirv_builder_import(struct spirv_builder *b, const char *name)
1191 {
1192    SpvId result = spirv_builder_new_id(b);
1193    size_t pos = b->imports.num_words;
1194    spirv_buffer_prepare(&b->imports, b->mem_ctx, 2);
1195    spirv_buffer_emit_word(&b->imports, SpvOpExtInstImport);
1196    spirv_buffer_emit_word(&b->imports, result);
1197    int len = spirv_buffer_emit_string(&b->imports, b->mem_ctx, name);
1198    b->imports.words[pos] |= (2 + len) << 16;
1199    return result;
1200 }
1201 
1202 size_t
spirv_builder_get_num_words(struct spirv_builder * b)1203 spirv_builder_get_num_words(struct spirv_builder *b)
1204 {
1205    const size_t header_size = 5;
1206    return header_size +
1207           b->capabilities.num_words +
1208           b->extensions.num_words +
1209           b->imports.num_words +
1210           b->memory_model.num_words +
1211           b->entry_points.num_words +
1212           b->exec_modes.num_words +
1213           b->debug_names.num_words +
1214           b->decorations.num_words +
1215           b->types_const_defs.num_words +
1216           b->instructions.num_words;
1217 }
1218 
1219 size_t
spirv_builder_get_words(struct spirv_builder * b,uint32_t * words,size_t num_words)1220 spirv_builder_get_words(struct spirv_builder *b, uint32_t *words,
1221                         size_t num_words)
1222 {
1223    assert(num_words >= spirv_builder_get_num_words(b));
1224 
1225    size_t written  = 0;
1226    words[written++] = SpvMagicNumber;
1227    words[written++] = 0x00010000;
1228    words[written++] = 0;
1229    words[written++] = b->prev_id + 1;
1230    words[written++] = 0;
1231 
1232    const struct spirv_buffer *buffers[] = {
1233       &b->capabilities,
1234       &b->extensions,
1235       &b->imports,
1236       &b->memory_model,
1237       &b->entry_points,
1238       &b->exec_modes,
1239       &b->debug_names,
1240       &b->decorations,
1241       &b->types_const_defs,
1242       &b->instructions
1243    };
1244 
1245    for (int i = 0; i < ARRAY_SIZE(buffers); ++i) {
1246       const struct spirv_buffer *buffer = buffers[i];
1247       for (int j = 0; j < buffer->num_words; ++j)
1248          words[written++] = buffer->words[j];
1249    }
1250 
1251    assert(written == spirv_builder_get_num_words(b));
1252    return written;
1253 }
1254