2 * Copyright © 2015 Intel Corporation
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:
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
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
24 * Jason Ekstrand (jason@jlekstrand.net)
28 #include "nir_spirv.h"
31 struct vtn_decoration
;
34 vtn_value_type_invalid
= 0,
36 vtn_value_type_string
,
37 vtn_value_type_decoration_group
,
43 enum vtn_value_type value_type
;
45 struct vtn_decoration
*decoration
;
54 struct vtn_decoration
{
55 struct vtn_decoration
*next
;
56 const uint32_t *literals
;
57 struct vtn_value
*group
;
58 SpvDecoration decoration
;
63 nir_function_impl
*impl
;
65 unsigned value_id_bound
;
66 struct vtn_value
*values
;
68 SpvExecutionModel execution_model
;
69 struct vtn_value
*entry_point
;
72 static struct vtn_value
*
73 vtn_push_value(struct vtn_builder
*b
, uint32_t value_id
,
74 enum vtn_value_type value_type
)
76 assert(value_id
< b
->value_id_bound
);
77 assert(b
->values
[value_id
].value_type
== vtn_value_type_invalid
);
79 b
->values
[value_id
].value_type
= value_type
;
81 return &b
->values
[value_id
];
85 vtn_string_literal(struct vtn_builder
*b
, const uint32_t *words
,
88 return ralloc_strndup(b
, (char *)words
, (word_count
- 2) * sizeof(*words
));
92 vtn_handle_extension(struct vtn_builder
*b
, SpvOp opcode
,
93 const uint32_t *w
, unsigned count
)
96 case SpvOpExtInstImport
:
97 /* Do nothing for the moment */
102 unreachable("Unhandled opcode");
106 typedef void (*decoration_foreach_cb
)(struct vtn_builder
*,
108 const struct vtn_decoration
*,
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
)
117 for (struct vtn_decoration
*dec
= value
->decoration
; dec
; dec
= dec
->next
) {
119 assert(dec
->group
->value_type
== vtn_value_type_decoration_group
);
120 _foreach_decoration_helper(b
, base_value
, dec
->group
, cb
, data
);
122 cb(b
, base_value
, dec
, data
);
127 /** Iterates (recursively if needed) over all of the decorations on a value
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.
134 vtn_foreach_decoration(struct vtn_builder
*b
, struct vtn_value
*value
,
135 decoration_foreach_cb cb
, void *data
)
137 _foreach_decoration_helper(b
, value
, value
, cb
, data
);
141 vtn_handle_decoration(struct vtn_builder
*b
, SpvOp opcode
,
142 const uint32_t *w
, unsigned count
)
145 case SpvOpDecorationGroup
:
146 vtn_push_value(b
, w
[1], vtn_value_type_undef
);
149 case SpvOpDecorate
: {
150 struct vtn_value
*val
= &b
->values
[w
[1]];
152 struct vtn_decoration
*dec
= rzalloc(b
, struct vtn_decoration
);
153 dec
->decoration
= w
[2];
154 dec
->literals
= &w
[3];
156 /* Link into the list */
157 dec
->next
= val
->decoration
;
158 val
->decoration
= dec
;
162 case SpvOpGroupDecorate
: {
163 struct vtn_value
*group
= &b
->values
[w
[1]];
164 assert(group
->value_type
== vtn_value_type_decoration_group
);
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
);
171 /* Link into the list */
172 dec
->next
= val
->decoration
;
173 val
->decoration
= dec
;
178 case SpvOpGroupMemberDecorate
:
179 assert(!"Bad instruction. Khronos Bug #13513");
183 unreachable("Unhandled opcode");
188 vtn_handle_type(struct vtn_builder
*b
, SpvOp opcode
,
189 const uint32_t *w
, unsigned count
)
191 unreachable("Unhandled opcode");
195 vtn_handle_constant(struct vtn_builder
*b
, SpvOp opcode
,
196 const uint32_t *w
, unsigned count
)
198 unreachable("Unhandled opcode");
202 vtn_handle_variables(struct vtn_builder
*b
, SpvOp opcode
,
203 const uint32_t *w
, unsigned count
)
205 unreachable("Unhandled opcode");
209 vtn_handle_texture(struct vtn_builder
*b
, SpvOp opcode
,
210 const uint32_t *w
, unsigned count
)
212 unreachable("Unhandled opcode");
216 vtn_handle_alu(struct vtn_builder
*b
, SpvOp opcode
,
217 const uint32_t *w
, unsigned count
)
219 unreachable("Unhandled opcode");
223 vtn_handle_instruction(struct vtn_builder
*b
, SpvOp opcode
,
224 const uint32_t *w
, unsigned count
)
228 case SpvOpSourceExtension
:
229 case SpvOpMemberName
:
232 /* Unhandled, but these are for debug so that's ok. */
236 b
->values
[w
[1]].name
= vtn_string_literal(b
, &w
[2], count
- 2);
240 vtn_push_value(b
, w
[1], vtn_value_type_string
)->str
=
241 vtn_string_literal(b
, &w
[2], count
- 2);
245 vtn_push_value(b
, w
[2], vtn_value_type_undef
);
248 case SpvOpMemoryModel
:
249 assert(w
[1] == SpvAddressingModelLogical
);
250 assert(w
[2] == SpvMemoryModelGLSL450
);
253 case SpvOpEntryPoint
:
254 assert(b
->entry_point
== NULL
);
255 b
->entry_point
= &b
->values
[w
[2]];
256 b
->execution_model
= w
[1];
259 case SpvOpExtInstImport
:
261 vtn_handle_extension(b
, opcode
, w
, count
);
268 case SpvOpTypeVector
:
269 case SpvOpTypeMatrix
:
270 case SpvOpTypeSampler
:
272 case SpvOpTypeRuntimeArray
:
273 case SpvOpTypeStruct
:
274 case SpvOpTypeOpaque
:
275 case SpvOpTypePointer
:
276 case SpvOpTypeFunction
:
278 case SpvOpTypeDeviceEvent
:
279 case SpvOpTypeReserveId
:
282 vtn_handle_type(b
, opcode
, w
, count
);
285 case SpvOpConstantTrue
:
286 case SpvOpConstantFalse
:
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
);
300 case SpvOpVariableArray
:
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
);
312 case SpvOpDecorationGroup
:
314 case SpvOpMemberDecorate
:
315 case SpvOpGroupDecorate
:
316 case SpvOpGroupMemberDecorate
:
317 vtn_handle_decoration(b
, opcode
, w
, count
);
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
);
353 case SpvOpConvertFToU
:
354 case SpvOpConvertFToS
:
355 case SpvOpConvertSToF
:
356 case SpvOpConvertUToF
:
360 case SpvOpConvertPtrToU
:
361 case SpvOpConvertUToPtr
:
362 case SpvOpPtrCastToGeneric
:
363 case SpvOpGenericCastToPtr
:
370 case SpvOpSignBitSet
:
371 case SpvOpLessOrGreater
:
388 case SpvOpVectorTimesScalar
:
389 case SpvOpMatrixTimesScalar
:
390 case SpvOpVectorTimesMatrix
:
391 case SpvOpMatrixTimesVector
:
392 case SpvOpMatrixTimesMatrix
:
393 case SpvOpOuterProduct
:
395 case SpvOpShiftRightLogical
:
396 case SpvOpShiftRightArithmetic
:
397 case SpvOpShiftLeftLogical
:
399 case SpvOpLogicalXor
:
400 case SpvOpLogicalAnd
:
402 case SpvOpBitwiseXor
:
403 case SpvOpBitwiseAnd
:
407 case SpvOpFUnordEqual
:
409 case SpvOpFOrdNotEqual
:
410 case SpvOpFUnordNotEqual
:
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
:
432 case SpvOpFwidthFine
:
433 case SpvOpDPdxCoarse
:
434 case SpvOpDPdyCoarse
:
435 case SpvOpFwidthCoarse
:
436 vtn_handle_alu(b
, opcode
, w
, count
);
440 unreachable("Unhandled opcode");
445 spirv_to_nir(const uint32_t *words
, size_t word_count
,
446 const nir_shader_compiler_options
*options
)
448 /* Handle the SPIR-V header (first 4 dwords) */
449 assert(word_count
> 5);
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);
459 nir_shader
*shader
= nir_shader_create(NULL
, options
);
461 /* Initialize the stn_builder object */
462 struct vtn_builder
*b
= rzalloc(NULL
, struct vtn_builder
);
464 b
->value_id_bound
= value_id_bound
;
465 b
->values
= ralloc_array(b
, struct vtn_value
, value_id_bound
);
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
);
474 vtn_handle_instruction(b
, opcode
, words
, count
);