nir/spirv: Rework the way values are added
[mesa.git] / src / glsl / nir / spirv_to_nir.c
1 /*
2 * Copyright © 2015 Intel Corporation
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * 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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Jason Ekstrand (jason@jlekstrand.net)
25 *
26 */
27
28 #include "nir_spirv.h"
29 #include "spirv.h"
30
31 struct vtn_decoration;
32
33 enum vtn_value_type {
34 vtn_value_type_invalid = 0,
35 vtn_value_type_undef,
36 vtn_value_type_string,
37 vtn_value_type_decoration_group,
38 vtn_value_type_ssa,
39 vtn_value_type_deref,
40 };
41
42 struct vtn_value {
43 enum vtn_value_type value_type;
44 const char *name;
45 struct vtn_decoration *decoration;
46 union {
47 void *ptr;
48 char *str;
49 nir_ssa_def *ssa;
50 nir_deref_var *deref;
51 };
52 };
53
54 struct vtn_decoration {
55 struct vtn_decoration *next;
56 const uint32_t *literals;
57 struct vtn_value *group;
58 SpvDecoration decoration;
59 };
60
61 struct vtn_builder {
62 nir_shader *shader;
63 nir_function_impl *impl;
64
65 unsigned value_id_bound;
66 struct vtn_value *values;
67
68 SpvExecutionModel execution_model;
69 struct vtn_value *entry_point;
70 };
71
72 static struct vtn_value *
73 vtn_push_value(struct vtn_builder *b, uint32_t value_id,
74 enum vtn_value_type value_type)
75 {
76 assert(value_id < b->value_id_bound);
77 assert(b->values[value_id].value_type == vtn_value_type_invalid);
78
79 b->values[value_id].value_type = value_type;
80
81 return &b->values[value_id];
82 }
83
84 static char *
85 vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
86 unsigned word_count)
87 {
88 return ralloc_strndup(b, (char *)words, (word_count - 2) * sizeof(*words));
89 }
90
91 static void
92 vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
93 const uint32_t *w, unsigned count)
94 {
95 switch (opcode) {
96 case SpvOpExtInstImport:
97 /* Do nothing for the moment */
98 break;
99
100 case SpvOpExtInst:
101 default:
102 unreachable("Unhandled opcode");
103 }
104 }
105
106 typedef void (*decoration_foreach_cb)(struct vtn_builder *,
107 struct vtn_value *,
108 const struct vtn_decoration *,
109 void *);
110
111 static void
112 _foreach_decoration_helper(struct vtn_builder *b,
113 struct vtn_value *base_value,
114 struct vtn_value *value,
115 decoration_foreach_cb cb, void *data)
116 {
117 for (struct vtn_decoration *dec = value->decoration; dec; dec = dec->next) {
118 if (dec->group) {
119 assert(dec->group->value_type == vtn_value_type_decoration_group);
120 _foreach_decoration_helper(b, base_value, dec->group, cb, data);
121 } else {
122 cb(b, base_value, dec, data);
123 }
124 }
125 }
126
127 /** Iterates (recursively if needed) over all of the decorations on a value
128 *
129 * This function iterates over all of the decorations applied to a given
130 * value. If it encounters a decoration group, it recurses into the group
131 * and iterates over all of those decorations as well.
132 */
133 static void
134 vtn_foreach_decoration(struct vtn_builder *b, struct vtn_value *value,
135 decoration_foreach_cb cb, void *data)
136 {
137 _foreach_decoration_helper(b, value, value, cb, data);
138 }
139
140 static void
141 vtn_handle_decoration(struct vtn_builder *b, SpvOp opcode,
142 const uint32_t *w, unsigned count)
143 {
144 switch (opcode) {
145 case SpvOpDecorationGroup:
146 vtn_push_value(b, w[1], vtn_value_type_undef);
147 break;
148
149 case SpvOpDecorate: {
150 struct vtn_value *val = &b->values[w[1]];
151
152 struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);
153 dec->decoration = w[2];
154 dec->literals = &w[3];
155
156 /* Link into the list */
157 dec->next = val->decoration;
158 val->decoration = dec;
159 break;
160 }
161
162 case SpvOpGroupDecorate: {
163 struct vtn_value *group = &b->values[w[1]];
164 assert(group->value_type == vtn_value_type_decoration_group);
165
166 for (unsigned i = 2; i < count; i++) {
167 struct vtn_value *val = &b->values[w[i]];
168 struct vtn_decoration *dec = rzalloc(b, struct vtn_decoration);
169 dec->group = group;
170
171 /* Link into the list */
172 dec->next = val->decoration;
173 val->decoration = dec;
174 }
175 break;
176 }
177
178 case SpvOpGroupMemberDecorate:
179 assert(!"Bad instruction. Khronos Bug #13513");
180 break;
181
182 default:
183 unreachable("Unhandled opcode");
184 }
185 }
186
187 static void
188 vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
189 const uint32_t *w, unsigned count)
190 {
191 unreachable("Unhandled opcode");
192 }
193
194 static void
195 vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
196 const uint32_t *w, unsigned count)
197 {
198 unreachable("Unhandled opcode");
199 }
200
201 static void
202 vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
203 const uint32_t *w, unsigned count)
204 {
205 unreachable("Unhandled opcode");
206 }
207
208 static void
209 vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
210 const uint32_t *w, unsigned count)
211 {
212 unreachable("Unhandled opcode");
213 }
214
215 static void
216 vtn_handle_alu(struct vtn_builder *b, SpvOp opcode,
217 const uint32_t *w, unsigned count)
218 {
219 unreachable("Unhandled opcode");
220 }
221
222 static void
223 vtn_handle_instruction(struct vtn_builder *b, SpvOp opcode,
224 const uint32_t *w, unsigned count)
225 {
226 switch (opcode) {
227 case SpvOpSource:
228 case SpvOpSourceExtension:
229 case SpvOpMemberName:
230 case SpvOpLine:
231 case SpvOpExtension:
232 /* Unhandled, but these are for debug so that's ok. */
233 break;
234
235 case SpvOpName:
236 b->values[w[1]].name = vtn_string_literal(b, &w[2], count - 2);
237 break;
238
239 case SpvOpString:
240 vtn_push_value(b, w[1], vtn_value_type_string)->str =
241 vtn_string_literal(b, &w[2], count - 2);
242 break;
243
244 case SpvOpUndef:
245 vtn_push_value(b, w[2], vtn_value_type_undef);
246 break;
247
248 case SpvOpMemoryModel:
249 assert(w[1] == SpvAddressingModelLogical);
250 assert(w[2] == SpvMemoryModelGLSL450);
251 break;
252
253 case SpvOpEntryPoint:
254 assert(b->entry_point == NULL);
255 b->entry_point = &b->values[w[2]];
256 b->execution_model = w[1];
257 break;
258
259 case SpvOpExtInstImport:
260 case SpvOpExtInst:
261 vtn_handle_extension(b, opcode, w, count);
262 break;
263
264 case SpvOpTypeVoid:
265 case SpvOpTypeBool:
266 case SpvOpTypeInt:
267 case SpvOpTypeFloat:
268 case SpvOpTypeVector:
269 case SpvOpTypeMatrix:
270 case SpvOpTypeSampler:
271 case SpvOpTypeArray:
272 case SpvOpTypeRuntimeArray:
273 case SpvOpTypeStruct:
274 case SpvOpTypeOpaque:
275 case SpvOpTypePointer:
276 case SpvOpTypeFunction:
277 case SpvOpTypeEvent:
278 case SpvOpTypeDeviceEvent:
279 case SpvOpTypeReserveId:
280 case SpvOpTypeQueue:
281 case SpvOpTypePipe:
282 vtn_handle_type(b, opcode, w, count);
283 break;
284
285 case SpvOpConstantTrue:
286 case SpvOpConstantFalse:
287 case SpvOpConstant:
288 case SpvOpConstantComposite:
289 case SpvOpConstantSampler:
290 case SpvOpConstantNullPointer:
291 case SpvOpConstantNullObject:
292 case SpvOpSpecConstantTrue:
293 case SpvOpSpecConstantFalse:
294 case SpvOpSpecConstant:
295 case SpvOpSpecConstantComposite:
296 vtn_handle_constant(b, opcode, w, count);
297 break;
298
299 case SpvOpVariable:
300 case SpvOpVariableArray:
301 case SpvOpLoad:
302 case SpvOpStore:
303 case SpvOpCopyMemory:
304 case SpvOpCopyMemorySized:
305 case SpvOpAccessChain:
306 case SpvOpInBoundsAccessChain:
307 case SpvOpArrayLength:
308 case SpvOpImagePointer:
309 vtn_handle_variables(b, opcode, w, count);
310 break;
311
312 case SpvOpDecorationGroup:
313 case SpvOpDecorate:
314 case SpvOpMemberDecorate:
315 case SpvOpGroupDecorate:
316 case SpvOpGroupMemberDecorate:
317 vtn_handle_decoration(b, opcode, w, count);
318 break;
319
320 case SpvOpTextureSample:
321 case SpvOpTextureSampleDref:
322 case SpvOpTextureSampleLod:
323 case SpvOpTextureSampleProj:
324 case SpvOpTextureSampleGrad:
325 case SpvOpTextureSampleOffset:
326 case SpvOpTextureSampleProjLod:
327 case SpvOpTextureSampleProjGrad:
328 case SpvOpTextureSampleLodOffset:
329 case SpvOpTextureSampleProjOffset:
330 case SpvOpTextureSampleGradOffset:
331 case SpvOpTextureSampleProjLodOffset:
332 case SpvOpTextureSampleProjGradOffset:
333 case SpvOpTextureFetchTexelLod:
334 case SpvOpTextureFetchTexelOffset:
335 case SpvOpTextureFetchSample:
336 case SpvOpTextureFetchTexel:
337 case SpvOpTextureGather:
338 case SpvOpTextureGatherOffset:
339 case SpvOpTextureGatherOffsets:
340 case SpvOpTextureQuerySizeLod:
341 case SpvOpTextureQuerySize:
342 case SpvOpTextureQueryLod:
343 case SpvOpTextureQueryLevels:
344 case SpvOpTextureQuerySamples:
345 vtn_handle_texture(b, opcode, w, count);
346 break;
347
348 case SpvOpSNegate:
349 case SpvOpFNegate:
350 case SpvOpNot:
351 case SpvOpAny:
352 case SpvOpAll:
353 case SpvOpConvertFToU:
354 case SpvOpConvertFToS:
355 case SpvOpConvertSToF:
356 case SpvOpConvertUToF:
357 case SpvOpUConvert:
358 case SpvOpSConvert:
359 case SpvOpFConvert:
360 case SpvOpConvertPtrToU:
361 case SpvOpConvertUToPtr:
362 case SpvOpPtrCastToGeneric:
363 case SpvOpGenericCastToPtr:
364 case SpvOpBitcast:
365 case SpvOpTranspose:
366 case SpvOpIsNan:
367 case SpvOpIsInf:
368 case SpvOpIsFinite:
369 case SpvOpIsNormal:
370 case SpvOpSignBitSet:
371 case SpvOpLessOrGreater:
372 case SpvOpOrdered:
373 case SpvOpUnordered:
374 case SpvOpIAdd:
375 case SpvOpFAdd:
376 case SpvOpISub:
377 case SpvOpFSub:
378 case SpvOpIMul:
379 case SpvOpFMul:
380 case SpvOpUDiv:
381 case SpvOpSDiv:
382 case SpvOpFDiv:
383 case SpvOpUMod:
384 case SpvOpSRem:
385 case SpvOpSMod:
386 case SpvOpFRem:
387 case SpvOpFMod:
388 case SpvOpVectorTimesScalar:
389 case SpvOpMatrixTimesScalar:
390 case SpvOpVectorTimesMatrix:
391 case SpvOpMatrixTimesVector:
392 case SpvOpMatrixTimesMatrix:
393 case SpvOpOuterProduct:
394 case SpvOpDot:
395 case SpvOpShiftRightLogical:
396 case SpvOpShiftRightArithmetic:
397 case SpvOpShiftLeftLogical:
398 case SpvOpLogicalOr:
399 case SpvOpLogicalXor:
400 case SpvOpLogicalAnd:
401 case SpvOpBitwiseOr:
402 case SpvOpBitwiseXor:
403 case SpvOpBitwiseAnd:
404 case SpvOpSelect:
405 case SpvOpIEqual:
406 case SpvOpFOrdEqual:
407 case SpvOpFUnordEqual:
408 case SpvOpINotEqual:
409 case SpvOpFOrdNotEqual:
410 case SpvOpFUnordNotEqual:
411 case SpvOpULessThan:
412 case SpvOpSLessThan:
413 case SpvOpFOrdLessThan:
414 case SpvOpFUnordLessThan:
415 case SpvOpUGreaterThan:
416 case SpvOpSGreaterThan:
417 case SpvOpFOrdGreaterThan:
418 case SpvOpFUnordGreaterThan:
419 case SpvOpULessThanEqual:
420 case SpvOpSLessThanEqual:
421 case SpvOpFOrdLessThanEqual:
422 case SpvOpFUnordLessThanEqual:
423 case SpvOpUGreaterThanEqual:
424 case SpvOpSGreaterThanEqual:
425 case SpvOpFOrdGreaterThanEqual:
426 case SpvOpFUnordGreaterThanEqual:
427 case SpvOpDPdx:
428 case SpvOpDPdy:
429 case SpvOpFwidth:
430 case SpvOpDPdxFine:
431 case SpvOpDPdyFine:
432 case SpvOpFwidthFine:
433 case SpvOpDPdxCoarse:
434 case SpvOpDPdyCoarse:
435 case SpvOpFwidthCoarse:
436 vtn_handle_alu(b, opcode, w, count);
437 break;
438
439 default:
440 unreachable("Unhandled opcode");
441 }
442 }
443
444 nir_shader *
445 spirv_to_nir(const uint32_t *words, size_t word_count,
446 const nir_shader_compiler_options *options)
447 {
448 /* Handle the SPIR-V header (first 4 dwords) */
449 assert(word_count > 5);
450
451 assert(words[0] == SpvMagicNumber);
452 assert(words[1] == 99);
453 /* words[2] == generator magic */
454 unsigned value_id_bound = words[3];
455 assert(words[4] == 0);
456
457 words+= 5;
458
459 nir_shader *shader = nir_shader_create(NULL, options);
460
461 /* Initialize the stn_builder object */
462 struct vtn_builder *b = rzalloc(NULL, struct vtn_builder);
463 b->shader = shader;
464 b->value_id_bound = value_id_bound;
465 b->values = ralloc_array(b, struct vtn_value, value_id_bound);
466
467 /* Start handling instructions */
468 const uint32_t *word_end = words + word_count;
469 while (words < word_end) {
470 SpvOp opcode = words[0] & SpvOpCodeMask;
471 unsigned count = words[0] >> SpvWordCountShift;
472 assert(words + count <= word_end);
473
474 vtn_handle_instruction(b, opcode, words, count);
475
476 words += count;
477 }
478
479 ralloc_free(b);
480
481 return shader;
482 }