2 * Copyright © 2017 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
26 #include "nir_spirv.h"
28 #include "vtn_private.h"
29 #include "spirv_info.h"
32 vtn_validate_preamble_instruction(struct vtn_builder
*b
, SpvOp opcode
,
33 const uint32_t *w
, unsigned count
)
37 case SpvOpSourceExtension
:
38 case SpvOpSourceContinued
:
41 case SpvOpExtInstImport
:
42 case SpvOpMemoryModel
:
46 case SpvOpExecutionMode
:
47 case SpvOpDecorationGroup
:
48 case SpvOpMemberDecorate
:
49 case SpvOpGroupDecorate
:
50 case SpvOpGroupMemberDecorate
:
54 vtn_handle_entry_point(b
, w
, count
);
58 vtn_handle_decoration(b
, opcode
, w
, count
);
62 return false; /* End of preamble */
69 spec_constant_decoration_cb(struct vtn_builder
*b
, struct vtn_value
*v
,
70 int member
, const struct vtn_decoration
*dec
,
73 vtn_assert(member
== -1);
74 if (dec
->decoration
!= SpvDecorationSpecId
)
77 for (unsigned i
= 0; i
< b
->num_specializations
; i
++) {
78 if (b
->specializations
[i
].id
== dec
->operands
[0]) {
79 b
->specializations
[i
].defined_on_module
= true;
86 vtn_validate_handle_constant(struct vtn_builder
*b
, SpvOp opcode
,
87 const uint32_t *w
, unsigned count
)
89 struct vtn_value
*val
= vtn_push_value(b
, w
[2], vtn_value_type_constant
);
93 case SpvOpConstantNull
:
94 case SpvOpSpecConstantComposite
:
95 case SpvOpConstantComposite
:
96 /* Nothing to do here for gl_spirv needs */
99 case SpvOpConstantTrue
:
100 case SpvOpConstantFalse
:
101 case SpvOpSpecConstantTrue
:
102 case SpvOpSpecConstantFalse
:
103 case SpvOpSpecConstant
:
104 case SpvOpSpecConstantOp
:
105 vtn_foreach_decoration(b
, val
, spec_constant_decoration_cb
, NULL
);
108 case SpvOpConstantSampler
:
109 vtn_fail("OpConstantSampler requires Kernel Capability");
113 vtn_fail("Unhandled opcode");
118 vtn_validate_handle_constant_instruction(struct vtn_builder
*b
, SpvOp opcode
,
119 const uint32_t *w
, unsigned count
)
123 case SpvOpSourceContinued
:
124 case SpvOpSourceExtension
:
126 case SpvOpCapability
:
127 case SpvOpExtInstImport
:
128 case SpvOpMemoryModel
:
129 case SpvOpEntryPoint
:
130 case SpvOpExecutionMode
:
133 case SpvOpMemberName
:
134 case SpvOpDecorationGroup
:
136 case SpvOpMemberDecorate
:
137 case SpvOpGroupDecorate
:
138 case SpvOpGroupMemberDecorate
:
139 vtn_fail("Invalid opcode types and variables section");
146 case SpvOpTypeVector
:
147 case SpvOpTypeMatrix
:
149 case SpvOpTypeSampler
:
150 case SpvOpTypeSampledImage
:
152 case SpvOpTypeRuntimeArray
:
153 case SpvOpTypeStruct
:
154 case SpvOpTypeOpaque
:
155 case SpvOpTypePointer
:
156 case SpvOpTypeFunction
:
158 case SpvOpTypeDeviceEvent
:
159 case SpvOpTypeReserveId
:
162 /* We don't need to handle types */
165 case SpvOpConstantTrue
:
166 case SpvOpConstantFalse
:
168 case SpvOpConstantComposite
:
169 case SpvOpConstantSampler
:
170 case SpvOpConstantNull
:
171 case SpvOpSpecConstantTrue
:
172 case SpvOpSpecConstantFalse
:
173 case SpvOpSpecConstant
:
174 case SpvOpSpecConstantComposite
:
175 case SpvOpSpecConstantOp
:
176 vtn_validate_handle_constant(b
, opcode
, w
, count
);
181 /* We don't need to handle them */
185 return false; /* End of preamble */
192 * Since OpenGL 4.6 you can use SPIR-V modules directly on OpenGL. One of the
193 * new methods, glSpecializeShader include some possible errors when trying to
196 * From OpenGL 4.6, Section 7.2.1, "Shader Specialization":
198 * "void SpecializeShaderARB(uint shader,
199 * const char* pEntryPoint,
200 * uint numSpecializationConstants,
201 * const uint* pConstantIndex,
202 * const uint* pConstantValue);
205 * INVALID_VALUE is generated if <pEntryPoint> does not name a valid
206 * entry point for <shader>.
208 * An INVALID_VALUE error is generated if any element of pConstantIndex refers
209 * to a specialization constant that does not exist in the shader module
210 * contained in shader."
212 * We could do those checks on spirv_to_nir, but we are only interested on the
213 * full translation later, during linking. This method is a simplified version
214 * of spirv_to_nir, looking for only the checks needed by SpecializeShader.
216 * This method returns NULL if no entry point was found, and fill the
217 * nir_spirv_specialization field "defined_on_module" accordingly. Caller
218 * would need to trigger the specific errors.
222 gl_spirv_validation(const uint32_t *words
, size_t word_count
,
223 struct nir_spirv_specialization
*spec
, unsigned num_spec
,
224 gl_shader_stage stage
, const char *entry_point_name
)
226 /* vtn_warn/vtn_log uses debug.func. Setting a null to prevent crash. Not
227 * need to print the warnings now, would be done later, on the real
230 const struct spirv_to_nir_options options
= { .debug
.func
= NULL
};
231 const uint32_t *word_end
= words
+ word_count
;
233 struct vtn_builder
*b
= vtn_create_builder(words
, word_count
,
234 stage
, entry_point_name
,
240 /* See also _vtn_fail() */
241 if (setjmp(b
->fail_jump
)) {
246 /* Skip the SPIR-V header, handled at vtn_create_builder */
249 /* Search entry point from preamble */
250 words
= vtn_foreach_instruction(b
, words
, word_end
,
251 vtn_validate_preamble_instruction
);
253 if (b
->entry_point
== NULL
) {
258 b
->specializations
= spec
;
259 b
->num_specializations
= num_spec
;
261 /* Handle constant instructions (we don't need to handle
262 * variables or types for gl_spirv)
264 words
= vtn_foreach_instruction(b
, words
, word_end
,
265 vtn_validate_handle_constant_instruction
);