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