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