Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/compiler/spirv/gl_spirv.c
4545 views
1
/*
2
* Copyright © 2017 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
*
24
*/
25
26
#include "nir_spirv.h"
27
28
#include "vtn_private.h"
29
#include "spirv_info.h"
30
31
static bool
32
vtn_validate_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
33
const uint32_t *w, unsigned count)
34
{
35
switch (opcode) {
36
case SpvOpSource:
37
case SpvOpSourceExtension:
38
case SpvOpSourceContinued:
39
case SpvOpExtension:
40
case SpvOpCapability:
41
case SpvOpExtInstImport:
42
case SpvOpMemoryModel:
43
case SpvOpString:
44
case SpvOpName:
45
case SpvOpMemberName:
46
case SpvOpExecutionMode:
47
case SpvOpDecorationGroup:
48
case SpvOpMemberDecorate:
49
case SpvOpGroupDecorate:
50
case SpvOpGroupMemberDecorate:
51
break;
52
53
case SpvOpEntryPoint:
54
vtn_handle_entry_point(b, w, count);
55
break;
56
57
case SpvOpDecorate:
58
vtn_handle_decoration(b, opcode, w, count);
59
break;
60
61
default:
62
return false; /* End of preamble */
63
}
64
65
return true;
66
}
67
68
static void
69
spec_constant_decoration_cb(struct vtn_builder *b, struct vtn_value *v,
70
int member, const struct vtn_decoration *dec,
71
void *data)
72
{
73
vtn_assert(member == -1);
74
if (dec->decoration != SpvDecorationSpecId)
75
return;
76
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;
80
return;
81
}
82
}
83
}
84
85
static void
86
vtn_validate_handle_constant(struct vtn_builder *b, SpvOp opcode,
87
const uint32_t *w, unsigned count)
88
{
89
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_constant);
90
91
switch (opcode) {
92
case SpvOpConstant:
93
case SpvOpConstantNull:
94
case SpvOpSpecConstantComposite:
95
case SpvOpConstantComposite:
96
/* Nothing to do here for gl_spirv needs */
97
break;
98
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);
106
break;
107
108
case SpvOpConstantSampler:
109
vtn_fail("OpConstantSampler requires Kernel Capability");
110
break;
111
112
default:
113
vtn_fail("Unhandled opcode");
114
}
115
}
116
117
static bool
118
vtn_validate_handle_constant_instruction(struct vtn_builder *b, SpvOp opcode,
119
const uint32_t *w, unsigned count)
120
{
121
switch (opcode) {
122
case SpvOpSource:
123
case SpvOpSourceContinued:
124
case SpvOpSourceExtension:
125
case SpvOpExtension:
126
case SpvOpCapability:
127
case SpvOpExtInstImport:
128
case SpvOpMemoryModel:
129
case SpvOpEntryPoint:
130
case SpvOpExecutionMode:
131
case SpvOpString:
132
case SpvOpName:
133
case SpvOpMemberName:
134
case SpvOpDecorationGroup:
135
case SpvOpDecorate:
136
case SpvOpMemberDecorate:
137
case SpvOpGroupDecorate:
138
case SpvOpGroupMemberDecorate:
139
vtn_fail("Invalid opcode types and variables section");
140
break;
141
142
case SpvOpTypeVoid:
143
case SpvOpTypeBool:
144
case SpvOpTypeInt:
145
case SpvOpTypeFloat:
146
case SpvOpTypeVector:
147
case SpvOpTypeMatrix:
148
case SpvOpTypeImage:
149
case SpvOpTypeSampler:
150
case SpvOpTypeSampledImage:
151
case SpvOpTypeArray:
152
case SpvOpTypeRuntimeArray:
153
case SpvOpTypeStruct:
154
case SpvOpTypeOpaque:
155
case SpvOpTypePointer:
156
case SpvOpTypeFunction:
157
case SpvOpTypeEvent:
158
case SpvOpTypeDeviceEvent:
159
case SpvOpTypeReserveId:
160
case SpvOpTypeQueue:
161
case SpvOpTypePipe:
162
/* We don't need to handle types */
163
break;
164
165
case SpvOpConstantTrue:
166
case SpvOpConstantFalse:
167
case SpvOpConstant:
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);
177
break;
178
179
case SpvOpUndef:
180
case SpvOpVariable:
181
/* We don't need to handle them */
182
break;
183
184
default:
185
return false; /* End of preamble */
186
}
187
188
return true;
189
}
190
191
/*
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
194
* use it.
195
*
196
* From OpenGL 4.6, Section 7.2.1, "Shader Specialization":
197
*
198
* "void SpecializeShaderARB(uint shader,
199
* const char* pEntryPoint,
200
* uint numSpecializationConstants,
201
* const uint* pConstantIndex,
202
* const uint* pConstantValue);
203
* <skip>
204
*
205
* INVALID_VALUE is generated if <pEntryPoint> does not name a valid
206
* entry point for <shader>.
207
*
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."
211
*
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.
215
*
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.
219
*
220
*/
221
bool
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)
225
{
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
228
* spirv_to_nir
229
*/
230
const struct spirv_to_nir_options options = { .debug.func = NULL};
231
const uint32_t *word_end = words + word_count;
232
233
struct vtn_builder *b = vtn_create_builder(words, word_count,
234
stage, entry_point_name,
235
&options);
236
237
if (b == NULL)
238
return false;
239
240
/* See also _vtn_fail() */
241
if (vtn_setjmp(b->fail_jump)) {
242
ralloc_free(b);
243
return false;
244
}
245
246
/* Skip the SPIR-V header, handled at vtn_create_builder */
247
words+= 5;
248
249
/* Search entry point from preamble */
250
words = vtn_foreach_instruction(b, words, word_end,
251
vtn_validate_preamble_instruction);
252
253
if (b->entry_point == NULL) {
254
ralloc_free(b);
255
return false;
256
}
257
258
b->specializations = spec;
259
b->num_specializations = num_spec;
260
261
/* Handle constant instructions (we don't need to handle
262
* variables or types for gl_spirv)
263
*/
264
words = vtn_foreach_instruction(b, words, word_end,
265
vtn_validate_handle_constant_instruction);
266
267
ralloc_free(b);
268
269
return true;
270
}
271
272
273