1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Validation tests for decorations
16
17 #include <string>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "source/val/decoration.h"
22 #include "test/unit_spirv.h"
23 #include "test/val/val_code_generator.h"
24 #include "test/val/val_fixtures.h"
25
26 namespace spvtools {
27 namespace val {
28 namespace {
29
30 using ::testing::Combine;
31 using ::testing::Eq;
32 using ::testing::HasSubstr;
33 using ::testing::Values;
34
35 struct TestResult {
TestResultspvtools::val::__anonb626e3150111::TestResult36 TestResult(spv_result_t in_validation_result = SPV_SUCCESS,
37 const std::string& in_error_str = "")
38 : validation_result(in_validation_result), error_str(in_error_str) {}
39 spv_result_t validation_result;
40 const std::string error_str;
41 };
42
43 using ValidateDecorations = spvtest::ValidateBase<bool>;
44 using ValidateDecorationString = spvtest::ValidateBase<std::string>;
45 using ValidateVulkanCombineDecorationResult =
46 spvtest::ValidateBase<std::tuple<const char*, const char*, TestResult>>;
47
TEST_F(ValidateDecorations,ValidateOpDecorateRegistration)48 TEST_F(ValidateDecorations, ValidateOpDecorateRegistration) {
49 std::string spirv = R"(
50 OpCapability Shader
51 OpCapability Linkage
52 OpMemoryModel Logical GLSL450
53 OpDecorate %1 Location 4
54 OpDecorate %1 Centroid
55 %2 = OpTypeFloat 32
56 %3 = OpTypePointer Output %2
57 %1 = OpVariable %3 Output
58 ; Since %1 is used first in Decoration, it gets id 1.
59 )";
60 const uint32_t id = 1;
61 CompileSuccessfully(spirv);
62 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
63 // Must have 2 decorations.
64 EXPECT_THAT(
65 vstate_->id_decorations(id),
66 Eq(std::set<Decoration>{Decoration(spv::Decoration::Location, {4}),
67 Decoration(spv::Decoration::Centroid)}));
68 }
69
TEST_F(ValidateDecorations,ValidateOpMemberDecorateRegistration)70 TEST_F(ValidateDecorations, ValidateOpMemberDecorateRegistration) {
71 std::string spirv = R"(
72 OpCapability Shader
73 OpCapability Linkage
74 OpMemoryModel Logical GLSL450
75 OpDecorate %_arr_double_uint_6 ArrayStride 4
76 OpMemberDecorate %_struct_115 2 NonReadable
77 OpMemberDecorate %_struct_115 2 Offset 2
78 OpDecorate %_struct_115 BufferBlock
79 %float = OpTypeFloat 32
80 %uint = OpTypeInt 32 0
81 %uint_6 = OpConstant %uint 6
82 %_arr_double_uint_6 = OpTypeArray %float %uint_6
83 %_struct_115 = OpTypeStruct %float %float %_arr_double_uint_6
84 )";
85 CompileSuccessfully(spirv);
86 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
87
88 // The array must have 1 decoration.
89 const uint32_t arr_id = 1;
90 EXPECT_THAT(
91 vstate_->id_decorations(arr_id),
92 Eq(std::set<Decoration>{Decoration(spv::Decoration::ArrayStride, {4})}));
93
94 // The struct must have 3 decorations.
95 const uint32_t struct_id = 2;
96 EXPECT_THAT(
97 vstate_->id_decorations(struct_id),
98 Eq(std::set<Decoration>{Decoration(spv::Decoration::NonReadable, {}, 2),
99 Decoration(spv::Decoration::Offset, {2}, 2),
100 Decoration(spv::Decoration::BufferBlock)}));
101 }
102
TEST_F(ValidateDecorations,ValidateOpMemberDecorateOutOfBound)103 TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) {
104 std::string spirv = R"(
105 OpCapability Shader
106 OpMemoryModel Logical GLSL450
107 OpEntryPoint Fragment %1 "Main"
108 OpExecutionMode %1 OriginUpperLeft
109 OpMemberDecorate %_struct_2 1 RelaxedPrecision
110 %void = OpTypeVoid
111 %4 = OpTypeFunction %void
112 %float = OpTypeFloat 32
113 %_struct_2 = OpTypeStruct %float
114 %1 = OpFunction %void None %4
115 %6 = OpLabel
116 OpReturn
117 OpFunctionEnd
118 )";
119 CompileSuccessfully(spirv);
120 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
121 EXPECT_THAT(getDiagnosticString(),
122 HasSubstr("Index 1 provided in OpMemberDecorate for struct <id> "
123 "'2[%_struct_2]' is out of bounds. The structure has 1 "
124 "members. Largest valid index is 0."));
125 }
126
TEST_F(ValidateDecorations,ValidateGroupDecorateRegistration)127 TEST_F(ValidateDecorations, ValidateGroupDecorateRegistration) {
128 std::string spirv = R"(
129 OpCapability Shader
130 OpCapability Linkage
131 OpMemoryModel Logical GLSL450
132 OpDecorate %1 DescriptorSet 0
133 OpDecorate %1 RelaxedPrecision
134 OpDecorate %1 Restrict
135 %1 = OpDecorationGroup
136 OpGroupDecorate %1 %2 %3
137 OpGroupDecorate %1 %4
138 %float = OpTypeFloat 32
139 %_runtimearr_float = OpTypeRuntimeArray %float
140 %_struct_9 = OpTypeStruct %_runtimearr_float
141 %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
142 %2 = OpVariable %_ptr_Uniform__struct_9 Uniform
143 %_struct_10 = OpTypeStruct %_runtimearr_float
144 %_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10
145 %3 = OpVariable %_ptr_Uniform__struct_10 Uniform
146 %_struct_11 = OpTypeStruct %_runtimearr_float
147 %_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11
148 %4 = OpVariable %_ptr_Uniform__struct_11 Uniform
149 )";
150 CompileSuccessfully(spirv);
151 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
152
153 // Decoration group has 3 decorations.
154 auto expected_decorations =
155 std::set<Decoration>{Decoration(spv::Decoration::DescriptorSet, {0}),
156 Decoration(spv::Decoration::RelaxedPrecision),
157 Decoration(spv::Decoration::Restrict)};
158
159 // Decoration group is applied to id 1, 2, 3, and 4. Note that id 1 (which is
160 // the decoration group id) also has all the decorations.
161 EXPECT_THAT(vstate_->id_decorations(1), Eq(expected_decorations));
162 EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
163 EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations));
164 EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations));
165 }
166
TEST_F(ValidateDecorations,ValidateGroupMemberDecorateRegistration)167 TEST_F(ValidateDecorations, ValidateGroupMemberDecorateRegistration) {
168 std::string spirv = R"(
169 OpCapability Shader
170 OpCapability Linkage
171 OpMemoryModel Logical GLSL450
172 OpDecorate %1 Offset 3
173 %1 = OpDecorationGroup
174 OpGroupMemberDecorate %1 %_struct_1 3 %_struct_2 3 %_struct_3 3
175 %float = OpTypeFloat 32
176 %_runtimearr = OpTypeRuntimeArray %float
177 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
178 %_struct_2 = OpTypeStruct %float %float %float %_runtimearr
179 %_struct_3 = OpTypeStruct %float %float %float %_runtimearr
180 )";
181 CompileSuccessfully(spirv);
182 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
183 // Decoration group has 1 decoration.
184 auto expected_decorations =
185 std::set<Decoration>{Decoration(spv::Decoration::Offset, {3}, 3)};
186
187 // Decoration group is applied to id 2, 3, and 4.
188 EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
189 EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations));
190 EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations));
191 }
192
TEST_F(ValidateDecorations,LinkageImportUsedForInitializedVariableBad)193 TEST_F(ValidateDecorations, LinkageImportUsedForInitializedVariableBad) {
194 std::string spirv = R"(
195 OpCapability Shader
196 OpCapability Linkage
197 OpMemoryModel Logical GLSL450
198 OpDecorate %target LinkageAttributes "link_ptr" Import
199 %float = OpTypeFloat 32
200 %_ptr_float = OpTypePointer Uniform %float
201 %zero = OpConstantNull %float
202 %target = OpVariable %_ptr_float Uniform %zero
203 )";
204 CompileSuccessfully(spirv);
205 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
206 EXPECT_THAT(getDiagnosticString(),
207 HasSubstr("A module-scope OpVariable with initialization value "
208 "cannot be marked with the Import Linkage Type."));
209 }
TEST_F(ValidateDecorations,LinkageExportUsedForInitializedVariableGood)210 TEST_F(ValidateDecorations, LinkageExportUsedForInitializedVariableGood) {
211 std::string spirv = R"(
212 OpCapability Shader
213 OpCapability Linkage
214 OpMemoryModel Logical GLSL450
215 OpDecorate %target LinkageAttributes "link_ptr" Export
216 %float = OpTypeFloat 32
217 %_ptr_float = OpTypePointer Uniform %float
218 %zero = OpConstantNull %float
219 %target = OpVariable %_ptr_float Uniform %zero
220 )";
221 CompileSuccessfully(spirv);
222 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
223 }
224
TEST_F(ValidateDecorations,StructAllMembersHaveBuiltInDecorationsGood)225 TEST_F(ValidateDecorations, StructAllMembersHaveBuiltInDecorationsGood) {
226 std::string spirv = R"(
227 OpCapability Shader
228 OpCapability Linkage
229 OpMemoryModel Logical GLSL450
230 OpDecorate %_struct_1 Block
231 OpMemberDecorate %_struct_1 0 BuiltIn Position
232 OpMemberDecorate %_struct_1 1 BuiltIn Position
233 OpMemberDecorate %_struct_1 2 BuiltIn Position
234 OpMemberDecorate %_struct_1 3 BuiltIn Position
235 %float = OpTypeFloat 32
236 %_runtimearr = OpTypeRuntimeArray %float
237 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
238 )";
239 CompileSuccessfully(spirv);
240 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
241 }
242
TEST_F(ValidateDecorations,MixedBuiltInDecorationsBad)243 TEST_F(ValidateDecorations, MixedBuiltInDecorationsBad) {
244 std::string spirv = R"(
245 OpCapability Shader
246 OpCapability Linkage
247 OpMemoryModel Logical GLSL450
248 OpDecorate %_struct_1 Block
249 OpMemberDecorate %_struct_1 0 BuiltIn Position
250 OpMemberDecorate %_struct_1 1 BuiltIn Position
251 %float = OpTypeFloat 32
252 %_runtimearr = OpTypeRuntimeArray %float
253 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
254 )";
255 CompileSuccessfully(spirv);
256 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
257 EXPECT_THAT(
258 getDiagnosticString(),
259 HasSubstr("When BuiltIn decoration is applied to a structure-type "
260 "member, all members of that structure type must also be "
261 "decorated with BuiltIn (No allowed mixing of built-in "
262 "variables and non-built-in variables within a single "
263 "structure). Structure id 1 does not meet this requirement."));
264 }
265
TEST_F(ValidateDecorations,StructContainsBuiltInStructBad)266 TEST_F(ValidateDecorations, StructContainsBuiltInStructBad) {
267 std::string spirv = R"(
268 OpCapability Shader
269 OpCapability Linkage
270 OpMemoryModel Logical GLSL450
271 OpDecorate %_struct_1 Block
272 OpMemberDecorate %_struct_1 0 BuiltIn Position
273 OpMemberDecorate %_struct_1 1 BuiltIn Position
274 OpMemberDecorate %_struct_1 2 BuiltIn Position
275 OpMemberDecorate %_struct_1 3 BuiltIn Position
276 %float = OpTypeFloat 32
277 %_runtimearr = OpTypeRuntimeArray %float
278 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
279 %_struct_2 = OpTypeStruct %_struct_1
280 )";
281 CompileSuccessfully(spirv);
282 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
283 EXPECT_THAT(
284 getDiagnosticString(),
285 HasSubstr("Structure <id> '1[%_struct_1]' contains members with "
286 "BuiltIn decoration. Therefore this structure may not "
287 "be contained as a member of another structure type. "
288 "Structure <id> '4[%_struct_4]' contains structure <id> "
289 "'1[%_struct_1]'."));
290 }
291
TEST_F(ValidateDecorations,StructContainsNonBuiltInStructGood)292 TEST_F(ValidateDecorations, StructContainsNonBuiltInStructGood) {
293 std::string spirv = R"(
294 OpCapability Shader
295 OpCapability Linkage
296 OpMemoryModel Logical GLSL450
297 %float = OpTypeFloat 32
298 %_struct_1 = OpTypeStruct %float
299 %_struct_2 = OpTypeStruct %_struct_1
300 )";
301 CompileSuccessfully(spirv);
302 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
303 }
304
TEST_F(ValidateDecorations,MultipleBuiltInObjectsConsumedByOpEntryPointBad)305 TEST_F(ValidateDecorations, MultipleBuiltInObjectsConsumedByOpEntryPointBad) {
306 std::string spirv = R"(
307 OpCapability Shader
308 OpCapability Geometry
309 OpMemoryModel Logical GLSL450
310 OpEntryPoint Geometry %main "main" %in_1 %in_2
311 OpExecutionMode %main InputPoints
312 OpExecutionMode %main OutputPoints
313 OpDecorate %struct_1 Block
314 OpDecorate %struct_2 Block
315 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
316 OpMemberDecorate %struct_2 0 BuiltIn Position
317 %int = OpTypeInt 32 1
318 %void = OpTypeVoid
319 %func = OpTypeFunction %void
320 %float = OpTypeFloat 32
321 %struct_1 = OpTypeStruct %int
322 %struct_2 = OpTypeStruct %float
323 %ptr_builtin_1 = OpTypePointer Input %struct_1
324 %ptr_builtin_2 = OpTypePointer Input %struct_2
325 %in_1 = OpVariable %ptr_builtin_1 Input
326 %in_2 = OpVariable %ptr_builtin_2 Input
327 %main = OpFunction %void None %func
328 %5 = OpLabel
329 OpReturn
330 OpFunctionEnd
331 )";
332 CompileSuccessfully(spirv);
333 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
334 EXPECT_THAT(getDiagnosticString(),
335 HasSubstr("There must be at most one object per Storage Class "
336 "that can contain a structure type containing members "
337 "decorated with BuiltIn, consumed per entry-point."));
338 }
339
TEST_F(ValidateDecorations,OneBuiltInObjectPerStorageClassConsumedByOpEntryPointGood)340 TEST_F(ValidateDecorations,
341 OneBuiltInObjectPerStorageClassConsumedByOpEntryPointGood) {
342 std::string spirv = R"(
343 OpCapability Shader
344 OpCapability Geometry
345 OpMemoryModel Logical GLSL450
346 OpEntryPoint Geometry %main "main" %in_1 %out_1
347 OpExecutionMode %main InputPoints
348 OpExecutionMode %main OutputPoints
349 OpDecorate %struct_1 Block
350 OpDecorate %struct_2 Block
351 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
352 OpMemberDecorate %struct_2 0 BuiltIn Position
353 %int = OpTypeInt 32 1
354 %void = OpTypeVoid
355 %func = OpTypeFunction %void
356 %float = OpTypeFloat 32
357 %struct_1 = OpTypeStruct %int
358 %struct_2 = OpTypeStruct %float
359 %ptr_builtin_1 = OpTypePointer Input %struct_1
360 %ptr_builtin_2 = OpTypePointer Output %struct_2
361 %in_1 = OpVariable %ptr_builtin_1 Input
362 %out_1 = OpVariable %ptr_builtin_2 Output
363 %main = OpFunction %void None %func
364 %5 = OpLabel
365 OpReturn
366 OpFunctionEnd
367 )";
368 CompileSuccessfully(spirv);
369 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
370 }
371
TEST_F(ValidateDecorations,NoBuiltInObjectsConsumedByOpEntryPointGood)372 TEST_F(ValidateDecorations, NoBuiltInObjectsConsumedByOpEntryPointGood) {
373 std::string spirv = R"(
374 OpCapability Shader
375 OpCapability Geometry
376 OpMemoryModel Logical GLSL450
377 OpEntryPoint Geometry %main "main" %in_1 %out_1
378 OpExecutionMode %main InputPoints
379 OpExecutionMode %main OutputPoints
380 %int = OpTypeInt 32 1
381 %void = OpTypeVoid
382 %func = OpTypeFunction %void
383 %float = OpTypeFloat 32
384 %struct_1 = OpTypeStruct %int
385 %struct_2 = OpTypeStruct %float
386 %ptr_builtin_1 = OpTypePointer Input %struct_1
387 %ptr_builtin_2 = OpTypePointer Output %struct_2
388 %in_1 = OpVariable %ptr_builtin_1 Input
389 %out_1 = OpVariable %ptr_builtin_2 Output
390 %main = OpFunction %void None %func
391 %5 = OpLabel
392 OpReturn
393 OpFunctionEnd
394 )";
395 CompileSuccessfully(spirv);
396 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
397 }
398
TEST_F(ValidateDecorations,EntryPointFunctionHasLinkageAttributeBad)399 TEST_F(ValidateDecorations, EntryPointFunctionHasLinkageAttributeBad) {
400 std::string spirv = R"(
401 OpCapability Shader
402 OpCapability Linkage
403 OpMemoryModel Logical GLSL450
404 OpEntryPoint GLCompute %main "main"
405 OpDecorate %main LinkageAttributes "import_main" Import
406 %1 = OpTypeVoid
407 %2 = OpTypeFunction %1
408 %main = OpFunction %1 None %2
409 %4 = OpLabel
410 OpReturn
411 OpFunctionEnd
412 )";
413 CompileSuccessfully(spirv.c_str());
414 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
415 EXPECT_THAT(
416 getDiagnosticString(),
417 HasSubstr("The LinkageAttributes Decoration (Linkage name: import_main) "
418 "cannot be applied to function id 1 because it is targeted by "
419 "an OpEntryPoint instruction."));
420 }
421
TEST_F(ValidateDecorations,FunctionDeclarationWithoutImportLinkageBad)422 TEST_F(ValidateDecorations, FunctionDeclarationWithoutImportLinkageBad) {
423 std::string spirv = R"(
424 OpCapability Shader
425 OpCapability Linkage
426 OpMemoryModel Logical GLSL450
427 %void = OpTypeVoid
428 %func = OpTypeFunction %void
429 %main = OpFunction %void None %func
430 OpFunctionEnd
431 )";
432 CompileSuccessfully(spirv);
433 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
434 EXPECT_THAT(
435 getDiagnosticString(),
436 HasSubstr("Function declaration (id 3) must have a LinkageAttributes "
437 "decoration with the Import Linkage type."));
438 }
439
TEST_F(ValidateDecorations,FunctionDeclarationWithImportLinkageGood)440 TEST_F(ValidateDecorations, FunctionDeclarationWithImportLinkageGood) {
441 std::string spirv = R"(
442 OpCapability Shader
443 OpCapability Linkage
444 OpMemoryModel Logical GLSL450
445 OpDecorate %main LinkageAttributes "link_fn" Import
446 %void = OpTypeVoid
447 %func = OpTypeFunction %void
448 %main = OpFunction %void None %func
449 OpFunctionEnd
450 )";
451 CompileSuccessfully(spirv);
452 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
453 }
454
TEST_F(ValidateDecorations,FunctionDeclarationWithExportLinkageBad)455 TEST_F(ValidateDecorations, FunctionDeclarationWithExportLinkageBad) {
456 std::string spirv = R"(
457 OpCapability Shader
458 OpCapability Linkage
459 OpMemoryModel Logical GLSL450
460 OpDecorate %main LinkageAttributes "link_fn" Export
461 %void = OpTypeVoid
462 %func = OpTypeFunction %void
463 %main = OpFunction %void None %func
464 OpFunctionEnd
465 )";
466 CompileSuccessfully(spirv);
467 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
468 EXPECT_THAT(
469 getDiagnosticString(),
470 HasSubstr("Function declaration (id 1) must have a LinkageAttributes "
471 "decoration with the Import Linkage type."));
472 }
473
TEST_F(ValidateDecorations,FunctionDefinitionWithImportLinkageBad)474 TEST_F(ValidateDecorations, FunctionDefinitionWithImportLinkageBad) {
475 std::string spirv = R"(
476 OpCapability Shader
477 OpCapability Linkage
478 OpMemoryModel Logical GLSL450
479 OpDecorate %main LinkageAttributes "link_fn" Import
480 %void = OpTypeVoid
481 %func = OpTypeFunction %void
482 %main = OpFunction %void None %func
483 %label = OpLabel
484 OpReturn
485 OpFunctionEnd
486 )";
487 CompileSuccessfully(spirv);
488 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
489 EXPECT_THAT(getDiagnosticString(),
490 HasSubstr("Function definition (id 1) may not be decorated with "
491 "Import Linkage type."));
492 }
493
TEST_F(ValidateDecorations,FunctionDefinitionWithoutImportLinkageGood)494 TEST_F(ValidateDecorations, FunctionDefinitionWithoutImportLinkageGood) {
495 std::string spirv = R"(
496 OpCapability Shader
497 OpCapability Linkage
498 OpMemoryModel Logical GLSL450
499 %void = OpTypeVoid
500 %func = OpTypeFunction %void
501 %main = OpFunction %void None %func
502 %label = OpLabel
503 OpReturn
504 OpFunctionEnd
505 )";
506 CompileSuccessfully(spirv);
507 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
508 }
509
TEST_F(ValidateDecorations,BuiltinVariablesGoodVulkan)510 TEST_F(ValidateDecorations, BuiltinVariablesGoodVulkan) {
511 const spv_target_env env = SPV_ENV_VULKAN_1_0;
512 std::string spirv = R"(
513 OpCapability Shader
514 OpMemoryModel Logical GLSL450
515 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
516 OpExecutionMode %main OriginUpperLeft
517 OpSource HLSL 500
518 OpDecorate %gl_FragCoord BuiltIn FragCoord
519 OpDecorate %_entryPointOutput Location 0
520 %void = OpTypeVoid
521 %3 = OpTypeFunction %void
522 %float = OpTypeFloat 32
523 %v4float = OpTypeVector %float 4
524 %float_0 = OpConstant %float 0
525 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
526 %_ptr_Input_v4float = OpTypePointer Input %v4float
527 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
528 %_ptr_Output_v4float = OpTypePointer Output %v4float
529 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
530 %main = OpFunction %void None %3
531 %5 = OpLabel
532 OpStore %_entryPointOutput %14
533 OpReturn
534 OpFunctionEnd
535 )";
536
537 CompileSuccessfully(spirv, env);
538 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
539 }
540
TEST_F(ValidateDecorations,BuiltinVariablesWithLocationDecorationVulkan)541 TEST_F(ValidateDecorations, BuiltinVariablesWithLocationDecorationVulkan) {
542 const spv_target_env env = SPV_ENV_VULKAN_1_0;
543 std::string spirv = R"(
544 OpCapability Shader
545 OpMemoryModel Logical GLSL450
546 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
547 OpExecutionMode %main OriginUpperLeft
548 OpSource HLSL 500
549 OpDecorate %gl_FragCoord BuiltIn FragCoord
550 OpDecorate %gl_FragCoord Location 0
551 OpDecorate %_entryPointOutput Location 0
552 %void = OpTypeVoid
553 %3 = OpTypeFunction %void
554 %float = OpTypeFloat 32
555 %v4float = OpTypeVector %float 4
556 %float_0 = OpConstant %float 0
557 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
558 %_ptr_Input_v4float = OpTypePointer Input %v4float
559 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
560 %_ptr_Output_v4float = OpTypePointer Output %v4float
561 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
562 %main = OpFunction %void None %3
563 %5 = OpLabel
564 OpStore %_entryPointOutput %14
565 OpReturn
566 OpFunctionEnd
567 )";
568
569 CompileSuccessfully(spirv, env);
570 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
571 EXPECT_THAT(getDiagnosticString(),
572 AnyVUID("VUID-StandaloneSpirv-Location-04915"));
573 EXPECT_THAT(getDiagnosticString(),
574 HasSubstr("A BuiltIn variable (id 2) cannot have any Location or "
575 "Component decorations"));
576 }
TEST_F(ValidateDecorations,BuiltinVariablesWithComponentDecorationVulkan)577 TEST_F(ValidateDecorations, BuiltinVariablesWithComponentDecorationVulkan) {
578 const spv_target_env env = SPV_ENV_VULKAN_1_0;
579 std::string spirv = R"(
580 OpCapability Shader
581 OpMemoryModel Logical GLSL450
582 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
583 OpExecutionMode %main OriginUpperLeft
584 OpSource HLSL 500
585 OpDecorate %gl_FragCoord BuiltIn FragCoord
586 OpDecorate %gl_FragCoord Component 0
587 OpDecorate %_entryPointOutput Location 0
588 %void = OpTypeVoid
589 %3 = OpTypeFunction %void
590 %float = OpTypeFloat 32
591 %v4float = OpTypeVector %float 4
592 %float_0 = OpConstant %float 0
593 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
594 %_ptr_Input_v4float = OpTypePointer Input %v4float
595 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
596 %_ptr_Output_v4float = OpTypePointer Output %v4float
597 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
598 %main = OpFunction %void None %3
599 %5 = OpLabel
600 OpStore %_entryPointOutput %14
601 OpReturn
602 OpFunctionEnd
603 )";
604
605 CompileSuccessfully(spirv, env);
606 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
607 EXPECT_THAT(getDiagnosticString(),
608 AnyVUID("VUID-StandaloneSpirv-Location-04915"));
609 EXPECT_THAT(getDiagnosticString(),
610 HasSubstr("A BuiltIn variable (id 2) cannot have any Location or "
611 "Component decorations"));
612 }
613
TEST_F(ValidateDecorations,LocationDecorationOnNumericTypeBad)614 TEST_F(ValidateDecorations, LocationDecorationOnNumericTypeBad) {
615 const spv_target_env env = SPV_ENV_VULKAN_1_0;
616 std::string spirv = R"(
617 OpCapability Shader
618 OpMemoryModel Logical GLSL450
619 OpEntryPoint Fragment %main "main" %fragCoord
620 OpExecutionMode %main OriginUpperLeft
621 OpDecorate %fragCoord Location 0
622 OpDecorate %v4float Location 1
623 %void = OpTypeVoid
624 %voidfn = OpTypeFunction %void
625 %float = OpTypeFloat 32
626 %v4float = OpTypeVector %float 4
627 %ptr_v4float = OpTypePointer Output %v4float
628 %fragCoord = OpVariable %ptr_v4float Output
629 %non_interface = OpVariable %ptr_v4float Output
630 %main = OpFunction %void None %voidfn
631 %label = OpLabel
632 OpReturn
633 OpFunctionEnd
634 )";
635
636 CompileSuccessfully(spirv, env);
637 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
638 EXPECT_THAT(getDiagnosticString(),
639 HasSubstr("Location decoration on target <id> '3[%v4float]' must "
640 "be a variable"));
641 }
642
TEST_F(ValidateDecorations,LocationDecorationOnStructBad)643 TEST_F(ValidateDecorations, LocationDecorationOnStructBad) {
644 const spv_target_env env = SPV_ENV_VULKAN_1_0;
645 std::string spirv = R"(
646 OpCapability Shader
647 OpMemoryModel Logical GLSL450
648 OpEntryPoint Fragment %main "main" %fragCoord
649 OpExecutionMode %main OriginUpperLeft
650 OpDecorate %fragCoord Location 0
651 OpDecorate %struct Location 1
652 %void = OpTypeVoid
653 %voidfn = OpTypeFunction %void
654 %float = OpTypeFloat 32
655 %struct = OpTypeStruct %float
656 %v4float = OpTypeVector %float 4
657 %ptr_v4float = OpTypePointer Output %v4float
658 %fragCoord = OpVariable %ptr_v4float Output
659 %non_interface = OpVariable %ptr_v4float Output
660 %main = OpFunction %void None %voidfn
661 %label = OpLabel
662 OpReturn
663 OpFunctionEnd
664 )";
665
666 CompileSuccessfully(spirv, env);
667 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
668 EXPECT_THAT(getDiagnosticString(),
669 HasSubstr("Location decoration on target <id> '3[%_struct_3]' "
670 "must be a variable"));
671 }
672
TEST_F(ValidateDecorations,LocationDecorationUnusedNonInterfaceVariableVulkan_Ignored)673 TEST_F(ValidateDecorations,
674 LocationDecorationUnusedNonInterfaceVariableVulkan_Ignored) {
675 const spv_target_env env = SPV_ENV_VULKAN_1_0;
676 std::string spirv = R"(
677 OpCapability Shader
678 OpMemoryModel Logical GLSL450
679 OpEntryPoint Fragment %main "main" %fragCoord
680 OpExecutionMode %main OriginUpperLeft
681 OpSource GLSL 450
682 OpDecorate %fragCoord Location 0
683 OpDecorate %non_interface Location 1
684 %void = OpTypeVoid
685 %voidfn = OpTypeFunction %void
686 %float = OpTypeFloat 32
687 %v4float = OpTypeVector %float 4
688 %ptr_v4float = OpTypePointer Output %v4float
689 %fragCoord = OpVariable %ptr_v4float Output
690 %non_interface = OpVariable %ptr_v4float Output
691 %main = OpFunction %void None %voidfn
692 %label = OpLabel
693 OpReturn
694 OpFunctionEnd
695 )";
696
697 CompileSuccessfully(spirv, env);
698 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
699 EXPECT_EQ(getDiagnosticString(), "");
700 }
701
TEST_F(ValidateDecorations,LocationDecorationNonInterfaceStructVulkan_Ignored)702 TEST_F(ValidateDecorations,
703 LocationDecorationNonInterfaceStructVulkan_Ignored) {
704 const spv_target_env env = SPV_ENV_VULKAN_1_0;
705 std::string spirv = R"(
706 OpCapability Shader
707 OpMemoryModel Logical GLSL450
708 OpEntryPoint Fragment %main "main" %fragCoord
709 OpExecutionMode %main OriginUpperLeft
710 OpDecorate %fragCoord Location 0
711 OpMemberDecorate %block 0 Location 2
712 OpMemberDecorate %block 0 Component 1
713 OpDecorate %block Block
714 %void = OpTypeVoid
715 %voidfn = OpTypeFunction %void
716 %float = OpTypeFloat 32
717 %vec3 = OpTypeVector %float 3
718 %outvar_ptr = OpTypePointer Output %vec3
719 %fragCoord = OpVariable %outvar_ptr Output
720 %block = OpTypeStruct %vec3
721 %invar_ptr = OpTypePointer Input %block
722 %non_interface = OpVariable %invar_ptr Input
723 %main = OpFunction %void None %voidfn
724 %label = OpLabel
725 OpReturn
726 OpFunctionEnd
727 )";
728
729 CompileSuccessfully(spirv, env);
730 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
731 EXPECT_EQ(getDiagnosticString(), "");
732 }
733
TEST_F(ValidateDecorations,LocationDecorationNonInterfaceStructVulkanGood)734 TEST_F(ValidateDecorations, LocationDecorationNonInterfaceStructVulkanGood) {
735 const spv_target_env env = SPV_ENV_VULKAN_1_0;
736 std::string spirv = R"(
737 OpCapability Shader
738 OpMemoryModel Logical GLSL450
739 OpEntryPoint Fragment %main "main" %fragCoord %interface
740 OpExecutionMode %main OriginUpperLeft
741 OpDecorate %fragCoord Location 0
742 OpMemberDecorate %block 0 Location 2
743 OpMemberDecorate %block 0 Component 1
744 OpDecorate %block Block
745 %void = OpTypeVoid
746 %voidfn = OpTypeFunction %void
747 %float = OpTypeFloat 32
748 %vec3 = OpTypeVector %float 3
749 %outvar_ptr = OpTypePointer Output %vec3
750 %fragCoord = OpVariable %outvar_ptr Output
751 %block = OpTypeStruct %vec3
752 %invar_ptr = OpTypePointer Input %block
753 %interface = OpVariable %invar_ptr Input ;; this variable is unused. Ignore it
754 %main = OpFunction %void None %voidfn
755 %label = OpLabel
756 OpReturn
757 OpFunctionEnd
758 )";
759
760 CompileSuccessfully(spirv, env);
761 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
762 }
763
TEST_F(ValidateDecorations,LocationDecorationVariableNonStructVulkanBad)764 TEST_F(ValidateDecorations, LocationDecorationVariableNonStructVulkanBad) {
765 const spv_target_env env = SPV_ENV_VULKAN_1_0;
766 std::string spirv = R"(
767 OpCapability Shader
768 OpMemoryModel Logical GLSL450
769 OpEntryPoint Fragment %main "main" %fragCoord %nonblock_var
770 OpExecutionMode %main OriginUpperLeft
771 OpSource GLSL 450
772 OpDecorate %fragCoord Location 0
773 %void = OpTypeVoid
774 %voidfn = OpTypeFunction %void
775 %float = OpTypeFloat 32
776 %v4float = OpTypeVector %float 4
777 %ptr_v4float = OpTypePointer Output %v4float
778 %fragCoord = OpVariable %ptr_v4float Output
779 %nonblock_var = OpVariable %ptr_v4float Output
780 %main = OpFunction %void None %voidfn
781 %label = OpLabel
782 OpReturn
783 OpFunctionEnd
784 )";
785
786 CompileSuccessfully(spirv, env);
787 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateAndRetrieveValidationState(env));
788 EXPECT_THAT(getDiagnosticString(),
789 AnyVUID("VUID-StandaloneSpirv-Location-04916"));
790 EXPECT_THAT(getDiagnosticString(),
791 HasSubstr("Variable must be decorated with a location"));
792 }
793
TEST_F(ValidateDecorations,LocationDecorationVariableStructNoBlockVulkanBad)794 TEST_F(ValidateDecorations, LocationDecorationVariableStructNoBlockVulkanBad) {
795 const spv_target_env env = SPV_ENV_VULKAN_1_0;
796 std::string spirv = R"(
797 OpCapability Shader
798 OpMemoryModel Logical GLSL450
799 OpEntryPoint Fragment %main "main" %fragCoord %block_var
800 OpExecutionMode %main OriginUpperLeft
801 OpSource GLSL 450
802 OpDecorate %fragCoord Location 0
803 %void = OpTypeVoid
804 %voidfn = OpTypeFunction %void
805 %float = OpTypeFloat 32
806 %v4float = OpTypeVector %float 4
807 %ptr_v4float = OpTypePointer Output %v4float
808 %fragCoord = OpVariable %ptr_v4float Output
809 %block = OpTypeStruct %v4float
810 %block_ptr = OpTypePointer Output %block
811 %block_var = OpVariable %block_ptr Output
812 %main = OpFunction %void None %voidfn
813 %label = OpLabel
814 OpReturn
815 OpFunctionEnd
816 )";
817
818 CompileSuccessfully(spirv, env);
819 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateAndRetrieveValidationState(env));
820 EXPECT_THAT(getDiagnosticString(),
821 AnyVUID("VUID-StandaloneSpirv-Location-04917"));
822 EXPECT_THAT(getDiagnosticString(),
823 HasSubstr("Variable must be decorated with a location"));
824 }
825
TEST_F(ValidateDecorations,LocationDecorationVariableNoBlockVulkanGood)826 TEST_F(ValidateDecorations, LocationDecorationVariableNoBlockVulkanGood) {
827 const spv_target_env env = SPV_ENV_VULKAN_1_0;
828 std::string spirv = R"(
829 OpCapability Shader
830 OpMemoryModel Logical GLSL450
831 OpEntryPoint Fragment %main "main" %fragCoord %block_var
832 OpExecutionMode %main OriginUpperLeft
833 OpSource GLSL 450
834 OpDecorate %fragCoord Location 0
835 OpDecorate %block_var Location 1
836 %void = OpTypeVoid
837 %voidfn = OpTypeFunction %void
838 %float = OpTypeFloat 32
839 %v4float = OpTypeVector %float 4
840 %ptr_v4float = OpTypePointer Output %v4float
841 %fragCoord = OpVariable %ptr_v4float Output
842 %block = OpTypeStruct %v4float
843 %block_ptr = OpTypePointer Output %block
844 %block_var = OpVariable %block_ptr Output
845 %main = OpFunction %void None %voidfn
846 %label = OpLabel
847 OpReturn
848 OpFunctionEnd
849 )";
850
851 CompileSuccessfully(spirv, env);
852 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
853 }
854
TEST_F(ValidateDecorations,LocationDecorationVariableExtraMemeberVulkan)855 TEST_F(ValidateDecorations, LocationDecorationVariableExtraMemeberVulkan) {
856 const spv_target_env env = SPV_ENV_VULKAN_1_0;
857 std::string spirv = R"(
858 OpCapability Shader
859 OpMemoryModel Logical GLSL450
860 OpEntryPoint Fragment %main "main" %fragCoord %block_var
861 OpExecutionMode %main OriginUpperLeft
862 OpSource GLSL 450
863 OpDecorate %fragCoord Location 0
864 OpDecorate %block Block
865 OpDecorate %block_var Location 1
866 OpMemberDecorate %block 0 Location 1
867 %void = OpTypeVoid
868 %voidfn = OpTypeFunction %void
869 %float = OpTypeFloat 32
870 %v4float = OpTypeVector %float 4
871 %ptr_v4float = OpTypePointer Output %v4float
872 %fragCoord = OpVariable %ptr_v4float Output
873 %block = OpTypeStruct %v4float
874 %block_ptr = OpTypePointer Output %block
875 %block_var = OpVariable %block_ptr Output
876 %main = OpFunction %void None %voidfn
877 %label = OpLabel
878 OpReturn
879 OpFunctionEnd
880
881 )";
882
883 CompileSuccessfully(spirv, env);
884 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateAndRetrieveValidationState(env));
885 EXPECT_THAT(getDiagnosticString(),
886 AnyVUID("VUID-StandaloneSpirv-Location-04918"));
887 EXPECT_THAT(getDiagnosticString(),
888 HasSubstr("Members cannot be assigned a location"));
889 }
890
TEST_F(ValidateDecorations,LocationDecorationVariableMissingMemeberVulkan)891 TEST_F(ValidateDecorations, LocationDecorationVariableMissingMemeberVulkan) {
892 const spv_target_env env = SPV_ENV_VULKAN_1_0;
893 std::string spirv = R"(
894 OpCapability Shader
895 OpMemoryModel Logical GLSL450
896 OpEntryPoint Fragment %main "main" %fragCoord %block_var
897 OpExecutionMode %main OriginUpperLeft
898 OpSource GLSL 450
899 OpDecorate %fragCoord Location 0
900 OpDecorate %block Block
901 OpMemberDecorate %block 0 Location 1
902 %void = OpTypeVoid
903 %voidfn = OpTypeFunction %void
904 %float = OpTypeFloat 32
905 %v4float = OpTypeVector %float 4
906 %ptr_v4float = OpTypePointer Output %v4float
907 %fragCoord = OpVariable %ptr_v4float Output
908 %block = OpTypeStruct %v4float %v4float
909 %block_ptr = OpTypePointer Output %block
910 %block_var = OpVariable %block_ptr Output
911 %main = OpFunction %void None %voidfn
912 %label = OpLabel
913 OpReturn
914 OpFunctionEnd
915 )";
916
917 CompileSuccessfully(spirv, env);
918 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateAndRetrieveValidationState(env));
919 EXPECT_THAT(getDiagnosticString(),
920 AnyVUID("VUID-StandaloneSpirv-Location-04919"));
921 EXPECT_THAT(getDiagnosticString(),
922 HasSubstr("Member index 1 is missing a location assignment"));
923 }
924
TEST_F(ValidateDecorations,LocationDecorationVariableOnlyMemeberVulkanGood)925 TEST_F(ValidateDecorations, LocationDecorationVariableOnlyMemeberVulkanGood) {
926 const spv_target_env env = SPV_ENV_VULKAN_1_0;
927 std::string spirv = R"(
928 OpCapability Shader
929 OpMemoryModel Logical GLSL450
930 OpEntryPoint Fragment %main "main" %fragCoord %block_var
931 OpExecutionMode %main OriginUpperLeft
932 OpSource GLSL 450
933 OpDecorate %fragCoord Location 0
934 OpDecorate %block Block
935 OpMemberDecorate %block 0 Location 1
936 OpMemberDecorate %block 1 Location 4
937 %void = OpTypeVoid
938 %voidfn = OpTypeFunction %void
939 %float = OpTypeFloat 32
940 %v4float = OpTypeVector %float 4
941 %ptr_v4float = OpTypePointer Output %v4float
942 %fragCoord = OpVariable %ptr_v4float Output
943 %block = OpTypeStruct %v4float %v4float
944 %block_ptr = OpTypePointer Output %block
945 %block_var = OpVariable %block_ptr Output
946 %main = OpFunction %void None %voidfn
947 %label = OpLabel
948 OpReturn
949 OpFunctionEnd
950 )";
951
952 CompileSuccessfully(spirv, env);
953 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
954 }
955
956 // #version 440
957 // #extension GL_EXT_nonuniform_qualifier : enable
958 // layout(binding = 1) uniform sampler2D s2d[];
959 // layout(location = 0) in nonuniformEXT int i;
960 // void main()
961 // {
962 // vec4 v = texture(s2d[i], vec2(0.3));
963 // }
TEST_F(ValidateDecorations,RuntimeArrayOfDescriptorSetsIsAllowed)964 TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) {
965 const spv_target_env env = SPV_ENV_VULKAN_1_0;
966 std::string spirv = R"(
967 OpCapability Shader
968 OpCapability ShaderNonUniformEXT
969 OpCapability RuntimeDescriptorArrayEXT
970 OpCapability SampledImageArrayNonUniformIndexingEXT
971 OpExtension "SPV_EXT_descriptor_indexing"
972 %1 = OpExtInstImport "GLSL.std.450"
973 OpMemoryModel Logical GLSL450
974 OpEntryPoint Vertex %main "main" %i
975 OpSource GLSL 440
976 OpSourceExtension "GL_EXT_nonuniform_qualifier"
977 OpName %main "main"
978 OpName %v "v"
979 OpName %s2d "s2d"
980 OpName %i "i"
981 OpDecorate %s2d DescriptorSet 0
982 OpDecorate %s2d Binding 1
983 OpDecorate %i Location 0
984 OpDecorate %i NonUniformEXT
985 OpDecorate %18 NonUniformEXT
986 OpDecorate %21 NonUniformEXT
987 %void = OpTypeVoid
988 %3 = OpTypeFunction %void
989 %float = OpTypeFloat 32
990 %v4float = OpTypeVector %float 4
991 %_ptr_Function_v4float = OpTypePointer Function %v4float
992 %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
993 %11 = OpTypeSampledImage %10
994 %_runtimearr_11 = OpTypeRuntimeArray %11
995 %_ptr_Uniform__runtimearr_11 = OpTypePointer Uniform %_runtimearr_11
996 %s2d = OpVariable %_ptr_Uniform__runtimearr_11 Uniform
997 %int = OpTypeInt 32 1
998 %_ptr_Input_int = OpTypePointer Input %int
999 %i = OpVariable %_ptr_Input_int Input
1000 %_ptr_Uniform_11 = OpTypePointer Uniform %11
1001 %v2float = OpTypeVector %float 2
1002 %float_0_300000012 = OpConstant %float 0.300000012
1003 %24 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
1004 %float_0 = OpConstant %float 0
1005 %main = OpFunction %void None %3
1006 %5 = OpLabel
1007 %v = OpVariable %_ptr_Function_v4float Function
1008 %18 = OpLoad %int %i
1009 %20 = OpAccessChain %_ptr_Uniform_11 %s2d %18
1010 %21 = OpLoad %11 %20
1011 %26 = OpImageSampleExplicitLod %v4float %21 %24 Lod %float_0
1012 OpStore %v %26
1013 OpReturn
1014 OpFunctionEnd
1015 )";
1016 CompileSuccessfully(spirv, env);
1017 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
1018 }
1019
TEST_F(ValidateDecorations,BlockDecoratingArrayBad)1020 TEST_F(ValidateDecorations, BlockDecoratingArrayBad) {
1021 std::string spirv = R"(
1022 OpCapability Shader
1023 %1 = OpExtInstImport "GLSL.std.450"
1024 OpMemoryModel Logical GLSL450
1025 OpEntryPoint GLCompute %main "main"
1026 OpExecutionMode %main LocalSize 1 1 1
1027 OpSource GLSL 430
1028 OpDecorate %Output Block
1029 %void = OpTypeVoid
1030 %3 = OpTypeFunction %void
1031 %float = OpTypeFloat 32
1032 %int = OpTypeInt 32 1
1033 %int_3 = OpConstant %int 3
1034 %Output = OpTypeArray %float %int_3
1035 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1036 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1037 %main = OpFunction %void None %3
1038 %5 = OpLabel
1039 OpReturn
1040 OpFunctionEnd
1041 )";
1042
1043 CompileSuccessfully(spirv);
1044 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1045 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
1046 }
1047
TEST_F(ValidateDecorations,BlockDecoratingIntBad)1048 TEST_F(ValidateDecorations, BlockDecoratingIntBad) {
1049 std::string spirv = R"(
1050 OpCapability Shader
1051 %1 = OpExtInstImport "GLSL.std.450"
1052 OpMemoryModel Logical GLSL450
1053 OpEntryPoint GLCompute %main "main"
1054 OpExecutionMode %main LocalSize 1 1 1
1055 OpSource GLSL 430
1056 OpDecorate %Output Block
1057 %void = OpTypeVoid
1058 %3 = OpTypeFunction %void
1059 %Output = OpTypeInt 32 1
1060 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1061 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1062 %main = OpFunction %void None %3
1063 %5 = OpLabel
1064 OpReturn
1065 OpFunctionEnd
1066 )";
1067
1068 CompileSuccessfully(spirv);
1069 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1070 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
1071 }
1072
TEST_F(ValidateDecorations,BlockMissingOffsetBad)1073 TEST_F(ValidateDecorations, BlockMissingOffsetBad) {
1074 std::string spirv = R"(
1075 OpCapability Shader
1076 %1 = OpExtInstImport "GLSL.std.450"
1077 OpMemoryModel Logical GLSL450
1078 OpEntryPoint GLCompute %main "main"
1079 OpExecutionMode %main LocalSize 1 1 1
1080 OpSource GLSL 430
1081 OpDecorate %Output Block
1082 %void = OpTypeVoid
1083 %3 = OpTypeFunction %void
1084 %float = OpTypeFloat 32
1085 %Output = OpTypeStruct %float
1086 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1087 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1088 %main = OpFunction %void None %3
1089 %5 = OpLabel
1090 OpReturn
1091 OpFunctionEnd
1092 )";
1093
1094 CompileSuccessfully(spirv);
1095 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1096 EXPECT_THAT(getDiagnosticString(),
1097 HasSubstr("must be explicitly laid out with Offset decorations"));
1098 }
1099
TEST_F(ValidateDecorations,BufferBlockMissingOffsetBad)1100 TEST_F(ValidateDecorations, BufferBlockMissingOffsetBad) {
1101 std::string spirv = R"(
1102 OpCapability Shader
1103 %1 = OpExtInstImport "GLSL.std.450"
1104 OpMemoryModel Logical GLSL450
1105 OpEntryPoint GLCompute %main "main"
1106 OpExecutionMode %main LocalSize 1 1 1
1107 OpSource GLSL 430
1108 OpDecorate %Output BufferBlock
1109 %void = OpTypeVoid
1110 %3 = OpTypeFunction %void
1111 %float = OpTypeFloat 32
1112 %Output = OpTypeStruct %float
1113 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1114 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1115 %main = OpFunction %void None %3
1116 %5 = OpLabel
1117 OpReturn
1118 OpFunctionEnd
1119 )";
1120
1121 CompileSuccessfully(spirv);
1122 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1123 EXPECT_THAT(getDiagnosticString(),
1124 HasSubstr("must be explicitly laid out with Offset decorations"));
1125 }
1126
TEST_F(ValidateDecorations,BlockNestedStructMissingOffsetBad)1127 TEST_F(ValidateDecorations, BlockNestedStructMissingOffsetBad) {
1128 std::string spirv = R"(
1129 OpCapability Shader
1130 %1 = OpExtInstImport "GLSL.std.450"
1131 OpMemoryModel Logical GLSL450
1132 OpEntryPoint GLCompute %main "main"
1133 OpExecutionMode %main LocalSize 1 1 1
1134 OpSource GLSL 430
1135 OpMemberDecorate %S 0 Offset 0
1136 OpMemberDecorate %Output 0 Offset 0
1137 OpMemberDecorate %Output 1 Offset 16
1138 OpMemberDecorate %Output 2 Offset 32
1139 OpDecorate %Output Block
1140 %void = OpTypeVoid
1141 %3 = OpTypeFunction %void
1142 %float = OpTypeFloat 32
1143 %v4float = OpTypeVector %float 4
1144 %v3float = OpTypeVector %float 3
1145 %int = OpTypeInt 32 1
1146 %S = OpTypeStruct %v3float %int
1147 %Output = OpTypeStruct %float %v4float %S
1148 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1149 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1150 %main = OpFunction %void None %3
1151 %5 = OpLabel
1152 OpReturn
1153 OpFunctionEnd
1154 )";
1155
1156 CompileSuccessfully(spirv);
1157 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1158 EXPECT_THAT(getDiagnosticString(),
1159 HasSubstr("must be explicitly laid out with Offset decorations"));
1160 }
1161
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingOffsetBad)1162 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingOffsetBad) {
1163 std::string spirv = R"(
1164 OpCapability Shader
1165 %1 = OpExtInstImport "GLSL.std.450"
1166 OpMemoryModel Logical GLSL450
1167 OpEntryPoint GLCompute %main "main"
1168 OpExecutionMode %main LocalSize 1 1 1
1169 OpSource GLSL 430
1170 OpMemberDecorate %S 0 Offset 0
1171 OpMemberDecorate %Output 0 Offset 0
1172 OpMemberDecorate %Output 1 Offset 16
1173 OpMemberDecorate %Output 2 Offset 32
1174 OpDecorate %Output BufferBlock
1175 %void = OpTypeVoid
1176 %3 = OpTypeFunction %void
1177 %float = OpTypeFloat 32
1178 %v4float = OpTypeVector %float 4
1179 %v3float = OpTypeVector %float 3
1180 %int = OpTypeInt 32 1
1181 %S = OpTypeStruct %v3float %int
1182 %Output = OpTypeStruct %float %v4float %S
1183 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1184 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1185 %main = OpFunction %void None %3
1186 %5 = OpLabel
1187 OpReturn
1188 OpFunctionEnd
1189 )";
1190
1191 CompileSuccessfully(spirv);
1192 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1193 EXPECT_THAT(getDiagnosticString(),
1194 HasSubstr("must be explicitly laid out with Offset decorations"));
1195 }
1196
TEST_F(ValidateDecorations,BlockGLSLSharedBad)1197 TEST_F(ValidateDecorations, BlockGLSLSharedBad) {
1198 std::string spirv = R"(
1199 OpCapability Shader
1200 %1 = OpExtInstImport "GLSL.std.450"
1201 OpMemoryModel Logical GLSL450
1202 OpEntryPoint GLCompute %main "main"
1203 OpExecutionMode %main LocalSize 1 1 1
1204 OpSource GLSL 430
1205 OpDecorate %Output Block
1206 OpDecorate %Output GLSLShared
1207 OpMemberDecorate %Output 0 Offset 0
1208 %void = OpTypeVoid
1209 %3 = OpTypeFunction %void
1210 %float = OpTypeFloat 32
1211 %Output = OpTypeStruct %float
1212 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1213 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1214 %main = OpFunction %void None %3
1215 %5 = OpLabel
1216 OpReturn
1217 OpFunctionEnd
1218 )";
1219
1220 CompileSuccessfully(spirv);
1221 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1222 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1223 EXPECT_THAT(
1224 getDiagnosticString(),
1225 HasSubstr(
1226 "'GLSLShared' is not valid for the Vulkan execution environment"));
1227 EXPECT_THAT(getDiagnosticString(),
1228 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1229 }
1230
TEST_F(ValidateDecorations,BufferBlockGLSLSharedBad)1231 TEST_F(ValidateDecorations, BufferBlockGLSLSharedBad) {
1232 std::string spirv = R"(
1233 OpCapability Shader
1234 %1 = OpExtInstImport "GLSL.std.450"
1235 OpMemoryModel Logical GLSL450
1236 OpEntryPoint GLCompute %main "main"
1237 OpExecutionMode %main LocalSize 1 1 1
1238 OpSource GLSL 430
1239 OpDecorate %Output BufferBlock
1240 OpDecorate %Output GLSLShared
1241 OpMemberDecorate %Output 0 Offset 0
1242 %void = OpTypeVoid
1243 %3 = OpTypeFunction %void
1244 %float = OpTypeFloat 32
1245 %Output = OpTypeStruct %float
1246 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1247 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1248 %main = OpFunction %void None %3
1249 %5 = OpLabel
1250 OpReturn
1251 OpFunctionEnd
1252 )";
1253
1254 CompileSuccessfully(spirv);
1255 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1256 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1257 EXPECT_THAT(
1258 getDiagnosticString(),
1259 HasSubstr(
1260 "'GLSLShared' is not valid for the Vulkan execution environment"));
1261 EXPECT_THAT(getDiagnosticString(),
1262 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1263 }
1264
TEST_F(ValidateDecorations,BlockNestedStructGLSLSharedBad)1265 TEST_F(ValidateDecorations, BlockNestedStructGLSLSharedBad) {
1266 std::string spirv = R"(
1267 OpCapability Shader
1268 %1 = OpExtInstImport "GLSL.std.450"
1269 OpMemoryModel Logical GLSL450
1270 OpEntryPoint GLCompute %main "main"
1271 OpExecutionMode %main LocalSize 1 1 1
1272 OpSource GLSL 430
1273 OpMemberDecorate %S 0 Offset 0
1274 OpDecorate %S GLSLShared
1275 OpMemberDecorate %Output 0 Offset 0
1276 OpMemberDecorate %Output 1 Offset 16
1277 OpMemberDecorate %Output 2 Offset 32
1278 OpDecorate %Output Block
1279 %void = OpTypeVoid
1280 %3 = OpTypeFunction %void
1281 %float = OpTypeFloat 32
1282 %v4float = OpTypeVector %float 4
1283 %int = OpTypeInt 32 1
1284 %S = OpTypeStruct %int
1285 %Output = OpTypeStruct %float %v4float %S
1286 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1287 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1288 %main = OpFunction %void None %3
1289 %5 = OpLabel
1290 OpReturn
1291 OpFunctionEnd
1292 )";
1293
1294 CompileSuccessfully(spirv);
1295 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1296 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1297 EXPECT_THAT(
1298 getDiagnosticString(),
1299 HasSubstr(
1300 "'GLSLShared' is not valid for the Vulkan execution environment"));
1301 EXPECT_THAT(getDiagnosticString(),
1302 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1303 }
1304
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLSharedBad)1305 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLSharedBad) {
1306 std::string spirv = R"(
1307 OpCapability Shader
1308 %1 = OpExtInstImport "GLSL.std.450"
1309 OpMemoryModel Logical GLSL450
1310 OpEntryPoint GLCompute %main "main"
1311 OpExecutionMode %main LocalSize 1 1 1
1312 OpSource GLSL 430
1313 OpMemberDecorate %S 0 Offset 0
1314 OpDecorate %S GLSLShared
1315 OpMemberDecorate %Output 0 Offset 0
1316 OpMemberDecorate %Output 1 Offset 16
1317 OpMemberDecorate %Output 2 Offset 32
1318 OpDecorate %Output BufferBlock
1319 %void = OpTypeVoid
1320 %3 = OpTypeFunction %void
1321 %float = OpTypeFloat 32
1322 %v4float = OpTypeVector %float 4
1323 %int = OpTypeInt 32 1
1324 %S = OpTypeStruct %int
1325 %Output = OpTypeStruct %float %v4float %S
1326 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1327 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1328 %main = OpFunction %void None %3
1329 %5 = OpLabel
1330 OpReturn
1331 OpFunctionEnd
1332 )";
1333
1334 CompileSuccessfully(spirv);
1335 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1336 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1337 EXPECT_THAT(
1338 getDiagnosticString(),
1339 HasSubstr(
1340 "'GLSLShared' is not valid for the Vulkan execution environment"));
1341 EXPECT_THAT(getDiagnosticString(),
1342 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1343 }
1344
TEST_F(ValidateDecorations,BlockGLSLPackedBad)1345 TEST_F(ValidateDecorations, BlockGLSLPackedBad) {
1346 std::string spirv = R"(
1347 OpCapability Shader
1348 %1 = OpExtInstImport "GLSL.std.450"
1349 OpMemoryModel Logical GLSL450
1350 OpEntryPoint GLCompute %main "main"
1351 OpExecutionMode %main LocalSize 1 1 1
1352 OpSource GLSL 430
1353 OpDecorate %Output Block
1354 OpDecorate %Output GLSLPacked
1355 OpMemberDecorate %Output 0 Offset 0
1356 %void = OpTypeVoid
1357 %3 = OpTypeFunction %void
1358 %float = OpTypeFloat 32
1359 %Output = OpTypeStruct %float
1360 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1361 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1362 %main = OpFunction %void None %3
1363 %5 = OpLabel
1364 OpReturn
1365 OpFunctionEnd
1366 )";
1367
1368 CompileSuccessfully(spirv);
1369 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1370 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1371 EXPECT_THAT(
1372 getDiagnosticString(),
1373 HasSubstr(
1374 "'GLSLPacked' is not valid for the Vulkan execution environment"));
1375 EXPECT_THAT(getDiagnosticString(),
1376 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1377 }
1378
TEST_F(ValidateDecorations,BufferBlockGLSLPackedBad)1379 TEST_F(ValidateDecorations, BufferBlockGLSLPackedBad) {
1380 std::string spirv = R"(
1381 OpCapability Shader
1382 %1 = OpExtInstImport "GLSL.std.450"
1383 OpMemoryModel Logical GLSL450
1384 OpEntryPoint GLCompute %main "main"
1385 OpExecutionMode %main LocalSize 1 1 1
1386 OpSource GLSL 430
1387 OpDecorate %Output BufferBlock
1388 OpDecorate %Output GLSLPacked
1389 OpMemberDecorate %Output 0 Offset 0
1390 %void = OpTypeVoid
1391 %3 = OpTypeFunction %void
1392 %float = OpTypeFloat 32
1393 %Output = OpTypeStruct %float
1394 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1395 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1396 %main = OpFunction %void None %3
1397 %5 = OpLabel
1398 OpReturn
1399 OpFunctionEnd
1400 )";
1401
1402 CompileSuccessfully(spirv);
1403 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1404 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1405 EXPECT_THAT(
1406 getDiagnosticString(),
1407 HasSubstr(
1408 "'GLSLPacked' is not valid for the Vulkan execution environment"));
1409 EXPECT_THAT(getDiagnosticString(),
1410 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1411 }
1412
TEST_F(ValidateDecorations,BlockNestedStructGLSLPackedBad)1413 TEST_F(ValidateDecorations, BlockNestedStructGLSLPackedBad) {
1414 std::string spirv = R"(
1415 OpCapability Shader
1416 %1 = OpExtInstImport "GLSL.std.450"
1417 OpMemoryModel Logical GLSL450
1418 OpEntryPoint GLCompute %main "main"
1419 OpExecutionMode %main LocalSize 1 1 1
1420 OpSource GLSL 430
1421 OpMemberDecorate %S 0 Offset 0
1422 OpDecorate %S GLSLPacked
1423 OpMemberDecorate %Output 0 Offset 0
1424 OpMemberDecorate %Output 1 Offset 16
1425 OpMemberDecorate %Output 2 Offset 32
1426 OpDecorate %Output Block
1427 %void = OpTypeVoid
1428 %3 = OpTypeFunction %void
1429 %float = OpTypeFloat 32
1430 %v4float = OpTypeVector %float 4
1431 %int = OpTypeInt 32 1
1432 %S = OpTypeStruct %int
1433 %Output = OpTypeStruct %float %v4float %S
1434 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1435 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1436 %main = OpFunction %void None %3
1437 %5 = OpLabel
1438 OpReturn
1439 OpFunctionEnd
1440 )";
1441
1442 CompileSuccessfully(spirv);
1443 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1444 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1445 EXPECT_THAT(
1446 getDiagnosticString(),
1447 HasSubstr(
1448 "'GLSLPacked' is not valid for the Vulkan execution environment"));
1449 EXPECT_THAT(getDiagnosticString(),
1450 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1451 }
1452
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLPackedBad)1453 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLPackedBad) {
1454 std::string spirv = R"(
1455 OpCapability Shader
1456 %1 = OpExtInstImport "GLSL.std.450"
1457 OpMemoryModel Logical GLSL450
1458 OpEntryPoint GLCompute %main "main"
1459 OpExecutionMode %main LocalSize 1 1 1
1460 OpSource GLSL 430
1461 OpMemberDecorate %S 0 Offset 0
1462 OpDecorate %S GLSLPacked
1463 OpMemberDecorate %Output 0 Offset 0
1464 OpMemberDecorate %Output 1 Offset 16
1465 OpMemberDecorate %Output 2 Offset 32
1466 OpDecorate %Output BufferBlock
1467 %void = OpTypeVoid
1468 %3 = OpTypeFunction %void
1469 %float = OpTypeFloat 32
1470 %v4float = OpTypeVector %float 4
1471 %int = OpTypeInt 32 1
1472 %S = OpTypeStruct %int
1473 %Output = OpTypeStruct %float %v4float %S
1474 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1475 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1476 %main = OpFunction %void None %3
1477 %5 = OpLabel
1478 OpReturn
1479 OpFunctionEnd
1480 )";
1481
1482 CompileSuccessfully(spirv);
1483 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1484 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1485 EXPECT_THAT(
1486 getDiagnosticString(),
1487 HasSubstr(
1488 "'GLSLPacked' is not valid for the Vulkan execution environment"));
1489 EXPECT_THAT(getDiagnosticString(),
1490 HasSubstr("[VUID-StandaloneSpirv-GLSLShared-04669]"));
1491 }
1492
TEST_F(ValidateDecorations,BlockMissingArrayStrideBad)1493 TEST_F(ValidateDecorations, BlockMissingArrayStrideBad) {
1494 std::string spirv = R"(
1495 OpCapability Shader
1496 %1 = OpExtInstImport "GLSL.std.450"
1497 OpMemoryModel Logical GLSL450
1498 OpEntryPoint GLCompute %main "main"
1499 OpExecutionMode %main LocalSize 1 1 1
1500 OpSource GLSL 430
1501 OpDecorate %Output Block
1502 OpMemberDecorate %Output 0 Offset 0
1503 %void = OpTypeVoid
1504 %3 = OpTypeFunction %void
1505 %float = OpTypeFloat 32
1506 %int = OpTypeInt 32 1
1507 %int_3 = OpConstant %int 3
1508 %array = OpTypeArray %float %int_3
1509 %Output = OpTypeStruct %array
1510 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1511 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1512 %main = OpFunction %void None %3
1513 %5 = OpLabel
1514 OpReturn
1515 OpFunctionEnd
1516 )";
1517
1518 CompileSuccessfully(spirv);
1519 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1520 EXPECT_THAT(
1521 getDiagnosticString(),
1522 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1523 }
1524
TEST_F(ValidateDecorations,BufferBlockMissingArrayStrideBad)1525 TEST_F(ValidateDecorations, BufferBlockMissingArrayStrideBad) {
1526 std::string spirv = R"(
1527 OpCapability Shader
1528 %1 = OpExtInstImport "GLSL.std.450"
1529 OpMemoryModel Logical GLSL450
1530 OpEntryPoint GLCompute %main "main"
1531 OpExecutionMode %main LocalSize 1 1 1
1532 OpSource GLSL 430
1533 OpDecorate %Output BufferBlock
1534 OpMemberDecorate %Output 0 Offset 0
1535 %void = OpTypeVoid
1536 %3 = OpTypeFunction %void
1537 %float = OpTypeFloat 32
1538 %int = OpTypeInt 32 1
1539 %int_3 = OpConstant %int 3
1540 %array = OpTypeArray %float %int_3
1541 %Output = OpTypeStruct %array
1542 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1543 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1544 %main = OpFunction %void None %3
1545 %5 = OpLabel
1546 OpReturn
1547 OpFunctionEnd
1548 )";
1549
1550 CompileSuccessfully(spirv);
1551 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1552 EXPECT_THAT(
1553 getDiagnosticString(),
1554 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1555 }
1556
TEST_F(ValidateDecorations,BlockNestedStructMissingArrayStrideBad)1557 TEST_F(ValidateDecorations, BlockNestedStructMissingArrayStrideBad) {
1558 std::string spirv = R"(
1559 OpCapability Shader
1560 %1 = OpExtInstImport "GLSL.std.450"
1561 OpMemoryModel Logical GLSL450
1562 OpEntryPoint GLCompute %main "main"
1563 OpExecutionMode %main LocalSize 1 1 1
1564 OpSource GLSL 430
1565 OpMemberDecorate %S 0 Offset 0
1566 OpMemberDecorate %Output 0 Offset 0
1567 OpMemberDecorate %Output 1 Offset 16
1568 OpMemberDecorate %Output 2 Offset 32
1569 OpDecorate %Output Block
1570 %void = OpTypeVoid
1571 %3 = OpTypeFunction %void
1572 %float = OpTypeFloat 32
1573 %v4float = OpTypeVector %float 4
1574 %int = OpTypeInt 32 1
1575 %int_3 = OpConstant %int 3
1576 %array = OpTypeArray %float %int_3
1577 %S = OpTypeStruct %array
1578 %Output = OpTypeStruct %float %v4float %S
1579 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1580 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1581 %main = OpFunction %void None %3
1582 %5 = OpLabel
1583 OpReturn
1584 OpFunctionEnd
1585 )";
1586
1587 CompileSuccessfully(spirv);
1588 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1589 EXPECT_THAT(
1590 getDiagnosticString(),
1591 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1592 }
1593
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingArrayStrideBad)1594 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingArrayStrideBad) {
1595 std::string spirv = R"(
1596 OpCapability Shader
1597 %1 = OpExtInstImport "GLSL.std.450"
1598 OpMemoryModel Logical GLSL450
1599 OpEntryPoint GLCompute %main "main"
1600 OpExecutionMode %main LocalSize 1 1 1
1601 OpSource GLSL 430
1602 OpMemberDecorate %S 0 Offset 0
1603 OpMemberDecorate %Output 0 Offset 0
1604 OpMemberDecorate %Output 1 Offset 16
1605 OpMemberDecorate %Output 2 Offset 32
1606 OpDecorate %Output BufferBlock
1607 %void = OpTypeVoid
1608 %3 = OpTypeFunction %void
1609 %float = OpTypeFloat 32
1610 %v4float = OpTypeVector %float 4
1611 %int = OpTypeInt 32 1
1612 %int_3 = OpConstant %int 3
1613 %array = OpTypeArray %float %int_3
1614 %S = OpTypeStruct %array
1615 %Output = OpTypeStruct %float %v4float %S
1616 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1617 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1618 %main = OpFunction %void None %3
1619 %5 = OpLabel
1620 OpReturn
1621 OpFunctionEnd
1622 )";
1623
1624 CompileSuccessfully(spirv);
1625 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1626 EXPECT_THAT(
1627 getDiagnosticString(),
1628 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1629 }
1630
TEST_F(ValidateDecorations,BlockMissingMatrixStrideBad)1631 TEST_F(ValidateDecorations, BlockMissingMatrixStrideBad) {
1632 std::string spirv = R"(
1633 OpCapability Shader
1634 %1 = OpExtInstImport "GLSL.std.450"
1635 OpMemoryModel Logical GLSL450
1636 OpEntryPoint GLCompute %main "main"
1637 OpExecutionMode %main LocalSize 1 1 1
1638 OpSource GLSL 430
1639 OpDecorate %Output Block
1640 OpMemberDecorate %Output 0 Offset 0
1641 %void = OpTypeVoid
1642 %3 = OpTypeFunction %void
1643 %float = OpTypeFloat 32
1644 %v3float = OpTypeVector %float 3
1645 %matrix = OpTypeMatrix %v3float 4
1646 %Output = OpTypeStruct %matrix
1647 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1648 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1649 %main = OpFunction %void None %3
1650 %5 = OpLabel
1651 OpReturn
1652 OpFunctionEnd
1653 )";
1654
1655 CompileSuccessfully(spirv);
1656 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1657 EXPECT_THAT(
1658 getDiagnosticString(),
1659 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1660 }
1661
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideBad)1662 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideBad) {
1663 std::string spirv = R"(
1664 OpCapability Shader
1665 %1 = OpExtInstImport "GLSL.std.450"
1666 OpMemoryModel Logical GLSL450
1667 OpEntryPoint GLCompute %main "main"
1668 OpExecutionMode %main LocalSize 1 1 1
1669 OpSource GLSL 430
1670 OpDecorate %Output BufferBlock
1671 OpMemberDecorate %Output 0 Offset 0
1672 %void = OpTypeVoid
1673 %3 = OpTypeFunction %void
1674 %float = OpTypeFloat 32
1675 %v3float = OpTypeVector %float 3
1676 %matrix = OpTypeMatrix %v3float 4
1677 %Output = OpTypeStruct %matrix
1678 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1679 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1680 %main = OpFunction %void None %3
1681 %5 = OpLabel
1682 OpReturn
1683 OpFunctionEnd
1684 )";
1685
1686 CompileSuccessfully(spirv);
1687 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1688 EXPECT_THAT(
1689 getDiagnosticString(),
1690 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1691 }
1692
TEST_F(ValidateDecorations,BlockMissingMatrixStrideArrayBad)1693 TEST_F(ValidateDecorations, BlockMissingMatrixStrideArrayBad) {
1694 std::string spirv = R"(
1695 OpCapability Shader
1696 %1 = OpExtInstImport "GLSL.std.450"
1697 OpMemoryModel Logical GLSL450
1698 OpEntryPoint GLCompute %main "main"
1699 OpExecutionMode %main LocalSize 1 1 1
1700 OpSource GLSL 430
1701 OpDecorate %Output Block
1702 OpMemberDecorate %Output 0 Offset 0
1703 %void = OpTypeVoid
1704 %3 = OpTypeFunction %void
1705 %float = OpTypeFloat 32
1706 %v3float = OpTypeVector %float 3
1707 %matrix = OpTypeMatrix %v3float 4
1708 %int = OpTypeInt 32 1
1709 %int_3 = OpConstant %int 3
1710 %array = OpTypeArray %matrix %int_3
1711 %Output = OpTypeStruct %matrix
1712 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1713 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1714 %main = OpFunction %void None %3
1715 %5 = OpLabel
1716 OpReturn
1717 OpFunctionEnd
1718 )";
1719
1720 CompileSuccessfully(spirv);
1721 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1722 EXPECT_THAT(
1723 getDiagnosticString(),
1724 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1725 }
1726
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideArrayBad)1727 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideArrayBad) {
1728 std::string spirv = R"(
1729 OpCapability Shader
1730 %1 = OpExtInstImport "GLSL.std.450"
1731 OpMemoryModel Logical GLSL450
1732 OpEntryPoint GLCompute %main "main"
1733 OpExecutionMode %main LocalSize 1 1 1
1734 OpSource GLSL 430
1735 OpDecorate %Output BufferBlock
1736 OpMemberDecorate %Output 0 Offset 0
1737 %void = OpTypeVoid
1738 %3 = OpTypeFunction %void
1739 %float = OpTypeFloat 32
1740 %v3float = OpTypeVector %float 3
1741 %matrix = OpTypeMatrix %v3float 4
1742 %int = OpTypeInt 32 1
1743 %int_3 = OpConstant %int 3
1744 %array = OpTypeArray %matrix %int_3
1745 %Output = OpTypeStruct %matrix
1746 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1747 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1748 %main = OpFunction %void None %3
1749 %5 = OpLabel
1750 OpReturn
1751 OpFunctionEnd
1752 )";
1753
1754 CompileSuccessfully(spirv);
1755 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1756 EXPECT_THAT(
1757 getDiagnosticString(),
1758 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1759 }
1760
TEST_F(ValidateDecorations,BlockNestedStructMissingMatrixStrideBad)1761 TEST_F(ValidateDecorations, BlockNestedStructMissingMatrixStrideBad) {
1762 std::string spirv = R"(
1763 OpCapability Shader
1764 %1 = OpExtInstImport "GLSL.std.450"
1765 OpMemoryModel Logical GLSL450
1766 OpEntryPoint GLCompute %main "main"
1767 OpExecutionMode %main LocalSize 1 1 1
1768 OpSource GLSL 430
1769 OpMemberDecorate %S 0 Offset 0
1770 OpMemberDecorate %Output 0 Offset 0
1771 OpMemberDecorate %Output 1 Offset 16
1772 OpMemberDecorate %Output 2 Offset 32
1773 OpDecorate %Output Block
1774 %void = OpTypeVoid
1775 %3 = OpTypeFunction %void
1776 %float = OpTypeFloat 32
1777 %v3float = OpTypeVector %float 3
1778 %v4float = OpTypeVector %float 4
1779 %matrix = OpTypeMatrix %v3float 4
1780 %S = OpTypeStruct %matrix
1781 %Output = OpTypeStruct %float %v4float %S
1782 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1783 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1784 %main = OpFunction %void None %3
1785 %5 = OpLabel
1786 OpReturn
1787 OpFunctionEnd
1788 )";
1789
1790 CompileSuccessfully(spirv);
1791 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1792 EXPECT_THAT(
1793 getDiagnosticString(),
1794 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1795 }
1796
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingMatrixStrideBad)1797 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingMatrixStrideBad) {
1798 std::string spirv = R"(
1799 OpCapability Shader
1800 %1 = OpExtInstImport "GLSL.std.450"
1801 OpMemoryModel Logical GLSL450
1802 OpEntryPoint GLCompute %main "main"
1803 OpExecutionMode %main LocalSize 1 1 1
1804 OpSource GLSL 430
1805 OpMemberDecorate %S 0 Offset 0
1806 OpMemberDecorate %Output 0 Offset 0
1807 OpMemberDecorate %Output 1 Offset 16
1808 OpMemberDecorate %Output 2 Offset 32
1809 OpDecorate %Output BufferBlock
1810 %void = OpTypeVoid
1811 %3 = OpTypeFunction %void
1812 %float = OpTypeFloat 32
1813 %v3float = OpTypeVector %float 3
1814 %v4float = OpTypeVector %float 4
1815 %matrix = OpTypeMatrix %v3float 4
1816 %S = OpTypeStruct %matrix
1817 %Output = OpTypeStruct %float %v4float %S
1818 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1819 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1820 %main = OpFunction %void None %3
1821 %5 = OpLabel
1822 OpReturn
1823 OpFunctionEnd
1824 )";
1825
1826 CompileSuccessfully(spirv);
1827 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1828 EXPECT_THAT(
1829 getDiagnosticString(),
1830 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1831 }
1832
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayout)1833 TEST_F(ValidateDecorations, BlockStandardUniformBufferLayout) {
1834 std::string spirv = R"(
1835 OpCapability Shader
1836 %1 = OpExtInstImport "GLSL.std.450"
1837 OpMemoryModel Logical GLSL450
1838 OpEntryPoint GLCompute %main "main"
1839 OpExecutionMode %main LocalSize 1 1 1
1840 OpSource GLSL 430
1841 OpMemberDecorate %F 0 Offset 0
1842 OpMemberDecorate %F 1 Offset 8
1843 OpDecorate %_arr_float_uint_2 ArrayStride 16
1844 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
1845 OpMemberDecorate %O 0 Offset 0
1846 OpMemberDecorate %O 1 Offset 16
1847 OpMemberDecorate %O 2 Offset 32
1848 OpMemberDecorate %O 3 Offset 64
1849 OpMemberDecorate %O 4 ColMajor
1850 OpMemberDecorate %O 4 Offset 80
1851 OpMemberDecorate %O 4 MatrixStride 16
1852 OpDecorate %_arr_O_uint_2 ArrayStride 176
1853 OpMemberDecorate %Output 0 Offset 0
1854 OpMemberDecorate %Output 1 Offset 8
1855 OpMemberDecorate %Output 2 Offset 16
1856 OpMemberDecorate %Output 3 Offset 32
1857 OpMemberDecorate %Output 4 Offset 48
1858 OpMemberDecorate %Output 5 Offset 64
1859 OpMemberDecorate %Output 6 ColMajor
1860 OpMemberDecorate %Output 6 Offset 96
1861 OpMemberDecorate %Output 6 MatrixStride 16
1862 OpMemberDecorate %Output 7 Offset 128
1863 OpDecorate %Output Block
1864 %void = OpTypeVoid
1865 %3 = OpTypeFunction %void
1866 %float = OpTypeFloat 32
1867 %v2float = OpTypeVector %float 2
1868 %v3float = OpTypeVector %float 3
1869 %int = OpTypeInt 32 1
1870 %uint = OpTypeInt 32 0
1871 %v2uint = OpTypeVector %uint 2
1872 %F = OpTypeStruct %int %v2uint
1873 %uint_2 = OpConstant %uint 2
1874 %_arr_float_uint_2 = OpTypeArray %float %uint_2
1875 %mat2v3float = OpTypeMatrix %v3float 2
1876 %v3uint = OpTypeVector %uint 3
1877 %mat3v3float = OpTypeMatrix %v3float 3
1878 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
1879 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
1880 %_arr_O_uint_2 = OpTypeArray %O %uint_2
1881 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
1882 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1883 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1884 %main = OpFunction %void None %3
1885 %5 = OpLabel
1886 OpReturn
1887 OpFunctionEnd
1888 )";
1889
1890 CompileSuccessfully(spirv);
1891 EXPECT_EQ(SPV_SUCCESS,
1892 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1893 }
1894
TEST_F(ValidateDecorations,BlockLayoutPermitsTightVec3ScalarPackingGood)1895 TEST_F(ValidateDecorations, BlockLayoutPermitsTightVec3ScalarPackingGood) {
1896 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
1897 std::string spirv = R"(
1898 OpCapability Shader
1899 OpMemoryModel Logical GLSL450
1900 OpEntryPoint Vertex %main "main"
1901 OpSource GLSL 450
1902 OpMemberDecorate %S 0 Offset 0
1903 OpMemberDecorate %S 1 Offset 12
1904 OpDecorate %S Block
1905 OpDecorate %B DescriptorSet 0
1906 OpDecorate %B Binding 0
1907 %void = OpTypeVoid
1908 %3 = OpTypeFunction %void
1909 %float = OpTypeFloat 32
1910 %v3float = OpTypeVector %float 3
1911 %S = OpTypeStruct %v3float %float
1912 %_ptr_Uniform_S = OpTypePointer Uniform %S
1913 %B = OpVariable %_ptr_Uniform_S Uniform
1914 %main = OpFunction %void None %3
1915 %5 = OpLabel
1916 OpReturn
1917 OpFunctionEnd
1918 )";
1919
1920 CompileSuccessfully(spirv);
1921 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
1922 << getDiagnosticString();
1923 }
1924
TEST_F(ValidateDecorations,BlockCantAppearWithinABlockBad)1925 TEST_F(ValidateDecorations, BlockCantAppearWithinABlockBad) {
1926 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1927 std::string spirv = R"(
1928 OpCapability Shader
1929 OpMemoryModel Logical GLSL450
1930 OpEntryPoint Vertex %main "main"
1931 OpSource GLSL 450
1932 OpMemberDecorate %S 0 Offset 0
1933 OpMemberDecorate %S 1 Offset 16
1934 OpMemberDecorate %S2 0 Offset 0
1935 OpMemberDecorate %S2 1 Offset 12
1936 OpDecorate %S Block
1937 OpDecorate %S2 Block
1938 OpDecorate %B DescriptorSet 0
1939 OpDecorate %B Binding 0
1940 %void = OpTypeVoid
1941 %3 = OpTypeFunction %void
1942 %float = OpTypeFloat 32
1943 %S2 = OpTypeStruct %float %float
1944 %S = OpTypeStruct %float %S2
1945 %_ptr_Uniform_S = OpTypePointer Uniform %S
1946 %B = OpVariable %_ptr_Uniform_S Uniform
1947 %main = OpFunction %void None %3
1948 %5 = OpLabel
1949 OpReturn
1950 OpFunctionEnd
1951 )";
1952
1953 CompileSuccessfully(spirv);
1954 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1955 EXPECT_THAT(getDiagnosticString(),
1956 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1957 "another Block or BufferBlock."));
1958 }
1959
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABufferblockBad)1960 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABufferblockBad) {
1961 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1962 std::string spirv = R"(
1963 OpCapability Shader
1964 OpMemoryModel Logical GLSL450
1965 OpEntryPoint Vertex %main "main"
1966 OpSource GLSL 450
1967 OpMemberDecorate %S 0 Offset 0
1968 OpMemberDecorate %S 1 Offset 16
1969 OpMemberDecorate %S2 0 Offset 0
1970 OpMemberDecorate %S2 1 Offset 16
1971 OpMemberDecorate %S3 0 Offset 0
1972 OpMemberDecorate %S3 1 Offset 12
1973 OpDecorate %S BufferBlock
1974 OpDecorate %S3 BufferBlock
1975 OpDecorate %B DescriptorSet 0
1976 OpDecorate %B Binding 0
1977 %void = OpTypeVoid
1978 %3 = OpTypeFunction %void
1979 %float = OpTypeFloat 32
1980 %S3 = OpTypeStruct %float %float
1981 %S2 = OpTypeStruct %float %S3
1982 %S = OpTypeStruct %float %S2
1983 %_ptr_Uniform_S = OpTypePointer Uniform %S
1984 %B = OpVariable %_ptr_Uniform_S Uniform
1985 %main = OpFunction %void None %3
1986 %5 = OpLabel
1987 OpReturn
1988 OpFunctionEnd
1989 )";
1990
1991 CompileSuccessfully(spirv);
1992 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1993 EXPECT_THAT(getDiagnosticString(),
1994 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1995 "another Block or BufferBlock."));
1996 }
1997
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABlockBad)1998 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABlockBad) {
1999 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
2000 std::string spirv = R"(
2001 OpCapability Shader
2002 OpMemoryModel Logical GLSL450
2003 OpEntryPoint Vertex %main "main"
2004 OpSource GLSL 450
2005 OpMemberDecorate %S 0 Offset 0
2006 OpMemberDecorate %S 1 Offset 16
2007 OpMemberDecorate %S2 0 Offset 0
2008 OpMemberDecorate %S2 1 Offset 16
2009 OpMemberDecorate %S3 0 Offset 0
2010 OpMemberDecorate %S3 1 Offset 12
2011 OpDecorate %S Block
2012 OpDecorate %S3 BufferBlock
2013 OpDecorate %B DescriptorSet 0
2014 OpDecorate %B Binding 0
2015 %void = OpTypeVoid
2016 %3 = OpTypeFunction %void
2017 %float = OpTypeFloat 32
2018 %S3 = OpTypeStruct %float %float
2019 %S2 = OpTypeStruct %float %S3
2020 %S = OpTypeStruct %float %S2
2021 %_ptr_Uniform_S = OpTypePointer Uniform %S
2022 %B = OpVariable %_ptr_Uniform_S Uniform
2023 %main = OpFunction %void None %3
2024 %5 = OpLabel
2025 OpReturn
2026 OpFunctionEnd
2027 )";
2028
2029 CompileSuccessfully(spirv);
2030 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2031 EXPECT_THAT(getDiagnosticString(),
2032 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
2033 "another Block or BufferBlock."));
2034 }
2035
TEST_F(ValidateDecorations,BlockCantAppearWithinABufferblockBad)2036 TEST_F(ValidateDecorations, BlockCantAppearWithinABufferblockBad) {
2037 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
2038 std::string spirv = R"(
2039 OpCapability Shader
2040 OpMemoryModel Logical GLSL450
2041 OpEntryPoint Vertex %main "main"
2042 OpSource GLSL 450
2043 OpMemberDecorate %S 0 Offset 0
2044 OpMemberDecorate %S 1 Offset 16
2045 OpMemberDecorate %S2 0 Offset 0
2046 OpMemberDecorate %S2 1 Offset 16
2047 OpMemberDecorate %S3 0 Offset 0
2048 OpMemberDecorate %S3 1 Offset 16
2049 OpMemberDecorate %S4 0 Offset 0
2050 OpMemberDecorate %S4 1 Offset 12
2051 OpDecorate %S BufferBlock
2052 OpDecorate %S4 Block
2053 OpDecorate %B DescriptorSet 0
2054 OpDecorate %B Binding 0
2055 %void = OpTypeVoid
2056 %3 = OpTypeFunction %void
2057 %float = OpTypeFloat 32
2058 %S4 = OpTypeStruct %float %float
2059 %S3 = OpTypeStruct %float %S4
2060 %S2 = OpTypeStruct %float %S3
2061 %S = OpTypeStruct %float %S2
2062 %_ptr_Uniform_S = OpTypePointer Uniform %S
2063 %B = OpVariable %_ptr_Uniform_S Uniform
2064 %main = OpFunction %void None %3
2065 %5 = OpLabel
2066 OpReturn
2067 OpFunctionEnd
2068 )";
2069
2070 CompileSuccessfully(spirv);
2071 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2072 EXPECT_THAT(getDiagnosticString(),
2073 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
2074 "another Block or BufferBlock."));
2075 }
2076
TEST_F(ValidateDecorations,BlockLayoutForbidsTightScalarVec3PackingBad)2077 TEST_F(ValidateDecorations, BlockLayoutForbidsTightScalarVec3PackingBad) {
2078 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2079 std::string spirv = R"(
2080 OpCapability Shader
2081 OpMemoryModel Logical GLSL450
2082 OpEntryPoint Vertex %main "main"
2083 OpSource GLSL 450
2084 OpMemberDecorate %S 0 Offset 0
2085 OpMemberDecorate %S 1 Offset 4
2086 OpDecorate %S Block
2087 OpDecorate %B DescriptorSet 0
2088 OpDecorate %B Binding 0
2089 %void = OpTypeVoid
2090 %3 = OpTypeFunction %void
2091 %float = OpTypeFloat 32
2092 %v3float = OpTypeVector %float 3
2093 %S = OpTypeStruct %float %v3float
2094 %_ptr_Uniform_S = OpTypePointer Uniform %S
2095 %B = OpVariable %_ptr_Uniform_S Uniform
2096 %main = OpFunction %void None %3
2097 %5 = OpLabel
2098 OpReturn
2099 OpFunctionEnd
2100 )";
2101
2102 CompileSuccessfully(spirv);
2103 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2104 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2105 EXPECT_THAT(
2106 getDiagnosticString(),
2107 HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
2108 "storage class must follow standard uniform buffer layout "
2109 "rules: member 1 at offset 4 is not aligned to 16"));
2110 }
2111
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood)2112 TEST_F(ValidateDecorations,
2113 BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood) {
2114 // Same as previous test, but with explicit option to relax block layout.
2115 std::string spirv = R"(
2116 OpCapability Shader
2117 OpMemoryModel Logical GLSL450
2118 OpEntryPoint Vertex %main "main"
2119 OpSource GLSL 450
2120 OpMemberDecorate %S 0 Offset 0
2121 OpMemberDecorate %S 1 Offset 4
2122 OpDecorate %S Block
2123 OpDecorate %B DescriptorSet 0
2124 OpDecorate %B Binding 0
2125 %void = OpTypeVoid
2126 %3 = OpTypeFunction %void
2127 %float = OpTypeFloat 32
2128 %v3float = OpTypeVector %float 3
2129 %S = OpTypeStruct %float %v3float
2130 %_ptr_Uniform_S = OpTypePointer Uniform %S
2131 %B = OpVariable %_ptr_Uniform_S Uniform
2132 %main = OpFunction %void None %3
2133 %5 = OpLabel
2134 OpReturn
2135 OpFunctionEnd
2136 )";
2137
2138 CompileSuccessfully(spirv);
2139 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2140 EXPECT_EQ(SPV_SUCCESS,
2141 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2142 EXPECT_THAT(getDiagnosticString(), Eq(""));
2143 }
2144
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad)2145 TEST_F(ValidateDecorations,
2146 BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad) {
2147 // Same as previous test, but with the vector not aligned to its scalar
2148 // element. Use offset 5 instead of a multiple of 4.
2149 std::string spirv = R"(
2150 OpCapability Shader
2151 OpMemoryModel Logical GLSL450
2152 OpEntryPoint Vertex %main "main"
2153 OpSource GLSL 450
2154 OpMemberDecorate %S 0 Offset 0
2155 OpMemberDecorate %S 1 Offset 5
2156 OpDecorate %S Block
2157 OpDecorate %B DescriptorSet 0
2158 OpDecorate %B Binding 0
2159 %void = OpTypeVoid
2160 %3 = OpTypeFunction %void
2161 %float = OpTypeFloat 32
2162 %v3float = OpTypeVector %float 3
2163 %S = OpTypeStruct %float %v3float
2164 %_ptr_Uniform_S = OpTypePointer Uniform %S
2165 %B = OpVariable %_ptr_Uniform_S Uniform
2166 %main = OpFunction %void None %3
2167 %5 = OpLabel
2168 OpReturn
2169 OpFunctionEnd
2170 )";
2171
2172 CompileSuccessfully(spirv);
2173 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2174 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2175 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2176 EXPECT_THAT(
2177 getDiagnosticString(),
2178 HasSubstr(
2179 "Structure id 2 decorated as Block for variable in Uniform storage "
2180 "class must follow relaxed uniform buffer layout rules: member 1 at "
2181 "offset 5 is not aligned to scalar element size 4"));
2182 }
2183
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good)2184 TEST_F(ValidateDecorations,
2185 BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good) {
2186 // Same as previous test, but with Vulkan 1.1. Vulkan 1.1 included
2187 // VK_KHR_relaxed_block_layout in core.
2188 std::string spirv = R"(
2189 OpCapability Shader
2190 OpMemoryModel Logical GLSL450
2191 OpEntryPoint Vertex %main "main"
2192 OpSource GLSL 450
2193 OpMemberDecorate %S 0 Offset 0
2194 OpMemberDecorate %S 1 Offset 4
2195 OpDecorate %S Block
2196 OpDecorate %B DescriptorSet 0
2197 OpDecorate %B Binding 0
2198 %void = OpTypeVoid
2199 %3 = OpTypeFunction %void
2200 %float = OpTypeFloat 32
2201 %v3float = OpTypeVector %float 3
2202 %S = OpTypeStruct %float %v3float
2203 %_ptr_Uniform_S = OpTypePointer Uniform %S
2204 %B = OpVariable %_ptr_Uniform_S Uniform
2205 %main = OpFunction %void None %3
2206 %5 = OpLabel
2207 OpReturn
2208 OpFunctionEnd
2209 )";
2210
2211 CompileSuccessfully(spirv);
2212 EXPECT_EQ(SPV_SUCCESS,
2213 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2214 EXPECT_THAT(getDiagnosticString(), Eq(""));
2215 }
2216
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood)2217 TEST_F(ValidateDecorations,
2218 BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood) {
2219 // Same as previous test, but with scalar block layout.
2220 std::string spirv = R"(
2221 OpCapability Shader
2222 OpMemoryModel Logical GLSL450
2223 OpEntryPoint Vertex %main "main"
2224 OpSource GLSL 450
2225 OpMemberDecorate %S 0 Offset 0
2226 OpMemberDecorate %S 1 Offset 4
2227 OpDecorate %S Block
2228 OpDecorate %B DescriptorSet 0
2229 OpDecorate %B Binding 0
2230 %void = OpTypeVoid
2231 %3 = OpTypeFunction %void
2232 %float = OpTypeFloat 32
2233 %v3float = OpTypeVector %float 3
2234 %S = OpTypeStruct %float %v3float
2235 %_ptr_Uniform_S = OpTypePointer Uniform %S
2236 %B = OpVariable %_ptr_Uniform_S Uniform
2237 %main = OpFunction %void None %3
2238 %5 = OpLabel
2239 OpReturn
2240 OpFunctionEnd
2241 )";
2242
2243 CompileSuccessfully(spirv);
2244 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2245 EXPECT_EQ(SPV_SUCCESS,
2246 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2247 EXPECT_THAT(getDiagnosticString(), Eq(""));
2248 }
2249
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood)2250 TEST_F(ValidateDecorations,
2251 BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood) {
2252 // The array at offset 4 is ok with scalar block layout.
2253 std::string spirv = R"(
2254 OpCapability Shader
2255 OpMemoryModel Logical GLSL450
2256 OpEntryPoint Vertex %main "main"
2257 OpSource GLSL 450
2258 OpMemberDecorate %S 0 Offset 0
2259 OpMemberDecorate %S 1 Offset 4
2260 OpDecorate %S Block
2261 OpDecorate %B DescriptorSet 0
2262 OpDecorate %B Binding 0
2263 OpDecorate %arr_float ArrayStride 4
2264 %void = OpTypeVoid
2265 %3 = OpTypeFunction %void
2266 %uint = OpTypeInt 32 0
2267 %uint_3 = OpConstant %uint 3
2268 %float = OpTypeFloat 32
2269 %arr_float = OpTypeArray %float %uint_3
2270 %S = OpTypeStruct %float %arr_float
2271 %_ptr_Uniform_S = OpTypePointer Uniform %S
2272 %B = OpVariable %_ptr_Uniform_S Uniform
2273 %main = OpFunction %void None %3
2274 %5 = OpLabel
2275 OpReturn
2276 OpFunctionEnd
2277 )";
2278
2279 CompileSuccessfully(spirv);
2280 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2281 EXPECT_EQ(SPV_SUCCESS,
2282 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2283 EXPECT_THAT(getDiagnosticString(), Eq(""));
2284 }
2285
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood)2286 TEST_F(ValidateDecorations,
2287 BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood) {
2288 // The array at offset 4 is ok with scalar block layout, even though
2289 // its elements are vec3.
2290 // This is the same as the previous case, but the array elements are vec3
2291 // instead of float.
2292 std::string spirv = R"(
2293 OpCapability Shader
2294 OpMemoryModel Logical GLSL450
2295 OpEntryPoint Vertex %main "main"
2296 OpSource GLSL 450
2297 OpMemberDecorate %S 0 Offset 0
2298 OpMemberDecorate %S 1 Offset 4
2299 OpDecorate %S Block
2300 OpDecorate %B DescriptorSet 0
2301 OpDecorate %B Binding 0
2302 OpDecorate %arr_vec3 ArrayStride 12
2303 %void = OpTypeVoid
2304 %3 = OpTypeFunction %void
2305 %uint = OpTypeInt 32 0
2306 %uint_3 = OpConstant %uint 3
2307 %float = OpTypeFloat 32
2308 %vec3 = OpTypeVector %float 3
2309 %arr_vec3 = OpTypeArray %vec3 %uint_3
2310 %S = OpTypeStruct %float %arr_vec3
2311 %_ptr_Uniform_S = OpTypePointer Uniform %S
2312 %B = OpVariable %_ptr_Uniform_S Uniform
2313 %main = OpFunction %void None %3
2314 %5 = OpLabel
2315 OpReturn
2316 OpFunctionEnd
2317 )";
2318
2319 CompileSuccessfully(spirv);
2320 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2321 EXPECT_EQ(SPV_SUCCESS,
2322 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2323 EXPECT_THAT(getDiagnosticString(), Eq(""));
2324 }
2325
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood)2326 TEST_F(ValidateDecorations,
2327 BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood) {
2328 // Scalar block layout permits the struct at offset 4, even though
2329 // it contains a vector with base alignment 8 and scalar alignment 4.
2330 std::string spirv = R"(
2331 OpCapability Shader
2332 OpMemoryModel Logical GLSL450
2333 OpEntryPoint Vertex %main "main"
2334 OpSource GLSL 450
2335 OpMemberDecorate %S 0 Offset 0
2336 OpMemberDecorate %S 1 Offset 4
2337 OpMemberDecorate %st 0 Offset 0
2338 OpMemberDecorate %st 1 Offset 8
2339 OpDecorate %S Block
2340 OpDecorate %B DescriptorSet 0
2341 OpDecorate %B Binding 0
2342 %void = OpTypeVoid
2343 %3 = OpTypeFunction %void
2344 %float = OpTypeFloat 32
2345 %vec2 = OpTypeVector %float 2
2346 %st = OpTypeStruct %vec2 %float
2347 %S = OpTypeStruct %float %st
2348 %_ptr_Uniform_S = OpTypePointer Uniform %S
2349 %B = OpVariable %_ptr_Uniform_S Uniform
2350 %main = OpFunction %void None %3
2351 %5 = OpLabel
2352 OpReturn
2353 OpFunctionEnd
2354 )";
2355
2356 CompileSuccessfully(spirv);
2357 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2358 EXPECT_EQ(SPV_SUCCESS,
2359 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2360 EXPECT_THAT(getDiagnosticString(), Eq(""));
2361 }
2362
TEST_F(ValidateDecorations,BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood)2363 TEST_F(
2364 ValidateDecorations,
2365 BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood) {
2366 // Scalar block layout permits fields in what would normally be the padding at
2367 // the end of a struct.
2368 std::string spirv = R"(
2369 OpCapability Shader
2370 OpCapability Float64
2371 OpMemoryModel Logical GLSL450
2372 OpEntryPoint Vertex %main "main"
2373 OpSource GLSL 450
2374 OpMemberDecorate %st 0 Offset 0
2375 OpMemberDecorate %st 1 Offset 8
2376 OpMemberDecorate %S 0 Offset 0
2377 OpMemberDecorate %S 1 Offset 12
2378 OpDecorate %S Block
2379 OpDecorate %B DescriptorSet 0
2380 OpDecorate %B Binding 0
2381 %void = OpTypeVoid
2382 %3 = OpTypeFunction %void
2383 %float = OpTypeFloat 32
2384 %double = OpTypeFloat 64
2385 %st = OpTypeStruct %double %float
2386 %S = OpTypeStruct %st %float
2387 %_ptr_Uniform_S = OpTypePointer Uniform %S
2388 %B = OpVariable %_ptr_Uniform_S Uniform
2389 %main = OpFunction %void None %3
2390 %5 = OpLabel
2391 OpReturn
2392 OpFunctionEnd
2393 )";
2394
2395 CompileSuccessfully(spirv);
2396 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2397 EXPECT_EQ(SPV_SUCCESS,
2398 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2399 EXPECT_THAT(getDiagnosticString(), Eq(""));
2400 }
2401
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood)2402 TEST_F(
2403 ValidateDecorations,
2404 BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood) {
2405 // Same as previous, but set relaxed block layout first. Scalar layout always
2406 // wins.
2407 std::string spirv = R"(
2408 OpCapability Shader
2409 OpMemoryModel Logical GLSL450
2410 OpEntryPoint Vertex %main "main"
2411 OpSource GLSL 450
2412 OpMemberDecorate %S 0 Offset 0
2413 OpMemberDecorate %S 1 Offset 4
2414 OpDecorate %S Block
2415 OpDecorate %B DescriptorSet 0
2416 OpDecorate %B Binding 0
2417 %void = OpTypeVoid
2418 %3 = OpTypeFunction %void
2419 %float = OpTypeFloat 32
2420 %vec4 = OpTypeVector %float 4
2421 %S = OpTypeStruct %float %vec4
2422 %_ptr_Uniform_S = OpTypePointer Uniform %S
2423 %B = OpVariable %_ptr_Uniform_S Uniform
2424 %main = OpFunction %void None %3
2425 %5 = OpLabel
2426 OpReturn
2427 OpFunctionEnd
2428 )";
2429
2430 CompileSuccessfully(spirv);
2431 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2432 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2433 EXPECT_EQ(SPV_SUCCESS,
2434 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2435 EXPECT_THAT(getDiagnosticString(), Eq(""));
2436 }
2437
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood)2438 TEST_F(
2439 ValidateDecorations,
2440 BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood) {
2441 // Same as previous, but set scalar block layout first. Scalar layout always
2442 // wins.
2443 std::string spirv = R"(
2444 OpCapability Shader
2445 OpMemoryModel Logical GLSL450
2446 OpEntryPoint Vertex %main "main"
2447 OpSource GLSL 450
2448 OpMemberDecorate %S 0 Offset 0
2449 OpMemberDecorate %S 1 Offset 4
2450 OpDecorate %S Block
2451 OpDecorate %B DescriptorSet 0
2452 OpDecorate %B Binding 0
2453 %void = OpTypeVoid
2454 %3 = OpTypeFunction %void
2455 %float = OpTypeFloat 32
2456 %vec4 = OpTypeVector %float 4
2457 %S = OpTypeStruct %float %vec4
2458 %_ptr_Uniform_S = OpTypePointer Uniform %S
2459 %B = OpVariable %_ptr_Uniform_S Uniform
2460 %main = OpFunction %void None %3
2461 %5 = OpLabel
2462 OpReturn
2463 OpFunctionEnd
2464 )";
2465
2466 CompileSuccessfully(spirv);
2467 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2468 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2469 EXPECT_EQ(SPV_SUCCESS,
2470 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2471 EXPECT_THAT(getDiagnosticString(), Eq(""));
2472 }
2473
TEST_F(ValidateDecorations,BufferBlock16bitStandardStorageBufferLayout)2474 TEST_F(ValidateDecorations, BufferBlock16bitStandardStorageBufferLayout) {
2475 std::string spirv = R"(
2476 OpCapability Shader
2477 OpCapability StorageUniform16
2478 OpExtension "SPV_KHR_16bit_storage"
2479 OpMemoryModel Logical GLSL450
2480 OpEntryPoint GLCompute %main "main"
2481 OpExecutionMode %main LocalSize 1 1 1
2482 OpDecorate %f32arr ArrayStride 4
2483 OpDecorate %f16arr ArrayStride 2
2484 OpMemberDecorate %SSBO32 0 Offset 0
2485 OpMemberDecorate %SSBO16 0 Offset 0
2486 OpDecorate %SSBO32 BufferBlock
2487 OpDecorate %SSBO16 BufferBlock
2488 %void = OpTypeVoid
2489 %voidf = OpTypeFunction %void
2490 %u32 = OpTypeInt 32 0
2491 %i32 = OpTypeInt 32 1
2492 %f32 = OpTypeFloat 32
2493 %uvec3 = OpTypeVector %u32 3
2494 %c_i32_32 = OpConstant %i32 32
2495 %c_i32_128 = OpConstant %i32 128
2496 %f32arr = OpTypeArray %f32 %c_i32_128
2497 %f16 = OpTypeFloat 16
2498 %f16arr = OpTypeArray %f16 %c_i32_128
2499 %SSBO32 = OpTypeStruct %f32arr
2500 %SSBO16 = OpTypeStruct %f16arr
2501 %_ptr_Uniform_SSBO32 = OpTypePointer Uniform %SSBO32
2502 %varSSBO32 = OpVariable %_ptr_Uniform_SSBO32 Uniform
2503 %_ptr_Uniform_SSBO16 = OpTypePointer Uniform %SSBO16
2504 %varSSBO16 = OpVariable %_ptr_Uniform_SSBO16 Uniform
2505 %main = OpFunction %void None %voidf
2506 %label = OpLabel
2507 OpReturn
2508 OpFunctionEnd
2509 )";
2510
2511 CompileSuccessfully(spirv);
2512 EXPECT_EQ(SPV_SUCCESS,
2513 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2514 }
2515
TEST_F(ValidateDecorations,BlockArrayExtendedAlignmentGood)2516 TEST_F(ValidateDecorations, BlockArrayExtendedAlignmentGood) {
2517 // For uniform buffer, Array base alignment is 16, and ArrayStride
2518 // must be a multiple of 16.
2519 std::string spirv = R"(
2520 OpCapability Shader
2521 OpMemoryModel Logical GLSL450
2522 OpEntryPoint Vertex %main "main"
2523 OpSource GLSL 450
2524 OpDecorate %_arr_float_uint_2 ArrayStride 16
2525 OpMemberDecorate %S 0 Offset 0
2526 OpMemberDecorate %S 1 Offset 16
2527 OpDecorate %S Block
2528 %void = OpTypeVoid
2529 %3 = OpTypeFunction %void
2530 %float = OpTypeFloat 32
2531 %v2float = OpTypeVector %float 2
2532 %uint = OpTypeInt 32 0
2533 %uint_2 = OpConstant %uint 2
2534 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2535 %S = OpTypeStruct %v2float %_arr_float_uint_2
2536 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2537 %u = OpVariable %_ptr_PushConstant_S PushConstant
2538 %main = OpFunction %void None %3
2539 %5 = OpLabel
2540 OpReturn
2541 OpFunctionEnd
2542 )";
2543
2544 CompileSuccessfully(spirv);
2545 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2546 << getDiagnosticString();
2547 }
2548
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentBad)2549 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentBad) {
2550 // For uniform buffer, Array base alignment is 16.
2551 std::string spirv = R"(
2552 OpCapability Shader
2553 OpMemoryModel Logical GLSL450
2554 OpEntryPoint Vertex %main "main"
2555 OpSource GLSL 450
2556 OpDecorate %_arr_float_uint_2 ArrayStride 16
2557 OpMemberDecorate %S 0 Offset 0
2558 OpMemberDecorate %S 1 Offset 8
2559 OpDecorate %S Block
2560 %void = OpTypeVoid
2561 %3 = OpTypeFunction %void
2562 %float = OpTypeFloat 32
2563 %v2float = OpTypeVector %float 2
2564 %uint = OpTypeInt 32 0
2565 %uint_2 = OpConstant %uint 2
2566 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2567 %S = OpTypeStruct %v2float %_arr_float_uint_2
2568 %_ptr_Uniform_S = OpTypePointer Uniform %S
2569 %u = OpVariable %_ptr_Uniform_S Uniform
2570 %main = OpFunction %void None %3
2571 %5 = OpLabel
2572 OpReturn
2573 OpFunctionEnd
2574 )";
2575
2576 CompileSuccessfully(spirv);
2577 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2578 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2579 EXPECT_THAT(
2580 getDiagnosticString(),
2581 HasSubstr(
2582 "Structure id 3 decorated as Block for variable in Uniform "
2583 "storage class must follow standard uniform buffer layout rules: "
2584 "member 1 at offset 8 is not aligned to 16"));
2585 }
2586
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithRelaxedLayoutStillBad)2587 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithRelaxedLayoutStillBad) {
2588 // For uniform buffer, Array base alignment is 16, and ArrayStride
2589 // must be a multiple of 16. This case uses relaxed block layout. Relaxed
2590 // layout only relaxes rules for vector alignment, not array alignment.
2591 std::string spirv = R"(
2592 OpCapability Shader
2593 OpMemoryModel Logical GLSL450
2594 OpEntryPoint Vertex %main "main"
2595 OpSource GLSL 450
2596 OpDecorate %_arr_float_uint_2 ArrayStride 16
2597 OpDecorate %u DescriptorSet 0
2598 OpDecorate %u Binding 0
2599 OpMemberDecorate %S 0 Offset 0
2600 OpMemberDecorate %S 1 Offset 8
2601 OpDecorate %S Block
2602 %void = OpTypeVoid
2603 %3 = OpTypeFunction %void
2604 %float = OpTypeFloat 32
2605 %v2float = OpTypeVector %float 2
2606 %uint = OpTypeInt 32 0
2607 %uint_2 = OpConstant %uint 2
2608 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2609 %S = OpTypeStruct %v2float %_arr_float_uint_2
2610 %_ptr_Uniform_S = OpTypePointer Uniform %S
2611 %u = OpVariable %_ptr_Uniform_S Uniform
2612 %main = OpFunction %void None %3
2613 %5 = OpLabel
2614 OpReturn
2615 OpFunctionEnd
2616 )";
2617
2618 CompileSuccessfully(spirv);
2619 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2620 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2621 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2622 EXPECT_THAT(
2623 getDiagnosticString(),
2624 HasSubstr(
2625 "Structure id 4 decorated as Block for variable in Uniform "
2626 "storage class must follow standard uniform buffer layout rules: "
2627 "member 1 at offset 8 is not aligned to 16"));
2628 }
2629
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithVulkan1_1StillBad)2630 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithVulkan1_1StillBad) {
2631 // Same as previous test, but with Vulkan 1.1, which includes
2632 // VK_KHR_relaxed_block_layout in core.
2633 std::string spirv = R"(
2634 OpCapability Shader
2635 OpMemoryModel Logical GLSL450
2636 OpEntryPoint Vertex %main "main"
2637 OpSource GLSL 450
2638 OpDecorate %_arr_float_uint_2 ArrayStride 16
2639 OpDecorate %u DescriptorSet 0
2640 OpDecorate %u Binding 0
2641 OpMemberDecorate %S 0 Offset 0
2642 OpMemberDecorate %S 1 Offset 8
2643 OpDecorate %S Block
2644 %void = OpTypeVoid
2645 %3 = OpTypeFunction %void
2646 %float = OpTypeFloat 32
2647 %v2float = OpTypeVector %float 2
2648 %uint = OpTypeInt 32 0
2649 %uint_2 = OpConstant %uint 2
2650 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2651 %S = OpTypeStruct %v2float %_arr_float_uint_2
2652 %_ptr_Uniform_S = OpTypePointer Uniform %S
2653 %u = OpVariable %_ptr_Uniform_S Uniform
2654 %main = OpFunction %void None %3
2655 %5 = OpLabel
2656 OpReturn
2657 OpFunctionEnd
2658 )";
2659
2660 CompileSuccessfully(spirv);
2661 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2662 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2663 EXPECT_THAT(
2664 getDiagnosticString(),
2665 HasSubstr(
2666 "Structure id 4 decorated as Block for variable in Uniform "
2667 "storage class must follow relaxed uniform buffer layout rules: "
2668 "member 1 at offset 8 is not aligned to 16"));
2669 }
2670
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithBlockStandardLayoutGood)2671 TEST_F(ValidateDecorations,
2672 BlockArrayBaseAlignmentWithBlockStandardLayoutGood) {
2673 // Same as previous test, but with VK_KHR_uniform_buffer_standard_layout
2674 std::string spirv = R"(
2675 OpCapability Shader
2676 OpMemoryModel Logical GLSL450
2677 OpEntryPoint Vertex %main "main"
2678 OpSource GLSL 450
2679 OpDecorate %_arr_float_uint_2 ArrayStride 16
2680 OpDecorate %u DescriptorSet 0
2681 OpDecorate %u Binding 0
2682 OpMemberDecorate %S 0 Offset 0
2683 OpMemberDecorate %S 1 Offset 8
2684 OpDecorate %S Block
2685 %void = OpTypeVoid
2686 %3 = OpTypeFunction %void
2687 %float = OpTypeFloat 32
2688 %v2float = OpTypeVector %float 2
2689 %uint = OpTypeInt 32 0
2690 %uint_2 = OpConstant %uint 2
2691 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2692 %S = OpTypeStruct %v2float %_arr_float_uint_2
2693 %_ptr_Uniform_S = OpTypePointer Uniform %S
2694 %u = OpVariable %_ptr_Uniform_S Uniform
2695 %main = OpFunction %void None %3
2696 %5 = OpLabel
2697 OpReturn
2698 OpFunctionEnd
2699 )";
2700
2701 CompileSuccessfully(spirv);
2702 spvValidatorOptionsSetUniformBufferStandardLayout(getValidatorOptions(),
2703 true);
2704 EXPECT_EQ(SPV_SUCCESS,
2705 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2706 EXPECT_THAT(getDiagnosticString(), Eq(""));
2707 }
2708
TEST_F(ValidateDecorations,VulkanBufferBlockOnStorageBufferBad)2709 TEST_F(ValidateDecorations, VulkanBufferBlockOnStorageBufferBad) {
2710 std::string spirv = R"(
2711 OpCapability Shader
2712 OpExtension "SPV_KHR_storage_buffer_storage_class"
2713 OpMemoryModel Logical GLSL450
2714 OpEntryPoint Fragment %1 "main"
2715 OpExecutionMode %1 OriginUpperLeft
2716
2717 OpDecorate %struct BufferBlock
2718
2719 %void = OpTypeVoid
2720 %voidfn = OpTypeFunction %void
2721 %float = OpTypeFloat 32
2722 %struct = OpTypeStruct %float
2723 %ptr = OpTypePointer StorageBuffer %struct
2724 %var = OpVariable %ptr StorageBuffer
2725
2726 %1 = OpFunction %void None %voidfn
2727 %label = OpLabel
2728 OpReturn
2729 OpFunctionEnd
2730 )";
2731
2732 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2733 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2734 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2735 EXPECT_THAT(getDiagnosticString(),
2736 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
2737 EXPECT_THAT(getDiagnosticString(),
2738 HasSubstr("In Vulkan, BufferBlock is disallowed on variables in "
2739 "the StorageBuffer storage class"));
2740 }
2741
TEST_F(ValidateDecorations,PushConstantArrayBaseAlignmentGood)2742 TEST_F(ValidateDecorations, PushConstantArrayBaseAlignmentGood) {
2743 // Tests https://github.com/KhronosGroup/SPIRV-Tools/issues/1664
2744 // From GLSL vertex shader:
2745 // #version 450
2746 // layout(push_constant) uniform S { vec2 v; float arr[2]; } u;
2747 // void main() { }
2748
2749 std::string spirv = R"(
2750 OpCapability Shader
2751 OpMemoryModel Logical GLSL450
2752 OpEntryPoint Vertex %main "main"
2753 OpSource GLSL 450
2754 OpDecorate %_arr_float_uint_2 ArrayStride 4
2755 OpMemberDecorate %S 0 Offset 0
2756 OpMemberDecorate %S 1 Offset 8
2757 OpDecorate %S Block
2758 %void = OpTypeVoid
2759 %3 = OpTypeFunction %void
2760 %float = OpTypeFloat 32
2761 %v2float = OpTypeVector %float 2
2762 %uint = OpTypeInt 32 0
2763 %uint_2 = OpConstant %uint 2
2764 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2765 %S = OpTypeStruct %v2float %_arr_float_uint_2
2766 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2767 %u = OpVariable %_ptr_PushConstant_S PushConstant
2768 %main = OpFunction %void None %3
2769 %5 = OpLabel
2770 OpReturn
2771 OpFunctionEnd
2772 )";
2773
2774 CompileSuccessfully(spirv);
2775 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
2776 << getDiagnosticString();
2777 }
2778
TEST_F(ValidateDecorations,PushConstantArrayBadAlignmentBad)2779 TEST_F(ValidateDecorations, PushConstantArrayBadAlignmentBad) {
2780 // Like the previous test, but with offset 7 instead of 8.
2781 std::string spirv = R"(
2782 OpCapability Shader
2783 OpMemoryModel Logical GLSL450
2784 OpEntryPoint Vertex %main "main"
2785 OpSource GLSL 450
2786 OpDecorate %_arr_float_uint_2 ArrayStride 4
2787 OpMemberDecorate %S 0 Offset 0
2788 OpMemberDecorate %S 1 Offset 7
2789 OpDecorate %S Block
2790 %void = OpTypeVoid
2791 %3 = OpTypeFunction %void
2792 %float = OpTypeFloat 32
2793 %v2float = OpTypeVector %float 2
2794 %uint = OpTypeInt 32 0
2795 %uint_2 = OpConstant %uint 2
2796 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2797 %S = OpTypeStruct %v2float %_arr_float_uint_2
2798 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2799 %u = OpVariable %_ptr_PushConstant_S PushConstant
2800 %main = OpFunction %void None %3
2801 %5 = OpLabel
2802 OpReturn
2803 OpFunctionEnd
2804 )";
2805
2806 CompileSuccessfully(spirv);
2807 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2808 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2809 EXPECT_THAT(
2810 getDiagnosticString(),
2811 HasSubstr(
2812 "Structure id 3 decorated as Block for variable in PushConstant "
2813 "storage class must follow standard storage buffer layout rules: "
2814 "member 1 at offset 7 is not aligned to 4"));
2815 }
2816
TEST_F(ValidateDecorations,PushConstantLayoutPermitsTightVec3ScalarPackingGood)2817 TEST_F(ValidateDecorations,
2818 PushConstantLayoutPermitsTightVec3ScalarPackingGood) {
2819 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2820 std::string spirv = R"(
2821 OpCapability Shader
2822 OpMemoryModel Logical GLSL450
2823 OpEntryPoint Vertex %main "main"
2824 OpSource GLSL 450
2825 OpMemberDecorate %S 0 Offset 0
2826 OpMemberDecorate %S 1 Offset 12
2827 OpDecorate %S Block
2828 %void = OpTypeVoid
2829 %3 = OpTypeFunction %void
2830 %float = OpTypeFloat 32
2831 %v3float = OpTypeVector %float 3
2832 %S = OpTypeStruct %v3float %float
2833 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2834 %B = OpVariable %_ptr_PushConstant_S PushConstant
2835 %main = OpFunction %void None %3
2836 %5 = OpLabel
2837 OpReturn
2838 OpFunctionEnd
2839 )";
2840
2841 CompileSuccessfully(spirv);
2842 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
2843 << getDiagnosticString();
2844 }
2845
TEST_F(ValidateDecorations,PushConstantLayoutForbidsTightScalarVec3PackingBad)2846 TEST_F(ValidateDecorations,
2847 PushConstantLayoutForbidsTightScalarVec3PackingBad) {
2848 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2849 std::string spirv = R"(
2850 OpCapability Shader
2851 OpMemoryModel Logical GLSL450
2852 OpEntryPoint Vertex %main "main"
2853 OpSource GLSL 450
2854 OpMemberDecorate %S 0 Offset 0
2855 OpMemberDecorate %S 1 Offset 4
2856 OpDecorate %S Block
2857 %void = OpTypeVoid
2858 %3 = OpTypeFunction %void
2859 %float = OpTypeFloat 32
2860 %v3float = OpTypeVector %float 3
2861 %S = OpTypeStruct %float %v3float
2862 %_ptr_Uniform_S = OpTypePointer PushConstant %S
2863 %B = OpVariable %_ptr_Uniform_S PushConstant
2864 %main = OpFunction %void None %3
2865 %5 = OpLabel
2866 OpReturn
2867 OpFunctionEnd
2868 )";
2869
2870 CompileSuccessfully(spirv);
2871 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2872 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2873 EXPECT_THAT(
2874 getDiagnosticString(),
2875 HasSubstr(
2876 "Structure id 2 decorated as Block for variable in PushConstant "
2877 "storage class must follow standard storage buffer layout "
2878 "rules: member 1 at offset 4 is not aligned to 16"));
2879 }
2880
TEST_F(ValidateDecorations,PushConstantMissingBlockGood)2881 TEST_F(ValidateDecorations, PushConstantMissingBlockGood) {
2882 std::string spirv = R"(
2883 OpCapability Shader
2884 OpMemoryModel Logical GLSL450
2885 OpEntryPoint Fragment %1 "main"
2886 OpExecutionMode %1 OriginUpperLeft
2887
2888 OpMemberDecorate %struct 0 Offset 0
2889
2890 %void = OpTypeVoid
2891 %voidfn = OpTypeFunction %void
2892 %float = OpTypeFloat 32
2893 %struct = OpTypeStruct %float
2894 %ptr = OpTypePointer PushConstant %struct
2895 %pc = OpVariable %ptr PushConstant
2896
2897 %1 = OpFunction %void None %voidfn
2898 %label = OpLabel
2899 OpReturn
2900 OpFunctionEnd
2901 )";
2902
2903 CompileSuccessfully(spirv);
2904 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2905 << getDiagnosticString();
2906 }
2907
TEST_F(ValidateDecorations,VulkanPushConstantMissingBlockBad)2908 TEST_F(ValidateDecorations, VulkanPushConstantMissingBlockBad) {
2909 std::string spirv = R"(
2910 OpCapability Shader
2911 OpMemoryModel Logical GLSL450
2912 OpEntryPoint Fragment %1 "main"
2913 OpExecutionMode %1 OriginUpperLeft
2914
2915 OpMemberDecorate %struct 0 Offset 0
2916
2917 %void = OpTypeVoid
2918 %voidfn = OpTypeFunction %void
2919 %float = OpTypeFloat 32
2920 %struct = OpTypeStruct %float
2921 %ptr = OpTypePointer PushConstant %struct
2922 %pc = OpVariable %ptr PushConstant
2923
2924 %1 = OpFunction %void None %voidfn
2925 %label = OpLabel
2926 OpReturn
2927 OpFunctionEnd
2928 )";
2929
2930 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2931 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2932 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2933 EXPECT_THAT(getDiagnosticString(),
2934 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
2935 EXPECT_THAT(getDiagnosticString(),
2936 HasSubstr("PushConstant id '2' is missing Block decoration.\n"
2937 "From Vulkan spec:\n"
2938 "Such variables must be identified with a Block "
2939 "decoration"));
2940 }
2941
TEST_F(ValidateDecorations,MultiplePushConstantsSingleEntryPointGood)2942 TEST_F(ValidateDecorations, MultiplePushConstantsSingleEntryPointGood) {
2943 std::string spirv = R"(
2944 OpCapability Shader
2945 OpMemoryModel Logical GLSL450
2946 OpEntryPoint Fragment %1 "main"
2947 OpExecutionMode %1 OriginUpperLeft
2948
2949 OpDecorate %struct Block
2950 OpMemberDecorate %struct 0 Offset 0
2951
2952 %void = OpTypeVoid
2953 %voidfn = OpTypeFunction %void
2954 %float = OpTypeFloat 32
2955 %int = OpTypeInt 32 0
2956 %int_0 = OpConstant %int 0
2957 %struct = OpTypeStruct %float
2958 %ptr = OpTypePointer PushConstant %struct
2959 %ptr_float = OpTypePointer PushConstant %float
2960 %pc1 = OpVariable %ptr PushConstant
2961 %pc2 = OpVariable %ptr PushConstant
2962
2963 %1 = OpFunction %void None %voidfn
2964 %label = OpLabel
2965 %2 = OpAccessChain %ptr_float %pc1 %int_0
2966 %3 = OpLoad %float %2
2967 %4 = OpAccessChain %ptr_float %pc2 %int_0
2968 %5 = OpLoad %float %4
2969 OpReturn
2970 OpFunctionEnd
2971 )";
2972
2973 CompileSuccessfully(spirv);
2974 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2975 << getDiagnosticString();
2976 }
2977
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointGood)2978 TEST_F(ValidateDecorations,
2979 VulkanMultiplePushConstantsDifferentEntryPointGood) {
2980 std::string spirv = R"(
2981 OpCapability Shader
2982 OpMemoryModel Logical GLSL450
2983 OpEntryPoint Vertex %1 "func1"
2984 OpEntryPoint Fragment %2 "func2"
2985 OpExecutionMode %2 OriginUpperLeft
2986
2987 OpDecorate %struct Block
2988 OpMemberDecorate %struct 0 Offset 0
2989
2990 %void = OpTypeVoid
2991 %voidfn = OpTypeFunction %void
2992 %float = OpTypeFloat 32
2993 %int = OpTypeInt 32 0
2994 %int_0 = OpConstant %int 0
2995 %struct = OpTypeStruct %float
2996 %ptr = OpTypePointer PushConstant %struct
2997 %ptr_float = OpTypePointer PushConstant %float
2998 %pc1 = OpVariable %ptr PushConstant
2999 %pc2 = OpVariable %ptr PushConstant
3000
3001 %1 = OpFunction %void None %voidfn
3002 %label1 = OpLabel
3003 %3 = OpAccessChain %ptr_float %pc1 %int_0
3004 %4 = OpLoad %float %3
3005 OpReturn
3006 OpFunctionEnd
3007
3008 %2 = OpFunction %void None %voidfn
3009 %label2 = OpLabel
3010 %5 = OpAccessChain %ptr_float %pc2 %int_0
3011 %6 = OpLoad %float %5
3012 OpReturn
3013 OpFunctionEnd
3014 )";
3015
3016 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3017 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3018 << getDiagnosticString();
3019 }
3020
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsUnusedSingleEntryPointGood)3021 TEST_F(ValidateDecorations,
3022 VulkanMultiplePushConstantsUnusedSingleEntryPointGood) {
3023 std::string spirv = R"(
3024 OpCapability Shader
3025 OpMemoryModel Logical GLSL450
3026 OpEntryPoint Fragment %1 "main"
3027 OpExecutionMode %1 OriginUpperLeft
3028
3029 OpDecorate %struct Block
3030 OpMemberDecorate %struct 0 Offset 0
3031
3032 %void = OpTypeVoid
3033 %voidfn = OpTypeFunction %void
3034 %float = OpTypeFloat 32
3035 %int = OpTypeInt 32 0
3036 %int_0 = OpConstant %int 0
3037 %struct = OpTypeStruct %float
3038 %ptr = OpTypePointer PushConstant %struct
3039 %ptr_float = OpTypePointer PushConstant %float
3040 %pc1 = OpVariable %ptr PushConstant
3041 %pc2 = OpVariable %ptr PushConstant
3042
3043 %1 = OpFunction %void None %voidfn
3044 %label = OpLabel
3045 OpReturn
3046 OpFunctionEnd
3047 )";
3048
3049 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3050 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3051 << getDiagnosticString();
3052 }
3053
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointBad)3054 TEST_F(ValidateDecorations, VulkanMultiplePushConstantsSingleEntryPointBad) {
3055 std::string spirv = R"(
3056 OpCapability Shader
3057 OpMemoryModel Logical GLSL450
3058 OpEntryPoint Fragment %1 "main"
3059 OpExecutionMode %1 OriginUpperLeft
3060
3061 OpDecorate %struct Block
3062 OpMemberDecorate %struct 0 Offset 0
3063
3064 %void = OpTypeVoid
3065 %voidfn = OpTypeFunction %void
3066 %float = OpTypeFloat 32
3067 %int = OpTypeInt 32 0
3068 %int_0 = OpConstant %int 0
3069 %struct = OpTypeStruct %float
3070 %ptr = OpTypePointer PushConstant %struct
3071 %ptr_float = OpTypePointer PushConstant %float
3072 %pc1 = OpVariable %ptr PushConstant
3073 %pc2 = OpVariable %ptr PushConstant
3074
3075 %1 = OpFunction %void None %voidfn
3076 %label = OpLabel
3077 %2 = OpAccessChain %ptr_float %pc1 %int_0
3078 %3 = OpLoad %float %2
3079 %4 = OpAccessChain %ptr_float %pc2 %int_0
3080 %5 = OpLoad %float %4
3081 OpReturn
3082 OpFunctionEnd
3083 )";
3084
3085 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3086 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3087 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3088 EXPECT_THAT(getDiagnosticString(),
3089 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-06674"));
3090 EXPECT_THAT(
3091 getDiagnosticString(),
3092 HasSubstr(
3093 "Entry point id '1' uses more than one PushConstant interface.\n"
3094 "From Vulkan spec:\n"
3095 "There must be no more than one push constant block "
3096 "statically used per shader entry point."));
3097 }
3098
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood)3099 TEST_F(ValidateDecorations,
3100 VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood) {
3101 std::string spirv = R"(
3102 OpCapability Shader
3103 OpMemoryModel Logical GLSL450
3104 OpEntryPoint Vertex %1 "func1"
3105 OpEntryPoint Fragment %2 "func2"
3106 OpExecutionMode %2 OriginUpperLeft
3107
3108 OpDecorate %struct Block
3109 OpMemberDecorate %struct 0 Offset 0
3110
3111 %void = OpTypeVoid
3112 %voidfn = OpTypeFunction %void
3113 %float = OpTypeFloat 32
3114 %int = OpTypeInt 32 0
3115 %int_0 = OpConstant %int 0
3116 %struct = OpTypeStruct %float
3117 %ptr = OpTypePointer PushConstant %struct
3118 %ptr_float = OpTypePointer PushConstant %float
3119 %pc1 = OpVariable %ptr PushConstant
3120 %pc2 = OpVariable %ptr PushConstant
3121
3122 %sub1 = OpFunction %void None %voidfn
3123 %label_sub1 = OpLabel
3124 %3 = OpAccessChain %ptr_float %pc1 %int_0
3125 %4 = OpLoad %float %3
3126 OpReturn
3127 OpFunctionEnd
3128
3129 %sub2 = OpFunction %void None %voidfn
3130 %label_sub2 = OpLabel
3131 %5 = OpAccessChain %ptr_float %pc2 %int_0
3132 %6 = OpLoad %float %5
3133 OpReturn
3134 OpFunctionEnd
3135
3136 %1 = OpFunction %void None %voidfn
3137 %label1 = OpLabel
3138 %call1 = OpFunctionCall %void %sub1
3139 OpReturn
3140 OpFunctionEnd
3141
3142 %2 = OpFunction %void None %voidfn
3143 %label2 = OpLabel
3144 %call2 = OpFunctionCall %void %sub2
3145 OpReturn
3146 OpFunctionEnd
3147 )";
3148
3149 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3150 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3151 << getDiagnosticString();
3152 }
3153
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad)3154 TEST_F(ValidateDecorations,
3155 VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad) {
3156 std::string spirv = R"(
3157 OpCapability Shader
3158 OpMemoryModel Logical GLSL450
3159 OpEntryPoint Fragment %1 "main"
3160 OpExecutionMode %1 OriginUpperLeft
3161
3162 OpDecorate %struct Block
3163 OpMemberDecorate %struct 0 Offset 0
3164
3165 %void = OpTypeVoid
3166 %voidfn = OpTypeFunction %void
3167 %float = OpTypeFloat 32
3168 %int = OpTypeInt 32 0
3169 %int_0 = OpConstant %int 0
3170 %struct = OpTypeStruct %float
3171 %ptr = OpTypePointer PushConstant %struct
3172 %ptr_float = OpTypePointer PushConstant %float
3173 %pc1 = OpVariable %ptr PushConstant
3174 %pc2 = OpVariable %ptr PushConstant
3175
3176 %sub1 = OpFunction %void None %voidfn
3177 %label_sub1 = OpLabel
3178 %3 = OpAccessChain %ptr_float %pc1 %int_0
3179 %4 = OpLoad %float %3
3180 OpReturn
3181 OpFunctionEnd
3182
3183 %sub2 = OpFunction %void None %voidfn
3184 %label_sub2 = OpLabel
3185 %5 = OpAccessChain %ptr_float %pc2 %int_0
3186 %6 = OpLoad %float %5
3187 OpReturn
3188 OpFunctionEnd
3189
3190 %1 = OpFunction %void None %voidfn
3191 %label1 = OpLabel
3192 %call1 = OpFunctionCall %void %sub1
3193 %call2 = OpFunctionCall %void %sub2
3194 OpReturn
3195 OpFunctionEnd
3196 )";
3197
3198 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3199 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3200 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3201 EXPECT_THAT(getDiagnosticString(),
3202 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-06674"));
3203 EXPECT_THAT(
3204 getDiagnosticString(),
3205 HasSubstr(
3206 "Entry point id '1' uses more than one PushConstant interface.\n"
3207 "From Vulkan spec:\n"
3208 "There must be no more than one push constant block "
3209 "statically used per shader entry point."));
3210 }
3211
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointInterfaceBad)3212 TEST_F(ValidateDecorations,
3213 VulkanMultiplePushConstantsSingleEntryPointInterfaceBad) {
3214 std::string spirv = R"(
3215 OpCapability Shader
3216 OpMemoryModel Logical GLSL450
3217 OpEntryPoint Vertex %func1 "func1" %pc1 %pc2
3218 OpDecorate %struct Block
3219 OpMemberDecorate %struct 0 Offset 0
3220 %void = OpTypeVoid
3221 %voidfn = OpTypeFunction %void
3222 %float = OpTypeFloat 32
3223 %int = OpTypeInt 32 0
3224 %int_0 = OpConstant %int 0
3225 %struct = OpTypeStruct %float
3226 %ptr = OpTypePointer PushConstant %struct
3227 %ptr_float = OpTypePointer PushConstant %float
3228 %pc1 = OpVariable %ptr PushConstant
3229 %pc2 = OpVariable %ptr PushConstant
3230 %func1 = OpFunction %void None %voidfn
3231 %label1 = OpLabel
3232 %access1 = OpAccessChain %ptr_float %pc1 %int_0
3233 %load1 = OpLoad %float %access1
3234 OpReturn
3235 OpFunctionEnd
3236 %func2 = OpFunction %void None %voidfn
3237 %label2 = OpLabel
3238 %access2 = OpAccessChain %ptr_float %pc2 %int_0
3239 %load2 = OpLoad %float %access2
3240 OpReturn
3241 OpFunctionEnd
3242 )";
3243
3244 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
3245 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3246 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
3247 EXPECT_THAT(getDiagnosticString(),
3248 AnyVUID("VUID-StandaloneSpirv-OpVariable-06673"));
3249 EXPECT_THAT(getDiagnosticString(),
3250 HasSubstr("Entry-point has more than one variable with the "
3251 "PushConstant storage class in the interface"));
3252 }
3253
TEST_F(ValidateDecorations,VulkanUniformMissingDescriptorSetBad)3254 TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
3255 std::string spirv = R"(
3256 OpCapability Shader
3257 OpMemoryModel Logical GLSL450
3258 OpEntryPoint Fragment %1 "main"
3259 OpExecutionMode %1 OriginUpperLeft
3260
3261 OpDecorate %struct Block
3262 OpMemberDecorate %struct 0 Offset 0
3263 OpDecorate %var Binding 0
3264
3265 %void = OpTypeVoid
3266 %voidfn = OpTypeFunction %void
3267 %float = OpTypeFloat 32
3268 %struct = OpTypeStruct %float
3269 %ptr = OpTypePointer Uniform %struct
3270 %ptr_float = OpTypePointer Uniform %float
3271 %var = OpVariable %ptr Uniform
3272 %int = OpTypeInt 32 0
3273 %int_0 = OpConstant %int 0
3274
3275 %1 = OpFunction %void None %voidfn
3276 %label = OpLabel
3277 %2 = OpAccessChain %ptr_float %var %int_0
3278 %3 = OpLoad %float %2
3279 OpReturn
3280 OpFunctionEnd
3281 )";
3282
3283 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3284 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3285 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3286 EXPECT_THAT(getDiagnosticString(),
3287 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3288 EXPECT_THAT(getDiagnosticString(),
3289 HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n"
3290 "From Vulkan spec:\n"
3291 "These variables must have DescriptorSet and Binding "
3292 "decorations specified"));
3293 }
3294
TEST_F(ValidateDecorations,VulkanUniformMissingBindingBad)3295 TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) {
3296 std::string spirv = R"(
3297 OpCapability Shader
3298 OpMemoryModel Logical GLSL450
3299 OpEntryPoint Fragment %1 "main"
3300 OpExecutionMode %1 OriginUpperLeft
3301
3302 OpDecorate %struct Block
3303 OpMemberDecorate %struct 0 Offset 0
3304 OpDecorate %var DescriptorSet 0
3305
3306 %void = OpTypeVoid
3307 %voidfn = OpTypeFunction %void
3308 %float = OpTypeFloat 32
3309 %struct = OpTypeStruct %float
3310 %ptr = OpTypePointer Uniform %struct
3311 %ptr_float = OpTypePointer Uniform %float
3312 %var = OpVariable %ptr Uniform
3313 %int = OpTypeInt 32 0
3314 %int_0 = OpConstant %int 0
3315
3316 %1 = OpFunction %void None %voidfn
3317 %label = OpLabel
3318 %2 = OpAccessChain %ptr_float %var %int_0
3319 %3 = OpLoad %float %2
3320 OpReturn
3321 OpFunctionEnd
3322 )";
3323
3324 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3325 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3326 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3327 EXPECT_THAT(getDiagnosticString(),
3328 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3329 EXPECT_THAT(getDiagnosticString(),
3330 HasSubstr("Uniform id '3' is missing Binding decoration.\n"
3331 "From Vulkan spec:\n"
3332 "These variables must have DescriptorSet and Binding "
3333 "decorations specified"));
3334 }
3335
TEST_F(ValidateDecorations,VulkanUniformConstantMissingDescriptorSetBad)3336 TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) {
3337 std::string spirv = R"(
3338 OpCapability Shader
3339 OpMemoryModel Logical GLSL450
3340 OpEntryPoint Fragment %1 "main"
3341 OpExecutionMode %1 OriginUpperLeft
3342
3343 OpDecorate %var Binding 0
3344
3345 %void = OpTypeVoid
3346 %voidfn = OpTypeFunction %void
3347 %sampler = OpTypeSampler
3348 %ptr = OpTypePointer UniformConstant %sampler
3349 %var = OpVariable %ptr UniformConstant
3350
3351 %1 = OpFunction %void None %voidfn
3352 %label = OpLabel
3353 %2 = OpLoad %sampler %var
3354 OpReturn
3355 OpFunctionEnd
3356 )";
3357
3358 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3359 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3360 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3361 EXPECT_THAT(getDiagnosticString(),
3362 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3363 EXPECT_THAT(
3364 getDiagnosticString(),
3365 HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n"
3366 "From Vulkan spec:\n"
3367 "These variables must have DescriptorSet and Binding "
3368 "decorations specified"));
3369 }
3370
TEST_F(ValidateDecorations,VulkanUniformConstantMissingBindingBad)3371 TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) {
3372 std::string spirv = R"(
3373 OpCapability Shader
3374 OpMemoryModel Logical GLSL450
3375 OpEntryPoint Fragment %1 "main"
3376 OpExecutionMode %1 OriginUpperLeft
3377
3378 OpDecorate %var DescriptorSet 0
3379
3380 %void = OpTypeVoid
3381 %voidfn = OpTypeFunction %void
3382 %sampler = OpTypeSampler
3383 %ptr = OpTypePointer UniformConstant %sampler
3384 %var = OpVariable %ptr UniformConstant
3385
3386 %1 = OpFunction %void None %voidfn
3387 %label = OpLabel
3388 %2 = OpLoad %sampler %var
3389 OpReturn
3390 OpFunctionEnd
3391 )";
3392
3393 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3394 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3395 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3396 EXPECT_THAT(getDiagnosticString(),
3397 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3398 EXPECT_THAT(
3399 getDiagnosticString(),
3400 HasSubstr("UniformConstant id '2' is missing Binding decoration.\n"
3401 "From Vulkan spec:\n"
3402 "These variables must have DescriptorSet and Binding "
3403 "decorations specified"));
3404 }
3405
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetBad)3406 TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) {
3407 std::string spirv = R"(
3408 OpCapability Shader
3409 OpExtension "SPV_KHR_storage_buffer_storage_class"
3410 OpMemoryModel Logical GLSL450
3411 OpEntryPoint Fragment %1 "main"
3412 OpExecutionMode %1 OriginUpperLeft
3413
3414 OpDecorate %struct Block
3415 OpDecorate %var Binding 0
3416
3417 %void = OpTypeVoid
3418 %voidfn = OpTypeFunction %void
3419 %float = OpTypeFloat 32
3420 %struct = OpTypeStruct %float
3421 %ptr = OpTypePointer StorageBuffer %struct
3422 %var = OpVariable %ptr StorageBuffer
3423 %ptr_float = OpTypePointer StorageBuffer %float
3424 %int = OpTypeInt 32 0
3425 %int_0 = OpConstant %int 0
3426
3427 %1 = OpFunction %void None %voidfn
3428 %label = OpLabel
3429 %2 = OpAccessChain %ptr_float %var %int_0
3430 %3 = OpLoad %float %2
3431 OpReturn
3432 OpFunctionEnd
3433 )";
3434
3435 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3436 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3437 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3438 EXPECT_THAT(getDiagnosticString(),
3439 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3440 EXPECT_THAT(
3441 getDiagnosticString(),
3442 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3443 "From Vulkan spec:\n"
3444 "These variables must have DescriptorSet and Binding "
3445 "decorations specified"));
3446 }
3447
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBindingBad)3448 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) {
3449 std::string spirv = R"(
3450 OpCapability Shader
3451 OpExtension "SPV_KHR_storage_buffer_storage_class"
3452 OpMemoryModel Logical GLSL450
3453 OpEntryPoint Fragment %1 "main"
3454 OpExecutionMode %1 OriginUpperLeft
3455
3456 OpDecorate %struct Block
3457 OpDecorate %var DescriptorSet 0
3458
3459 %void = OpTypeVoid
3460 %voidfn = OpTypeFunction %void
3461 %float = OpTypeFloat 32
3462 %struct = OpTypeStruct %float
3463 %ptr = OpTypePointer StorageBuffer %struct
3464 %var = OpVariable %ptr StorageBuffer
3465 %ptr_float = OpTypePointer StorageBuffer %float
3466 %int = OpTypeInt 32 0
3467 %int_0 = OpConstant %int 0
3468
3469 %1 = OpFunction %void None %voidfn
3470 %label = OpLabel
3471 %2 = OpAccessChain %ptr_float %var %int_0
3472 %3 = OpLoad %float %2
3473 OpReturn
3474 OpFunctionEnd
3475 )";
3476
3477 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3478 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3479 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3480 EXPECT_THAT(getDiagnosticString(),
3481 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3482 EXPECT_THAT(getDiagnosticString(),
3483 HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n"
3484 "From Vulkan spec:\n"
3485 "These variables must have DescriptorSet and Binding "
3486 "decorations specified"));
3487 }
3488
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetSubFunctionBad)3489 TEST_F(ValidateDecorations,
3490 VulkanStorageBufferMissingDescriptorSetSubFunctionBad) {
3491 std::string spirv = R"(
3492 OpCapability Shader
3493 OpExtension "SPV_KHR_storage_buffer_storage_class"
3494 OpMemoryModel Logical GLSL450
3495 OpEntryPoint Fragment %1 "main"
3496 OpExecutionMode %1 OriginUpperLeft
3497
3498 OpDecorate %struct Block
3499 OpDecorate %var Binding 0
3500
3501 %void = OpTypeVoid
3502 %voidfn = OpTypeFunction %void
3503 %float = OpTypeFloat 32
3504 %struct = OpTypeStruct %float
3505 %ptr = OpTypePointer StorageBuffer %struct
3506 %var = OpVariable %ptr StorageBuffer
3507 %ptr_float = OpTypePointer StorageBuffer %float
3508 %int = OpTypeInt 32 0
3509 %int_0 = OpConstant %int 0
3510
3511 %1 = OpFunction %void None %voidfn
3512 %label = OpLabel
3513 %call = OpFunctionCall %void %2
3514 OpReturn
3515 OpFunctionEnd
3516 %2 = OpFunction %void None %voidfn
3517 %label2 = OpLabel
3518 %3 = OpAccessChain %ptr_float %var %int_0
3519 %4 = OpLoad %float %3
3520 OpReturn
3521 OpFunctionEnd
3522 )";
3523
3524 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3525 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3526 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3527 EXPECT_THAT(getDiagnosticString(),
3528 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3529 EXPECT_THAT(
3530 getDiagnosticString(),
3531 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3532 "From Vulkan spec:\n"
3533 "These variables must have DescriptorSet and Binding "
3534 "decorations specified"));
3535 }
3536
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorAndBindingUnusedGood)3537 TEST_F(ValidateDecorations,
3538 VulkanStorageBufferMissingDescriptorAndBindingUnusedGood) {
3539 std::string spirv = R"(
3540 OpCapability Shader
3541 OpExtension "SPV_KHR_storage_buffer_storage_class"
3542 OpMemoryModel Logical GLSL450
3543 OpEntryPoint Fragment %1 "main"
3544 OpExecutionMode %1 OriginUpperLeft
3545 OpDecorate %struct Block
3546 OpMemberDecorate %struct 0 Offset 0
3547
3548 %void = OpTypeVoid
3549 %voidfn = OpTypeFunction %void
3550 %float = OpTypeFloat 32
3551 %struct = OpTypeStruct %float
3552 %ptr = OpTypePointer StorageBuffer %struct
3553 %var = OpVariable %ptr StorageBuffer
3554
3555 %1 = OpFunction %void None %voidfn
3556 %label = OpLabel
3557 OpReturn
3558 OpFunctionEnd
3559 )";
3560
3561 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3562 EXPECT_EQ(SPV_SUCCESS,
3563 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3564 }
3565
TEST_F(ValidateDecorations,UniformMissingDescriptorSetGood)3566 TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) {
3567 std::string spirv = R"(
3568 OpCapability Shader
3569 OpMemoryModel Logical GLSL450
3570 OpEntryPoint Fragment %1 "main"
3571 OpExecutionMode %1 OriginUpperLeft
3572
3573 OpDecorate %struct Block
3574 OpMemberDecorate %struct 0 Offset 0
3575 OpDecorate %var Binding 0
3576
3577 %void = OpTypeVoid
3578 %voidfn = OpTypeFunction %void
3579 %float = OpTypeFloat 32
3580 %struct = OpTypeStruct %float
3581 %ptr = OpTypePointer Uniform %struct
3582 %var = OpVariable %ptr Uniform
3583
3584 %1 = OpFunction %void None %voidfn
3585 %label = OpLabel
3586 OpReturn
3587 OpFunctionEnd
3588 )";
3589
3590 CompileSuccessfully(spirv);
3591 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3592 << getDiagnosticString();
3593 }
3594
TEST_F(ValidateDecorations,UniformMissingBindingGood)3595 TEST_F(ValidateDecorations, UniformMissingBindingGood) {
3596 std::string spirv = R"(
3597 OpCapability Shader
3598 OpMemoryModel Logical GLSL450
3599 OpEntryPoint Fragment %1 "main"
3600 OpExecutionMode %1 OriginUpperLeft
3601
3602 OpDecorate %struct Block
3603 OpMemberDecorate %struct 0 Offset 0
3604 OpDecorate %var DescriptorSet 0
3605
3606 %void = OpTypeVoid
3607 %voidfn = OpTypeFunction %void
3608 %float = OpTypeFloat 32
3609 %struct = OpTypeStruct %float
3610 %ptr = OpTypePointer Uniform %struct
3611 %var = OpVariable %ptr Uniform
3612
3613 %1 = OpFunction %void None %voidfn
3614 %label = OpLabel
3615 OpReturn
3616 OpFunctionEnd
3617 )";
3618
3619 CompileSuccessfully(spirv);
3620 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3621 << getDiagnosticString();
3622 }
3623
TEST_F(ValidateDecorations,UniformConstantMissingDescriptorSetGood)3624 TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) {
3625 std::string spirv = R"(
3626 OpCapability Shader
3627 OpMemoryModel Logical GLSL450
3628 OpEntryPoint Fragment %1 "main"
3629 OpExecutionMode %1 OriginUpperLeft
3630
3631 OpDecorate %var Binding 0
3632
3633 %void = OpTypeVoid
3634 %voidfn = OpTypeFunction %void
3635 %sampler = OpTypeSampler
3636 %ptr = OpTypePointer UniformConstant %sampler
3637 %var = OpVariable %ptr UniformConstant
3638
3639 %1 = OpFunction %void None %voidfn
3640 %label = OpLabel
3641 OpReturn
3642 OpFunctionEnd
3643 )";
3644
3645 CompileSuccessfully(spirv);
3646 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3647 << getDiagnosticString();
3648 }
3649
TEST_F(ValidateDecorations,UniformConstantMissingBindingGood)3650 TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) {
3651 std::string spirv = R"(
3652 OpCapability Shader
3653 OpMemoryModel Logical GLSL450
3654 OpEntryPoint Fragment %1 "main"
3655 OpExecutionMode %1 OriginUpperLeft
3656
3657 OpDecorate %var DescriptorSet 0
3658
3659 %void = OpTypeVoid
3660 %voidfn = OpTypeFunction %void
3661 %sampler = OpTypeSampler
3662 %ptr = OpTypePointer UniformConstant %sampler
3663 %var = OpVariable %ptr UniformConstant
3664
3665 %1 = OpFunction %void None %voidfn
3666 %label = OpLabel
3667 OpReturn
3668 OpFunctionEnd
3669 )";
3670
3671 CompileSuccessfully(spirv);
3672 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3673 << getDiagnosticString();
3674 }
3675
TEST_F(ValidateDecorations,StorageBufferMissingDescriptorSetGood)3676 TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) {
3677 std::string spirv = R"(
3678 OpCapability Shader
3679 OpExtension "SPV_KHR_storage_buffer_storage_class"
3680 OpMemoryModel Logical GLSL450
3681 OpEntryPoint Fragment %1 "main"
3682 OpExecutionMode %1 OriginUpperLeft
3683
3684 OpDecorate %struct BufferBlock
3685 OpDecorate %var Binding 0
3686
3687 %void = OpTypeVoid
3688 %voidfn = OpTypeFunction %void
3689 %float = OpTypeFloat 32
3690 %struct = OpTypeStruct %float
3691 %ptr = OpTypePointer StorageBuffer %struct
3692 %var = OpVariable %ptr StorageBuffer
3693
3694 %1 = OpFunction %void None %voidfn
3695 %label = OpLabel
3696 OpReturn
3697 OpFunctionEnd
3698 )";
3699
3700 CompileSuccessfully(spirv);
3701 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3702 << getDiagnosticString();
3703 }
3704
TEST_F(ValidateDecorations,StorageBufferMissingBindingGood)3705 TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) {
3706 std::string spirv = R"(
3707 OpCapability Shader
3708 OpExtension "SPV_KHR_storage_buffer_storage_class"
3709 OpMemoryModel Logical GLSL450
3710 OpEntryPoint Fragment %1 "main"
3711 OpExecutionMode %1 OriginUpperLeft
3712
3713 OpDecorate %struct BufferBlock
3714 OpDecorate %var DescriptorSet 0
3715
3716 %void = OpTypeVoid
3717 %voidfn = OpTypeFunction %void
3718 %float = OpTypeFloat 32
3719 %struct = OpTypeStruct %float
3720 %ptr = OpTypePointer StorageBuffer %struct
3721 %var = OpVariable %ptr StorageBuffer
3722
3723 %1 = OpFunction %void None %voidfn
3724 %label = OpLabel
3725 OpReturn
3726 OpFunctionEnd
3727 )";
3728
3729 CompileSuccessfully(spirv);
3730 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3731 << getDiagnosticString();
3732 }
3733
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBaseAlignmentGood)3734 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) {
3735 // Spot check buffer rules when using StorageBuffer storage class with Block
3736 // decoration.
3737 std::string spirv = R"(
3738 OpCapability Shader
3739 OpExtension "SPV_KHR_storage_buffer_storage_class"
3740 OpMemoryModel Logical GLSL450
3741 OpEntryPoint Vertex %main "main"
3742 OpSource GLSL 450
3743 OpDecorate %_arr_float_uint_2 ArrayStride 4
3744 OpMemberDecorate %S 0 Offset 0
3745 OpMemberDecorate %S 1 Offset 8
3746 OpDecorate %S Block
3747 OpDecorate %u DescriptorSet 0
3748 OpDecorate %u Binding 0
3749 %void = OpTypeVoid
3750 %3 = OpTypeFunction %void
3751 %float = OpTypeFloat 32
3752 %v2float = OpTypeVector %float 2
3753 %uint = OpTypeInt 32 0
3754 %uint_2 = OpConstant %uint 2
3755 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3756 %S = OpTypeStruct %v2float %_arr_float_uint_2
3757 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3758 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3759 %main = OpFunction %void None %3
3760 %5 = OpLabel
3761 OpReturn
3762 OpFunctionEnd
3763 )";
3764
3765 CompileSuccessfully(spirv);
3766 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
3767 << getDiagnosticString();
3768 }
3769
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBadAlignmentBad)3770 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad) {
3771 // Like the previous test, but with offset 7.
3772 std::string spirv = R"(
3773 OpCapability Shader
3774 OpExtension "SPV_KHR_storage_buffer_storage_class"
3775 OpMemoryModel Logical GLSL450
3776 OpEntryPoint Vertex %main "main"
3777 OpSource GLSL 450
3778 OpDecorate %_arr_float_uint_2 ArrayStride 4
3779 OpMemberDecorate %S 0 Offset 0
3780 OpMemberDecorate %S 1 Offset 7
3781 OpDecorate %S Block
3782 OpDecorate %u DescriptorSet 0
3783 OpDecorate %u Binding 0
3784 %void = OpTypeVoid
3785 %3 = OpTypeFunction %void
3786 %float = OpTypeFloat 32
3787 %v2float = OpTypeVector %float 2
3788 %uint = OpTypeInt 32 0
3789 %uint_2 = OpConstant %uint 2
3790 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3791 %S = OpTypeStruct %v2float %_arr_float_uint_2
3792 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3793 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3794 %main = OpFunction %void None %3
3795 %5 = OpLabel
3796 OpReturn
3797 OpFunctionEnd
3798 )";
3799
3800 CompileSuccessfully(spirv);
3801 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3802 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3803 EXPECT_THAT(
3804 getDiagnosticString(),
3805 HasSubstr(
3806 "Structure id 3 decorated as Block for variable in StorageBuffer "
3807 "storage class must follow standard storage buffer layout rules: "
3808 "member 1 at offset 7 is not aligned to 4"));
3809 }
3810
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayout)3811 TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout) {
3812 std::string spirv = R"(
3813 OpCapability Shader
3814 %1 = OpExtInstImport "GLSL.std.450"
3815 OpMemoryModel Logical GLSL450
3816 OpEntryPoint GLCompute %main "main"
3817 OpExecutionMode %main LocalSize 1 1 1
3818 OpSource GLSL 430
3819 OpMemberDecorate %F 0 Offset 0
3820 OpMemberDecorate %F 1 Offset 8
3821 OpDecorate %_arr_float_uint_2 ArrayStride 4
3822 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3823 OpMemberDecorate %O 0 Offset 0
3824 OpMemberDecorate %O 1 Offset 16
3825 OpMemberDecorate %O 2 Offset 24
3826 OpMemberDecorate %O 3 Offset 32
3827 OpMemberDecorate %O 4 ColMajor
3828 OpMemberDecorate %O 4 Offset 48
3829 OpMemberDecorate %O 4 MatrixStride 16
3830 OpDecorate %_arr_O_uint_2 ArrayStride 144
3831 OpMemberDecorate %Output 0 Offset 0
3832 OpMemberDecorate %Output 1 Offset 8
3833 OpMemberDecorate %Output 2 Offset 16
3834 OpMemberDecorate %Output 3 Offset 32
3835 OpMemberDecorate %Output 4 Offset 48
3836 OpMemberDecorate %Output 5 Offset 52
3837 OpMemberDecorate %Output 6 ColMajor
3838 OpMemberDecorate %Output 6 Offset 64
3839 OpMemberDecorate %Output 6 MatrixStride 16
3840 OpMemberDecorate %Output 7 Offset 96
3841 OpDecorate %Output BufferBlock
3842 %void = OpTypeVoid
3843 %3 = OpTypeFunction %void
3844 %float = OpTypeFloat 32
3845 %v2float = OpTypeVector %float 2
3846 %v3float = OpTypeVector %float 3
3847 %int = OpTypeInt 32 1
3848 %uint = OpTypeInt 32 0
3849 %v2uint = OpTypeVector %uint 2
3850 %F = OpTypeStruct %int %v2uint
3851 %uint_2 = OpConstant %uint 2
3852 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3853 %mat2v3float = OpTypeMatrix %v3float 2
3854 %v3uint = OpTypeVector %uint 3
3855 %mat3v3float = OpTypeMatrix %v3float 3
3856 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3857 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3858 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3859 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3860 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3861 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3862 %main = OpFunction %void None %3
3863 %5 = OpLabel
3864 OpReturn
3865 OpFunctionEnd
3866 )";
3867
3868 CompileSuccessfully(spirv);
3869 EXPECT_EQ(SPV_SUCCESS,
3870 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3871 }
3872
TEST_F(ValidateDecorations,StorageBufferLayoutPermitsTightVec3ScalarPackingGood)3873 TEST_F(ValidateDecorations,
3874 StorageBufferLayoutPermitsTightVec3ScalarPackingGood) {
3875 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3876 std::string spirv = R"(
3877 OpCapability Shader
3878 OpExtension "SPV_KHR_storage_buffer_storage_class"
3879 OpMemoryModel Logical GLSL450
3880 OpEntryPoint Vertex %main "main"
3881 OpSource GLSL 450
3882 OpMemberDecorate %S 0 Offset 0
3883 OpMemberDecorate %S 1 Offset 12
3884 OpDecorate %S Block
3885 OpDecorate %B DescriptorSet 0
3886 OpDecorate %B Binding 0
3887 %void = OpTypeVoid
3888 %3 = OpTypeFunction %void
3889 %float = OpTypeFloat 32
3890 %v3float = OpTypeVector %float 3
3891 %S = OpTypeStruct %v3float %float
3892 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3893 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3894 %main = OpFunction %void None %3
3895 %5 = OpLabel
3896 OpReturn
3897 OpFunctionEnd
3898 )";
3899
3900 CompileSuccessfully(spirv);
3901 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
3902 << getDiagnosticString();
3903 }
3904
TEST_F(ValidateDecorations,StorageBufferLayoutForbidsTightScalarVec3PackingBad)3905 TEST_F(ValidateDecorations,
3906 StorageBufferLayoutForbidsTightScalarVec3PackingBad) {
3907 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3908 std::string spirv = R"(
3909 OpCapability Shader
3910 OpExtension "SPV_KHR_storage_buffer_storage_class"
3911 OpMemoryModel Logical GLSL450
3912 OpEntryPoint Vertex %main "main"
3913 OpSource GLSL 450
3914 OpMemberDecorate %S 0 Offset 0
3915 OpMemberDecorate %S 1 Offset 4
3916 OpDecorate %S Block
3917 OpDecorate %B DescriptorSet 0
3918 OpDecorate %B Binding 0
3919 %void = OpTypeVoid
3920 %3 = OpTypeFunction %void
3921 %float = OpTypeFloat 32
3922 %v3float = OpTypeVector %float 3
3923 %S = OpTypeStruct %float %v3float
3924 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3925 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3926 %main = OpFunction %void None %3
3927 %5 = OpLabel
3928 OpReturn
3929 OpFunctionEnd
3930 )";
3931
3932 CompileSuccessfully(spirv);
3933 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3934 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3935 EXPECT_THAT(
3936 getDiagnosticString(),
3937 HasSubstr(
3938 "Structure id 2 decorated as Block for variable in StorageBuffer "
3939 "storage class must follow standard storage buffer layout "
3940 "rules: member 1 at offset 4 is not aligned to 16"));
3941 }
3942
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset0Bad)3943 TEST_F(ValidateDecorations,
3944 BlockStandardUniformBufferLayoutIncorrectOffset0Bad) {
3945 std::string spirv = R"(
3946 OpCapability Shader
3947 %1 = OpExtInstImport "GLSL.std.450"
3948 OpMemoryModel Logical GLSL450
3949 OpEntryPoint GLCompute %main "main"
3950 OpExecutionMode %main LocalSize 1 1 1
3951 OpSource GLSL 430
3952 OpMemberDecorate %F 0 Offset 0
3953 OpMemberDecorate %F 1 Offset 8
3954 OpDecorate %_arr_float_uint_2 ArrayStride 16
3955 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3956 OpMemberDecorate %O 0 Offset 0
3957 OpMemberDecorate %O 1 Offset 16
3958 OpMemberDecorate %O 2 Offset 24
3959 OpMemberDecorate %O 3 Offset 33
3960 OpMemberDecorate %O 4 ColMajor
3961 OpMemberDecorate %O 4 Offset 80
3962 OpMemberDecorate %O 4 MatrixStride 16
3963 OpDecorate %_arr_O_uint_2 ArrayStride 176
3964 OpMemberDecorate %Output 0 Offset 0
3965 OpMemberDecorate %Output 1 Offset 8
3966 OpMemberDecorate %Output 2 Offset 16
3967 OpMemberDecorate %Output 3 Offset 32
3968 OpMemberDecorate %Output 4 Offset 48
3969 OpMemberDecorate %Output 5 Offset 64
3970 OpMemberDecorate %Output 6 ColMajor
3971 OpMemberDecorate %Output 6 Offset 96
3972 OpMemberDecorate %Output 6 MatrixStride 16
3973 OpMemberDecorate %Output 7 Offset 128
3974 OpDecorate %Output Block
3975 %void = OpTypeVoid
3976 %3 = OpTypeFunction %void
3977 %float = OpTypeFloat 32
3978 %v2float = OpTypeVector %float 2
3979 %v3float = OpTypeVector %float 3
3980 %int = OpTypeInt 32 1
3981 %uint = OpTypeInt 32 0
3982 %v2uint = OpTypeVector %uint 2
3983 %F = OpTypeStruct %int %v2uint
3984 %uint_2 = OpConstant %uint 2
3985 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3986 %mat2v3float = OpTypeMatrix %v3float 2
3987 %v3uint = OpTypeVector %uint 3
3988 %mat3v3float = OpTypeMatrix %v3float 3
3989 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3990 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3991 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3992 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3993 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3994 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3995 %main = OpFunction %void None %3
3996 %5 = OpLabel
3997 OpReturn
3998 OpFunctionEnd
3999 )";
4000
4001 CompileSuccessfully(spirv);
4002 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4003 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4004 EXPECT_THAT(
4005 getDiagnosticString(),
4006 HasSubstr("Structure id 6 decorated as Block for variable in Uniform "
4007 "storage class must follow standard uniform buffer layout "
4008 "rules: member 2 at offset 152 is not aligned to 16"));
4009 }
4010
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset1Bad)4011 TEST_F(ValidateDecorations,
4012 BlockStandardUniformBufferLayoutIncorrectOffset1Bad) {
4013 std::string spirv = R"(
4014 OpCapability Shader
4015 %1 = OpExtInstImport "GLSL.std.450"
4016 OpMemoryModel Logical GLSL450
4017 OpEntryPoint GLCompute %main "main"
4018 OpExecutionMode %main LocalSize 1 1 1
4019 OpSource GLSL 430
4020 OpMemberDecorate %F 0 Offset 0
4021 OpMemberDecorate %F 1 Offset 8
4022 OpDecorate %_arr_float_uint_2 ArrayStride 16
4023 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
4024 OpMemberDecorate %O 0 Offset 0
4025 OpMemberDecorate %O 1 Offset 16
4026 OpMemberDecorate %O 2 Offset 32
4027 OpMemberDecorate %O 3 Offset 64
4028 OpMemberDecorate %O 4 ColMajor
4029 OpMemberDecorate %O 4 Offset 80
4030 OpMemberDecorate %O 4 MatrixStride 16
4031 OpDecorate %_arr_O_uint_2 ArrayStride 176
4032 OpMemberDecorate %Output 0 Offset 0
4033 OpMemberDecorate %Output 1 Offset 8
4034 OpMemberDecorate %Output 2 Offset 16
4035 OpMemberDecorate %Output 3 Offset 32
4036 OpMemberDecorate %Output 4 Offset 48
4037 OpMemberDecorate %Output 5 Offset 71
4038 OpMemberDecorate %Output 6 ColMajor
4039 OpMemberDecorate %Output 6 Offset 96
4040 OpMemberDecorate %Output 6 MatrixStride 16
4041 OpMemberDecorate %Output 7 Offset 128
4042 OpDecorate %Output Block
4043 %void = OpTypeVoid
4044 %3 = OpTypeFunction %void
4045 %float = OpTypeFloat 32
4046 %v2float = OpTypeVector %float 2
4047 %v3float = OpTypeVector %float 3
4048 %int = OpTypeInt 32 1
4049 %uint = OpTypeInt 32 0
4050 %v2uint = OpTypeVector %uint 2
4051 %F = OpTypeStruct %int %v2uint
4052 %uint_2 = OpConstant %uint 2
4053 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4054 %mat2v3float = OpTypeMatrix %v3float 2
4055 %v3uint = OpTypeVector %uint 3
4056 %mat3v3float = OpTypeMatrix %v3float 3
4057 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
4058 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
4059 %_arr_O_uint_2 = OpTypeArray %O %uint_2
4060 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
4061 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4062 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4063 %main = OpFunction %void None %3
4064 %5 = OpLabel
4065 OpReturn
4066 OpFunctionEnd
4067 )";
4068
4069 CompileSuccessfully(spirv);
4070 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4071 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4072 EXPECT_THAT(
4073 getDiagnosticString(),
4074 HasSubstr("Structure id 8 decorated as Block for variable in Uniform "
4075 "storage class must follow standard uniform buffer layout "
4076 "rules: member 5 at offset 71 is not aligned to 16"));
4077 }
4078
TEST_F(ValidateDecorations,BlockUniformBufferLayoutIncorrectArrayStrideBad)4079 TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad) {
4080 std::string spirv = R"(
4081 OpCapability Shader
4082 %1 = OpExtInstImport "GLSL.std.450"
4083 OpMemoryModel Logical GLSL450
4084 OpEntryPoint GLCompute %main "main"
4085 OpExecutionMode %main LocalSize 1 1 1
4086 OpSource GLSL 430
4087 OpMemberDecorate %F 0 Offset 0
4088 OpMemberDecorate %F 1 Offset 8
4089 OpDecorate %_arr_float_uint_2 ArrayStride 16
4090 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 49
4091 OpMemberDecorate %O 0 Offset 0
4092 OpMemberDecorate %O 1 Offset 16
4093 OpMemberDecorate %O 2 Offset 32
4094 OpMemberDecorate %O 3 Offset 64
4095 OpMemberDecorate %O 4 ColMajor
4096 OpMemberDecorate %O 4 Offset 80
4097 OpMemberDecorate %O 4 MatrixStride 16
4098 OpDecorate %_arr_O_uint_2 ArrayStride 176
4099 OpMemberDecorate %Output 0 Offset 0
4100 OpMemberDecorate %Output 1 Offset 8
4101 OpMemberDecorate %Output 2 Offset 16
4102 OpMemberDecorate %Output 3 Offset 32
4103 OpMemberDecorate %Output 4 Offset 48
4104 OpMemberDecorate %Output 5 Offset 64
4105 OpMemberDecorate %Output 6 ColMajor
4106 OpMemberDecorate %Output 6 Offset 96
4107 OpMemberDecorate %Output 6 MatrixStride 16
4108 OpMemberDecorate %Output 7 Offset 128
4109 OpDecorate %Output Block
4110 %void = OpTypeVoid
4111 %3 = OpTypeFunction %void
4112 %float = OpTypeFloat 32
4113 %v2float = OpTypeVector %float 2
4114 %v3float = OpTypeVector %float 3
4115 %int = OpTypeInt 32 1
4116 %uint = OpTypeInt 32 0
4117 %v2uint = OpTypeVector %uint 2
4118 %F = OpTypeStruct %int %v2uint
4119 %uint_2 = OpConstant %uint 2
4120 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4121 %mat2v3float = OpTypeMatrix %v3float 2
4122 %v3uint = OpTypeVector %uint 3
4123 %mat3v3float = OpTypeMatrix %v3float 3
4124 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
4125 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
4126 %_arr_O_uint_2 = OpTypeArray %O %uint_2
4127 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
4128 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4129 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4130 %main = OpFunction %void None %3
4131 %5 = OpLabel
4132 OpReturn
4133 OpFunctionEnd
4134 )";
4135
4136 CompileSuccessfully(spirv);
4137 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4138 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4139 EXPECT_THAT(
4140 getDiagnosticString(),
4141 HasSubstr(
4142 "Structure id 6 decorated as Block for variable in Uniform storage "
4143 "class must follow standard uniform buffer layout rules: member 4 "
4144 "contains "
4145 "an array with stride 49 not satisfying alignment to 16"));
4146 }
4147
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayoutImproperStraddleBad)4148 TEST_F(ValidateDecorations,
4149 BufferBlockStandardStorageBufferLayoutImproperStraddleBad) {
4150 std::string spirv = R"(
4151 OpCapability Shader
4152 %1 = OpExtInstImport "GLSL.std.450"
4153 OpMemoryModel Logical GLSL450
4154 OpEntryPoint GLCompute %main "main"
4155 OpExecutionMode %main LocalSize 1 1 1
4156 OpSource GLSL 430
4157 OpMemberDecorate %Output 0 Offset 0
4158 OpMemberDecorate %Output 1 Offset 8
4159 OpDecorate %Output BufferBlock
4160 %void = OpTypeVoid
4161 %3 = OpTypeFunction %void
4162 %float = OpTypeFloat 32
4163 %v3float = OpTypeVector %float 3
4164 %Output = OpTypeStruct %float %v3float
4165 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4166 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4167 %main = OpFunction %void None %3
4168 %5 = OpLabel
4169 OpReturn
4170 OpFunctionEnd
4171 )";
4172
4173 CompileSuccessfully(spirv);
4174 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4175 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4176 EXPECT_THAT(
4177 getDiagnosticString(),
4178 HasSubstr("Structure id 3 decorated as BufferBlock for variable in "
4179 "Uniform storage class must follow standard storage buffer "
4180 "layout rules: member 1 at offset 8 is not aligned to 16"));
4181 }
4182
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideArrayPaddingBad)4183 TEST_F(ValidateDecorations,
4184 BlockUniformBufferLayoutOffsetInsideArrayPaddingBad) {
4185 // In this case the 2nd member fits entirely within the padding.
4186 std::string spirv = R"(
4187 OpCapability Shader
4188 %1 = OpExtInstImport "GLSL.std.450"
4189 OpMemoryModel Logical GLSL450
4190 OpEntryPoint GLCompute %main "main"
4191 OpExecutionMode %main LocalSize 1 1 1
4192 OpSource GLSL 430
4193 OpDecorate %_arr_float_uint_2 ArrayStride 16
4194 OpMemberDecorate %Output 0 Offset 0
4195 OpMemberDecorate %Output 1 Offset 20
4196 OpDecorate %Output Block
4197 %void = OpTypeVoid
4198 %3 = OpTypeFunction %void
4199 %float = OpTypeFloat 32
4200 %uint = OpTypeInt 32 0
4201 %v2uint = OpTypeVector %uint 2
4202 %uint_2 = OpConstant %uint 2
4203 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4204 %Output = OpTypeStruct %_arr_float_uint_2 %float
4205 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4206 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4207 %main = OpFunction %void None %3
4208 %5 = OpLabel
4209 OpReturn
4210 OpFunctionEnd
4211 )";
4212
4213 CompileSuccessfully(spirv);
4214 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4215 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4216 EXPECT_THAT(
4217 getDiagnosticString(),
4218 HasSubstr(
4219 "Structure id 4 decorated as Block for variable in Uniform storage "
4220 "class must follow standard uniform buffer layout rules: member 1 at "
4221 "offset 20 overlaps previous member ending at offset 31"));
4222 }
4223
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideStructPaddingBad)4224 TEST_F(ValidateDecorations,
4225 BlockUniformBufferLayoutOffsetInsideStructPaddingBad) {
4226 // In this case the 2nd member fits entirely within the padding.
4227 std::string spirv = R"(
4228 OpCapability Shader
4229 OpMemoryModel Logical GLSL450
4230 OpEntryPoint GLCompute %1 "main"
4231 OpExecutionMode %1 LocalSize 1 1 1
4232 OpMemberDecorate %_struct_6 0 Offset 0
4233 OpMemberDecorate %_struct_2 0 Offset 0
4234 OpMemberDecorate %_struct_2 1 Offset 4
4235 OpDecorate %_struct_2 Block
4236 %void = OpTypeVoid
4237 %4 = OpTypeFunction %void
4238 %float = OpTypeFloat 32
4239 %_struct_6 = OpTypeStruct %float
4240 %_struct_2 = OpTypeStruct %_struct_6 %float
4241 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4242 %8 = OpVariable %_ptr_Uniform__struct_2 Uniform
4243 %1 = OpFunction %void None %4
4244 %9 = OpLabel
4245 OpReturn
4246 OpFunctionEnd
4247 )";
4248
4249 CompileSuccessfully(spirv);
4250 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4251 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4252 EXPECT_THAT(
4253 getDiagnosticString(),
4254 HasSubstr(
4255 "Structure id 3 decorated as Block for variable in Uniform storage "
4256 "class must follow standard uniform buffer layout rules: member 1 at "
4257 "offset 4 overlaps previous member ending at offset 15"));
4258 }
4259
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodUniversal1_0)4260 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0) {
4261 std::string spirv = R"(
4262 OpCapability Shader
4263 %1 = OpExtInstImport "GLSL.std.450"
4264 OpMemoryModel Logical GLSL450
4265 OpEntryPoint GLCompute %main "main"
4266 OpExecutionMode %main LocalSize 1 1 1
4267 OpMemberDecorate %Outer 0 Offset 4
4268 OpMemberDecorate %Outer 1 Offset 0
4269 OpDecorate %Outer Block
4270 OpDecorate %O DescriptorSet 0
4271 OpDecorate %O Binding 0
4272 %void = OpTypeVoid
4273 %3 = OpTypeFunction %void
4274 %uint = OpTypeInt 32 0
4275 %Outer = OpTypeStruct %uint %uint
4276 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4277 %O = OpVariable %_ptr_Uniform_Outer Uniform
4278 %main = OpFunction %void None %3
4279 %5 = OpLabel
4280 OpReturn
4281 OpFunctionEnd
4282 )";
4283
4284 CompileSuccessfully(spirv);
4285 EXPECT_EQ(SPV_SUCCESS,
4286 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
4287 }
4288
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodOpenGL4_5)4289 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5) {
4290 std::string spirv = R"(
4291 OpCapability Shader
4292 %1 = OpExtInstImport "GLSL.std.450"
4293 OpMemoryModel Logical GLSL450
4294 OpEntryPoint GLCompute %main "main"
4295 OpExecutionMode %main LocalSize 1 1 1
4296 OpMemberDecorate %Outer 0 Offset 4
4297 OpMemberDecorate %Outer 1 Offset 0
4298 OpDecorate %Outer Block
4299 OpDecorate %O DescriptorSet 0
4300 OpDecorate %O Binding 0
4301 %void = OpTypeVoid
4302 %3 = OpTypeFunction %void
4303 %uint = OpTypeInt 32 0
4304 %Outer = OpTypeStruct %uint %uint
4305 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4306 %O = OpVariable %_ptr_Uniform_Outer Uniform
4307 %main = OpFunction %void None %3
4308 %5 = OpLabel
4309 OpReturn
4310 OpFunctionEnd
4311 )";
4312
4313 CompileSuccessfully(spirv);
4314 EXPECT_EQ(SPV_SUCCESS,
4315 ValidateAndRetrieveValidationState(SPV_ENV_OPENGL_4_5));
4316 }
4317
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodVulkan1_1)4318 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1) {
4319 std::string spirv = R"(
4320 OpCapability Shader
4321 %1 = OpExtInstImport "GLSL.std.450"
4322 OpMemoryModel Logical GLSL450
4323 OpEntryPoint GLCompute %main "main"
4324 OpExecutionMode %main LocalSize 1 1 1
4325 OpMemberDecorate %Outer 0 Offset 4
4326 OpMemberDecorate %Outer 1 Offset 0
4327 OpDecorate %Outer Block
4328 OpDecorate %O DescriptorSet 0
4329 OpDecorate %O Binding 0
4330 %void = OpTypeVoid
4331 %3 = OpTypeFunction %void
4332 %uint = OpTypeInt 32 0
4333 %Outer = OpTypeStruct %uint %uint
4334 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4335 %O = OpVariable %_ptr_Uniform_Outer Uniform
4336 %main = OpFunction %void None %3
4337 %5 = OpLabel
4338 OpReturn
4339 OpFunctionEnd
4340 )";
4341
4342 CompileSuccessfully(spirv);
4343 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
4344 << getDiagnosticString();
4345 EXPECT_THAT(getDiagnosticString(), Eq(""));
4346 }
4347
TEST_F(ValidateDecorations,BlockLayoutOffsetOverlapBad)4348 TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad) {
4349 std::string spirv = R"(
4350 OpCapability Shader
4351 %1 = OpExtInstImport "GLSL.std.450"
4352 OpMemoryModel Logical GLSL450
4353 OpEntryPoint GLCompute %main "main"
4354 OpExecutionMode %main LocalSize 1 1 1
4355 OpMemberDecorate %Outer 0 Offset 0
4356 OpMemberDecorate %Outer 1 Offset 16
4357 OpMemberDecorate %Inner 0 Offset 0
4358 OpMemberDecorate %Inner 1 Offset 16
4359 OpDecorate %Outer Block
4360 OpDecorate %O DescriptorSet 0
4361 OpDecorate %O Binding 0
4362 %void = OpTypeVoid
4363 %3 = OpTypeFunction %void
4364 %uint = OpTypeInt 32 0
4365 %Inner = OpTypeStruct %uint %uint
4366 %Outer = OpTypeStruct %Inner %uint
4367 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4368 %O = OpVariable %_ptr_Uniform_Outer Uniform
4369 %main = OpFunction %void None %3
4370 %5 = OpLabel
4371 OpReturn
4372 OpFunctionEnd
4373 )";
4374
4375 CompileSuccessfully(spirv);
4376 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4377 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4378 EXPECT_THAT(
4379 getDiagnosticString(),
4380 HasSubstr(
4381 "Structure id 3 decorated as Block for variable in Uniform storage "
4382 "class must follow standard uniform buffer layout rules: member 1 at "
4383 "offset 16 overlaps previous member ending at offset 31"));
4384 }
4385
TEST_F(ValidateDecorations,BufferBlockEmptyStruct)4386 TEST_F(ValidateDecorations, BufferBlockEmptyStruct) {
4387 std::string spirv = R"(
4388 OpCapability Shader
4389 %1 = OpExtInstImport "GLSL.std.450"
4390 OpMemoryModel Logical GLSL450
4391 OpEntryPoint GLCompute %main "main"
4392 OpExecutionMode %main LocalSize 1 1 1
4393 OpSource GLSL 430
4394 OpMemberDecorate %Output 0 Offset 0
4395 OpDecorate %Output BufferBlock
4396 %void = OpTypeVoid
4397 %3 = OpTypeFunction %void
4398 %S = OpTypeStruct
4399 %Output = OpTypeStruct %S
4400 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4401 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4402 %main = OpFunction %void None %3
4403 %5 = OpLabel
4404 OpReturn
4405 OpFunctionEnd
4406 )";
4407
4408 CompileSuccessfully(spirv);
4409 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4410 }
4411
TEST_F(ValidateDecorations,RowMajorMatrixTightPackingGood)4412 TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood) {
4413 // Row major matrix rule:
4414 // A row-major matrix of C columns has a base alignment equal to
4415 // the base alignment of a vector of C matrix components.
4416 // Note: The "matrix component" is the scalar element type.
4417
4418 // The matrix has 3 columns and 2 rows (C=3, R=2).
4419 // So the base alignment of b is the same as a vector of 3 floats, which is 16
4420 // bytes. The matrix consists of two of these, and therefore occupies 2 x 16
4421 // bytes, or 32 bytes.
4422 //
4423 // So the offsets can be:
4424 // a -> 0
4425 // b -> 16
4426 // c -> 48
4427 // d -> 60 ; d fits at bytes 12-15 after offset of c. Tight (vec3;float)
4428 // packing
4429
4430 std::string spirv = R"(
4431 OpCapability Shader
4432 OpMemoryModel Logical GLSL450
4433 OpEntryPoint Vertex %1 "main"
4434 OpSource GLSL 450
4435 OpMemberDecorate %_struct_2 0 Offset 0
4436 OpMemberDecorate %_struct_2 1 RowMajor
4437 OpMemberDecorate %_struct_2 1 Offset 16
4438 OpMemberDecorate %_struct_2 1 MatrixStride 16
4439 OpMemberDecorate %_struct_2 2 Offset 48
4440 OpMemberDecorate %_struct_2 3 Offset 60
4441 OpDecorate %_struct_2 Block
4442 OpDecorate %3 DescriptorSet 0
4443 OpDecorate %3 Binding 0
4444 %void = OpTypeVoid
4445 %5 = OpTypeFunction %void
4446 %float = OpTypeFloat 32
4447 %v4float = OpTypeVector %float 4
4448 %v2float = OpTypeVector %float 2
4449 %mat3v2float = OpTypeMatrix %v2float 3
4450 %v3float = OpTypeVector %float 3
4451 %_struct_2 = OpTypeStruct %v4float %mat3v2float %v3float %float
4452 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4453 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4454 %1 = OpFunction %void None %5
4455 %12 = OpLabel
4456 OpReturn
4457 OpFunctionEnd
4458 )";
4459
4460 CompileSuccessfully(spirv);
4461 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
4462 << getDiagnosticString();
4463 }
4464
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixTightPackingGood)4465 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood) {
4466 // Like the previous case, but we have an array of arrays of matrices.
4467 // The RowMajor decoration goes on the struct member (surprisingly).
4468
4469 std::string spirv = R"(
4470 OpCapability Shader
4471 OpMemoryModel Logical GLSL450
4472 OpEntryPoint Vertex %1 "main"
4473 OpSource GLSL 450
4474 OpMemberDecorate %_struct_2 0 Offset 0
4475 OpMemberDecorate %_struct_2 1 RowMajor
4476 OpMemberDecorate %_struct_2 1 Offset 16
4477 OpMemberDecorate %_struct_2 1 MatrixStride 16
4478 OpMemberDecorate %_struct_2 2 Offset 80
4479 OpMemberDecorate %_struct_2 3 Offset 92
4480 OpDecorate %arr_mat ArrayStride 32
4481 OpDecorate %arr_arr_mat ArrayStride 32
4482 OpDecorate %_struct_2 Block
4483 OpDecorate %3 DescriptorSet 0
4484 OpDecorate %3 Binding 0
4485 %void = OpTypeVoid
4486 %5 = OpTypeFunction %void
4487 %float = OpTypeFloat 32
4488 %v4float = OpTypeVector %float 4
4489 %v2float = OpTypeVector %float 2
4490 %mat3v2float = OpTypeMatrix %v2float 3
4491 %uint = OpTypeInt 32 0
4492 %uint_1 = OpConstant %uint 1
4493 %uint_2 = OpConstant %uint 2
4494 %arr_mat = OpTypeArray %mat3v2float %uint_1
4495 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4496 %v3float = OpTypeVector %float 3
4497 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4498 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4499 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4500 %1 = OpFunction %void None %5
4501 %12 = OpLabel
4502 OpReturn
4503 OpFunctionEnd
4504 )";
4505
4506 CompileSuccessfully(spirv);
4507 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
4508 << getDiagnosticString();
4509 }
4510
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixNextMemberOverlapsBad)4511 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad) {
4512 // Like the previous case, but the offset of member 2 overlaps the matrix.
4513 std::string spirv = R"(
4514 OpCapability Shader
4515 OpMemoryModel Logical GLSL450
4516 OpEntryPoint Vertex %1 "main"
4517 OpSource GLSL 450
4518 OpMemberDecorate %_struct_2 0 Offset 0
4519 OpMemberDecorate %_struct_2 1 RowMajor
4520 OpMemberDecorate %_struct_2 1 Offset 16
4521 OpMemberDecorate %_struct_2 1 MatrixStride 16
4522 OpMemberDecorate %_struct_2 2 Offset 64
4523 OpMemberDecorate %_struct_2 3 Offset 92
4524 OpDecorate %arr_mat ArrayStride 32
4525 OpDecorate %arr_arr_mat ArrayStride 32
4526 OpDecorate %_struct_2 Block
4527 OpDecorate %3 DescriptorSet 0
4528 OpDecorate %3 Binding 0
4529 %void = OpTypeVoid
4530 %5 = OpTypeFunction %void
4531 %float = OpTypeFloat 32
4532 %v4float = OpTypeVector %float 4
4533 %v2float = OpTypeVector %float 2
4534 %mat3v2float = OpTypeMatrix %v2float 3
4535 %uint = OpTypeInt 32 0
4536 %uint_1 = OpConstant %uint 1
4537 %uint_2 = OpConstant %uint 2
4538 %arr_mat = OpTypeArray %mat3v2float %uint_1
4539 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4540 %v3float = OpTypeVector %float 3
4541 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4542 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4543 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4544 %1 = OpFunction %void None %5
4545 %12 = OpLabel
4546 OpReturn
4547 OpFunctionEnd
4548 )";
4549
4550 CompileSuccessfully(spirv);
4551 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4552 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4553 EXPECT_THAT(
4554 getDiagnosticString(),
4555 HasSubstr(
4556 "Structure id 2 decorated as Block for variable in Uniform storage "
4557 "class must follow standard uniform buffer layout rules: member 2 at "
4558 "offset 64 overlaps previous member ending at offset 79"));
4559 }
4560
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackGood)4561 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood) {
4562 // Original GLSL
4563
4564 // #version 450
4565 // layout (set=0,binding=0) buffer S {
4566 // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
4567 // uint i; // Can't have offset 60 = 3x16 + 12
4568 // } B;
4569 // void main() {}
4570
4571 std::string spirv = R"(
4572 OpCapability Shader
4573 OpMemoryModel Logical GLSL450
4574 OpEntryPoint Vertex %1 "main"
4575 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4576 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4577 OpMemberDecorate %_struct_4 0 Offset 0
4578 OpMemberDecorate %_struct_4 1 Offset 64
4579 OpDecorate %_struct_4 BufferBlock
4580 OpDecorate %5 DescriptorSet 0
4581 OpDecorate %5 Binding 0
4582 %void = OpTypeVoid
4583 %7 = OpTypeFunction %void
4584 %uint = OpTypeInt 32 0
4585 %v3uint = OpTypeVector %uint 3
4586 %uint_2 = OpConstant %uint 2
4587 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4588 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4589 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4590 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4591 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4592 %1 = OpFunction %void None %7
4593 %12 = OpLabel
4594 OpReturn
4595 OpFunctionEnd
4596 )";
4597
4598 CompileSuccessfully(spirv);
4599 EXPECT_EQ(SPV_SUCCESS,
4600 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4601 }
4602
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackGoodScalar)4603 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGoodScalar) {
4604 // Original GLSL
4605
4606 // #version 450
4607 // layout (set=0,binding=0) buffer S {
4608 // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
4609 // uint i; // Can have offset 60 = 3x16 + 12
4610 // } B;
4611 // void main() {}
4612
4613 std::string spirv = R"(
4614 OpCapability Shader
4615 OpMemoryModel Logical GLSL450
4616 OpEntryPoint Vertex %1 "main"
4617 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4618 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4619 OpMemberDecorate %_struct_4 0 Offset 0
4620 OpMemberDecorate %_struct_4 1 Offset 60
4621 OpDecorate %_struct_4 BufferBlock
4622 OpDecorate %5 DescriptorSet 0
4623 OpDecorate %5 Binding 0
4624 %void = OpTypeVoid
4625 %7 = OpTypeFunction %void
4626 %uint = OpTypeInt 32 0
4627 %v3uint = OpTypeVector %uint 3
4628 %uint_2 = OpConstant %uint 2
4629 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4630 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4631 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4632 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4633 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4634 %1 = OpFunction %void None %7
4635 %12 = OpLabel
4636 OpReturn
4637 OpFunctionEnd
4638 )";
4639
4640 options_->scalar_block_layout = true;
4641 CompileSuccessfully(spirv);
4642 EXPECT_EQ(SPV_SUCCESS,
4643 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4644 }
4645
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackBad)4646 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) {
4647 // Like previous but, the offset of the second member is too small.
4648
4649 std::string spirv = R"(
4650 OpCapability Shader
4651 OpMemoryModel Logical GLSL450
4652 OpEntryPoint Vertex %1 "main"
4653 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4654 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4655 OpMemberDecorate %_struct_4 0 Offset 0
4656 OpMemberDecorate %_struct_4 1 Offset 60
4657 OpDecorate %_struct_4 BufferBlock
4658 OpDecorate %5 DescriptorSet 0
4659 OpDecorate %5 Binding 0
4660 %void = OpTypeVoid
4661 %7 = OpTypeFunction %void
4662 %uint = OpTypeInt 32 0
4663 %v3uint = OpTypeVector %uint 3
4664 %uint_2 = OpConstant %uint 2
4665 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4666 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4667 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4668 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4669 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4670 %1 = OpFunction %void None %7
4671 %12 = OpLabel
4672 OpReturn
4673 OpFunctionEnd
4674 )";
4675
4676 CompileSuccessfully(spirv);
4677 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4678 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4679 EXPECT_THAT(getDiagnosticString(),
4680 HasSubstr("Structure id 4 decorated as BufferBlock for variable "
4681 "in Uniform storage class must follow standard storage "
4682 "buffer layout rules: member 1 at offset 60 overlaps "
4683 "previous member ending at offset 63"));
4684 }
4685
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackGood)4686 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) {
4687 // Like the corresponding buffer block case, but the array padding must
4688 // count for the last element as well, and so the offset of the second
4689 // member must be at least 64.
4690 std::string spirv = R"(
4691 OpCapability Shader
4692 OpMemoryModel Logical GLSL450
4693 OpEntryPoint Vertex %1 "main"
4694 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4695 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4696 OpMemberDecorate %_struct_4 0 Offset 0
4697 OpMemberDecorate %_struct_4 1 Offset 64
4698 OpDecorate %_struct_4 Block
4699 OpDecorate %5 DescriptorSet 0
4700 OpDecorate %5 Binding 0
4701 %void = OpTypeVoid
4702 %7 = OpTypeFunction %void
4703 %uint = OpTypeInt 32 0
4704 %v3uint = OpTypeVector %uint 3
4705 %uint_2 = OpConstant %uint 2
4706 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4707 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4708 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4709 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4710 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4711 %1 = OpFunction %void None %7
4712 %12 = OpLabel
4713 OpReturn
4714 OpFunctionEnd
4715 )";
4716
4717 CompileSuccessfully(spirv);
4718 EXPECT_EQ(SPV_SUCCESS,
4719 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4720 }
4721
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackBad)4722 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) {
4723 // Like previous but, the offset of the second member is too small.
4724
4725 std::string spirv = R"(
4726 OpCapability Shader
4727 OpMemoryModel Logical GLSL450
4728 OpEntryPoint Vertex %1 "main"
4729 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4730 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4731 OpMemberDecorate %_struct_4 0 Offset 0
4732 OpMemberDecorate %_struct_4 1 Offset 60
4733 OpDecorate %_struct_4 Block
4734 OpDecorate %5 DescriptorSet 0
4735 OpDecorate %5 Binding 0
4736 %void = OpTypeVoid
4737 %7 = OpTypeFunction %void
4738 %uint = OpTypeInt 32 0
4739 %v3uint = OpTypeVector %uint 3
4740 %uint_2 = OpConstant %uint 2
4741 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4742 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4743 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4744 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4745 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4746 %1 = OpFunction %void None %7
4747 %12 = OpLabel
4748 OpReturn
4749 OpFunctionEnd
4750 )";
4751
4752 CompileSuccessfully(spirv);
4753 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4754 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4755 EXPECT_THAT(
4756 getDiagnosticString(),
4757 HasSubstr(
4758 "Structure id 4 decorated as Block for variable in Uniform storage "
4759 "class must follow standard uniform buffer layout rules: member 1 at "
4760 "offset 60 overlaps previous member ending at offset 63"));
4761 }
4762
TEST_F(ValidateDecorations,LayoutNotCheckedWhenSkipBlockLayout)4763 TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) {
4764 // Checks that block layout is not verified in skipping block layout mode.
4765 // Even for obviously wrong layout.
4766 std::string spirv = R"(
4767 OpCapability Shader
4768 OpMemoryModel Logical GLSL450
4769 OpEntryPoint Vertex %main "main"
4770 OpSource GLSL 450
4771 OpMemberDecorate %S 0 Offset 3 ; wrong alignment
4772 OpMemberDecorate %S 1 Offset 3 ; same offset as before!
4773 OpDecorate %S Block
4774 OpDecorate %B DescriptorSet 0
4775 OpDecorate %B Binding 0
4776 %void = OpTypeVoid
4777 %3 = OpTypeFunction %void
4778 %float = OpTypeFloat 32
4779 %v3float = OpTypeVector %float 3
4780 %S = OpTypeStruct %float %v3float
4781 %_ptr_Uniform_S = OpTypePointer Uniform %S
4782 %B = OpVariable %_ptr_Uniform_S Uniform
4783 %main = OpFunction %void None %3
4784 %5 = OpLabel
4785 OpReturn
4786 OpFunctionEnd
4787 )";
4788
4789 CompileSuccessfully(spirv);
4790 spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true);
4791 EXPECT_EQ(SPV_SUCCESS,
4792 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4793 EXPECT_THAT(getDiagnosticString(), Eq(""));
4794 }
4795
TEST_F(ValidateDecorations,EntryPointVariableWrongStorageClass)4796 TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) {
4797 const std::string spirv = R"(
4798 OpCapability Shader
4799 OpMemoryModel Logical GLSL450
4800 OpEntryPoint Fragment %1 "func" %var
4801 OpExecutionMode %1 OriginUpperLeft
4802 %void = OpTypeVoid
4803 %int = OpTypeInt 32 0
4804 %ptr_int_Workgroup = OpTypePointer Workgroup %int
4805 %var = OpVariable %ptr_int_Workgroup Workgroup
4806 %func_ty = OpTypeFunction %void
4807 %1 = OpFunction %void None %func_ty
4808 %2 = OpLabel
4809 OpReturn
4810 OpFunctionEnd
4811 )";
4812
4813 CompileSuccessfully(spirv);
4814 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4815 EXPECT_THAT(getDiagnosticString(),
4816 HasSubstr("OpEntryPoint interfaces must be OpVariables with "
4817 "Storage Class of Input(1) or Output(3). Found Storage "
4818 "Class 4 for Entry Point id 1."));
4819 }
4820
TEST_F(ValidateDecorations,VulkanMemoryModelNonCoherent)4821 TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent) {
4822 const std::string spirv = R"(
4823 OpCapability Shader
4824 OpCapability VulkanMemoryModelKHR
4825 OpCapability Linkage
4826 OpExtension "SPV_KHR_vulkan_memory_model"
4827 OpExtension "SPV_KHR_storage_buffer_storage_class"
4828 OpMemoryModel Logical VulkanKHR
4829 OpDecorate %1 Coherent
4830 %2 = OpTypeInt 32 0
4831 %3 = OpTypePointer StorageBuffer %2
4832 %1 = OpVariable %3 StorageBuffer
4833 )";
4834
4835 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4836 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4837 EXPECT_THAT(getDiagnosticString(),
4838 HasSubstr("Coherent decoration targeting '1[%1]' is "
4839 "banned when using the Vulkan memory model."));
4840 }
4841
TEST_F(ValidateDecorations,VulkanMemoryModelNoCoherentMember)4842 TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember) {
4843 const std::string spirv = R"(
4844 OpCapability Shader
4845 OpCapability VulkanMemoryModelKHR
4846 OpCapability Linkage
4847 OpExtension "SPV_KHR_vulkan_memory_model"
4848 OpMemoryModel Logical VulkanKHR
4849 OpMemberDecorate %1 0 Coherent
4850 %2 = OpTypeInt 32 0
4851 %1 = OpTypeStruct %2 %2
4852 )";
4853
4854 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4855 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4856 EXPECT_THAT(
4857 getDiagnosticString(),
4858 HasSubstr(
4859 "Coherent decoration targeting '1[%_struct_1]' (member index 0) "
4860 "is banned when using the Vulkan memory model."));
4861 }
4862
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatile)4863 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) {
4864 const std::string spirv = R"(
4865 OpCapability Shader
4866 OpCapability VulkanMemoryModelKHR
4867 OpCapability Linkage
4868 OpExtension "SPV_KHR_vulkan_memory_model"
4869 OpExtension "SPV_KHR_storage_buffer_storage_class"
4870 OpMemoryModel Logical VulkanKHR
4871 OpDecorate %1 Volatile
4872 %2 = OpTypeInt 32 0
4873 %3 = OpTypePointer StorageBuffer %2
4874 %1 = OpVariable %3 StorageBuffer
4875 )";
4876
4877 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4878 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4879 EXPECT_THAT(getDiagnosticString(),
4880 HasSubstr("Volatile decoration targeting '1[%1]' is banned when "
4881 "using the Vulkan memory model."));
4882 }
4883
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatileMember)4884 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember) {
4885 const std::string spirv = R"(
4886 OpCapability Shader
4887 OpCapability VulkanMemoryModelKHR
4888 OpCapability Linkage
4889 OpExtension "SPV_KHR_vulkan_memory_model"
4890 OpMemoryModel Logical VulkanKHR
4891 OpMemberDecorate %1 1 Volatile
4892 %2 = OpTypeInt 32 0
4893 %1 = OpTypeStruct %2 %2
4894 )";
4895
4896 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4897 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4898 EXPECT_THAT(getDiagnosticString(),
4899 HasSubstr("Volatile decoration targeting '1[%_struct_1]' (member "
4900 "index 1) is banned when using the Vulkan memory "
4901 "model."));
4902 }
4903
TEST_F(ValidateDecorations,FPRoundingModeGood)4904 TEST_F(ValidateDecorations, FPRoundingModeGood) {
4905 std::string spirv = R"(
4906 OpCapability Shader
4907 OpCapability Linkage
4908 OpCapability StorageBuffer16BitAccess
4909 OpExtension "SPV_KHR_storage_buffer_storage_class"
4910 OpExtension "SPV_KHR_variable_pointers"
4911 OpExtension "SPV_KHR_16bit_storage"
4912 OpMemoryModel Logical GLSL450
4913 OpEntryPoint GLCompute %main "main"
4914 OpDecorate %_ FPRoundingMode RTE
4915 %half = OpTypeFloat 16
4916 %float = OpTypeFloat 32
4917 %float_1_25 = OpConstant %float 1.25
4918 %half_ptr = OpTypePointer StorageBuffer %half
4919 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4920 %void = OpTypeVoid
4921 %func = OpTypeFunction %void
4922 %main = OpFunction %void None %func
4923 %main_entry = OpLabel
4924 %_ = OpFConvert %half %float_1_25
4925 OpStore %half_ptr_var %_
4926 OpReturn
4927 OpFunctionEnd
4928 )";
4929
4930 CompileSuccessfully(spirv);
4931 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4932 }
4933
TEST_F(ValidateDecorations,FPRoundingModeVectorGood)4934 TEST_F(ValidateDecorations, FPRoundingModeVectorGood) {
4935 std::string spirv = R"(
4936 OpCapability Shader
4937 OpCapability Linkage
4938 OpCapability StorageBuffer16BitAccess
4939 OpExtension "SPV_KHR_storage_buffer_storage_class"
4940 OpExtension "SPV_KHR_variable_pointers"
4941 OpExtension "SPV_KHR_16bit_storage"
4942 OpMemoryModel Logical GLSL450
4943 OpEntryPoint GLCompute %main "main"
4944 OpDecorate %_ FPRoundingMode RTE
4945 %half = OpTypeFloat 16
4946 %float = OpTypeFloat 32
4947 %v2half = OpTypeVector %half 2
4948 %v2float = OpTypeVector %float 2
4949 %float_1_25 = OpConstant %float 1.25
4950 %floats = OpConstantComposite %v2float %float_1_25 %float_1_25
4951 %halfs_ptr = OpTypePointer StorageBuffer %v2half
4952 %halfs_ptr_var = OpVariable %halfs_ptr StorageBuffer
4953 %void = OpTypeVoid
4954 %func = OpTypeFunction %void
4955 %main = OpFunction %void None %func
4956 %main_entry = OpLabel
4957 %_ = OpFConvert %v2half %floats
4958 OpStore %halfs_ptr_var %_
4959 OpReturn
4960 OpFunctionEnd
4961 )";
4962
4963 CompileSuccessfully(spirv);
4964 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4965 }
4966
TEST_F(ValidateDecorations,FPRoundingModeNotOpFConvert)4967 TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert) {
4968 std::string spirv = R"(
4969 OpCapability Shader
4970 OpCapability Linkage
4971 OpCapability StorageBuffer16BitAccess
4972 OpExtension "SPV_KHR_storage_buffer_storage_class"
4973 OpExtension "SPV_KHR_variable_pointers"
4974 OpExtension "SPV_KHR_16bit_storage"
4975 OpMemoryModel Logical GLSL450
4976 OpEntryPoint GLCompute %main "main"
4977 OpDecorate %_ FPRoundingMode RTE
4978 %short = OpTypeInt 16 1
4979 %int = OpTypeInt 32 1
4980 %int_17 = OpConstant %int 17
4981 %short_ptr = OpTypePointer StorageBuffer %short
4982 %short_ptr_var = OpVariable %short_ptr StorageBuffer
4983 %void = OpTypeVoid
4984 %func = OpTypeFunction %void
4985 %main = OpFunction %void None %func
4986 %main_entry = OpLabel
4987 %_ = OpSConvert %short %int_17
4988 OpStore %short_ptr_var %_
4989 OpReturn
4990 OpFunctionEnd
4991 )";
4992
4993 CompileSuccessfully(spirv);
4994 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4995 EXPECT_THAT(getDiagnosticString(),
4996 HasSubstr("FPRoundingMode decoration can be applied only to a "
4997 "width-only conversion instruction for floating-point "
4998 "object."));
4999 }
5000
TEST_F(ValidateDecorations,FPRoundingModeNoOpStoreGood)5001 TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood) {
5002 std::string spirv = R"(
5003 OpCapability Shader
5004 OpCapability Linkage
5005 OpCapability StorageBuffer16BitAccess
5006 OpExtension "SPV_KHR_storage_buffer_storage_class"
5007 OpExtension "SPV_KHR_variable_pointers"
5008 OpExtension "SPV_KHR_16bit_storage"
5009 OpMemoryModel Logical GLSL450
5010 OpEntryPoint GLCompute %main "main"
5011 OpDecorate %_ FPRoundingMode RTE
5012 %half = OpTypeFloat 16
5013 %float = OpTypeFloat 32
5014 %float_1_25 = OpConstant %float 1.25
5015 %half_ptr = OpTypePointer StorageBuffer %half
5016 %half_ptr_var = OpVariable %half_ptr StorageBuffer
5017 %void = OpTypeVoid
5018 %func = OpTypeFunction %void
5019 %main = OpFunction %void None %func
5020 %main_entry = OpLabel
5021 %_ = OpFConvert %half %float_1_25
5022 OpReturn
5023 OpFunctionEnd
5024 )";
5025
5026 CompileSuccessfully(spirv);
5027 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5028 }
5029
TEST_F(ValidateDecorations,FPRoundingModeFConvert64to16Good)5030 TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good) {
5031 std::string spirv = R"(
5032 OpCapability Shader
5033 OpCapability Linkage
5034 OpCapability StorageBuffer16BitAccess
5035 OpCapability Float64
5036 OpExtension "SPV_KHR_storage_buffer_storage_class"
5037 OpExtension "SPV_KHR_variable_pointers"
5038 OpExtension "SPV_KHR_16bit_storage"
5039 OpMemoryModel Logical GLSL450
5040 OpEntryPoint GLCompute %main "main"
5041 OpDecorate %_ FPRoundingMode RTE
5042 %half = OpTypeFloat 16
5043 %double = OpTypeFloat 64
5044 %double_1_25 = OpConstant %double 1.25
5045 %half_ptr = OpTypePointer StorageBuffer %half
5046 %half_ptr_var = OpVariable %half_ptr StorageBuffer
5047 %void = OpTypeVoid
5048 %func = OpTypeFunction %void
5049 %main = OpFunction %void None %func
5050 %main_entry = OpLabel
5051 %_ = OpFConvert %half %double_1_25
5052 OpStore %half_ptr_var %_
5053 OpReturn
5054 OpFunctionEnd
5055 )";
5056
5057 CompileSuccessfully(spirv);
5058 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5059 }
5060
TEST_F(ValidateDecorations,FPRoundingModeNotStoreInFloat16)5061 TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16) {
5062 std::string spirv = R"(
5063 OpCapability Shader
5064 OpCapability Linkage
5065 OpCapability StorageBuffer16BitAccess
5066 OpCapability Float64
5067 OpExtension "SPV_KHR_storage_buffer_storage_class"
5068 OpExtension "SPV_KHR_variable_pointers"
5069 OpExtension "SPV_KHR_16bit_storage"
5070 OpMemoryModel Logical GLSL450
5071 OpEntryPoint GLCompute %main "main"
5072 OpDecorate %_ FPRoundingMode RTE
5073 %float = OpTypeFloat 32
5074 %double = OpTypeFloat 64
5075 %double_1_25 = OpConstant %double 1.25
5076 %float_ptr = OpTypePointer StorageBuffer %float
5077 %float_ptr_var = OpVariable %float_ptr StorageBuffer
5078 %void = OpTypeVoid
5079 %func = OpTypeFunction %void
5080 %main = OpFunction %void None %func
5081 %main_entry = OpLabel
5082 %_ = OpFConvert %float %double_1_25
5083 OpStore %float_ptr_var %_
5084 OpReturn
5085 OpFunctionEnd
5086 )";
5087
5088 CompileSuccessfully(spirv);
5089 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5090 EXPECT_THAT(
5091 getDiagnosticString(),
5092 HasSubstr("FPRoundingMode decoration can be applied only to the "
5093 "Object operand of an OpStore storing through a "
5094 "pointer to a 16-bit floating-point scalar or vector object."));
5095 }
5096
TEST_F(ValidateDecorations,FPRoundingModeMultipleOpStoreGood)5097 TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood) {
5098 std::string spirv = R"(
5099 OpCapability Shader
5100 OpCapability Linkage
5101 OpCapability StorageBuffer16BitAccess
5102 OpExtension "SPV_KHR_storage_buffer_storage_class"
5103 OpExtension "SPV_KHR_variable_pointers"
5104 OpExtension "SPV_KHR_16bit_storage"
5105 OpMemoryModel Logical GLSL450
5106 OpEntryPoint GLCompute %main "main"
5107 OpDecorate %_ FPRoundingMode RTE
5108 %half = OpTypeFloat 16
5109 %float = OpTypeFloat 32
5110 %float_1_25 = OpConstant %float 1.25
5111 %half_ptr = OpTypePointer StorageBuffer %half
5112 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
5113 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
5114 %half_ptr_var_2 = OpVariable %half_ptr StorageBuffer
5115 %void = OpTypeVoid
5116 %func = OpTypeFunction %void
5117 %main = OpFunction %void None %func
5118 %main_entry = OpLabel
5119 %_ = OpFConvert %half %float_1_25
5120 OpStore %half_ptr_var_0 %_
5121 OpStore %half_ptr_var_1 %_
5122 OpStore %half_ptr_var_2 %_
5123 OpReturn
5124 OpFunctionEnd
5125 )";
5126
5127 CompileSuccessfully(spirv);
5128 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5129 }
5130
TEST_F(ValidateDecorations,FPRoundingModeMultipleUsesBad)5131 TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad) {
5132 std::string spirv = R"(
5133 OpCapability Shader
5134 OpCapability Linkage
5135 OpCapability StorageBuffer16BitAccess
5136 OpExtension "SPV_KHR_storage_buffer_storage_class"
5137 OpExtension "SPV_KHR_variable_pointers"
5138 OpExtension "SPV_KHR_16bit_storage"
5139 OpMemoryModel Logical GLSL450
5140 OpEntryPoint GLCompute %main "main"
5141 OpDecorate %_ FPRoundingMode RTE
5142 %half = OpTypeFloat 16
5143 %float = OpTypeFloat 32
5144 %float_1_25 = OpConstant %float 1.25
5145 %half_ptr = OpTypePointer StorageBuffer %half
5146 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
5147 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
5148 %void = OpTypeVoid
5149 %func = OpTypeFunction %void
5150 %main = OpFunction %void None %func
5151 %main_entry = OpLabel
5152 %_ = OpFConvert %half %float_1_25
5153 OpStore %half_ptr_var_0 %_
5154 %result = OpFAdd %half %_ %_
5155 OpStore %half_ptr_var_1 %_
5156 OpReturn
5157 OpFunctionEnd
5158 )";
5159
5160 CompileSuccessfully(spirv);
5161 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5162 EXPECT_THAT(getDiagnosticString(),
5163 HasSubstr("FPRoundingMode decoration can be applied only to the "
5164 "Object operand of an OpStore."));
5165 }
5166
TEST_F(ValidateDecorations,VulkanFPRoundingModeGood)5167 TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
5168 std::string spirv = R"(
5169 OpCapability Shader
5170 OpCapability StorageBuffer16BitAccess
5171 %1 = OpExtInstImport "GLSL.std.450"
5172 OpMemoryModel Logical GLSL450
5173 OpEntryPoint GLCompute %main "main" %_
5174 OpExecutionMode %main LocalSize 1 1 1
5175 OpMemberDecorate %ssbo 0 Offset 0
5176 OpDecorate %ssbo Block
5177 OpDecorate %_ DescriptorSet 0
5178 OpDecorate %_ Binding 0
5179 OpDecorate %17 FPRoundingMode RTE
5180 %void = OpTypeVoid
5181 %3 = OpTypeFunction %void
5182 %float = OpTypeFloat 32
5183 %_ptr_Function_float = OpTypePointer Function %float
5184 %float_1 = OpConstant %float 1
5185 %half = OpTypeFloat 16
5186 %ssbo = OpTypeStruct %half
5187 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
5188 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
5189 %int = OpTypeInt 32 1
5190 %int_0 = OpConstant %int 0
5191 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
5192 %main = OpFunction %void None %3
5193 %5 = OpLabel
5194 %b = OpVariable %_ptr_Function_float Function
5195 OpStore %b %float_1
5196 %16 = OpLoad %float %b
5197 %17 = OpFConvert %half %16
5198 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
5199 OpStore %19 %17
5200 OpReturn
5201 OpFunctionEnd
5202 )";
5203
5204 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5205 EXPECT_EQ(SPV_SUCCESS,
5206 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5207 }
5208
TEST_F(ValidateDecorations,VulkanFPRoundingModeBadMode)5209 TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
5210 std::string spirv = R"(
5211 OpCapability Shader
5212 OpCapability StorageBuffer16BitAccess
5213 %1 = OpExtInstImport "GLSL.std.450"
5214 OpMemoryModel Logical GLSL450
5215 OpEntryPoint GLCompute %main "main" %_
5216 OpExecutionMode %main LocalSize 1 1 1
5217 OpMemberDecorate %ssbo 0 Offset 0
5218 OpDecorate %ssbo Block
5219 OpDecorate %_ DescriptorSet 0
5220 OpDecorate %_ Binding 0
5221 OpDecorate %17 FPRoundingMode RTP
5222 %void = OpTypeVoid
5223 %3 = OpTypeFunction %void
5224 %float = OpTypeFloat 32
5225 %_ptr_Function_float = OpTypePointer Function %float
5226 %float_1 = OpConstant %float 1
5227 %half = OpTypeFloat 16
5228 %ssbo = OpTypeStruct %half
5229 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
5230 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
5231 %int = OpTypeInt 32 1
5232 %int_0 = OpConstant %int 0
5233 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
5234 %main = OpFunction %void None %3
5235 %5 = OpLabel
5236 %b = OpVariable %_ptr_Function_float Function
5237 OpStore %b %float_1
5238 %16 = OpLoad %float %b
5239 %17 = OpFConvert %half %16
5240 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
5241 OpStore %19 %17
5242 OpReturn
5243 OpFunctionEnd
5244 )";
5245
5246 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5247 EXPECT_EQ(SPV_ERROR_INVALID_ID,
5248 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5249 EXPECT_THAT(getDiagnosticString(),
5250 AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
5251 EXPECT_THAT(
5252 getDiagnosticString(),
5253 HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
5254 }
5255
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup)5256 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
5257 std::string spirv = R"(
5258 OpCapability Shader
5259 OpCapability Linkage
5260 OpMemoryModel Logical GLSL450
5261 %1 = OpDecorationGroup
5262 OpGroupDecorate %1 %1
5263 )";
5264
5265 CompileSuccessfully(spirv);
5266 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5267 EXPECT_THAT(getDiagnosticString(),
5268 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5269 "'1[%1]'"));
5270 }
5271
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup2)5272 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2) {
5273 std::string spirv = R"(
5274 OpCapability Shader
5275 OpCapability Linkage
5276 OpMemoryModel Logical GLSL450
5277 %1 = OpDecorationGroup
5278 OpGroupDecorate %1 %2 %1
5279 %2 = OpTypeVoid
5280 )";
5281
5282 CompileSuccessfully(spirv);
5283 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5284 EXPECT_THAT(getDiagnosticString(),
5285 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5286 "'1[%1]'"));
5287 }
5288
TEST_F(ValidateDecorations,RecurseThroughRuntimeArray)5289 TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) {
5290 const std::string spirv = R"(
5291 OpCapability Shader
5292 OpExtension "SPV_KHR_storage_buffer_storage_class"
5293 OpMemoryModel Logical GLSL450
5294 OpEntryPoint GLCompute %main "main"
5295 OpExecutionMode %main LocalSize 1 1 1
5296 OpDecorate %outer Block
5297 OpMemberDecorate %inner 0 Offset 0
5298 OpMemberDecorate %inner 1 Offset 1
5299 OpDecorate %runtime ArrayStride 16
5300 OpMemberDecorate %outer 0 Offset 0
5301 %int = OpTypeInt 32 0
5302 %inner = OpTypeStruct %int %int
5303 %runtime = OpTypeRuntimeArray %inner
5304 %outer = OpTypeStruct %runtime
5305 %outer_ptr = OpTypePointer StorageBuffer %outer
5306 %var = OpVariable %outer_ptr StorageBuffer
5307 %void = OpTypeVoid
5308 %void_fn = OpTypeFunction %void
5309 %main = OpFunction %void None %void_fn
5310 %entry = OpLabel
5311 OpReturn
5312 OpFunctionEnd
5313 )";
5314
5315 CompileSuccessfully(spirv);
5316 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5317 EXPECT_THAT(
5318 getDiagnosticString(),
5319 HasSubstr(
5320 "Structure id 3 decorated as Block for variable in StorageBuffer "
5321 "storage class must follow standard storage buffer layout "
5322 "rules: member 1 at offset 1 is not aligned to 4"));
5323 }
5324
TEST_F(ValidateDecorations,VulkanStructWithoutDecorationWithRuntimeArray)5325 TEST_F(ValidateDecorations, VulkanStructWithoutDecorationWithRuntimeArray) {
5326 std::string str = R"(
5327 OpCapability Shader
5328 OpMemoryModel Logical GLSL450
5329 OpEntryPoint Fragment %func "func"
5330 OpExecutionMode %func OriginUpperLeft
5331 OpDecorate %array_t ArrayStride 4
5332 OpMemberDecorate %struct_t 0 Offset 0
5333 OpMemberDecorate %struct_t 1 Offset 4
5334 %uint_t = OpTypeInt 32 0
5335 %array_t = OpTypeRuntimeArray %uint_t
5336 %struct_t = OpTypeStruct %uint_t %array_t
5337 %struct_ptr = OpTypePointer StorageBuffer %struct_t
5338 %2 = OpVariable %struct_ptr StorageBuffer
5339 %void = OpTypeVoid
5340 %func_t = OpTypeFunction %void
5341 %func = OpFunction %void None %func_t
5342 %1 = OpLabel
5343 OpReturn
5344 OpFunctionEnd
5345 )";
5346
5347 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
5348 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5349 EXPECT_THAT(getDiagnosticString(),
5350 AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
5351 EXPECT_THAT(getDiagnosticString(),
5352 HasSubstr("Vulkan, OpTypeStruct containing an OpTypeRuntimeArray "
5353 "must be decorated with Block or BufferBlock."));
5354 }
5355
TEST_F(ValidateDecorations,EmptyStructAtNonZeroOffsetGood)5356 TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) {
5357 const std::string spirv = R"(
5358 OpCapability Shader
5359 OpMemoryModel Logical GLSL450
5360 OpEntryPoint GLCompute %main "main"
5361 OpExecutionMode %main LocalSize 1 1 1
5362 OpDecorate %struct Block
5363 OpMemberDecorate %struct 0 Offset 0
5364 OpMemberDecorate %struct 1 Offset 16
5365 OpDecorate %var DescriptorSet 0
5366 OpDecorate %var Binding 0
5367 %void = OpTypeVoid
5368 %float = OpTypeFloat 32
5369 %empty = OpTypeStruct
5370 %struct = OpTypeStruct %float %empty
5371 %ptr_struct_ubo = OpTypePointer Uniform %struct
5372 %var = OpVariable %ptr_struct_ubo Uniform
5373 %voidfn = OpTypeFunction %void
5374 %main = OpFunction %void None %voidfn
5375 %entry = OpLabel
5376 OpReturn
5377 OpFunctionEnd
5378 )";
5379
5380 CompileSuccessfully(spirv);
5381 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5382 }
5383
5384 // Uniform and UniformId decorations
5385
TEST_F(ValidateDecorations,UniformDecorationGood)5386 TEST_F(ValidateDecorations, UniformDecorationGood) {
5387 const std::string spirv = R"(
5388 OpCapability Shader
5389 OpMemoryModel Logical Simple
5390 OpEntryPoint GLCompute %main "main"
5391 OpExecutionMode %main LocalSize 1 1 1
5392 OpDecorate %int0 Uniform
5393 OpDecorate %var Uniform
5394 OpDecorate %val Uniform
5395 %void = OpTypeVoid
5396 %int = OpTypeInt 32 1
5397 %int0 = OpConstantNull %int
5398 %intptr = OpTypePointer Private %int
5399 %var = OpVariable %intptr Private
5400 %fn = OpTypeFunction %void
5401 %main = OpFunction %void None %fn
5402 %entry = OpLabel
5403 %val = OpLoad %int %var
5404 OpReturn
5405 OpFunctionEnd
5406 )";
5407
5408 CompileSuccessfully(spirv);
5409 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5410 EXPECT_THAT(getDiagnosticString(), Eq(""));
5411 }
5412
5413 // Returns SPIR-V assembly for a shader that uses a given decoration
5414 // instruction.
ShaderWithUniformLikeDecoration(const std::string & inst)5415 std::string ShaderWithUniformLikeDecoration(const std::string& inst) {
5416 return std::string(R"(
5417 OpCapability Shader
5418 OpMemoryModel Logical Simple
5419 OpEntryPoint GLCompute %main "main"
5420 OpExecutionMode %main LocalSize 1 1 1
5421 OpName %subgroupscope "subgroupscope"
5422 OpName %call "call"
5423 OpName %myfunc "myfunc"
5424 OpName %int0 "int0"
5425 OpName %float0 "float0"
5426 OpName %fn "fn"
5427 )") + inst +
5428 R"(
5429 %void = OpTypeVoid
5430 %float = OpTypeFloat 32
5431 %int = OpTypeInt 32 1
5432 %int0 = OpConstantNull %int
5433 %int_99 = OpConstant %int 99
5434 %subgroupscope = OpConstant %int 3
5435 %float0 = OpConstantNull %float
5436 %fn = OpTypeFunction %void
5437 %myfunc = OpFunction %void None %fn
5438 %myfuncentry = OpLabel
5439 OpReturn
5440 OpFunctionEnd
5441 %main = OpFunction %void None %fn
5442 %entry = OpLabel
5443 %call = OpFunctionCall %void %myfunc
5444 OpReturn
5445 OpFunctionEnd
5446 )";
5447 }
5448
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13Bad)5449 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad) {
5450 const std::string spirv = ShaderWithUniformLikeDecoration(
5451 "OpDecorateId %int0 UniformId %subgroupscope");
5452 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5453 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5454 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5455 EXPECT_THAT(getDiagnosticString(),
5456 HasSubstr("requires SPIR-V version 1.4 or later\n"
5457 " OpDecorateId %int0 UniformId %subgroupscope"))
5458 << spirv;
5459 }
5460
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13BadTargetV14)5461 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14) {
5462 const std::string spirv = ShaderWithUniformLikeDecoration(
5463 "OpDecorateId %int0 UniformId %subgroupscope");
5464 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5465 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5466 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5467 EXPECT_THAT(getDiagnosticString(),
5468 HasSubstr("requires SPIR-V version 1.4 or later"));
5469 }
5470
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV14Good)5471 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good) {
5472 const std::string spirv = ShaderWithUniformLikeDecoration(
5473 "OpDecorateId %int0 UniformId %subgroupscope");
5474 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5475 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5476 EXPECT_THAT(getDiagnosticString(), Eq(""));
5477 }
5478
TEST_F(ValidateDecorations,UniformDecorationTargetsTypeBad)5479 TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad) {
5480 const std::string spirv =
5481 ShaderWithUniformLikeDecoration("OpDecorate %fn Uniform");
5482
5483 CompileSuccessfully(spirv);
5484 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5485 EXPECT_THAT(getDiagnosticString(),
5486 HasSubstr("Uniform decoration applied to a non-object"));
5487 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5488 }
5489
TEST_F(ValidateDecorations,UniformIdDecorationTargetsTypeBad)5490 TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad) {
5491 const std::string spirv = ShaderWithUniformLikeDecoration(
5492 "OpDecorateId %fn UniformId %subgroupscope");
5493
5494 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5495 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5496 EXPECT_THAT(getDiagnosticString(),
5497 HasSubstr("UniformId decoration applied to a non-object"));
5498 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5499 }
5500
TEST_F(ValidateDecorations,UniformDecorationTargetsVoidValueBad)5501 TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad) {
5502 const std::string spirv =
5503 ShaderWithUniformLikeDecoration("OpDecorate %call Uniform");
5504
5505 CompileSuccessfully(spirv);
5506 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5507 EXPECT_THAT(getDiagnosticString(),
5508 HasSubstr("Uniform decoration applied to a value with void type\n"
5509 " %call = OpFunctionCall %void %myfunc"));
5510 }
5511
TEST_F(ValidateDecorations,UniformIdDecorationTargetsVoidValueBad)5512 TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad) {
5513 const std::string spirv = ShaderWithUniformLikeDecoration(
5514 "OpDecorateId %call UniformId %subgroupscope");
5515
5516 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5517 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4))
5518 << spirv;
5519 EXPECT_THAT(
5520 getDiagnosticString(),
5521 HasSubstr("UniformId decoration applied to a value with void type\n"
5522 " %call = OpFunctionCall %void %myfunc"));
5523 }
5524
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsFloatValueIsBad)5525 TEST_F(ValidateDecorations,
5526 UniformDecorationWithScopeIdV14IdIsFloatValueIsBad) {
5527 const std::string spirv =
5528 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %float0");
5529
5530 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5531 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5532 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5533 EXPECT_THAT(getDiagnosticString(),
5534 HasSubstr("ConstantNull: expected scope to be a 32-bit int"));
5535 }
5536
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad)5537 TEST_F(ValidateDecorations,
5538 UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad) {
5539 const std::string spirv =
5540 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int_99");
5541
5542 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5543 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5544 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5545 EXPECT_THAT(
5546 getDiagnosticString(),
5547 HasSubstr("Invalid scope value:\n %int_99 = OpConstant %int 99\n"));
5548 }
5549
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14VulkanEnv)5550 TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
5551 const std::string spirv =
5552 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int0");
5553
5554 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
5555 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5556 ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
5557 EXPECT_THAT(getDiagnosticString(),
5558 AnyVUID("VUID-StandaloneSpirv-None-04636"));
5559 EXPECT_THAT(getDiagnosticString(),
5560 HasSubstr(": in Vulkan environment Execution Scope is limited to "
5561 "Workgroup and Subgroup"));
5562 }
5563
TEST_F(ValidateDecorations,UniformDecorationWithWrongInstructionBad)5564 TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) {
5565 const std::string spirv =
5566 ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform");
5567
5568 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
5569 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
5570 EXPECT_THAT(getDiagnosticString(),
5571 HasSubstr("Decorations that don't take ID parameters may not be "
5572 "used with OpDecorateId\n"
5573 " OpDecorateId %int0 Uniform"));
5574 }
5575
TEST_F(ValidateDecorations,UniformIdDecorationWithWrongInstructionBad)5576 TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) {
5577 const std::string spirv = ShaderWithUniformLikeDecoration(
5578 "OpDecorate %int0 UniformId %subgroupscope");
5579
5580 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5581 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5582 EXPECT_THAT(
5583 getDiagnosticString(),
5584 HasSubstr(
5585 "Decorations taking ID parameters may not be used with OpDecorateId\n"
5586 " OpDecorate %int0 UniformId %subgroupscope"));
5587 }
5588
TEST_F(ValidateDecorations,MultipleOffsetDecorationsOnSameID)5589 TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) {
5590 std::string spirv = R"(
5591 OpCapability Shader
5592 OpMemoryModel Logical GLSL450
5593 OpEntryPoint Fragment %1 "main"
5594 OpExecutionMode %1 OriginUpperLeft
5595
5596 OpMemberDecorate %struct 0 Offset 0
5597 OpMemberDecorate %struct 0 Offset 0
5598
5599 %void = OpTypeVoid
5600 %voidfn = OpTypeFunction %void
5601 %float = OpTypeFloat 32
5602 %struct = OpTypeStruct %float
5603
5604 %1 = OpFunction %void None %voidfn
5605 %label = OpLabel
5606 OpReturn
5607 OpFunctionEnd
5608 )";
5609
5610 CompileSuccessfully(spirv);
5611 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5612 EXPECT_THAT(getDiagnosticString(),
5613 HasSubstr("ID '2', member '0' decorated with Offset multiple "
5614 "times is not allowed."));
5615 }
5616
TEST_F(ValidateDecorations,MultipleArrayStrideDecorationsOnSameID)5617 TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) {
5618 std::string spirv = R"(
5619 OpCapability Shader
5620 OpMemoryModel Logical GLSL450
5621 OpEntryPoint Fragment %1 "main"
5622 OpExecutionMode %1 OriginUpperLeft
5623
5624 OpDecorate %array ArrayStride 4
5625 OpDecorate %array ArrayStride 4
5626
5627 %void = OpTypeVoid
5628 %voidfn = OpTypeFunction %void
5629 %float = OpTypeFloat 32
5630 %uint = OpTypeInt 32 0
5631 %uint_4 = OpConstant %uint 4
5632 %array = OpTypeArray %float %uint_4
5633
5634 %1 = OpFunction %void None %voidfn
5635 %label = OpLabel
5636 OpReturn
5637 OpFunctionEnd
5638 )";
5639
5640 CompileSuccessfully(spirv);
5641 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5642 EXPECT_THAT(getDiagnosticString(),
5643 HasSubstr("ID '2' decorated with ArrayStride multiple "
5644 "times is not allowed."));
5645 }
5646
TEST_F(ValidateDecorations,MultipleMatrixStrideDecorationsOnSameID)5647 TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) {
5648 std::string spirv = R"(
5649 OpCapability Shader
5650 OpMemoryModel Logical GLSL450
5651 OpEntryPoint Fragment %1 "main"
5652 OpExecutionMode %1 OriginUpperLeft
5653
5654 OpMemberDecorate %struct 0 Offset 0
5655 OpMemberDecorate %struct 0 ColMajor
5656 OpMemberDecorate %struct 0 MatrixStride 16
5657 OpMemberDecorate %struct 0 MatrixStride 16
5658
5659 %void = OpTypeVoid
5660 %voidfn = OpTypeFunction %void
5661 %float = OpTypeFloat 32
5662 %fvec4 = OpTypeVector %float 4
5663 %fmat4 = OpTypeMatrix %fvec4 4
5664 %struct = OpTypeStruct %fmat4
5665
5666 %1 = OpFunction %void None %voidfn
5667 %label = OpLabel
5668 OpReturn
5669 OpFunctionEnd
5670 )";
5671
5672 CompileSuccessfully(spirv);
5673 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5674 EXPECT_THAT(getDiagnosticString(),
5675 HasSubstr("ID '2', member '0' decorated with MatrixStride "
5676 "multiple times is not allowed."));
5677 }
5678
TEST_F(ValidateDecorations,MultipleRowMajorDecorationsOnSameID)5679 TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) {
5680 std::string spirv = R"(
5681 OpCapability Shader
5682 OpMemoryModel Logical GLSL450
5683 OpEntryPoint Fragment %1 "main"
5684 OpExecutionMode %1 OriginUpperLeft
5685
5686 OpMemberDecorate %struct 0 Offset 0
5687 OpMemberDecorate %struct 0 MatrixStride 16
5688 OpMemberDecorate %struct 0 RowMajor
5689 OpMemberDecorate %struct 0 RowMajor
5690
5691 %void = OpTypeVoid
5692 %voidfn = OpTypeFunction %void
5693 %float = OpTypeFloat 32
5694 %fvec4 = OpTypeVector %float 4
5695 %fmat4 = OpTypeMatrix %fvec4 4
5696 %struct = OpTypeStruct %fmat4
5697
5698 %1 = OpFunction %void None %voidfn
5699 %label = OpLabel
5700 OpReturn
5701 OpFunctionEnd
5702 )";
5703
5704 CompileSuccessfully(spirv);
5705 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5706 EXPECT_THAT(getDiagnosticString(),
5707 HasSubstr("ID '2', member '0' decorated with RowMajor multiple "
5708 "times is not allowed."));
5709 }
5710
TEST_F(ValidateDecorations,MultipleColMajorDecorationsOnSameID)5711 TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) {
5712 std::string spirv = R"(
5713 OpCapability Shader
5714 OpMemoryModel Logical GLSL450
5715 OpEntryPoint Fragment %1 "main"
5716 OpExecutionMode %1 OriginUpperLeft
5717
5718 OpMemberDecorate %struct 0 Offset 0
5719 OpMemberDecorate %struct 0 MatrixStride 16
5720 OpMemberDecorate %struct 0 ColMajor
5721 OpMemberDecorate %struct 0 ColMajor
5722
5723 %void = OpTypeVoid
5724 %voidfn = OpTypeFunction %void
5725 %float = OpTypeFloat 32
5726 %fvec4 = OpTypeVector %float 4
5727 %fmat4 = OpTypeMatrix %fvec4 4
5728 %struct = OpTypeStruct %fmat4
5729
5730 %1 = OpFunction %void None %voidfn
5731 %label = OpLabel
5732 OpReturn
5733 OpFunctionEnd
5734 )";
5735
5736 CompileSuccessfully(spirv);
5737 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5738 EXPECT_THAT(getDiagnosticString(),
5739 HasSubstr("ID '2', member '0' decorated with ColMajor multiple "
5740 "times is not allowed."));
5741 }
5742
TEST_F(ValidateDecorations,RowMajorAndColMajorDecorationsOnSameID)5743 TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) {
5744 std::string spirv = R"(
5745 OpCapability Shader
5746 OpMemoryModel Logical GLSL450
5747 OpEntryPoint Fragment %1 "main"
5748 OpExecutionMode %1 OriginUpperLeft
5749
5750 OpMemberDecorate %struct 0 Offset 0
5751 OpMemberDecorate %struct 0 MatrixStride 16
5752 OpMemberDecorate %struct 0 ColMajor
5753 OpMemberDecorate %struct 0 RowMajor
5754
5755 %void = OpTypeVoid
5756 %voidfn = OpTypeFunction %void
5757 %float = OpTypeFloat 32
5758 %fvec4 = OpTypeVector %float 4
5759 %fmat4 = OpTypeMatrix %fvec4 4
5760 %struct = OpTypeStruct %fmat4
5761
5762 %1 = OpFunction %void None %voidfn
5763 %label = OpLabel
5764 OpReturn
5765 OpFunctionEnd
5766 )";
5767
5768 CompileSuccessfully(spirv);
5769 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5770 EXPECT_THAT(getDiagnosticString(),
5771 HasSubstr("ID '2', member '0' decorated with both RowMajor and "
5772 "ColMajor is not allowed."));
5773 }
5774
TEST_F(ValidateDecorations,BlockAndBufferBlockDecorationsOnSameID)5775 TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
5776 std::string spirv = R"(
5777 OpCapability Shader
5778 OpMemoryModel Logical GLSL450
5779 OpEntryPoint Fragment %1 "main"
5780 OpExecutionMode %1 OriginUpperLeft
5781
5782 OpDecorate %struct Block
5783 OpDecorate %struct BufferBlock
5784 OpMemberDecorate %struct 0 Offset 0
5785 OpMemberDecorate %struct 0 MatrixStride 16
5786 OpMemberDecorate %struct 0 RowMajor
5787
5788 %void = OpTypeVoid
5789 %voidfn = OpTypeFunction %void
5790 %float = OpTypeFloat 32
5791 %fvec4 = OpTypeVector %float 4
5792 %fmat4 = OpTypeMatrix %fvec4 4
5793 %struct = OpTypeStruct %fmat4
5794
5795 %1 = OpFunction %void None %voidfn
5796 %label = OpLabel
5797 OpReturn
5798 OpFunctionEnd
5799 )";
5800
5801 CompileSuccessfully(spirv);
5802 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5803 EXPECT_THAT(
5804 getDiagnosticString(),
5805 HasSubstr(
5806 "ID '2' decorated with both BufferBlock and Block is not allowed."));
5807 }
5808
MakeIntegerShader(const std::string & decoration,const std::string & inst,const std::string & extension="OpExtension \\"SPV_KHR_no_integer_wrap_decoration\\"")5809 std::string MakeIntegerShader(
5810 const std::string& decoration, const std::string& inst,
5811 const std::string& extension =
5812 "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
5813 return R"(
5814 OpCapability Shader
5815 OpCapability Linkage
5816 )" + extension +
5817 R"(
5818 %glsl = OpExtInstImport "GLSL.std.450"
5819 %opencl = OpExtInstImport "OpenCL.std"
5820 OpMemoryModel Logical GLSL450
5821 OpEntryPoint GLCompute %main "main"
5822 OpName %entry "entry"
5823 )" + decoration +
5824 R"(
5825 %void = OpTypeVoid
5826 %voidfn = OpTypeFunction %void
5827 %int = OpTypeInt 32 1
5828 %zero = OpConstantNull %int
5829 %float = OpTypeFloat 32
5830 %float0 = OpConstantNull %float
5831 %main = OpFunction %void None %voidfn
5832 %entry = OpLabel
5833 )" + inst +
5834 R"(
5835 OpReturn
5836 OpFunctionEnd)";
5837 }
5838
5839 // NoSignedWrap
5840
TEST_F(ValidateDecorations,NoSignedWrapOnTypeBad)5841 TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
5842 std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
5843
5844 CompileSuccessfully(spirv);
5845 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5846 EXPECT_THAT(
5847 getDiagnosticString(),
5848 HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
5849 }
5850
TEST_F(ValidateDecorations,NoSignedWrapOnLabelBad)5851 TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
5852 std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
5853
5854 CompileSuccessfully(spirv);
5855 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5856 EXPECT_THAT(getDiagnosticString(),
5857 HasSubstr("NoSignedWrap decoration may not be applied to Label"));
5858 }
5859
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionBad)5860 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
5861 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5862 "%val = OpIAdd %int %zero %zero", "");
5863
5864 CompileSuccessfully(spirv);
5865 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5866 EXPECT_THAT(getDiagnosticString(),
5867 HasSubstr("requires one of these extensions: "
5868 "SPV_KHR_no_integer_wrap_decoration"));
5869 }
5870
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionV13Bad)5871 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) {
5872 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5873 "%val = OpIAdd %int %zero %zero", "");
5874
5875 CompileSuccessfully(spirv);
5876 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5877 EXPECT_THAT(getDiagnosticString(),
5878 HasSubstr("requires one of these extensions: "
5879 "SPV_KHR_no_integer_wrap_decoration"));
5880 }
5881
TEST_F(ValidateDecorations,NoSignedWrapOkInSPV14Good)5882 TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) {
5883 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5884 "%val = OpIAdd %int %zero %zero", "");
5885
5886 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5887 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5888 EXPECT_THAT(getDiagnosticString(), Eq(""));
5889 }
5890
TEST_F(ValidateDecorations,NoSignedWrapIAddGood)5891 TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
5892 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5893 "%val = OpIAdd %int %zero %zero");
5894
5895 CompileSuccessfully(spirv);
5896 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5897 EXPECT_THAT(getDiagnosticString(), Eq(""));
5898 }
5899
TEST_F(ValidateDecorations,NoSignedWrapISubGood)5900 TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
5901 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5902 "%val = OpISub %int %zero %zero");
5903
5904 CompileSuccessfully(spirv);
5905 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5906 EXPECT_THAT(getDiagnosticString(), Eq(""));
5907 }
5908
TEST_F(ValidateDecorations,NoSignedWrapIMulGood)5909 TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
5910 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5911 "%val = OpIMul %int %zero %zero");
5912
5913 CompileSuccessfully(spirv);
5914 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5915 EXPECT_THAT(getDiagnosticString(), Eq(""));
5916 }
5917
TEST_F(ValidateDecorations,NoSignedWrapShiftLeftLogicalGood)5918 TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
5919 std::string spirv =
5920 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5921 "%val = OpShiftLeftLogical %int %zero %zero");
5922
5923 CompileSuccessfully(spirv);
5924 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5925 EXPECT_THAT(getDiagnosticString(), Eq(""));
5926 }
5927
TEST_F(ValidateDecorations,NoSignedWrapSNegateGood)5928 TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
5929 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5930 "%val = OpSNegate %int %zero");
5931
5932 CompileSuccessfully(spirv);
5933 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5934 EXPECT_THAT(getDiagnosticString(), Eq(""));
5935 }
5936
TEST_F(ValidateDecorations,NoSignedWrapSRemBad)5937 TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
5938 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5939 "%val = OpSRem %int %zero %zero");
5940
5941 CompileSuccessfully(spirv);
5942 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5943 EXPECT_THAT(getDiagnosticString(),
5944 HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
5945 }
5946
TEST_F(ValidateDecorations,NoSignedWrapFAddBad)5947 TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
5948 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5949 "%val = OpFAdd %float %float0 %float0");
5950
5951 CompileSuccessfully(spirv);
5952 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5953 EXPECT_THAT(getDiagnosticString(),
5954 HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
5955 }
5956
TEST_F(ValidateDecorations,NoSignedWrapExtInstOpenCLGood)5957 TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
5958 std::string spirv =
5959 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5960 "%val = OpExtInst %int %opencl s_abs %zero");
5961
5962 CompileSuccessfully(spirv);
5963 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5964 EXPECT_THAT(getDiagnosticString(), Eq(""));
5965 }
5966
TEST_F(ValidateDecorations,NoSignedWrapExtInstGLSLGood)5967 TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
5968 std::string spirv = MakeIntegerShader(
5969 "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
5970
5971 CompileSuccessfully(spirv);
5972 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5973 EXPECT_THAT(getDiagnosticString(), Eq(""));
5974 }
5975
5976 // TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
5977 // "OpExtInst for instruction numbers specified in the extended
5978 // instruction-set specifications as accepting this decoration."
5979
5980 // NoUnignedWrap
5981
TEST_F(ValidateDecorations,NoUnsignedWrapOnTypeBad)5982 TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
5983 std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
5984
5985 CompileSuccessfully(spirv);
5986 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5987 EXPECT_THAT(
5988 getDiagnosticString(),
5989 HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
5990 }
5991
TEST_F(ValidateDecorations,NoUnsignedWrapOnLabelBad)5992 TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
5993 std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
5994
5995 CompileSuccessfully(spirv);
5996 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5997 EXPECT_THAT(
5998 getDiagnosticString(),
5999 HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
6000 }
6001
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionBad)6002 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
6003 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6004 "%val = OpIAdd %int %zero %zero", "");
6005
6006 CompileSuccessfully(spirv);
6007 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
6008 EXPECT_THAT(getDiagnosticString(),
6009 HasSubstr("requires one of these extensions: "
6010 "SPV_KHR_no_integer_wrap_decoration"));
6011 }
6012
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionV13Bad)6013 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) {
6014 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6015 "%val = OpIAdd %int %zero %zero", "");
6016
6017 CompileSuccessfully(spirv);
6018 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6019 EXPECT_THAT(getDiagnosticString(),
6020 HasSubstr("requires one of these extensions: "
6021 "SPV_KHR_no_integer_wrap_decoration"));
6022 }
6023
TEST_F(ValidateDecorations,NoUnsignedWrapOkInSPV14Good)6024 TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) {
6025 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6026 "%val = OpIAdd %int %zero %zero", "");
6027
6028 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6029 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6030 EXPECT_THAT(getDiagnosticString(), Eq(""));
6031 }
6032
TEST_F(ValidateDecorations,NoUnsignedWrapIAddGood)6033 TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
6034 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6035 "%val = OpIAdd %int %zero %zero");
6036
6037 CompileSuccessfully(spirv);
6038 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6039 EXPECT_THAT(getDiagnosticString(), Eq(""));
6040 }
6041
TEST_F(ValidateDecorations,NoUnsignedWrapISubGood)6042 TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
6043 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6044 "%val = OpISub %int %zero %zero");
6045
6046 CompileSuccessfully(spirv);
6047 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6048 EXPECT_THAT(getDiagnosticString(), Eq(""));
6049 }
6050
TEST_F(ValidateDecorations,NoUnsignedWrapIMulGood)6051 TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
6052 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6053 "%val = OpIMul %int %zero %zero");
6054
6055 CompileSuccessfully(spirv);
6056 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6057 EXPECT_THAT(getDiagnosticString(), Eq(""));
6058 }
6059
TEST_F(ValidateDecorations,NoUnsignedWrapShiftLeftLogicalGood)6060 TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
6061 std::string spirv =
6062 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6063 "%val = OpShiftLeftLogical %int %zero %zero");
6064
6065 CompileSuccessfully(spirv);
6066 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6067 EXPECT_THAT(getDiagnosticString(), Eq(""));
6068 }
6069
TEST_F(ValidateDecorations,NoUnsignedWrapSNegateGood)6070 TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
6071 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6072 "%val = OpSNegate %int %zero");
6073
6074 CompileSuccessfully(spirv);
6075 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6076 EXPECT_THAT(getDiagnosticString(), Eq(""));
6077 }
6078
TEST_F(ValidateDecorations,NoUnsignedWrapSRemBad)6079 TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
6080 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6081 "%val = OpSRem %int %zero %zero");
6082
6083 CompileSuccessfully(spirv);
6084 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6085 EXPECT_THAT(
6086 getDiagnosticString(),
6087 HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
6088 }
6089
TEST_F(ValidateDecorations,NoUnsignedWrapFAddBad)6090 TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
6091 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6092 "%val = OpFAdd %float %float0 %float0");
6093
6094 CompileSuccessfully(spirv);
6095 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6096 EXPECT_THAT(
6097 getDiagnosticString(),
6098 HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
6099 }
6100
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstOpenCLGood)6101 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
6102 std::string spirv =
6103 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6104 "%val = OpExtInst %int %opencl s_abs %zero");
6105
6106 CompileSuccessfully(spirv);
6107 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6108 EXPECT_THAT(getDiagnosticString(), Eq(""));
6109 }
6110
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstGLSLGood)6111 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
6112 std::string spirv =
6113 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6114 "%val = OpExtInst %int %glsl SAbs %zero");
6115
6116 CompileSuccessfully(spirv);
6117 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6118 EXPECT_THAT(getDiagnosticString(), Eq(""));
6119 }
6120
TEST_F(ValidateDecorations,AliasedandRestrictBad)6121 TEST_F(ValidateDecorations, AliasedandRestrictBad) {
6122 const std::string body = R"(
6123 OpCapability Shader
6124 %1 = OpExtInstImport "GLSL.std.450"
6125 OpMemoryModel Logical GLSL450
6126 OpEntryPoint GLCompute %main "main"
6127 OpExecutionMode %main LocalSize 1 1 1
6128 OpSource GLSL 430
6129 OpMemberDecorate %Output 0 Offset 0
6130 OpDecorate %Output BufferBlock
6131 OpDecorate %dataOutput Restrict
6132 OpDecorate %dataOutput Aliased
6133 %void = OpTypeVoid
6134 %3 = OpTypeFunction %void
6135 %float = OpTypeFloat 32
6136 %Output = OpTypeStruct %float
6137 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
6138 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
6139 %main = OpFunction %void None %3
6140 %5 = OpLabel
6141 OpReturn
6142 OpFunctionEnd
6143 )";
6144
6145 CompileSuccessfully(body.c_str());
6146 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6147 EXPECT_THAT(
6148 getDiagnosticString(),
6149 HasSubstr("decorated with both Aliased and Restrict is not allowed"));
6150 }
6151
6152 // TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
6153 // "OpExtInst for instruction numbers specified in the extended
6154 // instruction-set specifications as accepting this decoration."
6155
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerSuccess)6156 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
6157 const std::string body = R"(
6158 OpCapability PhysicalStorageBufferAddresses
6159 OpCapability Int64
6160 OpCapability Shader
6161 OpExtension "SPV_EXT_physical_storage_buffer"
6162 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6163 OpEntryPoint Fragment %main "main"
6164 OpExecutionMode %main OriginUpperLeft
6165 OpDecorate %val1 RestrictPointer
6166 %uint64 = OpTypeInt 64 0
6167 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6168 %pptr_f = OpTypePointer Function %ptr
6169 %void = OpTypeVoid
6170 %voidfn = OpTypeFunction %void
6171 %main = OpFunction %void None %voidfn
6172 %entry = OpLabel
6173 %val1 = OpVariable %pptr_f Function
6174 OpReturn
6175 OpFunctionEnd
6176 )";
6177
6178 CompileSuccessfully(body.c_str());
6179 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6180 }
6181
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerMissing)6182 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) {
6183 const std::string body = R"(
6184 OpCapability PhysicalStorageBufferAddresses
6185 OpCapability Int64
6186 OpCapability Shader
6187 OpExtension "SPV_EXT_physical_storage_buffer"
6188 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6189 OpEntryPoint Fragment %main "main"
6190 OpExecutionMode %main OriginUpperLeft
6191 %uint64 = OpTypeInt 64 0
6192 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6193 %pptr_f = OpTypePointer Function %ptr
6194 %void = OpTypeVoid
6195 %voidfn = OpTypeFunction %void
6196 %main = OpFunction %void None %voidfn
6197 %entry = OpLabel
6198 %val1 = OpVariable %pptr_f Function
6199 OpReturn
6200 OpFunctionEnd
6201 )";
6202
6203 CompileSuccessfully(body.c_str());
6204 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6205 EXPECT_THAT(getDiagnosticString(),
6206 HasSubstr("expected AliasedPointer or RestrictPointer for "
6207 "PhysicalStorageBuffer pointer"));
6208 }
6209
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerBoth)6210 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) {
6211 const std::string body = R"(
6212 OpCapability PhysicalStorageBufferAddresses
6213 OpCapability Int64
6214 OpCapability Shader
6215 OpExtension "SPV_EXT_physical_storage_buffer"
6216 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6217 OpEntryPoint Fragment %main "main"
6218 OpExecutionMode %main OriginUpperLeft
6219 OpDecorate %val1 RestrictPointer
6220 OpDecorate %val1 AliasedPointer
6221 %uint64 = OpTypeInt 64 0
6222 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6223 %pptr_f = OpTypePointer Function %ptr
6224 %void = OpTypeVoid
6225 %voidfn = OpTypeFunction %void
6226 %main = OpFunction %void None %voidfn
6227 %entry = OpLabel
6228 %val1 = OpVariable %pptr_f Function
6229 OpReturn
6230 OpFunctionEnd
6231 )";
6232
6233 CompileSuccessfully(body.c_str());
6234 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6235 EXPECT_THAT(getDiagnosticString(),
6236 HasSubstr("can't specify both AliasedPointer and RestrictPointer "
6237 "for PhysicalStorageBuffer pointer"));
6238 }
6239
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamSuccess)6240 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) {
6241 const std::string body = R"(
6242 OpCapability PhysicalStorageBufferAddresses
6243 OpCapability Int64
6244 OpCapability Shader
6245 OpExtension "SPV_EXT_physical_storage_buffer"
6246 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6247 OpEntryPoint Fragment %main "main"
6248 OpExecutionMode %main OriginUpperLeft
6249 OpDecorate %fparam Restrict
6250 %uint64 = OpTypeInt 64 0
6251 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6252 %void = OpTypeVoid
6253 %voidfn = OpTypeFunction %void
6254 %fnptr = OpTypeFunction %void %ptr
6255 %main = OpFunction %void None %voidfn
6256 %entry = OpLabel
6257 OpReturn
6258 OpFunctionEnd
6259 %fn = OpFunction %void None %fnptr
6260 %fparam = OpFunctionParameter %ptr
6261 %lab = OpLabel
6262 OpReturn
6263 OpFunctionEnd
6264 )";
6265
6266 CompileSuccessfully(body.c_str());
6267 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6268 }
6269
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamMissing)6270 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) {
6271 const std::string body = R"(
6272 OpCapability PhysicalStorageBufferAddresses
6273 OpCapability Int64
6274 OpCapability Shader
6275 OpExtension "SPV_EXT_physical_storage_buffer"
6276 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6277 OpEntryPoint Fragment %main "main"
6278 OpExecutionMode %main OriginUpperLeft
6279 %uint64 = OpTypeInt 64 0
6280 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6281 %void = OpTypeVoid
6282 %voidfn = OpTypeFunction %void
6283 %fnptr = OpTypeFunction %void %ptr
6284 %main = OpFunction %void None %voidfn
6285 %entry = OpLabel
6286 OpReturn
6287 OpFunctionEnd
6288 %fn = OpFunction %void None %fnptr
6289 %fparam = OpFunctionParameter %ptr
6290 %lab = OpLabel
6291 OpReturn
6292 OpFunctionEnd
6293 )";
6294
6295 CompileSuccessfully(body.c_str());
6296 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6297 EXPECT_THAT(getDiagnosticString(),
6298 HasSubstr("expected Aliased or Restrict for "
6299 "PhysicalStorageBuffer pointer"));
6300 }
6301
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamBoth)6302 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
6303 const std::string body = R"(
6304 OpCapability PhysicalStorageBufferAddresses
6305 OpCapability Int64
6306 OpCapability Shader
6307 OpExtension "SPV_EXT_physical_storage_buffer"
6308 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6309 OpEntryPoint Fragment %main "main"
6310 OpExecutionMode %main OriginUpperLeft
6311 OpDecorate %fparam Restrict
6312 OpDecorate %fparam Aliased
6313 %uint64 = OpTypeInt 64 0
6314 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6315 %void = OpTypeVoid
6316 %voidfn = OpTypeFunction %void
6317 %fnptr = OpTypeFunction %void %ptr
6318 %main = OpFunction %void None %voidfn
6319 %entry = OpLabel
6320 OpReturn
6321 OpFunctionEnd
6322 %fn = OpFunction %void None %fnptr
6323 %fparam = OpFunctionParameter %ptr
6324 %lab = OpLabel
6325 OpReturn
6326 OpFunctionEnd
6327 )";
6328
6329 CompileSuccessfully(body.c_str());
6330 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6331 EXPECT_THAT(getDiagnosticString(),
6332 HasSubstr("can't specify both Aliased and Restrict for "
6333 "PhysicalStorageBuffer pointer"));
6334 }
6335
TEST_F(ValidateDecorations,PSBFPRoundingModeSuccess)6336 TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) {
6337 std::string spirv = R"(
6338 OpCapability PhysicalStorageBufferAddresses
6339 OpCapability Shader
6340 OpCapability Linkage
6341 OpCapability StorageBuffer16BitAccess
6342 OpExtension "SPV_EXT_physical_storage_buffer"
6343 OpExtension "SPV_KHR_storage_buffer_storage_class"
6344 OpExtension "SPV_KHR_variable_pointers"
6345 OpExtension "SPV_KHR_16bit_storage"
6346 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6347 OpEntryPoint GLCompute %main "main"
6348 OpDecorate %_ FPRoundingMode RTE
6349 OpDecorate %half_ptr_var AliasedPointer
6350 %half = OpTypeFloat 16
6351 %float = OpTypeFloat 32
6352 %float_1_25 = OpConstant %float 1.25
6353 %half_ptr = OpTypePointer PhysicalStorageBuffer %half
6354 %half_pptr_f = OpTypePointer Function %half_ptr
6355 %void = OpTypeVoid
6356 %func = OpTypeFunction %void
6357 %main = OpFunction %void None %func
6358 %main_entry = OpLabel
6359 %half_ptr_var = OpVariable %half_pptr_f Function
6360 %val1 = OpLoad %half_ptr %half_ptr_var
6361 %_ = OpFConvert %half %float_1_25
6362 OpStore %val1 %_ Aligned 2
6363 OpReturn
6364 OpFunctionEnd
6365 )";
6366
6367 CompileSuccessfully(spirv);
6368 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6369 }
6370
TEST_F(ValidateDecorations,InvalidStraddle)6371 TEST_F(ValidateDecorations, InvalidStraddle) {
6372 const std::string spirv = R"(
6373 OpCapability Shader
6374 OpMemoryModel Logical GLSL450
6375 OpEntryPoint GLCompute %main "main"
6376 OpExecutionMode %main LocalSize 1 1 1
6377 OpMemberDecorate %inner_struct 0 Offset 0
6378 OpMemberDecorate %inner_struct 1 Offset 4
6379 OpDecorate %outer_struct Block
6380 OpMemberDecorate %outer_struct 0 Offset 0
6381 OpMemberDecorate %outer_struct 1 Offset 8
6382 OpDecorate %var DescriptorSet 0
6383 OpDecorate %var Binding 0
6384 %void = OpTypeVoid
6385 %float = OpTypeFloat 32
6386 %float2 = OpTypeVector %float 2
6387 %inner_struct = OpTypeStruct %float %float2
6388 %outer_struct = OpTypeStruct %float2 %inner_struct
6389 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct
6390 %var = OpVariable %ptr_ssbo_outer StorageBuffer
6391 %void_fn = OpTypeFunction %void
6392 %main = OpFunction %void None %void_fn
6393 %entry = OpLabel
6394 OpReturn
6395 OpFunctionEnd
6396 )";
6397
6398 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6399 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6400 EXPECT_THAT(getDiagnosticString(),
6401 HasSubstr("Structure id 2 decorated as Block for variable in "
6402 "StorageBuffer storage class must follow relaxed "
6403 "storage buffer layout rules: member 1 is an "
6404 "improperly straddling vector at offset 12"));
6405 }
6406
TEST_F(ValidateDecorations,DescriptorArray)6407 TEST_F(ValidateDecorations, DescriptorArray) {
6408 const std::string spirv = R"(
6409 OpCapability Shader
6410 OpExtension "SPV_KHR_storage_buffer_storage_class"
6411 OpMemoryModel Logical GLSL450
6412 OpEntryPoint GLCompute %main "main"
6413 OpExecutionMode %main LocalSize 1 1 1
6414 OpDecorate %struct Block
6415 OpMemberDecorate %struct 0 Offset 0
6416 OpMemberDecorate %struct 1 Offset 1
6417 OpDecorate %var DescriptorSet 0
6418 OpDecorate %var Binding 0
6419 %void = OpTypeVoid
6420 %float = OpTypeFloat 32
6421 %int = OpTypeInt 32 0
6422 %int_2 = OpConstant %int 2
6423 %float2 = OpTypeVector %float 2
6424 %struct = OpTypeStruct %float %float2
6425 %struct_array = OpTypeArray %struct %int_2
6426 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6427 %var = OpVariable %ptr_ssbo_array StorageBuffer
6428 %void_fn = OpTypeFunction %void
6429 %main = OpFunction %void None %void_fn
6430 %entry = OpLabel
6431 OpReturn
6432 OpFunctionEnd
6433 )";
6434
6435 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6436 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6437 EXPECT_THAT(getDiagnosticString(),
6438 HasSubstr("Structure id 2 decorated as Block for variable in "
6439 "StorageBuffer storage class must follow standard "
6440 "storage buffer layout rules: member 1 at offset 1 is "
6441 "not aligned to 8"));
6442 }
6443
TEST_F(ValidateDecorations,DescriptorRuntimeArray)6444 TEST_F(ValidateDecorations, DescriptorRuntimeArray) {
6445 const std::string spirv = R"(
6446 OpCapability Shader
6447 OpCapability RuntimeDescriptorArrayEXT
6448 OpExtension "SPV_KHR_storage_buffer_storage_class"
6449 OpExtension "SPV_EXT_descriptor_indexing"
6450 OpMemoryModel Logical GLSL450
6451 OpEntryPoint GLCompute %main "main"
6452 OpExecutionMode %main LocalSize 1 1 1
6453 OpDecorate %struct Block
6454 OpMemberDecorate %struct 0 Offset 0
6455 OpMemberDecorate %struct 1 Offset 1
6456 OpDecorate %var DescriptorSet 0
6457 OpDecorate %var Binding 0
6458 %void = OpTypeVoid
6459 %float = OpTypeFloat 32
6460 %int = OpTypeInt 32 0
6461 %float2 = OpTypeVector %float 2
6462 %struct = OpTypeStruct %float %float2
6463 %struct_array = OpTypeRuntimeArray %struct
6464 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6465 %var = OpVariable %ptr_ssbo_array StorageBuffer
6466 %void_fn = OpTypeFunction %void
6467 %main = OpFunction %void None %void_fn
6468 %entry = OpLabel
6469 OpReturn
6470 OpFunctionEnd
6471 )";
6472
6473 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6474 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6475 EXPECT_THAT(getDiagnosticString(),
6476 HasSubstr("Structure id 2 decorated as Block for variable in "
6477 "StorageBuffer storage class must follow standard "
6478 "storage buffer layout rules: member 1 at offset 1 is "
6479 "not aligned to 8"));
6480 }
6481
TEST_F(ValidateDecorations,MultiDimensionalArray)6482 TEST_F(ValidateDecorations, MultiDimensionalArray) {
6483 const std::string spirv = R"(
6484 OpCapability Shader
6485 OpMemoryModel Logical GLSL450
6486 OpEntryPoint GLCompute %main "main"
6487 OpExecutionMode %main LocalSize 1 1 1
6488 OpDecorate %struct Block
6489 OpMemberDecorate %struct 0 Offset 0
6490 OpDecorate %array_4 ArrayStride 4
6491 OpDecorate %array_3 ArrayStride 48
6492 OpDecorate %var DescriptorSet 0
6493 OpDecorate %var Binding 0
6494 %void = OpTypeVoid
6495 %int = OpTypeInt 32 0
6496 %int_3 = OpConstant %int 3
6497 %int_4 = OpConstant %int 4
6498 %array_4 = OpTypeArray %int %int_4
6499 %array_3 = OpTypeArray %array_4 %int_3
6500 %struct = OpTypeStruct %array_3
6501 %ptr_struct = OpTypePointer Uniform %struct
6502 %var = OpVariable %ptr_struct Uniform
6503 %void_fn = OpTypeFunction %void
6504 %main = OpFunction %void None %void_fn
6505 %entry = OpLabel
6506 OpReturn
6507 OpFunctionEnd
6508 )";
6509
6510 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6511 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6512 EXPECT_THAT(getDiagnosticString(),
6513 HasSubstr("Structure id 2 decorated as Block for variable in "
6514 "Uniform storage class must follow standard uniform "
6515 "buffer layout rules: member 0 contains an array with "
6516 "stride 4 not satisfying alignment to 16"));
6517 }
6518
TEST_F(ValidateDecorations,ImproperStraddleInArray)6519 TEST_F(ValidateDecorations, ImproperStraddleInArray) {
6520 const std::string spirv = R"(
6521 OpCapability Shader
6522 OpMemoryModel Logical GLSL450
6523 OpEntryPoint GLCompute %main "main"
6524 OpExecutionMode %main LocalSize 1 1 1
6525 OpDecorate %struct Block
6526 OpMemberDecorate %struct 0 Offset 0
6527 OpDecorate %array ArrayStride 24
6528 OpMemberDecorate %inner 0 Offset 0
6529 OpMemberDecorate %inner 1 Offset 4
6530 OpMemberDecorate %inner 2 Offset 12
6531 OpMemberDecorate %inner 3 Offset 16
6532 OpDecorate %var DescriptorSet 0
6533 OpDecorate %var Binding 0
6534 %void = OpTypeVoid
6535 %int = OpTypeInt 32 0
6536 %int_2 = OpConstant %int 2
6537 %int2 = OpTypeVector %int 2
6538 %inner = OpTypeStruct %int %int2 %int %int
6539 %array = OpTypeArray %inner %int_2
6540 %struct = OpTypeStruct %array
6541 %ptr_struct = OpTypePointer StorageBuffer %struct
6542 %var = OpVariable %ptr_struct StorageBuffer
6543 %void_fn = OpTypeFunction %void
6544 %main = OpFunction %void None %void_fn
6545 %entry = OpLabel
6546 OpReturn
6547 OpFunctionEnd
6548 )";
6549
6550 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6551 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6552 EXPECT_THAT(getDiagnosticString(),
6553 HasSubstr("Structure id 4 decorated as Block for variable in "
6554 "StorageBuffer storage class must follow relaxed "
6555 "storage buffer layout rules: member 1 is an "
6556 "improperly straddling vector at offset 28"));
6557 }
6558
TEST_F(ValidateDecorations,LargeArray)6559 TEST_F(ValidateDecorations, LargeArray) {
6560 const std::string spirv = R"(
6561 OpCapability Shader
6562 OpMemoryModel Logical GLSL450
6563 OpEntryPoint GLCompute %main "main"
6564 OpExecutionMode %main LocalSize 1 1 1
6565 OpDecorate %struct Block
6566 OpMemberDecorate %struct 0 Offset 0
6567 OpDecorate %array ArrayStride 24
6568 OpMemberDecorate %inner 0 Offset 0
6569 OpMemberDecorate %inner 1 Offset 8
6570 OpMemberDecorate %inner 2 Offset 16
6571 OpMemberDecorate %inner 3 Offset 20
6572 OpDecorate %var DescriptorSet 0
6573 OpDecorate %var Binding 0
6574 %void = OpTypeVoid
6575 %int = OpTypeInt 32 0
6576 %int_2000000 = OpConstant %int 2000000
6577 %int2 = OpTypeVector %int 2
6578 %inner = OpTypeStruct %int %int2 %int %int
6579 %array = OpTypeArray %inner %int_2000000
6580 %struct = OpTypeStruct %array
6581 %ptr_struct = OpTypePointer StorageBuffer %struct
6582 %var = OpVariable %ptr_struct StorageBuffer
6583 %void_fn = OpTypeFunction %void
6584 %main = OpFunction %void None %void_fn
6585 %entry = OpLabel
6586 OpReturn
6587 OpFunctionEnd
6588 )";
6589
6590 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6591 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6592 }
6593
6594 // NonWritable
6595
6596 // Returns a SPIR-V shader module with variables in various storage classes,
6597 // parameterizable by which ID should be decorated as NonWritable.
ShaderWithNonWritableTarget(const std::string & target,bool member_decorate=false)6598 std::string ShaderWithNonWritableTarget(const std::string& target,
6599 bool member_decorate = false) {
6600 const std::string decoration_inst =
6601 std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") +
6602 target + (member_decorate ? " 0" : "");
6603
6604 return std::string(R"(
6605 OpCapability Shader
6606 OpCapability RuntimeDescriptorArrayEXT
6607 OpExtension "SPV_EXT_descriptor_indexing"
6608 OpExtension "SPV_KHR_storage_buffer_storage_class"
6609 OpMemoryModel Logical GLSL450
6610 OpEntryPoint Vertex %main "main"
6611 OpName %label "label"
6612 OpName %param_f "param_f"
6613 OpName %param_p "param_p"
6614 OpName %_ptr_imstor "_ptr_imstor"
6615 OpName %_ptr_imsam "_ptr_imsam"
6616 OpName %var_wg "var_wg"
6617 OpName %var_imsam "var_imsam"
6618 OpName %var_priv "var_priv"
6619 OpName %var_func "var_func"
6620 OpName %simple_struct "simple_struct"
6621
6622 OpDecorate %struct_b Block
6623 OpDecorate %struct_b_rtarr Block
6624 OpMemberDecorate %struct_b 0 Offset 0
6625 OpMemberDecorate %struct_b_rtarr 0 Offset 0
6626 OpDecorate %rtarr ArrayStride 4
6627 )") + decoration_inst +
6628
6629 R"( NonWritable
6630
6631 %void = OpTypeVoid
6632 %void_fn = OpTypeFunction %void
6633 %float = OpTypeFloat 32
6634 %float_0 = OpConstant %float 0
6635 %int = OpTypeInt 32 0
6636 %int_2 = OpConstant %int 2
6637 %struct_b = OpTypeStruct %float
6638 %rtarr = OpTypeRuntimeArray %float
6639 %struct_b_rtarr = OpTypeStruct %rtarr
6640 %simple_struct = OpTypeStruct %float
6641 ; storage image
6642 %imstor = OpTypeImage %float 2D 0 0 0 2 R32f
6643 ; sampled image
6644 %imsam = OpTypeImage %float 2D 0 0 0 1 R32f
6645 %array_imstor = OpTypeArray %imstor %int_2
6646 %rta_imstor = OpTypeRuntimeArray %imstor
6647
6648 %_ptr_Uniform_stb = OpTypePointer Uniform %struct_b
6649 %_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b
6650 %_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr
6651 %_ptr_Workgroup = OpTypePointer Workgroup %float
6652 %_ptr_Private = OpTypePointer Private %float
6653 %_ptr_Function = OpTypePointer Function %float
6654 %_ptr_imstor = OpTypePointer UniformConstant %imstor
6655 %_ptr_imsam = OpTypePointer UniformConstant %imsam
6656 %_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor
6657 %_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor
6658
6659 %extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor
6660
6661 %var_ubo = OpVariable %_ptr_Uniform_stb Uniform
6662 %var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer
6663 %var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer
6664 %var_wg = OpVariable %_ptr_Workgroup Workgroup
6665 %var_priv = OpVariable %_ptr_Private Private
6666 %var_imstor = OpVariable %_ptr_imstor UniformConstant
6667 %var_imsam = OpVariable %_ptr_imsam UniformConstant
6668 %var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant
6669 %var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant
6670
6671 %helper = OpFunction %void None %extra_fn
6672 %param_f = OpFunctionParameter %float
6673 %param_p = OpFunctionParameter %_ptr_Private
6674 %param_pimstor = OpFunctionParameter %_ptr_imstor
6675 %helper_label = OpLabel
6676 %helper_func_var = OpVariable %_ptr_Function Function
6677 OpReturn
6678 OpFunctionEnd
6679
6680 %main = OpFunction %void None %void_fn
6681 %label = OpLabel
6682 %var_func = OpVariable %_ptr_Function Function
6683 OpReturn
6684 OpFunctionEnd
6685 )";
6686 }
6687
TEST_F(ValidateDecorations,NonWritableLabelTargetBad)6688 TEST_F(ValidateDecorations, NonWritableLabelTargetBad) {
6689 std::string spirv = ShaderWithNonWritableTarget("%label");
6690
6691 CompileSuccessfully(spirv);
6692 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6693 EXPECT_THAT(getDiagnosticString(),
6694 HasSubstr("must be a memory object declaration"));
6695 }
6696
TEST_F(ValidateDecorations,NonWritableTypeTargetBad)6697 TEST_F(ValidateDecorations, NonWritableTypeTargetBad) {
6698 std::string spirv = ShaderWithNonWritableTarget("%void");
6699
6700 CompileSuccessfully(spirv);
6701 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6702 EXPECT_THAT(getDiagnosticString(),
6703 HasSubstr("must be a memory object declaration"));
6704 }
6705
TEST_F(ValidateDecorations,NonWritableValueTargetBad)6706 TEST_F(ValidateDecorations, NonWritableValueTargetBad) {
6707 std::string spirv = ShaderWithNonWritableTarget("%float_0");
6708
6709 CompileSuccessfully(spirv);
6710 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6711 EXPECT_THAT(getDiagnosticString(),
6712 HasSubstr("must be a memory object declaration"));
6713 }
6714
TEST_F(ValidateDecorations,NonWritableValueParamBad)6715 TEST_F(ValidateDecorations, NonWritableValueParamBad) {
6716 std::string spirv = ShaderWithNonWritableTarget("%param_f");
6717
6718 CompileSuccessfully(spirv);
6719 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6720 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
6721 }
6722
TEST_F(ValidateDecorations,NonWritablePointerParamButWrongTypeBad)6723 TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) {
6724 std::string spirv = ShaderWithNonWritableTarget("%param_p");
6725
6726 CompileSuccessfully(spirv);
6727 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6728 EXPECT_THAT(
6729 getDiagnosticString(),
6730 HasSubstr(
6731 "Target of NonWritable decoration is invalid: must "
6732 "point to a storage image, uniform block, or storage "
6733 "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float"));
6734 }
6735
TEST_F(ValidateDecorations,NonWritablePointerParamStorageImageGood)6736 TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) {
6737 std::string spirv = ShaderWithNonWritableTarget("%param_pimstor");
6738
6739 CompileSuccessfully(spirv);
6740 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6741 EXPECT_THAT(getDiagnosticString(), Eq(""));
6742 }
6743
TEST_F(ValidateDecorations,NonWritableVarStorageImageGood)6744 TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) {
6745 std::string spirv = ShaderWithNonWritableTarget("%var_imstor");
6746
6747 CompileSuccessfully(spirv);
6748 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6749 EXPECT_THAT(getDiagnosticString(), Eq(""));
6750 }
6751
TEST_F(ValidateDecorations,NonWritableVarSampledImageBad)6752 TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) {
6753 std::string spirv = ShaderWithNonWritableTarget("%var_imsam");
6754
6755 CompileSuccessfully(spirv);
6756 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6757 EXPECT_THAT(getDiagnosticString(),
6758 HasSubstr("Target of NonWritable decoration is invalid: must "
6759 "point to a storage image, uniform block, or storage "
6760 "buffer\n %var_imsam"));
6761 }
6762
TEST_F(ValidateDecorations,NonWritableVarUboGood)6763 TEST_F(ValidateDecorations, NonWritableVarUboGood) {
6764 std::string spirv = ShaderWithNonWritableTarget("%var_ubo");
6765
6766 CompileSuccessfully(spirv);
6767 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6768 EXPECT_THAT(getDiagnosticString(), Eq(""));
6769 }
6770
TEST_F(ValidateDecorations,NonWritableVarSsboInUniformGood)6771 TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) {
6772 const std::string spirv = R"(
6773 OpCapability Shader
6774 OpMemoryModel Logical GLSL450
6775 OpEntryPoint Vertex %main "main"
6776 OpDecorate %struct_bb BufferBlock
6777 OpMemberDecorate %struct_bb 0 Offset 0
6778 OpDecorate %var_ssbo_u NonWritable
6779 %void = OpTypeVoid
6780 %void_fn = OpTypeFunction %void
6781 %float = OpTypeFloat 32
6782 %struct_bb = OpTypeStruct %float
6783 %_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb
6784 %var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform
6785 %main = OpFunction %void None %void_fn
6786 %label = OpLabel
6787 OpReturn
6788 OpFunctionEnd
6789 )";
6790
6791 CompileSuccessfully(spirv);
6792 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6793 EXPECT_THAT(getDiagnosticString(), Eq(""));
6794 }
6795
TEST_F(ValidateDecorations,NonWritableVarSsboInStorageBufferGood)6796 TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) {
6797 std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb");
6798
6799 CompileSuccessfully(spirv);
6800 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6801 EXPECT_THAT(getDiagnosticString(), Eq(""));
6802 }
6803
TEST_F(ValidateDecorations,NonWritableMemberOfSsboInStorageBufferGood)6804 TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) {
6805 std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true);
6806
6807 CompileSuccessfully(spirv);
6808 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6809 EXPECT_THAT(getDiagnosticString(), Eq(""));
6810 }
6811
TEST_F(ValidateDecorations,NonWritableMemberOfStructGood)6812 TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) {
6813 std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true);
6814
6815 CompileSuccessfully(spirv);
6816 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6817 }
6818
TEST_F(ValidateDecorations,NonWritableVarWorkgroupBad)6819 TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) {
6820 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6821
6822 CompileSuccessfully(spirv);
6823 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6824 EXPECT_THAT(getDiagnosticString(),
6825 HasSubstr("Target of NonWritable decoration is invalid: must "
6826 "point to a storage image, uniform block, or storage "
6827 "buffer\n %var_wg"));
6828 }
6829
TEST_F(ValidateDecorations,NonWritableVarWorkgroupV14Bad)6830 TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) {
6831 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6832
6833 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6834 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6835 EXPECT_THAT(getDiagnosticString(),
6836 HasSubstr("Target of NonWritable decoration is invalid: must "
6837 "point to a storage image, uniform block, storage "
6838 "buffer, or variable in Private or Function storage "
6839 "class\n %var_wg"));
6840 }
6841
TEST_F(ValidateDecorations,NonWritableVarPrivateBad)6842 TEST_F(ValidateDecorations, NonWritableVarPrivateBad) {
6843 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6844
6845 CompileSuccessfully(spirv);
6846 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6847 EXPECT_THAT(getDiagnosticString(),
6848 HasSubstr("Target of NonWritable decoration is invalid: must "
6849 "point to a storage image, uniform block, or storage "
6850 "buffer\n %var_priv"));
6851 }
6852
TEST_F(ValidateDecorations,NonWritableVarPrivateV13Bad)6853 TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) {
6854 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6855
6856 CompileSuccessfully(spirv);
6857 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6858 EXPECT_THAT(getDiagnosticString(),
6859 HasSubstr("Target of NonWritable decoration is invalid: must "
6860 "point to a storage image, uniform block, or storage "
6861 "buffer\n %var_priv"));
6862 }
6863
TEST_F(ValidateDecorations,NonWritableVarPrivateV14Good)6864 TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) {
6865 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6866
6867 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6868 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6869 EXPECT_THAT(getDiagnosticString(), Eq(""));
6870 }
6871
TEST_F(ValidateDecorations,NonWritableVarPrivateV13TargetV14Bad)6872 TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) {
6873 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6874
6875 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6876 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6877 EXPECT_THAT(getDiagnosticString(),
6878 HasSubstr("Target of NonWritable decoration is invalid: must "
6879 "point to a storage image, uniform block, or storage "
6880 "buffer\n %var_priv"));
6881 }
6882
TEST_F(ValidateDecorations,NonWritableVarFunctionBad)6883 TEST_F(ValidateDecorations, NonWritableVarFunctionBad) {
6884 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6885
6886 CompileSuccessfully(spirv);
6887 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6888 EXPECT_THAT(getDiagnosticString(),
6889 HasSubstr("Target of NonWritable decoration is invalid: must "
6890 "point to a storage image, uniform block, or storage "
6891 "buffer\n %var_func"));
6892 }
6893
TEST_F(ValidateDecorations,NonWritableArrayGood)6894 TEST_F(ValidateDecorations, NonWritableArrayGood) {
6895 std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor");
6896
6897 CompileSuccessfully(spirv);
6898 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6899 }
6900
TEST_F(ValidateDecorations,NonWritableRuntimeArrayGood)6901 TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) {
6902 std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor");
6903
6904 CompileSuccessfully(spirv);
6905 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6906 }
6907
TEST_P(ValidateVulkanCombineDecorationResult,Decorate)6908 TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
6909 const char* const decoration = std::get<0>(GetParam());
6910 const char* const vuid = std::get<1>(GetParam());
6911 const TestResult& test_result = std::get<2>(GetParam());
6912
6913 CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
6914 generator.before_types_ = "OpDecorate %u32 ";
6915 generator.before_types_ += decoration;
6916 generator.before_types_ += "\n";
6917
6918 EntryPoint entry_point;
6919 entry_point.name = "main";
6920 entry_point.execution_model = "Vertex";
6921 generator.entry_points_.push_back(std::move(entry_point));
6922
6923 CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
6924 ASSERT_EQ(test_result.validation_result,
6925 ValidateInstructions(SPV_ENV_VULKAN_1_0));
6926 if (!test_result.error_str.empty()) {
6927 EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
6928 }
6929 if (vuid) {
6930 EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
6931 }
6932 }
6933
6934 INSTANTIATE_TEST_SUITE_P(
6935 DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
6936 Combine(Values("GLSLShared", "GLSLPacked"),
6937 Values("VUID-StandaloneSpirv-GLSLShared-04669"),
6938 Values(TestResult(
6939 SPV_ERROR_INVALID_ID,
6940 "is not valid for the Vulkan execution environment."))));
6941
TEST_F(ValidateDecorations,NonWritableVarFunctionV13Bad)6942 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
6943 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6944
6945 CompileSuccessfully(spirv);
6946 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6947 EXPECT_THAT(getDiagnosticString(),
6948 HasSubstr("Target of NonWritable decoration is invalid: must "
6949 "point to a storage image, uniform block, or storage "
6950 "buffer\n %var_func"));
6951 }
6952
TEST_F(ValidateDecorations,NonWritableVarFunctionV14Good)6953 TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) {
6954 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6955
6956 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6957 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6958 EXPECT_THAT(getDiagnosticString(), Eq(""));
6959 }
6960
TEST_F(ValidateDecorations,NonWritableVarFunctionV13TargetV14Bad)6961 TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) {
6962 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6963
6964 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6965 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6966 EXPECT_THAT(getDiagnosticString(),
6967 HasSubstr("Target of NonWritable decoration is invalid: must "
6968 "point to a storage image, uniform block, or storage "
6969 "buffer\n %var_func"));
6970 }
6971
TEST_F(ValidateDecorations,BufferBlockV13ValV14Good)6972 TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) {
6973 std::string spirv = R"(
6974 OpCapability Shader
6975 OpCapability Linkage
6976 OpMemoryModel Logical GLSL450
6977 OpDecorate %1 BufferBlock
6978 %1 = OpTypeStruct
6979 )";
6980
6981 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6982 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6983 }
6984
TEST_F(ValidateDecorations,BufferBlockV14Bad)6985 TEST_F(ValidateDecorations, BufferBlockV14Bad) {
6986 std::string spirv = R"(
6987 OpCapability Shader
6988 OpCapability Linkage
6989 OpMemoryModel Logical GLSL450
6990 OpDecorate %1 BufferBlock
6991 %1 = OpTypeStruct
6992 )";
6993
6994 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6995 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
6996 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6997 EXPECT_THAT(getDiagnosticString(),
6998 HasSubstr("2nd operand of Decorate: operand BufferBlock(3) "
6999 "requires SPIR-V version 1.3 or earlier"));
7000 }
7001
7002 // Component
7003
TEST_F(ValidateDecorations,ComponentDecorationBadTarget)7004 TEST_F(ValidateDecorations, ComponentDecorationBadTarget) {
7005 std::string spirv = R"(
7006 OpCapability Shader
7007 OpMemoryModel Logical GLSL450
7008 OpEntryPoint Vertex %main "main"
7009 OpDecorate %t Component 0
7010 %void = OpTypeVoid
7011 %3 = OpTypeFunction %void
7012 %float = OpTypeFloat 32
7013 %t = OpTypeVector %float 2
7014 %main = OpFunction %void None %3
7015 %5 = OpLabel
7016 OpReturn
7017 OpFunctionEnd
7018 )";
7019
7020 CompileSuccessfully(spirv);
7021 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7022 EXPECT_THAT(getDiagnosticString(),
7023 HasSubstr("must be a memory object declaration"));
7024 }
7025
TEST_F(ValidateDecorations,ComponentDecorationBadStorageClass)7026 TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) {
7027 std::string spirv = R"(
7028 OpCapability Shader
7029 OpMemoryModel Logical GLSL450
7030 OpEntryPoint Vertex %main "main"
7031 OpDecorate %v Component 0
7032 %void = OpTypeVoid
7033 %3 = OpTypeFunction %void
7034 %float = OpTypeFloat 32
7035 %t = OpTypeVector %float 2
7036 %ptr_private = OpTypePointer Private %t
7037 %v = OpVariable %ptr_private Private
7038 %main = OpFunction %void None %3
7039 %5 = OpLabel
7040 OpReturn
7041 OpFunctionEnd
7042 )";
7043
7044 CompileSuccessfully(spirv);
7045 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7046 EXPECT_THAT(getDiagnosticString(),
7047 HasSubstr("Target of Component decoration is invalid: must "
7048 "point to a Storage Class of Input(1) or Output(3)"));
7049 }
7050
TEST_F(ValidateDecorations,ComponentDecorationBadTypeVulkan)7051 TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) {
7052 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7053 std::string spirv = R"(
7054 OpCapability Shader
7055 OpCapability Matrix
7056 OpMemoryModel Logical GLSL450
7057 OpEntryPoint Vertex %main "main"
7058 OpDecorate %v Component 0
7059 %void = OpTypeVoid
7060 %3 = OpTypeFunction %void
7061 %float = OpTypeFloat 32
7062 %vtype = OpTypeVector %float 4
7063 %t = OpTypeMatrix %vtype 4
7064 %ptr_input = OpTypePointer Input %t
7065 %v = OpVariable %ptr_input Input
7066 %main = OpFunction %void None %3
7067 %5 = OpLabel
7068 OpReturn
7069 OpFunctionEnd
7070 )";
7071
7072 CompileSuccessfully(spirv, env);
7073 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7074 EXPECT_THAT(getDiagnosticString(),
7075 AnyVUID("VUID-StandaloneSpirv-Component-04924"));
7076 EXPECT_THAT(getDiagnosticString(),
7077 HasSubstr("Component decoration specified for type"));
7078 EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
7079 }
7080
ShaderWithComponentDecoration(const std::string & type,const std::string & decoration)7081 std::string ShaderWithComponentDecoration(const std::string& type,
7082 const std::string& decoration) {
7083 return R"(
7084 OpCapability Shader
7085 OpCapability Int64
7086 OpMemoryModel Logical GLSL450
7087 OpEntryPoint Fragment %main "main" %entryPointOutput
7088 OpExecutionMode %main OriginUpperLeft
7089 OpDecorate %entryPointOutput Location 0
7090 OpDecorate %entryPointOutput )" +
7091 decoration + R"(
7092 %void = OpTypeVoid
7093 %3 = OpTypeFunction %void
7094 %float = OpTypeFloat 32
7095 %v3float = OpTypeVector %float 3
7096 %v4float = OpTypeVector %float 4
7097 %uint = OpTypeInt 32 0
7098 %uint64 = OpTypeInt 64 0
7099 %v2uint64 = OpTypeVector %uint64 2
7100 %v3uint64 = OpTypeVector %uint64 3
7101 %uint_2 = OpConstant %uint 2
7102 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
7103 %float_0 = OpConstant %float 0
7104 %_ptr_Output_type = OpTypePointer Output %)" + type + R"(
7105 %entryPointOutput = OpVariable %_ptr_Output_type Output
7106 %main = OpFunction %void None %3
7107 %5 = OpLabel
7108 OpReturn
7109 OpFunctionEnd
7110 )";
7111 }
7112
TEST_F(ValidateDecorations,ComponentDecorationIntGood0Vulkan)7113 TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
7114 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7115 std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
7116
7117 CompileSuccessfully(spirv, env);
7118 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7119 EXPECT_THAT(getDiagnosticString(), Eq(""));
7120 }
7121
TEST_F(ValidateDecorations,ComponentDecorationIntGood1Vulkan)7122 TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
7123 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7124 std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
7125
7126 CompileSuccessfully(spirv, env);
7127 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7128 EXPECT_THAT(getDiagnosticString(), Eq(""));
7129 }
7130
TEST_F(ValidateDecorations,ComponentDecorationIntGood2Vulkan)7131 TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
7132 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7133 std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
7134
7135 CompileSuccessfully(spirv, env);
7136 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7137 EXPECT_THAT(getDiagnosticString(), Eq(""));
7138 }
7139
TEST_F(ValidateDecorations,ComponentDecorationIntGood3Vulkan)7140 TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
7141 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7142 std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
7143
7144 CompileSuccessfully(spirv, env);
7145 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7146 EXPECT_THAT(getDiagnosticString(), Eq(""));
7147 }
7148
TEST_F(ValidateDecorations,ComponentDecorationIntBad4Vulkan)7149 TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
7150 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7151 std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
7152
7153 CompileSuccessfully(spirv, env);
7154 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7155 EXPECT_THAT(getDiagnosticString(),
7156 AnyVUID("VUID-StandaloneSpirv-Component-04920"));
7157 EXPECT_THAT(
7158 getDiagnosticString(),
7159 HasSubstr("Component decoration value must not be greater than 3"));
7160 }
7161
TEST_F(ValidateDecorations,ComponentDecorationVector3GoodVulkan)7162 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
7163 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7164 std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
7165
7166 CompileSuccessfully(spirv, env);
7167 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7168 EXPECT_THAT(getDiagnosticString(), Eq(""));
7169 }
7170
TEST_F(ValidateDecorations,ComponentDecorationVector4GoodVulkan)7171 TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
7172 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7173 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
7174
7175 CompileSuccessfully(spirv, env);
7176 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7177 EXPECT_THAT(getDiagnosticString(), Eq(""));
7178 }
7179
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad1Vulkan)7180 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
7181 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7182 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
7183
7184 CompileSuccessfully(spirv, env);
7185 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7186 EXPECT_THAT(getDiagnosticString(),
7187 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7188 EXPECT_THAT(getDiagnosticString(),
7189 HasSubstr("Sequence of components starting with 1 "
7190 "and ending with 4 gets larger than 3"));
7191 }
7192
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad3Vulkan)7193 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
7194 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7195 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
7196
7197 CompileSuccessfully(spirv, env);
7198 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7199 EXPECT_THAT(getDiagnosticString(),
7200 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7201 EXPECT_THAT(getDiagnosticString(),
7202 HasSubstr("Sequence of components starting with 3 "
7203 "and ending with 6 gets larger than 3"));
7204 }
7205
TEST_F(ValidateDecorations,ComponentDecorationArrayGoodVulkan)7206 TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
7207 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7208 std::string spirv =
7209 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
7210
7211 CompileSuccessfully(spirv, env);
7212 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7213 EXPECT_THAT(getDiagnosticString(), Eq(""));
7214 }
7215
TEST_F(ValidateDecorations,ComponentDecorationArrayBadVulkan)7216 TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
7217 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7218 std::string spirv =
7219 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
7220
7221 CompileSuccessfully(spirv, env);
7222 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7223 EXPECT_THAT(getDiagnosticString(),
7224 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7225 EXPECT_THAT(getDiagnosticString(),
7226 HasSubstr("Sequence of components starting with 2 "
7227 "and ending with 4 gets larger than 3"));
7228 }
7229
TEST_F(ValidateDecorations,ComponentDecoration64ScalarGoodVulkan)7230 TEST_F(ValidateDecorations, ComponentDecoration64ScalarGoodVulkan) {
7231 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7232 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 0");
7233
7234 CompileSuccessfully(spirv, env);
7235 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7236 }
7237
TEST_F(ValidateDecorations,ComponentDecoration64Scalar1BadVulkan)7238 TEST_F(ValidateDecorations, ComponentDecoration64Scalar1BadVulkan) {
7239 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7240 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 1");
7241
7242 CompileSuccessfully(spirv, env);
7243 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7244 EXPECT_THAT(getDiagnosticString(),
7245 AnyVUID("VUID-StandaloneSpirv-Component-04923"));
7246 EXPECT_THAT(getDiagnosticString(),
7247 HasSubstr("Component decoration value must not be 1 or 3 for "
7248 "64-bit data types"));
7249 }
7250
TEST_F(ValidateDecorations,ComponentDecoration64Scalar2GoodVulkan)7251 TEST_F(ValidateDecorations, ComponentDecoration64Scalar2GoodVulkan) {
7252 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7253 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 2");
7254
7255 CompileSuccessfully(spirv, env);
7256 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7257 }
7258
TEST_F(ValidateDecorations,ComponentDecoration64Scalar3BadVulkan)7259 TEST_F(ValidateDecorations, ComponentDecoration64Scalar3BadVulkan) {
7260 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7261 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 3");
7262
7263 CompileSuccessfully(spirv, env);
7264 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7265 EXPECT_THAT(getDiagnosticString(),
7266 AnyVUID("VUID-StandaloneSpirv-Component-04923"));
7267 EXPECT_THAT(getDiagnosticString(),
7268 HasSubstr("Component decoration value must not be 1 or 3 for "
7269 "64-bit data types"));
7270 }
7271
TEST_F(ValidateDecorations,ComponentDecoration64Vec0GoodVulkan)7272 TEST_F(ValidateDecorations, ComponentDecoration64Vec0GoodVulkan) {
7273 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7274 std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 0");
7275
7276 CompileSuccessfully(spirv, env);
7277 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7278 }
7279
TEST_F(ValidateDecorations,ComponentDecoration64Vec1BadVulkan)7280 TEST_F(ValidateDecorations, ComponentDecoration64Vec1BadVulkan) {
7281 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7282 std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 1");
7283
7284 CompileSuccessfully(spirv, env);
7285 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7286 EXPECT_THAT(getDiagnosticString(),
7287 AnyVUID("VUID-StandaloneSpirv-Component-04923"));
7288 EXPECT_THAT(getDiagnosticString(),
7289 HasSubstr("Component decoration value must not be 1 or 3 for "
7290 "64-bit data types"));
7291 }
7292
TEST_F(ValidateDecorations,ComponentDecoration64Vec2BadVulkan)7293 TEST_F(ValidateDecorations, ComponentDecoration64Vec2BadVulkan) {
7294 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7295 std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 2");
7296
7297 CompileSuccessfully(spirv, env);
7298 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7299 EXPECT_THAT(getDiagnosticString(),
7300 AnyVUID("VUID-StandaloneSpirv-Component-04922"));
7301 HasSubstr(
7302 "Sequence of components starting with 2 "
7303 "and ending with 6 gets larger than 3");
7304 }
7305
TEST_F(ValidateDecorations,ComponentDecoration64VecWideBadVulkan)7306 TEST_F(ValidateDecorations, ComponentDecoration64VecWideBadVulkan) {
7307 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7308 std::string spirv = ShaderWithComponentDecoration("v3uint64", "Component 0");
7309
7310 CompileSuccessfully(spirv, env);
7311 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7312 EXPECT_THAT(getDiagnosticString(),
7313 AnyVUID("VUID-StandaloneSpirv-Component-07703"));
7314 EXPECT_THAT(getDiagnosticString(),
7315 HasSubstr("Component decoration only allowed on 64-bit scalar "
7316 "and 2-component vector"));
7317 }
7318
TEST_F(ValidateDecorations,ComponentDecorationBlockGood)7319 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
7320 std::string spirv = R"(
7321 OpCapability Shader
7322 OpMemoryModel Logical GLSL450
7323 OpEntryPoint Fragment %4 "main" %9 %12
7324 OpExecutionMode %4 OriginUpperLeft
7325 OpDecorate %9 Location 0
7326 OpMemberDecorate %block 0 Location 2
7327 OpMemberDecorate %block 0 Component 1
7328 OpDecorate %block Block
7329 %2 = OpTypeVoid
7330 %3 = OpTypeFunction %2
7331 %float = OpTypeFloat 32
7332 %vec3 = OpTypeVector %float 3
7333 %8 = OpTypePointer Output %vec3
7334 %9 = OpVariable %8 Output
7335 %block = OpTypeStruct %vec3
7336 %11 = OpTypePointer Input %block
7337 %12 = OpVariable %11 Input
7338 %int = OpTypeInt 32 1
7339 %14 = OpConstant %int 0
7340 %15 = OpTypePointer Input %vec3
7341 %4 = OpFunction %2 None %3
7342 %5 = OpLabel
7343 %16 = OpAccessChain %15 %12 %14
7344 %17 = OpLoad %vec3 %16
7345 OpStore %9 %17
7346 OpReturn
7347 OpFunctionEnd
7348 )";
7349
7350 CompileSuccessfully(spirv);
7351 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7352 EXPECT_THAT(getDiagnosticString(), Eq(""));
7353 }
7354
TEST_F(ValidateDecorations,ComponentDecorationBlockBadVulkan)7355 TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) {
7356 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7357 std::string spirv = R"(
7358 OpCapability Shader
7359 OpMemoryModel Logical GLSL450
7360 OpEntryPoint Fragment %4 "main" %9 %12
7361 OpExecutionMode %4 OriginUpperLeft
7362 OpDecorate %9 Location 0
7363 OpMemberDecorate %block 0 Location 2
7364 OpMemberDecorate %block 0 Component 2
7365 OpDecorate %block Block
7366 %2 = OpTypeVoid
7367 %3 = OpTypeFunction %2
7368 %float = OpTypeFloat 32
7369 %vec3 = OpTypeVector %float 3
7370 %8 = OpTypePointer Output %vec3
7371 %9 = OpVariable %8 Output
7372 %block = OpTypeStruct %vec3
7373 %11 = OpTypePointer Input %block
7374 %12 = OpVariable %11 Input
7375 %int = OpTypeInt 32 1
7376 %14 = OpConstant %int 0
7377 %15 = OpTypePointer Input %vec3
7378 %4 = OpFunction %2 None %3
7379 %5 = OpLabel
7380 %16 = OpAccessChain %15 %12 %14
7381 %17 = OpLoad %vec3 %16
7382 OpStore %9 %17
7383 OpReturn
7384 OpFunctionEnd
7385 )";
7386
7387 CompileSuccessfully(spirv, env);
7388 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7389 EXPECT_THAT(getDiagnosticString(),
7390 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7391 EXPECT_THAT(getDiagnosticString(),
7392 HasSubstr("Sequence of components starting with 2 "
7393 "and ending with 4 gets larger than 3"));
7394 }
7395
TEST_F(ValidateDecorations,ComponentDecorationFunctionParameter)7396 TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
7397 std::string spirv = R"(
7398 OpCapability Shader
7399 OpMemoryModel Logical GLSL450
7400 OpEntryPoint Vertex %main "main"
7401
7402 OpDecorate %param_f Component 0
7403
7404 %void = OpTypeVoid
7405 %void_fn = OpTypeFunction %void
7406 %float = OpTypeFloat 32
7407 %float_0 = OpConstant %float 0
7408 %int = OpTypeInt 32 0
7409 %int_2 = OpConstant %int 2
7410 %struct_b = OpTypeStruct %float
7411
7412 %extra_fn = OpTypeFunction %void %float
7413
7414 %helper = OpFunction %void None %extra_fn
7415 %param_f = OpFunctionParameter %float
7416 %helper_label = OpLabel
7417 OpReturn
7418 OpFunctionEnd
7419
7420 %main = OpFunction %void None %void_fn
7421 %label = OpLabel
7422 OpReturn
7423 OpFunctionEnd
7424 )";
7425
7426 CompileSuccessfully(spirv);
7427 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7428 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
7429 }
7430
TEST_F(ValidateDecorations,VulkanStorageBufferBlock)7431 TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
7432 const std::string spirv = R"(
7433 OpCapability Shader
7434 OpExtension "SPV_KHR_storage_buffer_storage_class"
7435 OpMemoryModel Logical GLSL450
7436 OpEntryPoint GLCompute %main "main"
7437 OpExecutionMode %main LocalSize 1 1 1
7438 OpDecorate %struct Block
7439 OpMemberDecorate %struct 0 Offset 0
7440 %void = OpTypeVoid
7441 %uint = OpTypeInt 32 0
7442 %struct = OpTypeStruct %uint
7443 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7444 %var = OpVariable %ptr_ssbo StorageBuffer
7445 %void_fn = OpTypeFunction %void
7446 %main = OpFunction %void None %void_fn
7447 %entry = OpLabel
7448 OpReturn
7449 OpFunctionEnd
7450 )";
7451
7452 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7453 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7454 }
7455
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBlock)7456 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
7457 const std::string spirv = R"(
7458 OpCapability Shader
7459 OpExtension "SPV_KHR_storage_buffer_storage_class"
7460 OpMemoryModel Logical GLSL450
7461 OpEntryPoint GLCompute %main "main"
7462 OpExecutionMode %main LocalSize 1 1 1
7463 %void = OpTypeVoid
7464 %uint = OpTypeInt 32 0
7465 %struct = OpTypeStruct %uint
7466 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7467 %var = OpVariable %ptr_ssbo StorageBuffer
7468 %void_fn = OpTypeFunction %void
7469 %main = OpFunction %void None %void_fn
7470 %entry = OpLabel
7471 OpReturn
7472 OpFunctionEnd
7473 )";
7474
7475 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7476 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7477 EXPECT_THAT(getDiagnosticString(),
7478 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7479 EXPECT_THAT(getDiagnosticString(),
7480 HasSubstr("From Vulkan spec:\nSuch variables "
7481 "must be identified with a Block decoration"));
7482 }
7483
TEST_F(ValidateDecorations,VulkanStorageBufferArrayMissingBlock)7484 TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
7485 const std::string spirv = R"(
7486 OpCapability Shader
7487 OpExtension "SPV_KHR_storage_buffer_storage_class"
7488 OpMemoryModel Logical GLSL450
7489 OpEntryPoint GLCompute %main "main"
7490 OpExecutionMode %main LocalSize 1 1 1
7491 %void = OpTypeVoid
7492 %uint = OpTypeInt 32 0
7493 %uint_4 = OpConstant %uint 4
7494 %struct = OpTypeStruct %uint
7495 %array = OpTypeArray %struct %uint_4
7496 %ptr_ssbo = OpTypePointer StorageBuffer %array
7497 %var = OpVariable %ptr_ssbo StorageBuffer
7498 %void_fn = OpTypeFunction %void
7499 %main = OpFunction %void None %void_fn
7500 %entry = OpLabel
7501 OpReturn
7502 OpFunctionEnd
7503 )";
7504
7505 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7506 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7507 EXPECT_THAT(getDiagnosticString(),
7508 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7509 EXPECT_THAT(getDiagnosticString(),
7510 HasSubstr("From Vulkan spec:\nSuch variables "
7511 "must be identified with a Block decoration"));
7512 }
7513
TEST_F(ValidateDecorations,VulkanStorageBufferRuntimeArrayMissingBlock)7514 TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
7515 const std::string spirv = R"(
7516 OpCapability Shader
7517 OpCapability RuntimeDescriptorArrayEXT
7518 OpExtension "SPV_EXT_descriptor_indexing"
7519 OpExtension "SPV_KHR_storage_buffer_storage_class"
7520 OpMemoryModel Logical GLSL450
7521 OpEntryPoint GLCompute %main "main"
7522 OpExecutionMode %main LocalSize 1 1 1
7523 %void = OpTypeVoid
7524 %uint = OpTypeInt 32 0
7525 %struct = OpTypeStruct %uint
7526 %array = OpTypeRuntimeArray %struct
7527 %ptr_ssbo = OpTypePointer StorageBuffer %array
7528 %var = OpVariable %ptr_ssbo StorageBuffer
7529 %void_fn = OpTypeFunction %void
7530 %main = OpFunction %void None %void_fn
7531 %entry = OpLabel
7532 OpReturn
7533 OpFunctionEnd
7534 )";
7535
7536 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7537 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7538 EXPECT_THAT(getDiagnosticString(),
7539 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7540 EXPECT_THAT(getDiagnosticString(),
7541 HasSubstr("From Vulkan spec:\nSuch variables "
7542 "must be identified with a Block decoration"));
7543 }
7544
TEST_F(ValidateDecorations,VulkanUniformBlock)7545 TEST_F(ValidateDecorations, VulkanUniformBlock) {
7546 const std::string spirv = R"(
7547 OpCapability Shader
7548 OpMemoryModel Logical GLSL450
7549 OpEntryPoint GLCompute %main "main"
7550 OpExecutionMode %main LocalSize 1 1 1
7551 OpDecorate %struct Block
7552 OpMemberDecorate %struct 0 Offset 0
7553 %void = OpTypeVoid
7554 %uint = OpTypeInt 32 0
7555 %struct = OpTypeStruct %uint
7556 %ptr_ubo = OpTypePointer Uniform %struct
7557 %var = OpVariable %ptr_ubo Uniform
7558 %void_fn = OpTypeFunction %void
7559 %main = OpFunction %void None %void_fn
7560 %entry = OpLabel
7561 OpReturn
7562 OpFunctionEnd
7563 )";
7564
7565 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7566 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7567 }
7568
TEST_F(ValidateDecorations,VulkanUniformBufferBlock)7569 TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
7570 const std::string spirv = R"(
7571 OpCapability Shader
7572 OpMemoryModel Logical GLSL450
7573 OpEntryPoint GLCompute %main "main"
7574 OpExecutionMode %main LocalSize 1 1 1
7575 OpDecorate %struct BufferBlock
7576 OpMemberDecorate %struct 0 Offset 0
7577 %void = OpTypeVoid
7578 %uint = OpTypeInt 32 0
7579 %struct = OpTypeStruct %uint
7580 %ptr_ubo = OpTypePointer Uniform %struct
7581 %var = OpVariable %ptr_ubo Uniform
7582 %void_fn = OpTypeFunction %void
7583 %main = OpFunction %void None %void_fn
7584 %entry = OpLabel
7585 OpReturn
7586 OpFunctionEnd
7587 )";
7588
7589 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7590 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7591 }
7592
TEST_F(ValidateDecorations,VulkanUniformMissingBlock)7593 TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
7594 const std::string spirv = R"(
7595 OpCapability Shader
7596 OpMemoryModel Logical GLSL450
7597 OpEntryPoint GLCompute %main "main"
7598 OpExecutionMode %main LocalSize 1 1 1
7599 %void = OpTypeVoid
7600 %uint = OpTypeInt 32 0
7601 %struct = OpTypeStruct %uint
7602 %ptr_ubo = OpTypePointer Uniform %struct
7603 %var = OpVariable %ptr_ubo Uniform
7604 %void_fn = OpTypeFunction %void
7605 %main = OpFunction %void None %void_fn
7606 %entry = OpLabel
7607 OpReturn
7608 OpFunctionEnd
7609 )";
7610
7611 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7612 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7613 EXPECT_THAT(getDiagnosticString(),
7614 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7615 EXPECT_THAT(getDiagnosticString(),
7616 HasSubstr("From Vulkan spec:\nSuch variables must be "
7617 "identified with a Block or BufferBlock decoration"));
7618 }
7619
TEST_F(ValidateDecorations,VulkanUniformArrayMissingBlock)7620 TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
7621 const std::string spirv = R"(
7622 OpCapability Shader
7623 OpMemoryModel Logical GLSL450
7624 OpEntryPoint GLCompute %main "main"
7625 OpExecutionMode %main LocalSize 1 1 1
7626 %void = OpTypeVoid
7627 %uint = OpTypeInt 32 0
7628 %uint_4 = OpConstant %uint 4
7629 %struct = OpTypeStruct %uint
7630 %array = OpTypeArray %struct %uint_4
7631 %ptr_ubo = OpTypePointer Uniform %array
7632 %var = OpVariable %ptr_ubo Uniform
7633 %void_fn = OpTypeFunction %void
7634 %main = OpFunction %void None %void_fn
7635 %entry = OpLabel
7636 OpReturn
7637 OpFunctionEnd
7638 )";
7639
7640 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7641 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7642 EXPECT_THAT(getDiagnosticString(),
7643 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7644 EXPECT_THAT(getDiagnosticString(),
7645 HasSubstr("From Vulkan spec:\nSuch variables must be "
7646 "identified with a Block or BufferBlock decoration"));
7647 }
7648
TEST_F(ValidateDecorations,VulkanUniformRuntimeArrayMissingBlock)7649 TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
7650 const std::string spirv = R"(
7651 OpCapability Shader
7652 OpCapability RuntimeDescriptorArrayEXT
7653 OpExtension "SPV_EXT_descriptor_indexing"
7654 OpMemoryModel Logical GLSL450
7655 OpEntryPoint GLCompute %main "main"
7656 OpExecutionMode %main LocalSize 1 1 1
7657 %void = OpTypeVoid
7658 %uint = OpTypeInt 32 0
7659 %struct = OpTypeStruct %uint
7660 %array = OpTypeRuntimeArray %struct
7661 %ptr_ubo = OpTypePointer Uniform %array
7662 %var = OpVariable %ptr_ubo Uniform
7663 %void_fn = OpTypeFunction %void
7664 %main = OpFunction %void None %void_fn
7665 %entry = OpLabel
7666 OpReturn
7667 OpFunctionEnd
7668 )";
7669
7670 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7671 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7672 EXPECT_THAT(getDiagnosticString(),
7673 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7674 EXPECT_THAT(getDiagnosticString(),
7675 HasSubstr("From Vulkan spec:\nSuch variables must be "
7676 "identified with a Block or BufferBlock decoration"));
7677 }
7678
TEST_F(ValidateDecorations,VulkanArrayStrideZero)7679 TEST_F(ValidateDecorations, VulkanArrayStrideZero) {
7680 const std::string spirv = R"(
7681 OpCapability Shader
7682 OpMemoryModel Logical GLSL450
7683 OpEntryPoint GLCompute %main "main"
7684 OpExecutionMode %main LocalSize 1 1 1
7685 OpDecorate %var DescriptorSet 0
7686 OpDecorate %var Binding 0
7687 OpDecorate %struct Block
7688 OpMemberDecorate %struct 0 Offset 0
7689 OpDecorate %array ArrayStride 0
7690 %void = OpTypeVoid
7691 %int = OpTypeInt 32 0
7692 %int_4 = OpConstant %int 4
7693 %array = OpTypeArray %int %int_4
7694 %struct = OpTypeStruct %array
7695 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7696 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7697 %void_fn = OpTypeFunction %void
7698 %main = OpFunction %void None %void_fn
7699 %entry = OpLabel
7700 OpReturn
7701 OpFunctionEnd
7702 )";
7703
7704 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7705 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7706 EXPECT_THAT(getDiagnosticString(),
7707 HasSubstr("contains an array with stride 0"));
7708 }
7709
TEST_F(ValidateDecorations,VulkanArrayStrideTooSmall)7710 TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) {
7711 const std::string spirv = R"(
7712 OpCapability Shader
7713 OpMemoryModel Logical GLSL450
7714 OpEntryPoint GLCompute %main "main"
7715 OpExecutionMode %main LocalSize 1 1 1
7716 OpDecorate %var DescriptorSet 0
7717 OpDecorate %var Binding 0
7718 OpDecorate %struct Block
7719 OpMemberDecorate %struct 0 Offset 0
7720 OpDecorate %inner ArrayStride 4
7721 OpDecorate %outer ArrayStride 4
7722 %void = OpTypeVoid
7723 %int = OpTypeInt 32 0
7724 %int_4 = OpConstant %int 4
7725 %inner = OpTypeArray %int %int_4
7726 %outer = OpTypeArray %inner %int_4
7727 %struct = OpTypeStruct %outer
7728 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7729 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7730 %void_fn = OpTypeFunction %void
7731 %main = OpFunction %void None %void_fn
7732 %entry = OpLabel
7733 OpReturn
7734 OpFunctionEnd
7735 )";
7736
7737 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7738 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7739 EXPECT_THAT(
7740 getDiagnosticString(),
7741 HasSubstr(
7742 "contains an array with stride 4, but with an element size of 16"));
7743 }
7744
TEST_F(ValidateDecorations,FunctionsWithOpGroupDecorate)7745 TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate) {
7746 std::string spirv = R"(
7747 OpCapability Addresses
7748 OpCapability Linkage
7749 OpCapability Kernel
7750 OpCapability Int8
7751 %1 = OpExtInstImport "OpenCL.std"
7752 OpMemoryModel Physical32 OpenCL
7753 OpName %foo "foo"
7754 OpName %entry "entry"
7755 OpName %bar "bar"
7756 OpName %entry_0 "entry"
7757 OpName %k "k"
7758 OpName %entry_1 "entry"
7759 OpName %b "b"
7760 OpDecorate %28 FuncParamAttr Zext
7761 %28 = OpDecorationGroup
7762 OpDecorate %k LinkageAttributes "k" Export
7763 OpDecorate %foo LinkageAttributes "foo" Export
7764 OpDecorate %bar LinkageAttributes "bar" Export
7765 OpDecorate %b Alignment 1
7766 OpGroupDecorate %28 %foo %bar
7767 %uchar = OpTypeInt 8 0
7768 %bool = OpTypeBool
7769 %3 = OpTypeFunction %bool
7770 %void = OpTypeVoid
7771 %10 = OpTypeFunction %void
7772 %_ptr_Function_uchar = OpTypePointer Function %uchar
7773 %true = OpConstantTrue %bool
7774 %foo = OpFunction %bool DontInline %3
7775 %entry = OpLabel
7776 OpReturnValue %true
7777 OpFunctionEnd
7778 %bar = OpFunction %bool DontInline %3
7779 %entry_0 = OpLabel
7780 OpReturnValue %true
7781 OpFunctionEnd
7782 %k = OpFunction %void DontInline %10
7783 %entry_1 = OpLabel
7784 %b = OpVariable %_ptr_Function_uchar Function
7785 OpReturn
7786 OpFunctionEnd
7787 )";
7788 CompileSuccessfully(spirv);
7789 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7790 }
7791
TEST_F(ValidateDecorations,LocationVariableGood)7792 TEST_F(ValidateDecorations, LocationVariableGood) {
7793 const std::string spirv = R"(
7794 OpCapability Shader
7795 OpCapability Linkage
7796 OpMemoryModel Logical GLSL450
7797 OpDecorate %in_var Location 0
7798 %float = OpTypeFloat 32
7799 %ptr_input_float = OpTypePointer Input %float
7800 %in_var = OpVariable %ptr_input_float Input
7801 )";
7802
7803 CompileSuccessfully(spirv);
7804 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7805 }
7806
TEST_F(ValidateDecorations,LocationStructMemberGood)7807 TEST_F(ValidateDecorations, LocationStructMemberGood) {
7808 const std::string spirv = R"(
7809 OpCapability Shader
7810 OpCapability Linkage
7811 OpMemoryModel Logical GLSL450
7812 OpMemberDecorate %struct 0 Location 0
7813 %float = OpTypeFloat 32
7814 %struct = OpTypeStruct %float
7815 )";
7816
7817 CompileSuccessfully(spirv);
7818 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7819 }
7820
TEST_F(ValidateDecorations,LocationStructBad)7821 TEST_F(ValidateDecorations, LocationStructBad) {
7822 const std::string spirv = R"(
7823 OpCapability Shader
7824 OpCapability Linkage
7825 OpMemoryModel Logical GLSL450
7826 OpDecorate %struct Location 0
7827 %float = OpTypeFloat 32
7828 %struct = OpTypeStruct %float
7829 )";
7830
7831 CompileSuccessfully(spirv);
7832 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7833 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7834 }
7835
TEST_F(ValidateDecorations,LocationFloatBad)7836 TEST_F(ValidateDecorations, LocationFloatBad) {
7837 const std::string spirv = R"(
7838 OpCapability Shader
7839 OpCapability Linkage
7840 OpMemoryModel Logical GLSL450
7841 OpDecorate %float Location 0
7842 %float = OpTypeFloat 32
7843 )";
7844
7845 CompileSuccessfully(spirv);
7846 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7847 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7848 }
7849
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariable)7850 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable) {
7851 std::string spirv = R"(
7852 OpCapability Shader
7853 OpCapability WorkgroupMemoryExplicitLayoutKHR
7854 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7855 OpMemoryModel Logical GLSL450
7856 OpEntryPoint GLCompute %main "main" %_
7857 OpExecutionMode %main LocalSize 8 1 1
7858 OpMemberDecorate %first 0 Offset 0
7859 OpDecorate %first Block
7860 %void = OpTypeVoid
7861 %3 = OpTypeFunction %void
7862 %int = OpTypeInt 32 1
7863 %first = OpTypeStruct %int
7864 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7865 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7866 %int_0 = OpConstant %int 0
7867 %int_2 = OpConstant %int 2
7868 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7869 %main = OpFunction %void None %3
7870 %5 = OpLabel
7871 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7872 OpStore %13 %int_2
7873 OpReturn
7874 OpFunctionEnd
7875 )";
7876
7877 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7878 EXPECT_EQ(SPV_SUCCESS,
7879 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7880 }
7881
TEST_F(ValidateDecorations,WorkgroupBlockVariableRequiresV14)7882 TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14) {
7883 std::string spirv = R"(
7884 OpCapability Shader
7885 OpCapability WorkgroupMemoryExplicitLayoutKHR
7886 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7887 OpMemoryModel Logical GLSL450
7888 OpEntryPoint GLCompute %main "main" %_
7889 OpExecutionMode %main LocalSize 8 1 1
7890 OpMemberDecorate %first 0 Offset 0
7891 OpDecorate %first Block
7892 %void = OpTypeVoid
7893 %3 = OpTypeFunction %void
7894 %int = OpTypeInt 32 1
7895 %first = OpTypeStruct %int
7896 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7897 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7898 %int_0 = OpConstant %int 0
7899 %int_2 = OpConstant %int 2
7900 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7901 %main = OpFunction %void None %3
7902 %5 = OpLabel
7903 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7904 OpStore %13 %int_2
7905 OpReturn
7906 OpFunctionEnd
7907 )";
7908
7909 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7910 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
7911 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7912 EXPECT_THAT(getDiagnosticString(),
7913 HasSubstr("requires SPIR-V version 1.4 or later"));
7914 }
7915
TEST_F(ValidateDecorations,WorkgroupSingleNonBlockVariable)7916 TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable) {
7917 std::string spirv = R"(
7918 OpCapability Shader
7919 OpMemoryModel Logical GLSL450
7920 OpEntryPoint GLCompute %main "main" %a
7921 OpExecutionMode %main LocalSize 8 1 1
7922 %void = OpTypeVoid
7923 %3 = OpTypeFunction %void
7924 %int = OpTypeInt 32 1
7925 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7926 %a = OpVariable %_ptr_Workgroup_int Workgroup
7927 %int_2 = OpConstant %int 2
7928 %main = OpFunction %void None %3
7929 %5 = OpLabel
7930 OpStore %a %int_2
7931 OpReturn
7932 OpFunctionEnd
7933 )";
7934
7935 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7936 EXPECT_EQ(SPV_SUCCESS,
7937 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7938 }
7939
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariable)7940 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable) {
7941 std::string spirv = R"(
7942 OpCapability Shader
7943 OpCapability WorkgroupMemoryExplicitLayoutKHR
7944 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7945 OpMemoryModel Logical GLSL450
7946 OpEntryPoint GLCompute %main "main" %_ %__0
7947 OpExecutionMode %main LocalSize 8 1 1
7948 OpMemberDecorate %first 0 Offset 0
7949 OpDecorate %first Block
7950 OpMemberDecorate %second 0 Offset 0
7951 OpDecorate %second Block
7952 OpDecorate %_ Aliased
7953 OpDecorate %__0 Aliased
7954 %void = OpTypeVoid
7955 %3 = OpTypeFunction %void
7956 %int = OpTypeInt 32 1
7957 %first = OpTypeStruct %int
7958 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7959 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7960 %int_0 = OpConstant %int 0
7961 %int_2 = OpConstant %int 2
7962 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7963 %second = OpTypeStruct %int
7964 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7965 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7966 %int_3 = OpConstant %int 3
7967 %main = OpFunction %void None %3
7968 %5 = OpLabel
7969 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7970 OpStore %13 %int_2
7971 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7972 OpStore %18 %int_3
7973 OpReturn
7974 OpFunctionEnd
7975 )";
7976
7977 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7978 EXPECT_EQ(SPV_SUCCESS,
7979 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7980 }
7981
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith8BitType)7982 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith8BitType) {
7983 std::string spirv = R"(
7984 OpCapability Shader
7985 OpCapability Int8
7986 OpCapability WorkgroupMemoryExplicitLayout8BitAccessKHR
7987 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7988 OpMemoryModel Logical GLSL450
7989 OpEntryPoint GLCompute %main "main" %_
7990 OpExecutionMode %main LocalSize 2 1 1
7991 OpMemberDecorate %first 0 Offset 0
7992 OpDecorate %first Block
7993 %void = OpTypeVoid
7994 %3 = OpTypeFunction %void
7995 %char = OpTypeInt 8 1
7996 %first = OpTypeStruct %char
7997 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7998 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7999 %int = OpTypeInt 32 1
8000 %int_0 = OpConstant %int 0
8001 %char_2 = OpConstant %char 2
8002 %_ptr_Workgroup_char = OpTypePointer Workgroup %char
8003 %main = OpFunction %void None %3
8004 %5 = OpLabel
8005 %14 = OpAccessChain %_ptr_Workgroup_char %_ %int_0
8006 OpStore %14 %char_2
8007 OpReturn
8008 OpFunctionEnd
8009 )";
8010
8011 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8012 EXPECT_EQ(SPV_SUCCESS,
8013 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8014 }
8015
TEST_F(ValidateDecorations,WorkgroupMultiNonBlockVariable)8016 TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable) {
8017 std::string spirv = R"(
8018 OpCapability Shader
8019 OpMemoryModel Logical GLSL450
8020 OpEntryPoint GLCompute %main "main" %a %b
8021 OpExecutionMode %main LocalSize 8 1 1
8022 %void = OpTypeVoid
8023 %3 = OpTypeFunction %void
8024 %int = OpTypeInt 32 1
8025 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8026 %a = OpVariable %_ptr_Workgroup_int Workgroup
8027 %int_2 = OpConstant %int 2
8028 %b = OpVariable %_ptr_Workgroup_int Workgroup
8029 %int_3 = OpConstant %int 3
8030 %main = OpFunction %void None %3
8031 %5 = OpLabel
8032 OpStore %a %int_2
8033 OpStore %b %int_3
8034 OpReturn
8035 OpFunctionEnd
8036 )";
8037
8038 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8039 EXPECT_EQ(SPV_SUCCESS,
8040 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8041 }
8042
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith16BitType)8043 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType) {
8044 std::string spirv = R"(
8045 OpCapability Shader
8046 OpCapability Float16
8047 OpCapability Int16
8048 OpCapability WorkgroupMemoryExplicitLayoutKHR
8049 OpCapability WorkgroupMemoryExplicitLayout16BitAccessKHR
8050 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8051 OpMemoryModel Logical GLSL450
8052 OpEntryPoint GLCompute %main "main" %_
8053 OpExecutionMode %main LocalSize 2 1 1
8054 OpMemberDecorate %first 0 Offset 0
8055 OpMemberDecorate %first 1 Offset 2
8056 OpDecorate %first Block
8057 %void = OpTypeVoid
8058 %3 = OpTypeFunction %void
8059 %short = OpTypeInt 16 1
8060 %half = OpTypeFloat 16
8061 %first = OpTypeStruct %short %half
8062 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8063 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8064 %int = OpTypeInt 32 1
8065 %int_0 = OpConstant %int 0
8066 %short_3 = OpConstant %short 3
8067 %_ptr_Workgroup_short = OpTypePointer Workgroup %short
8068 %int_1 = OpConstant %int 1
8069 %half_0x1_898p_3 = OpConstant %half 0x1.898p+3
8070 %_ptr_Workgroup_half = OpTypePointer Workgroup %half
8071 %main = OpFunction %void None %3
8072 %5 = OpLabel
8073 %15 = OpAccessChain %_ptr_Workgroup_short %_ %int_0
8074 OpStore %15 %short_3
8075 %19 = OpAccessChain %_ptr_Workgroup_half %_ %int_1
8076 OpStore %19 %half_0x1_898p_3
8077 OpReturn
8078 OpFunctionEnd
8079 )";
8080
8081 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8082 EXPECT_EQ(SPV_SUCCESS,
8083 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8084 }
8085
TEST_F(ValidateDecorations,WorkgroupBlockVariableScalarLayout)8086 TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout) {
8087 std::string spirv = R"(
8088 OpCapability Shader
8089 OpCapability WorkgroupMemoryExplicitLayoutKHR
8090 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8091 OpMemoryModel Logical GLSL450
8092 OpEntryPoint Vertex %main "main" %B
8093 OpSource GLSL 450
8094 OpMemberDecorate %S 0 Offset 0
8095 OpMemberDecorate %S 1 Offset 4
8096 OpMemberDecorate %S 2 Offset 16
8097 OpMemberDecorate %S 3 Offset 28
8098 OpDecorate %S Block
8099 OpDecorate %B Aliased
8100 %void = OpTypeVoid
8101 %3 = OpTypeFunction %void
8102 %float = OpTypeFloat 32
8103 %v3float = OpTypeVector %float 3
8104 %S = OpTypeStruct %float %v3float %v3float %v3float
8105 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
8106 %B = OpVariable %_ptr_Workgroup_S Workgroup
8107 %main = OpFunction %void None %3
8108 %5 = OpLabel
8109 OpReturn
8110 OpFunctionEnd
8111 )";
8112
8113 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8114 spvValidatorOptionsSetWorkgroupScalarBlockLayout(getValidatorOptions(), true);
8115 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4))
8116 << getDiagnosticString();
8117 }
8118
TEST_F(ValidateDecorations,WorkgroupMixBlockAndNonBlockBad)8119 TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad) {
8120 std::string spirv = R"(
8121 OpCapability Shader
8122 OpCapability WorkgroupMemoryExplicitLayoutKHR
8123 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8124 OpMemoryModel Logical GLSL450
8125 OpEntryPoint GLCompute %main "main" %_ %b
8126 OpExecutionMode %main LocalSize 8 1 1
8127 OpMemberDecorate %first 0 Offset 0
8128 OpDecorate %first Block
8129 OpDecorate %_ Aliased
8130 OpDecorate %b Aliased
8131 %void = OpTypeVoid
8132 %3 = OpTypeFunction %void
8133 %int = OpTypeInt 32 1
8134 %first = OpTypeStruct %int
8135 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8136 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8137 %int_0 = OpConstant %int 0
8138 %int_2 = OpConstant %int 2
8139 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8140 %b = OpVariable %_ptr_Workgroup_int Workgroup
8141 %int_3 = OpConstant %int 3
8142 %main = OpFunction %void None %3
8143 %5 = OpLabel
8144 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8145 OpStore %13 %int_2
8146 OpStore %b %int_3
8147 OpReturn
8148 OpFunctionEnd
8149 )";
8150
8151 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8152 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8153 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8154 EXPECT_THAT(
8155 getDiagnosticString(),
8156 HasSubstr("either all or none of the Workgroup Storage Class variables "
8157 "in the entry point interface must point to struct types "
8158 "decorated with Block"));
8159 }
8160
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariableMissingAliased)8161 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased) {
8162 std::string spirv = R"(
8163 OpCapability Shader
8164 OpCapability WorkgroupMemoryExplicitLayoutKHR
8165 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8166 OpMemoryModel Logical GLSL450
8167 OpEntryPoint GLCompute %main "main" %_ %__0
8168 OpExecutionMode %main LocalSize 8 1 1
8169 OpMemberDecorate %first 0 Offset 0
8170 OpDecorate %first Block
8171 OpMemberDecorate %second 0 Offset 0
8172 OpDecorate %second Block
8173 OpDecorate %_ Aliased
8174 %void = OpTypeVoid
8175 %3 = OpTypeFunction %void
8176 %int = OpTypeInt 32 1
8177 %first = OpTypeStruct %int
8178 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8179 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8180 %int_0 = OpConstant %int 0
8181 %int_2 = OpConstant %int 2
8182 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8183 %second = OpTypeStruct %int
8184 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
8185 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
8186 %int_3 = OpConstant %int 3
8187 %main = OpFunction %void None %3
8188 %5 = OpLabel
8189 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8190 OpStore %13 %int_2
8191 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
8192 OpStore %18 %int_3
8193 OpReturn
8194 OpFunctionEnd
8195 )";
8196
8197 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8198 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8199 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8200 EXPECT_THAT(
8201 getDiagnosticString(),
8202 HasSubstr("more than one Workgroup Storage Class variable in the "
8203 "entry point interface point to a type decorated with Block, "
8204 "all of them must be decorated with Aliased"));
8205 }
8206
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableNotAStruct)8207 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct) {
8208 std::string spirv = R"(
8209 OpCapability Shader
8210 OpCapability WorkgroupMemoryExplicitLayoutKHR
8211 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8212 OpMemoryModel Logical GLSL450
8213 OpEntryPoint GLCompute %main "main" %_
8214 OpExecutionMode %main LocalSize 8 1 1
8215 OpDecorate %first Block
8216 %void = OpTypeVoid
8217 %3 = OpTypeFunction %void
8218 %int = OpTypeInt 32 1
8219 %int_3 = OpConstant %int 3
8220 %first = OpTypeArray %int %int_3
8221 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8222 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8223 %int_0 = OpConstant %int 0
8224 %int_2 = OpConstant %int 2
8225 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8226 %main = OpFunction %void None %3
8227 %5 = OpLabel
8228 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8229 OpStore %13 %int_2
8230 OpReturn
8231 OpFunctionEnd
8232 )";
8233
8234 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8235 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8236 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8237 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
8238 }
8239
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableMissingLayout)8240 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout) {
8241 std::string spirv = R"(
8242 OpCapability Shader
8243 OpCapability WorkgroupMemoryExplicitLayoutKHR
8244 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8245 OpMemoryModel Logical GLSL450
8246 OpEntryPoint GLCompute %main "main" %_
8247 OpExecutionMode %main LocalSize 8 1 1
8248 OpDecorate %first Block
8249 %void = OpTypeVoid
8250 %3 = OpTypeFunction %void
8251 %int = OpTypeInt 32 1
8252 %first = OpTypeStruct %int
8253 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8254 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8255 %int_0 = OpConstant %int 0
8256 %int_2 = OpConstant %int 2
8257 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8258 %main = OpFunction %void None %3
8259 %5 = OpLabel
8260 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8261 OpStore %13 %int_2
8262 OpReturn
8263 OpFunctionEnd
8264 )";
8265
8266 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8267 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8268 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8269 EXPECT_THAT(
8270 getDiagnosticString(),
8271 HasSubstr("Block must be explicitly laid out with Offset decorations"));
8272 }
8273
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableBadLayout)8274 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout) {
8275 std::string spirv = R"(
8276 OpCapability Shader
8277 OpCapability WorkgroupMemoryExplicitLayoutKHR
8278 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8279 OpMemoryModel Logical GLSL450
8280 OpEntryPoint GLCompute %main "main" %_
8281 OpExecutionMode %main LocalSize 8 1 1
8282 OpMemberDecorate %first 0 Offset 1
8283 OpDecorate %first Block
8284 %void = OpTypeVoid
8285 %3 = OpTypeFunction %void
8286 %int = OpTypeInt 32 1
8287 %first = OpTypeStruct %int
8288 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8289 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8290 %int_0 = OpConstant %int 0
8291 %int_2 = OpConstant %int 2
8292 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8293 %main = OpFunction %void None %3
8294 %5 = OpLabel
8295 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8296 OpStore %13 %int_2
8297 OpReturn
8298 OpFunctionEnd
8299 )";
8300
8301 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8302 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8303 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8304 EXPECT_THAT(
8305 getDiagnosticString(),
8306 HasSubstr("Block for variable in Workgroup storage class must follow "
8307 "relaxed storage buffer layout rules: "
8308 "member 0 at offset 1 is not aligned to 4"));
8309 }
8310
TEST_F(ValidateDecorations,WorkgroupBlockNoCapability)8311 TEST_F(ValidateDecorations, WorkgroupBlockNoCapability) {
8312 std::string spirv = R"(
8313 OpCapability Shader
8314 OpMemoryModel Logical GLSL450
8315 OpEntryPoint GLCompute %main "main" %_
8316 OpExecutionMode %main LocalSize 1 1 1
8317 OpMemberDecorate %struct 0 Offset 0
8318 OpMemberDecorate %struct 1 Offset 4
8319 OpDecorate %struct Block
8320 %void = OpTypeVoid
8321 %3 = OpTypeFunction %void
8322 %int = OpTypeInt 32 1
8323 %struct = OpTypeStruct %int %int
8324 %ptr_workgroup = OpTypePointer Workgroup %struct
8325 %_ = OpVariable %ptr_workgroup Workgroup
8326 %main = OpFunction %void None %3
8327 %5 = OpLabel
8328 OpReturn
8329 OpFunctionEnd
8330 )";
8331
8332 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8333 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8334 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8335 EXPECT_THAT(
8336 getDiagnosticString(),
8337 HasSubstr(
8338 "Workgroup Storage Class variables can't be decorated with Block "
8339 "unless declaring the WorkgroupMemoryExplicitLayoutKHR capability"));
8340 }
8341
TEST_F(ValidateDecorations,BadMatrixStrideUniform)8342 TEST_F(ValidateDecorations, BadMatrixStrideUniform) {
8343 const std::string spirv = R"(
8344 OpCapability Shader
8345 OpMemoryModel Logical GLSL450
8346 OpEntryPoint GLCompute %main "main"
8347 OpExecutionMode %main LocalSize 1 1 1
8348 OpDecorate %block Block
8349 OpMemberDecorate %block 0 Offset 0
8350 OpMemberDecorate %block 0 MatrixStride 3
8351 OpMemberDecorate %block 0 ColMajor
8352 OpDecorate %var DescriptorSet 0
8353 OpDecorate %var Binding 0
8354 %void = OpTypeVoid
8355 %float = OpTypeFloat 32
8356 %float4 = OpTypeVector %float 4
8357 %matrix4x4 = OpTypeMatrix %float4 4
8358 %block = OpTypeStruct %matrix4x4
8359 %block_ptr = OpTypePointer Uniform %block
8360 %var = OpVariable %block_ptr Uniform
8361 %void_fn = OpTypeFunction %void
8362 %main = OpFunction %void None %void_fn
8363 %entry = OpLabel
8364 OpReturn
8365 OpFunctionEnd
8366 )";
8367
8368 CompileSuccessfully(spirv);
8369 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8370 EXPECT_THAT(
8371 getDiagnosticString(),
8372 HasSubstr(
8373 "Structure id 2 decorated as Block for variable in Uniform storage "
8374 "class must follow standard uniform buffer layout rules: member 0 is "
8375 "a matrix with stride 3 not satisfying alignment to 16"));
8376 }
8377
TEST_F(ValidateDecorations,BadMatrixStrideStorageBuffer)8378 TEST_F(ValidateDecorations, BadMatrixStrideStorageBuffer) {
8379 const std::string spirv = R"(
8380 OpCapability Shader
8381 OpExtension "SPV_KHR_storage_buffer_storage_class"
8382 OpMemoryModel Logical GLSL450
8383 OpEntryPoint GLCompute %main "main"
8384 OpExecutionMode %main LocalSize 1 1 1
8385 OpDecorate %block Block
8386 OpMemberDecorate %block 0 Offset 0
8387 OpMemberDecorate %block 0 MatrixStride 3
8388 OpMemberDecorate %block 0 ColMajor
8389 OpDecorate %var DescriptorSet 0
8390 OpDecorate %var Binding 0
8391 %void = OpTypeVoid
8392 %float = OpTypeFloat 32
8393 %float4 = OpTypeVector %float 4
8394 %matrix4x4 = OpTypeMatrix %float4 4
8395 %block = OpTypeStruct %matrix4x4
8396 %block_ptr = OpTypePointer StorageBuffer %block
8397 %var = OpVariable %block_ptr StorageBuffer
8398 %void_fn = OpTypeFunction %void
8399 %main = OpFunction %void None %void_fn
8400 %entry = OpLabel
8401 OpReturn
8402 OpFunctionEnd
8403 )";
8404
8405 CompileSuccessfully(spirv);
8406 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8407 EXPECT_THAT(
8408 getDiagnosticString(),
8409 HasSubstr(
8410 "Structure id 2 decorated as Block for variable in StorageBuffer "
8411 "storage class must follow standard storage buffer layout rules: "
8412 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8413 }
8414
TEST_F(ValidateDecorations,BadMatrixStridePushConstant)8415 TEST_F(ValidateDecorations, BadMatrixStridePushConstant) {
8416 const std::string spirv = R"(
8417 OpCapability Shader
8418 OpMemoryModel Logical GLSL450
8419 OpEntryPoint GLCompute %main "main"
8420 OpExecutionMode %main LocalSize 1 1 1
8421 OpDecorate %block Block
8422 OpMemberDecorate %block 0 Offset 0
8423 OpMemberDecorate %block 0 MatrixStride 3
8424 OpMemberDecorate %block 0 ColMajor
8425 %void = OpTypeVoid
8426 %float = OpTypeFloat 32
8427 %float4 = OpTypeVector %float 4
8428 %matrix4x4 = OpTypeMatrix %float4 4
8429 %block = OpTypeStruct %matrix4x4
8430 %block_ptr = OpTypePointer PushConstant %block
8431 %var = OpVariable %block_ptr PushConstant
8432 %void_fn = OpTypeFunction %void
8433 %main = OpFunction %void None %void_fn
8434 %entry = OpLabel
8435 OpReturn
8436 OpFunctionEnd
8437 )";
8438
8439 CompileSuccessfully(spirv);
8440 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8441 EXPECT_THAT(
8442 getDiagnosticString(),
8443 HasSubstr(
8444 "Structure id 2 decorated as Block for variable in PushConstant "
8445 "storage class must follow standard storage buffer layout rules: "
8446 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8447 }
8448
TEST_F(ValidateDecorations,BadMatrixStrideStorageBufferScalarLayout)8449 TEST_F(ValidateDecorations, BadMatrixStrideStorageBufferScalarLayout) {
8450 const std::string spirv = R"(
8451 OpCapability Shader
8452 OpExtension "SPV_KHR_storage_buffer_storage_class"
8453 OpMemoryModel Logical GLSL450
8454 OpEntryPoint GLCompute %main "main"
8455 OpExecutionMode %main LocalSize 1 1 1
8456 OpDecorate %block Block
8457 OpMemberDecorate %block 0 Offset 0
8458 OpMemberDecorate %block 0 MatrixStride 3
8459 OpMemberDecorate %block 0 RowMajor
8460 OpDecorate %var DescriptorSet 0
8461 OpDecorate %var Binding 0
8462 %void = OpTypeVoid
8463 %float = OpTypeFloat 32
8464 %float4 = OpTypeVector %float 4
8465 %matrix4x4 = OpTypeMatrix %float4 4
8466 %block = OpTypeStruct %matrix4x4
8467 %block_ptr = OpTypePointer StorageBuffer %block
8468 %var = OpVariable %block_ptr StorageBuffer
8469 %void_fn = OpTypeFunction %void
8470 %main = OpFunction %void None %void_fn
8471 %entry = OpLabel
8472 OpReturn
8473 OpFunctionEnd
8474 )";
8475
8476 options_->scalar_block_layout = true;
8477 CompileSuccessfully(spirv);
8478 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8479 EXPECT_THAT(
8480 getDiagnosticString(),
8481 HasSubstr(
8482 "Structure id 2 decorated as Block for variable in StorageBuffer "
8483 "storage class must follow scalar storage buffer layout rules: "
8484 "member 0 is a matrix with stride 3 not satisfying alignment to 4"));
8485 }
8486
TEST_F(ValidateDecorations,MissingOffsetStructNestedInArray)8487 TEST_F(ValidateDecorations, MissingOffsetStructNestedInArray) {
8488 const std::string spirv = R"(
8489 OpCapability Shader
8490 OpExtension "SPV_KHR_storage_buffer_storage_class"
8491 OpMemoryModel Logical GLSL450
8492 OpEntryPoint GLCompute %main "main"
8493 OpExecutionMode %main LocalSize 1 1 1
8494 OpDecorate %array ArrayStride 4
8495 OpDecorate %outer Block
8496 OpMemberDecorate %outer 0 Offset 0
8497 OpDecorate %var DescriptorSet 0
8498 OpDecorate %var Binding 0
8499 %void = OpTypeVoid
8500 %int = OpTypeInt 32 0
8501 %int_4 = OpConstant %int 4
8502 %inner = OpTypeStruct %int
8503 %array = OpTypeArray %inner %int_4
8504 %outer = OpTypeStruct %array
8505 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer
8506 %var = OpVariable %ptr_ssbo_outer StorageBuffer
8507 %void_fn = OpTypeFunction %void
8508 %main = OpFunction %void None %void_fn
8509 %entry = OpLabel
8510 OpReturn
8511 OpFunctionEnd
8512 )";
8513
8514 CompileSuccessfully(spirv);
8515 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8516 EXPECT_THAT(getDiagnosticString(),
8517 HasSubstr("Structure id 3 decorated as Block must be explicitly "
8518 "laid out with Offset decorations"));
8519 }
8520
TEST_F(ValidateDecorations,AllOnesOffset)8521 TEST_F(ValidateDecorations, AllOnesOffset) {
8522 const std::string spirv = R"(
8523 OpCapability Shader
8524 OpMemoryModel Logical GLSL450
8525 OpEntryPoint GLCompute %main "main"
8526 OpDecorate %var DescriptorSet 0
8527 OpDecorate %var Binding 0
8528 OpDecorate %outer Block
8529 OpMemberDecorate %outer 0 Offset 0
8530 OpMemberDecorate %struct 0 Offset 4294967295
8531 %void = OpTypeVoid
8532 %int = OpTypeInt 32 0
8533 %struct = OpTypeStruct %int
8534 %outer = OpTypeStruct %struct
8535 %ptr = OpTypePointer Uniform %outer
8536 %var = OpVariable %ptr Uniform
8537 %void_fn = OpTypeFunction %void
8538 %main = OpFunction %void None %void_fn
8539 %entry = OpLabel
8540 OpReturn
8541 OpFunctionEnd
8542 )";
8543
8544 CompileSuccessfully(spirv);
8545 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8546 EXPECT_THAT(getDiagnosticString(),
8547 HasSubstr("decorated as Block must be explicitly laid out with "
8548 "Offset decorations"));
8549 }
8550
TEST_F(ValidateDecorations,PerVertexVulkanGood)8551 TEST_F(ValidateDecorations, PerVertexVulkanGood) {
8552 const std::string spirv = R"(
8553 OpCapability Shader
8554 OpCapability FragmentBarycentricKHR
8555 OpExtension "SPV_KHR_fragment_shader_barycentric"
8556 %1 = OpExtInstImport "GLSL.std.450"
8557 OpMemoryModel Logical GLSL450
8558 OpEntryPoint Fragment %main "main" %vertexIDs
8559 OpExecutionMode %main OriginUpperLeft
8560 OpDecorate %vertexIDs Location 0
8561 OpDecorate %vertexIDs PerVertexKHR
8562 %void = OpTypeVoid
8563 %func = OpTypeFunction %void
8564 %float = OpTypeFloat 32
8565 %uint = OpTypeInt 32 0
8566 %ptrFloat = OpTypePointer Input %float
8567 %uint_3 = OpConstant %uint 3
8568 %floatArray = OpTypeArray %float %uint_3
8569 %ptrFloatArray = OpTypePointer Input %floatArray
8570 %vertexIDs = OpVariable %ptrFloatArray Input
8571 %int = OpTypeInt 32 1
8572 %int_0 = OpConstant %int 0
8573 %main = OpFunction %void None %func
8574 %label = OpLabel
8575 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8576 %load = OpLoad %float %access
8577 OpReturn
8578 OpFunctionEnd
8579 )";
8580
8581 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8582 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8583 }
8584
TEST_F(ValidateDecorations,PerVertexVulkanOutput)8585 TEST_F(ValidateDecorations, PerVertexVulkanOutput) {
8586 const std::string spirv = R"(
8587 OpCapability Shader
8588 OpCapability FragmentBarycentricKHR
8589 OpExtension "SPV_KHR_fragment_shader_barycentric"
8590 %1 = OpExtInstImport "GLSL.std.450"
8591 OpMemoryModel Logical GLSL450
8592 OpEntryPoint Fragment %main "main" %vertexIDs
8593 OpExecutionMode %main OriginUpperLeft
8594 OpDecorate %vertexIDs Location 0
8595 OpDecorate %vertexIDs PerVertexKHR
8596 %void = OpTypeVoid
8597 %func = OpTypeFunction %void
8598 %float = OpTypeFloat 32
8599 %uint = OpTypeInt 32 0
8600 %ptrFloat = OpTypePointer Output %float
8601 %uint_3 = OpConstant %uint 3
8602 %floatArray = OpTypeArray %float %uint_3
8603 %ptrFloatArray = OpTypePointer Output %floatArray
8604 %vertexIDs = OpVariable %ptrFloatArray Output
8605 %int = OpTypeInt 32 1
8606 %int_0 = OpConstant %int 0
8607 %main = OpFunction %void None %func
8608 %label = OpLabel
8609 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8610 %load = OpLoad %float %access
8611 OpReturn
8612 OpFunctionEnd
8613 )";
8614
8615 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8616 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8617 EXPECT_THAT(getDiagnosticString(),
8618 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8619 EXPECT_THAT(getDiagnosticString(), HasSubstr("storage class must be Input"));
8620 }
8621
TEST_F(ValidateDecorations,PerVertexVulkanNonFragment)8622 TEST_F(ValidateDecorations, PerVertexVulkanNonFragment) {
8623 const std::string spirv = R"(
8624 OpCapability Shader
8625 OpCapability FragmentBarycentricKHR
8626 OpExtension "SPV_KHR_fragment_shader_barycentric"
8627 %1 = OpExtInstImport "GLSL.std.450"
8628 OpMemoryModel Logical GLSL450
8629 OpEntryPoint Vertex %main "main" %vertexIDs
8630 OpDecorate %vertexIDs Location 0
8631 OpDecorate %vertexIDs PerVertexKHR
8632 %void = OpTypeVoid
8633 %func = OpTypeFunction %void
8634 %float = OpTypeFloat 32
8635 %uint = OpTypeInt 32 0
8636 %ptrFloat = OpTypePointer Input %float
8637 %uint_3 = OpConstant %uint 3
8638 %floatArray = OpTypeArray %float %uint_3
8639 %ptrFloatArray = OpTypePointer Input %floatArray
8640 %vertexIDs = OpVariable %ptrFloatArray Input
8641 %int = OpTypeInt 32 1
8642 %int_0 = OpConstant %int 0
8643 %main = OpFunction %void None %func
8644 %label = OpLabel
8645 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8646 %load = OpLoad %float %access
8647 OpReturn
8648 OpFunctionEnd
8649 )";
8650
8651 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8652 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8653 EXPECT_THAT(getDiagnosticString(),
8654 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8655 EXPECT_THAT(
8656 getDiagnosticString(),
8657 HasSubstr(
8658 "PerVertexKHR can only be applied to Fragment Execution Models"));
8659 }
8660
TEST_F(ValidateDecorations,PerVertexVulkanNonArray)8661 TEST_F(ValidateDecorations, PerVertexVulkanNonArray) {
8662 const std::string spirv = R"(
8663 OpCapability Shader
8664 OpCapability FragmentBarycentricKHR
8665 OpExtension "SPV_KHR_fragment_shader_barycentric"
8666 %1 = OpExtInstImport "GLSL.std.450"
8667 OpMemoryModel Logical GLSL450
8668 OpEntryPoint Fragment %main "main" %vertexIDs
8669 OpExecutionMode %main OriginUpperLeft
8670 OpDecorate %vertexIDs Location 0
8671 OpDecorate %vertexIDs PerVertexKHR
8672 %void = OpTypeVoid
8673 %func = OpTypeFunction %void
8674 %float = OpTypeFloat 32
8675 %ptrFloat = OpTypePointer Input %float
8676 %vertexIDs = OpVariable %ptrFloat Input
8677 %int = OpTypeInt 32 1
8678 %int_0 = OpConstant %int 0
8679 %main = OpFunction %void None %func
8680 %label = OpLabel
8681 %load = OpLoad %float %vertexIDs
8682 OpReturn
8683 OpFunctionEnd
8684 )";
8685
8686 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8687 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8688 EXPECT_THAT(getDiagnosticString(),
8689 AnyVUID("VUID-StandaloneSpirv-Input-06778"));
8690 EXPECT_THAT(getDiagnosticString(),
8691 HasSubstr("PerVertexKHR must be declared as arrays"));
8692 }
8693
TEST_F(ValidateDecorations,RelaxedPrecisionDecorationOnNumericTypeBad)8694 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnNumericTypeBad) {
8695 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8696 std::string spirv = R"(
8697 OpCapability Shader
8698 OpMemoryModel Logical GLSL450
8699 OpEntryPoint Fragment %main "main"
8700 OpExecutionMode %main OriginUpperLeft
8701 OpDecorate %float RelaxedPrecision
8702 %void = OpTypeVoid
8703 %voidfn = OpTypeFunction %void
8704 %float = OpTypeFloat 32
8705 %main = OpFunction %void None %voidfn
8706 %label = OpLabel
8707 OpReturn
8708 OpFunctionEnd
8709 )";
8710
8711 CompileSuccessfully(spirv, env);
8712 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
8713 EXPECT_THAT(
8714 getDiagnosticString(),
8715 HasSubstr("RelaxPrecision decoration cannot be applied to a type"));
8716 }
8717
TEST_F(ValidateDecorations,RelaxedPrecisionDecorationOnStructMember)8718 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnStructMember) {
8719 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8720 std::string spirv = R"(
8721 OpCapability Shader
8722 OpMemoryModel Logical GLSL450
8723 OpEntryPoint Fragment %main "main"
8724 OpExecutionMode %main OriginUpperLeft
8725 OpMemberDecorate %struct 0 RelaxedPrecision
8726 %void = OpTypeVoid
8727 %voidfn = OpTypeFunction %void
8728 %float = OpTypeFloat 32
8729 %struct = OpTypeStruct %float
8730 %main = OpFunction %void None %voidfn
8731 %label = OpLabel
8732 OpReturn
8733 OpFunctionEnd
8734 )";
8735
8736 CompileSuccessfully(spirv, env);
8737 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
8738 }
8739
TEST_F(ValidateDecorations,VulkanFlatMultipleInterfaceGood)8740 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceGood) {
8741 std::string spirv = R"(
8742 OpCapability Shader
8743 OpCapability Geometry
8744 %1 = OpExtInstImport "GLSL.std.450"
8745 OpMemoryModel Logical GLSL450
8746 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8747 OpExecutionMode %main OriginUpperLeft
8748 OpSource GLSL 450
8749 OpDecorate %layer Location 0
8750 OpDecorate %gl_Layer Flat
8751 OpDecorate %gl_Layer BuiltIn Layer
8752 %void = OpTypeVoid
8753 %3 = OpTypeFunction %void
8754 %int = OpTypeInt 32 1
8755 %_ptr_Output_int = OpTypePointer Output %int
8756 %layer = OpVariable %_ptr_Output_int Output
8757 %_ptr_Input_int = OpTypePointer Input %int
8758 %gl_Layer = OpVariable %_ptr_Input_int Input
8759 %main = OpFunction %void None %3
8760 %5 = OpLabel
8761 %11 = OpLoad %int %gl_Layer
8762 OpStore %layer %11
8763 OpReturn
8764 OpFunctionEnd
8765 )";
8766
8767 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8768 EXPECT_EQ(SPV_SUCCESS,
8769 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8770 }
8771
TEST_F(ValidateDecorations,VulkanFlatMultipleInterfaceBad)8772 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceBad) {
8773 std::string spirv = R"(
8774 OpCapability Shader
8775 OpCapability Geometry
8776 %1 = OpExtInstImport "GLSL.std.450"
8777 OpMemoryModel Logical GLSL450
8778 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8779 OpExecutionMode %main OriginUpperLeft
8780 OpSource GLSL 450
8781 OpDecorate %layer Location 0
8782 OpDecorate %gl_Layer BuiltIn Layer
8783 %void = OpTypeVoid
8784 %3 = OpTypeFunction %void
8785 %int = OpTypeInt 32 1
8786 %_ptr_Output_int = OpTypePointer Output %int
8787 %layer = OpVariable %_ptr_Output_int Output
8788 %_ptr_Input_int = OpTypePointer Input %int
8789 %gl_Layer = OpVariable %_ptr_Input_int Input
8790 %main = OpFunction %void None %3
8791 %5 = OpLabel
8792 %11 = OpLoad %int %gl_Layer
8793 OpStore %layer %11
8794 OpReturn
8795 OpFunctionEnd
8796 )";
8797
8798 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8799 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8800 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8801 EXPECT_THAT(getDiagnosticString(),
8802 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8803 EXPECT_THAT(
8804 getDiagnosticString(),
8805 HasSubstr(
8806 "Fragment OpEntryPoint operand 4 with Input interfaces with integer "
8807 "or float type must have a Flat decoration for Entry Point id 2."));
8808 }
8809
TEST_F(ValidateDecorations,VulkanNoFlatFloat32)8810 TEST_F(ValidateDecorations, VulkanNoFlatFloat32) {
8811 std::string spirv = R"(
8812 OpCapability Shader
8813 %1 = OpExtInstImport "GLSL.std.450"
8814 OpMemoryModel Logical GLSL450
8815 OpEntryPoint Fragment %main "main" %in
8816 OpExecutionMode %main OriginUpperLeft
8817 OpSource GLSL 450
8818 OpDecorate %in Location 0
8819 %void = OpTypeVoid
8820 %3 = OpTypeFunction %void
8821 %float = OpTypeFloat 32
8822 %_ptr_Function_float = OpTypePointer Function %float
8823 %_ptr_Input_float = OpTypePointer Input %float
8824 %in = OpVariable %_ptr_Input_float Input
8825 %main = OpFunction %void None %3
8826 %5 = OpLabel
8827 %b = OpVariable %_ptr_Function_float Function
8828 %11 = OpLoad %float %in
8829 OpStore %b %11
8830 OpReturn
8831 OpFunctionEnd
8832 )";
8833
8834 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8835 EXPECT_EQ(SPV_SUCCESS,
8836 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8837 }
8838
TEST_F(ValidateDecorations,VulkanNoFlatFloat64)8839 TEST_F(ValidateDecorations, VulkanNoFlatFloat64) {
8840 std::string spirv = R"(
8841 OpCapability Shader
8842 OpCapability Float64
8843 %1 = OpExtInstImport "GLSL.std.450"
8844 OpMemoryModel Logical GLSL450
8845 OpEntryPoint Fragment %main "main" %in
8846 OpExecutionMode %main OriginUpperLeft
8847 OpSource GLSL 450
8848 OpDecorate %in Location 0
8849 %void = OpTypeVoid
8850 %3 = OpTypeFunction %void
8851 %double = OpTypeFloat 64
8852 %_ptr_Function_double = OpTypePointer Function %double
8853 %_ptr_Input_double = OpTypePointer Input %double
8854 %in = OpVariable %_ptr_Input_double Input
8855 %main = OpFunction %void None %3
8856 %5 = OpLabel
8857 %b = OpVariable %_ptr_Function_double Function
8858 %11 = OpLoad %double %in
8859 OpStore %b %11
8860 OpReturn
8861 OpFunctionEnd
8862 )";
8863
8864 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8865 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8866 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8867 EXPECT_THAT(getDiagnosticString(),
8868 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8869 EXPECT_THAT(
8870 getDiagnosticString(),
8871 HasSubstr(
8872 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8873 "or float type must have a Flat decoration for Entry Point id 2."));
8874 }
8875
TEST_F(ValidateDecorations,VulkanNoFlatVectorFloat64)8876 TEST_F(ValidateDecorations, VulkanNoFlatVectorFloat64) {
8877 std::string spirv = R"(
8878 OpCapability Shader
8879 OpCapability Float64
8880 %1 = OpExtInstImport "GLSL.std.450"
8881 OpMemoryModel Logical GLSL450
8882 OpEntryPoint Fragment %main "main" %in
8883 OpExecutionMode %main OriginUpperLeft
8884 OpSource GLSL 450
8885 OpDecorate %in Location 0
8886 %void = OpTypeVoid
8887 %3 = OpTypeFunction %void
8888 %double = OpTypeFloat 64
8889 %v2double = OpTypeVector %double 2
8890 %_ptr_Function_v2double = OpTypePointer Function %v2double
8891 %_ptr_Input_v2double = OpTypePointer Input %v2double
8892 %in = OpVariable %_ptr_Input_v2double Input
8893 %main = OpFunction %void None %3
8894 %5 = OpLabel
8895 %b = OpVariable %_ptr_Function_v2double Function
8896 %11 = OpLoad %v2double %in
8897 OpStore %b %11
8898 OpReturn
8899 OpFunctionEnd
8900 )";
8901
8902 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8903 EXPECT_EQ(SPV_SUCCESS,
8904 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8905 }
8906
TEST_F(ValidateDecorations,VulkanNoFlatIntVector)8907 TEST_F(ValidateDecorations, VulkanNoFlatIntVector) {
8908 std::string spirv = R"(
8909 OpCapability Shader
8910 %1 = OpExtInstImport "GLSL.std.450"
8911 OpMemoryModel Logical GLSL450
8912 OpEntryPoint Fragment %main "main" %in
8913 OpExecutionMode %main OriginUpperLeft
8914 OpSource GLSL 450
8915 OpDecorate %in Location 0
8916 %void = OpTypeVoid
8917 %3 = OpTypeFunction %void
8918 %int = OpTypeInt 32 1
8919 %v2int = OpTypeVector %int 2
8920 %_ptr_Function_v2int = OpTypePointer Function %v2int
8921 %_ptr_Input_v2int = OpTypePointer Input %v2int
8922 %in = OpVariable %_ptr_Input_v2int Input
8923 %main = OpFunction %void None %3
8924 %5 = OpLabel
8925 %b = OpVariable %_ptr_Function_v2int Function
8926 %12 = OpLoad %v2int %in
8927 OpStore %b %12
8928 OpReturn
8929 OpFunctionEnd
8930 )";
8931
8932 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8933 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8934 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8935 EXPECT_THAT(getDiagnosticString(),
8936 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8937 EXPECT_THAT(
8938 getDiagnosticString(),
8939 HasSubstr(
8940 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8941 "or float type must have a Flat decoration for Entry Point id 2."));
8942 }
8943
TEST_P(ValidateDecorationString,VulkanOutputInvalidInterface)8944 TEST_P(ValidateDecorationString, VulkanOutputInvalidInterface) {
8945 const std::string decoration = GetParam();
8946 std::stringstream ss;
8947 ss << R"(
8948 OpCapability Shader
8949 OpCapability SampleRateShading
8950 %1 = OpExtInstImport "GLSL.std.450"
8951 OpMemoryModel Logical GLSL450
8952 OpEntryPoint Fragment %main "main" %out
8953 OpExecutionMode %main OriginUpperLeft
8954 OpSource GLSL 450
8955 OpDecorate %out )"
8956 << decoration << R"(
8957 OpDecorate %out Location 0
8958 %void = OpTypeVoid
8959 %3 = OpTypeFunction %void
8960 %int = OpTypeInt 32 1
8961 %_ptr_Output_int = OpTypePointer Output %int
8962 %out = OpVariable %_ptr_Output_int Output
8963 %int_1 = OpConstant %int 1
8964 %main = OpFunction %void None %3
8965 %5 = OpLabel
8966 OpStore %out %int_1
8967 OpReturn
8968 OpFunctionEnd
8969 )";
8970
8971 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
8972 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8973 EXPECT_THAT(getDiagnosticString(),
8974 AnyVUID("VUID-StandaloneSpirv-Flat-06201"));
8975 EXPECT_THAT(
8976 getDiagnosticString(),
8977 HasSubstr("decorated variable must not be used in fragment execution "
8978 "model as an Output storage class for Entry Point id 2."));
8979 }
8980
TEST_P(ValidateDecorationString,VulkanVertexInputInvalidInterface)8981 TEST_P(ValidateDecorationString, VulkanVertexInputInvalidInterface) {
8982 const std::string decoration = GetParam();
8983 std::stringstream ss;
8984 ss << R"(
8985 OpCapability Shader
8986 OpCapability SampleRateShading
8987 %1 = OpExtInstImport "GLSL.std.450"
8988 OpMemoryModel Logical GLSL450
8989 OpEntryPoint Vertex %main "main" %out %in
8990 OpSource GLSL 450
8991 OpDecorate %in )"
8992 << decoration << R"(
8993 OpDecorate %out Location 0
8994 OpDecorate %in Location 0
8995 %void = OpTypeVoid
8996 %3 = OpTypeFunction %void
8997 %int = OpTypeInt 32 1
8998 %_ptr_Output_int = OpTypePointer Output %int
8999 %out = OpVariable %_ptr_Output_int Output
9000 %_ptr_Input_int = OpTypePointer Input %int
9001 %in = OpVariable %_ptr_Input_int Input
9002 %main = OpFunction %void None %3
9003 %5 = OpLabel
9004 %11 = OpLoad %int %in
9005 OpStore %out %11
9006 OpReturn
9007 OpFunctionEnd
9008 )";
9009
9010 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
9011 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9012 EXPECT_THAT(getDiagnosticString(),
9013 AnyVUID("VUID-StandaloneSpirv-Flat-06202"));
9014 EXPECT_THAT(
9015 getDiagnosticString(),
9016 HasSubstr("decorated variable must not be used in vertex execution model "
9017 "as an Input storage class for Entry Point id 2."));
9018 }
9019
9020 INSTANTIATE_TEST_SUITE_P(FragmentInputInterface, ValidateDecorationString,
9021 ::testing::Values("Flat", "NoPerspective", "Sample",
9022 "Centroid"));
9023
TEST_F(ValidateDecorations,NVBindlessSamplerArrayInBlock)9024 TEST_F(ValidateDecorations, NVBindlessSamplerArrayInBlock) {
9025 const std::string spirv = R"(
9026 OpCapability Shader
9027 OpCapability BindlessTextureNV
9028 OpExtension "SPV_NV_bindless_texture"
9029 %1 = OpExtInstImport "GLSL.std.450"
9030 OpMemoryModel Logical GLSL450
9031 OpSamplerImageAddressingModeNV 64
9032 OpEntryPoint Fragment %main "main"
9033 OpExecutionMode %main OriginUpperLeft
9034 OpSource GLSL 450
9035 OpName %main "main"
9036 OpName %UBO "UBO"
9037 OpMemberName %UBO 0 "uboSampler"
9038 OpName %_ ""
9039 OpDecorate %array ArrayStride 16
9040 OpMemberDecorate %UBO 0 Offset 0
9041 OpDecorate %UBO Block
9042 OpDecorate %_ DescriptorSet 0
9043 OpDecorate %_ Binding 2
9044 %void = OpTypeVoid
9045 %3 = OpTypeFunction %void
9046 %float = OpTypeFloat 32
9047 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
9048 %8 = OpTypeSampledImage %7
9049 %uint = OpTypeInt 32 0
9050 %uint_3 = OpConstant %uint 3
9051 %array = OpTypeArray %8 %uint_3
9052 %UBO = OpTypeStruct %array
9053 %pointer = OpTypePointer Uniform %UBO
9054 %_ = OpVariable %pointer Uniform
9055 %main = OpFunction %void None %3
9056 %5 = OpLabel
9057 OpReturn
9058 OpFunctionEnd
9059 )";
9060
9061 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
9062 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
9063 }
9064
TEST_F(ValidateDecorations,Std140ColMajorMat2x2)9065 TEST_F(ValidateDecorations, Std140ColMajorMat2x2) {
9066 const std::string spirv = R"(
9067 OpCapability Shader
9068 OpMemoryModel Logical GLSL450
9069 OpEntryPoint GLCompute %main "main"
9070 OpExecutionMode %main LocalSize 1 1 1
9071 OpDecorate %block Block
9072 OpMemberDecorate %block 0 Offset 0
9073 OpMemberDecorate %block 0 ColMajor
9074 OpMemberDecorate %block 0 MatrixStride 8
9075 OpDecorate %var DescriptorSet 0
9076 OpDecorate %var Binding 0
9077 %void = OpTypeVoid
9078 %void_fn = OpTypeFunction %void
9079 %float = OpTypeFloat 32
9080 %float2 = OpTypeVector %float 2
9081 %matrix = OpTypeMatrix %float2 2
9082 %block = OpTypeStruct %matrix
9083 %ptr_block = OpTypePointer Uniform %block
9084 %var = OpVariable %ptr_block Uniform
9085 %main = OpFunction %void None %void_fn
9086 %entry = OpLabel
9087 OpReturn
9088 OpFunctionEnd
9089 )";
9090
9091 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9092 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9093 EXPECT_THAT(
9094 getDiagnosticString(),
9095 HasSubstr(
9096 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9097 }
9098
TEST_F(ValidateDecorations,Std140RowMajorMat2x2)9099 TEST_F(ValidateDecorations, Std140RowMajorMat2x2) {
9100 const std::string spirv = R"(
9101 OpCapability Shader
9102 OpMemoryModel Logical GLSL450
9103 OpEntryPoint GLCompute %main "main"
9104 OpExecutionMode %main LocalSize 1 1 1
9105 OpDecorate %block Block
9106 OpMemberDecorate %block 0 Offset 0
9107 OpMemberDecorate %block 0 RowMajor
9108 OpMemberDecorate %block 0 MatrixStride 8
9109 OpDecorate %var DescriptorSet 0
9110 OpDecorate %var Binding 0
9111 %void = OpTypeVoid
9112 %void_fn = OpTypeFunction %void
9113 %float = OpTypeFloat 32
9114 %float2 = OpTypeVector %float 2
9115 %matrix = OpTypeMatrix %float2 2
9116 %block = OpTypeStruct %matrix
9117 %ptr_block = OpTypePointer Uniform %block
9118 %var = OpVariable %ptr_block Uniform
9119 %main = OpFunction %void None %void_fn
9120 %entry = OpLabel
9121 OpReturn
9122 OpFunctionEnd
9123 )";
9124
9125 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9126 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9127 EXPECT_THAT(
9128 getDiagnosticString(),
9129 HasSubstr(
9130 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9131 }
9132
TEST_F(ValidateDecorations,Std140ColMajorMat4x2)9133 TEST_F(ValidateDecorations, Std140ColMajorMat4x2) {
9134 const std::string spirv = R"(
9135 OpCapability Shader
9136 OpMemoryModel Logical GLSL450
9137 OpEntryPoint GLCompute %main "main"
9138 OpExecutionMode %main LocalSize 1 1 1
9139 OpDecorate %block Block
9140 OpMemberDecorate %block 0 Offset 0
9141 OpMemberDecorate %block 0 ColMajor
9142 OpMemberDecorate %block 0 MatrixStride 8
9143 OpDecorate %var DescriptorSet 0
9144 OpDecorate %var Binding 0
9145 %void = OpTypeVoid
9146 %void_fn = OpTypeFunction %void
9147 %float = OpTypeFloat 32
9148 %float2 = OpTypeVector %float 2
9149 %matrix = OpTypeMatrix %float2 4
9150 %block = OpTypeStruct %matrix
9151 %ptr_block = OpTypePointer Uniform %block
9152 %var = OpVariable %ptr_block Uniform
9153 %main = OpFunction %void None %void_fn
9154 %entry = OpLabel
9155 OpReturn
9156 OpFunctionEnd
9157 )";
9158
9159 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9160 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9161 EXPECT_THAT(
9162 getDiagnosticString(),
9163 HasSubstr(
9164 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9165 }
9166
TEST_F(ValidateDecorations,Std140ColMajorMat2x3)9167 TEST_F(ValidateDecorations, Std140ColMajorMat2x3) {
9168 const std::string spirv = R"(
9169 OpCapability Shader
9170 OpMemoryModel Logical GLSL450
9171 OpEntryPoint GLCompute %main "main"
9172 OpExecutionMode %main LocalSize 1 1 1
9173 OpDecorate %block Block
9174 OpMemberDecorate %block 0 Offset 0
9175 OpMemberDecorate %block 0 ColMajor
9176 OpMemberDecorate %block 0 MatrixStride 12
9177 OpDecorate %var DescriptorSet 0
9178 OpDecorate %var Binding 0
9179 %void = OpTypeVoid
9180 %void_fn = OpTypeFunction %void
9181 %float = OpTypeFloat 32
9182 %float3 = OpTypeVector %float 3
9183 %matrix = OpTypeMatrix %float3 2
9184 %block = OpTypeStruct %matrix
9185 %ptr_block = OpTypePointer Uniform %block
9186 %var = OpVariable %ptr_block Uniform
9187 %main = OpFunction %void None %void_fn
9188 %entry = OpLabel
9189 OpReturn
9190 OpFunctionEnd
9191 )";
9192
9193 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9194 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9195 EXPECT_THAT(getDiagnosticString(),
9196 HasSubstr("member 0 is a matrix with stride 12 not satisfying "
9197 "alignment to 16"));
9198 }
9199
TEST_F(ValidateDecorations,MatrixMissingMajornessUniform)9200 TEST_F(ValidateDecorations, MatrixMissingMajornessUniform) {
9201 const std::string spirv = R"(
9202 OpCapability Shader
9203 OpMemoryModel Logical GLSL450
9204 OpEntryPoint GLCompute %main "main"
9205 OpExecutionMode %main LocalSize 1 1 1
9206 OpDecorate %block Block
9207 OpMemberDecorate %block 0 Offset 0
9208 OpMemberDecorate %block 0 MatrixStride 16
9209 OpDecorate %var DescriptorSet 0
9210 OpDecorate %var Binding 0
9211 %void = OpTypeVoid
9212 %void_fn = OpTypeFunction %void
9213 %float = OpTypeFloat 32
9214 %float2 = OpTypeVector %float 2
9215 %matrix = OpTypeMatrix %float2 2
9216 %block = OpTypeStruct %matrix
9217 %ptr_block = OpTypePointer Uniform %block
9218 %var = OpVariable %ptr_block Uniform
9219 %main = OpFunction %void None %void_fn
9220 %entry = OpLabel
9221 OpReturn
9222 OpFunctionEnd
9223 )";
9224
9225 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9226 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9227 EXPECT_THAT(
9228 getDiagnosticString(),
9229 HasSubstr(
9230 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9231 }
9232
TEST_F(ValidateDecorations,MatrixMissingMajornessStorageBuffer)9233 TEST_F(ValidateDecorations, MatrixMissingMajornessStorageBuffer) {
9234 const std::string spirv = R"(
9235 OpCapability Shader
9236 OpExtension "SPV_KHR_storage_buffer_storage_class"
9237 OpMemoryModel Logical GLSL450
9238 OpEntryPoint GLCompute %main "main"
9239 OpExecutionMode %main LocalSize 1 1 1
9240 OpDecorate %block Block
9241 OpMemberDecorate %block 0 Offset 0
9242 OpMemberDecorate %block 0 MatrixStride 16
9243 OpDecorate %var DescriptorSet 0
9244 OpDecorate %var Binding 0
9245 %void = OpTypeVoid
9246 %void_fn = OpTypeFunction %void
9247 %float = OpTypeFloat 32
9248 %float2 = OpTypeVector %float 2
9249 %matrix = OpTypeMatrix %float2 2
9250 %block = OpTypeStruct %matrix
9251 %ptr_block = OpTypePointer StorageBuffer %block
9252 %var = OpVariable %ptr_block StorageBuffer
9253 %main = OpFunction %void None %void_fn
9254 %entry = OpLabel
9255 OpReturn
9256 OpFunctionEnd
9257 )";
9258
9259 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9260 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9261 EXPECT_THAT(
9262 getDiagnosticString(),
9263 HasSubstr(
9264 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9265 }
9266
TEST_F(ValidateDecorations,MatrixMissingMajornessPushConstant)9267 TEST_F(ValidateDecorations, MatrixMissingMajornessPushConstant) {
9268 const std::string spirv = R"(
9269 OpCapability Shader
9270 OpMemoryModel Logical GLSL450
9271 OpEntryPoint GLCompute %main "main"
9272 OpExecutionMode %main LocalSize 1 1 1
9273 OpDecorate %block Block
9274 OpMemberDecorate %block 0 Offset 0
9275 OpMemberDecorate %block 0 MatrixStride 16
9276 %void = OpTypeVoid
9277 %void_fn = OpTypeFunction %void
9278 %float = OpTypeFloat 32
9279 %float2 = OpTypeVector %float 2
9280 %matrix = OpTypeMatrix %float2 2
9281 %block = OpTypeStruct %matrix
9282 %ptr_block = OpTypePointer PushConstant %block
9283 %var = OpVariable %ptr_block PushConstant
9284 %main = OpFunction %void None %void_fn
9285 %entry = OpLabel
9286 OpReturn
9287 OpFunctionEnd
9288 )";
9289
9290 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9291 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9292 EXPECT_THAT(
9293 getDiagnosticString(),
9294 HasSubstr(
9295 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9296 }
9297
TEST_F(ValidateDecorations,StructWithRowAndColMajor)9298 TEST_F(ValidateDecorations, StructWithRowAndColMajor) {
9299 const std::string spirv = R"(
9300 OpCapability Shader
9301 OpMemoryModel Logical GLSL450
9302 OpEntryPoint GLCompute %main "main"
9303 OpExecutionMode %main LocalSize 1 1 1
9304 OpDecorate %block Block
9305 OpMemberDecorate %block 0 Offset 0
9306 OpMemberDecorate %block 0 MatrixStride 16
9307 OpMemberDecorate %block 0 ColMajor
9308 OpMemberDecorate %block 1 Offset 32
9309 OpMemberDecorate %block 1 MatrixStride 16
9310 OpMemberDecorate %block 1 RowMajor
9311 %void = OpTypeVoid
9312 %void_fn = OpTypeFunction %void
9313 %float = OpTypeFloat 32
9314 %float2 = OpTypeVector %float 2
9315 %matrix = OpTypeMatrix %float2 2
9316 %block = OpTypeStruct %matrix %matrix
9317 %ptr_block = OpTypePointer PushConstant %block
9318 %var = OpVariable %ptr_block PushConstant
9319 %main = OpFunction %void None %void_fn
9320 %entry = OpLabel
9321 OpReturn
9322 OpFunctionEnd
9323 )";
9324
9325 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9326 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9327 }
9328
TEST_F(ValidateDecorations,PhysicalStorageBufferWithOffset)9329 TEST_F(ValidateDecorations, PhysicalStorageBufferWithOffset) {
9330 const std::string spirv = R"(
9331 OpCapability Shader
9332 OpCapability Int64
9333 OpCapability PhysicalStorageBufferAddresses
9334 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9335 OpEntryPoint GLCompute %main "main" %pc
9336 OpExecutionMode %main LocalSize 1 1 1
9337 OpDecorate %pc_block Block
9338 OpMemberDecorate %pc_block 0 Offset 0
9339 OpMemberDecorate %pssbo_struct 0 Offset 0
9340 %void = OpTypeVoid
9341 %long = OpTypeInt 64 0
9342 %float = OpTypeFloat 32
9343 %int = OpTypeInt 32 0
9344 %int_0 = OpConstant %int 0
9345 %pc_block = OpTypeStruct %long
9346 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9347 %pc_long_ptr = OpTypePointer PushConstant %long
9348 %pc = OpVariable %pc_block_ptr PushConstant
9349 %pssbo_struct = OpTypeStruct %float
9350 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_struct
9351 %void_fn = OpTypeFunction %void
9352 %main = OpFunction %void None %void_fn
9353 %entry = OpLabel
9354 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9355 %addr = OpLoad %long %pc_gep
9356 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9357 OpReturn
9358 OpFunctionEnd
9359 )";
9360
9361 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9362 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9363 }
9364
TEST_F(ValidateDecorations,UntypedVariableDuplicateInterface)9365 TEST_F(ValidateDecorations, UntypedVariableDuplicateInterface) {
9366 const std::string spirv = R"(
9367 OpCapability Shader
9368 OpCapability UntypedPointersKHR
9369 OpCapability WorkgroupMemoryExplicitLayoutKHR
9370 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
9371 OpExtension "SPV_KHR_untyped_pointers"
9372 OpMemoryModel Logical GLSL450
9373 OpEntryPoint GLCompute %main "main" %var %var
9374 OpName %var "var"
9375 OpDecorate %struct Block
9376 OpMemberDecorate %struct 0 Offset 0
9377 %void = OpTypeVoid
9378 %int = OpTypeInt 32 0
9379 %struct = OpTypeStruct %int
9380 %ptr = OpTypeUntypedPointerKHR Workgroup
9381 %var = OpUntypedVariableKHR %ptr Workgroup %struct
9382 %void_fn = OpTypeFunction %void
9383 %main = OpFunction %void None %void_fn
9384 %entry = OpLabel
9385 OpReturn
9386 OpFunctionEnd
9387 )";
9388
9389 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
9390 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
9391 EXPECT_THAT(
9392 getDiagnosticString(),
9393 HasSubstr("Non-unique OpEntryPoint interface '2[%var]' is disallowed"));
9394 }
9395
TEST_F(ValidateDecorations,PhysicalStorageBufferMissingOffset)9396 TEST_F(ValidateDecorations, PhysicalStorageBufferMissingOffset) {
9397 const std::string spirv = R"(
9398 OpCapability Shader
9399 OpCapability Int64
9400 OpCapability PhysicalStorageBufferAddresses
9401 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9402 OpEntryPoint GLCompute %main "main" %pc
9403 OpExecutionMode %main LocalSize 1 1 1
9404 OpDecorate %pc_block Block
9405 OpMemberDecorate %pc_block 0 Offset 0
9406 %void = OpTypeVoid
9407 %long = OpTypeInt 64 0
9408 %float = OpTypeFloat 32
9409 %int = OpTypeInt 32 0
9410 %int_0 = OpConstant %int 0
9411 %pc_block = OpTypeStruct %long
9412 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9413 %pc_long_ptr = OpTypePointer PushConstant %long
9414 %pc = OpVariable %pc_block_ptr PushConstant
9415 %pssbo_struct = OpTypeStruct %float
9416 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_struct
9417 %void_fn = OpTypeFunction %void
9418 %main = OpFunction %void None %void_fn
9419 %entry = OpLabel
9420 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9421 %addr = OpLoad %long %pc_gep
9422 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9423 OpReturn
9424 OpFunctionEnd
9425 )";
9426
9427 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9428 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9429 EXPECT_THAT(
9430 getDiagnosticString(),
9431 HasSubstr("decorated as Block for variable in PhysicalStorageBuffer "
9432 "storage class must follow relaxed storage buffer layout "
9433 "rules: member 0 is missing an Offset decoration"));
9434 }
9435
TEST_F(ValidateDecorations,PhysicalStorageBufferMissingArrayStride)9436 TEST_F(ValidateDecorations, PhysicalStorageBufferMissingArrayStride) {
9437 const std::string spirv = R"(
9438 OpCapability Shader
9439 OpCapability Int64
9440 OpCapability PhysicalStorageBufferAddresses
9441 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9442 OpEntryPoint GLCompute %main "main" %pc
9443 OpExecutionMode %main LocalSize 1 1 1
9444 OpDecorate %pc_block Block
9445 OpMemberDecorate %pc_block 0 Offset 0
9446 %void = OpTypeVoid
9447 %long = OpTypeInt 64 0
9448 %float = OpTypeFloat 32
9449 %int = OpTypeInt 32 0
9450 %int_0 = OpConstant %int 0
9451 %int_4 = OpConstant %int 4
9452 %pc_block = OpTypeStruct %long
9453 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9454 %pc_long_ptr = OpTypePointer PushConstant %long
9455 %pc = OpVariable %pc_block_ptr PushConstant
9456 %pssbo_array = OpTypeArray %float %int_4
9457 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_array
9458 %void_fn = OpTypeFunction %void
9459 %main = OpFunction %void None %void_fn
9460 %entry = OpLabel
9461 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9462 %addr = OpLoad %long %pc_gep
9463 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9464 OpReturn
9465 OpFunctionEnd
9466 )";
9467
9468 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9469 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9470 EXPECT_THAT(
9471 getDiagnosticString(),
9472 HasSubstr(
9473 "decorated as Block for variable in PhysicalStorageBuffer storage "
9474 "class must follow relaxed storage buffer layout rules: member 0 "
9475 "contains an array with stride 0, but with an element size of 4"));
9476 }
9477
TEST_F(ValidateDecorations,MatrixArrayMissingMajorness)9478 TEST_F(ValidateDecorations, MatrixArrayMissingMajorness) {
9479 const std::string spirv = R"(
9480 OpCapability Shader
9481 OpMemoryModel Logical GLSL450
9482 OpEntryPoint GLCompute %main "main"
9483 OpExecutionMode %main LocalSize 1 1 1
9484 OpDecorate %var DescriptorSet 0
9485 OpDecorate %var Binding 0
9486 OpDecorate %block Block
9487 OpMemberDecorate %block 0 Offset 0
9488 OpMemberDecorate %block 0 MatrixStride 16
9489 OpDecorate %array ArrayStride 32
9490 %void = OpTypeVoid
9491 %float = OpTypeFloat 32
9492 %int = OpTypeInt 32 0
9493 %int_2 = OpConstant %int 2
9494 %vec = OpTypeVector %float 2
9495 %mat = OpTypeMatrix %vec 2
9496 %array = OpTypeArray %mat %int_2
9497 %block = OpTypeStruct %array
9498 %ptr = OpTypePointer Uniform %block
9499 %var = OpVariable %ptr Uniform
9500 %void_fn = OpTypeFunction %void
9501 %main = OpFunction %void None %void_fn
9502 %entry = OpLabel
9503 OpReturn
9504 OpFunctionEnd
9505 )";
9506
9507 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9508 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9509 EXPECT_THAT(
9510 getDiagnosticString(),
9511 HasSubstr(
9512 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9513 }
9514
TEST_F(ValidateDecorations,MatrixArrayMissingStride)9515 TEST_F(ValidateDecorations, MatrixArrayMissingStride) {
9516 const std::string spirv = R"(
9517 OpCapability Shader
9518 OpMemoryModel Logical GLSL450
9519 OpEntryPoint GLCompute %main "main"
9520 OpExecutionMode %main LocalSize 1 1 1
9521 OpDecorate %var DescriptorSet 0
9522 OpDecorate %var Binding 0
9523 OpDecorate %block Block
9524 OpMemberDecorate %block 0 Offset 0
9525 OpMemberDecorate %block 0 ColMajor
9526 OpDecorate %array ArrayStride 32
9527 %void = OpTypeVoid
9528 %float = OpTypeFloat 32
9529 %int = OpTypeInt 32 0
9530 %int_2 = OpConstant %int 2
9531 %vec = OpTypeVector %float 2
9532 %mat = OpTypeMatrix %vec 2
9533 %array = OpTypeArray %mat %int_2
9534 %block = OpTypeStruct %array
9535 %ptr = OpTypePointer Uniform %block
9536 %var = OpVariable %ptr Uniform
9537 %void_fn = OpTypeFunction %void
9538 %main = OpFunction %void None %void_fn
9539 %entry = OpLabel
9540 OpReturn
9541 OpFunctionEnd
9542 )";
9543
9544 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9545 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9546 EXPECT_THAT(
9547 getDiagnosticString(),
9548 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
9549 }
9550
TEST_F(ValidateDecorations,MatrixArrayBadStride)9551 TEST_F(ValidateDecorations, MatrixArrayBadStride) {
9552 const std::string spirv = R"(
9553 OpCapability Shader
9554 OpMemoryModel Logical GLSL450
9555 OpEntryPoint GLCompute %main "main"
9556 OpExecutionMode %main LocalSize 1 1 1
9557 OpDecorate %var DescriptorSet 0
9558 OpDecorate %var Binding 0
9559 OpDecorate %block Block
9560 OpMemberDecorate %block 0 Offset 0
9561 OpMemberDecorate %block 0 ColMajor
9562 OpMemberDecorate %block 0 MatrixStride 8
9563 OpDecorate %array ArrayStride 32
9564 %void = OpTypeVoid
9565 %float = OpTypeFloat 32
9566 %int = OpTypeInt 32 0
9567 %int_2 = OpConstant %int 2
9568 %vec = OpTypeVector %float 2
9569 %mat = OpTypeMatrix %vec 2
9570 %array = OpTypeArray %mat %int_2
9571 %block = OpTypeStruct %array
9572 %ptr = OpTypePointer Uniform %block
9573 %var = OpVariable %ptr Uniform
9574 %void_fn = OpTypeFunction %void
9575 %main = OpFunction %void None %void_fn
9576 %entry = OpLabel
9577 OpReturn
9578 OpFunctionEnd
9579 )";
9580
9581 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9582 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9583 EXPECT_THAT(
9584 getDiagnosticString(),
9585 HasSubstr("is a matrix with stride 8 not satisfying alignment to 16"));
9586 }
9587
TEST_F(ValidateDecorations,MatrixArrayArrayMissingMajorness)9588 TEST_F(ValidateDecorations, MatrixArrayArrayMissingMajorness) {
9589 const std::string spirv = R"(
9590 OpCapability Shader
9591 OpMemoryModel Logical GLSL450
9592 OpEntryPoint GLCompute %main "main"
9593 OpExecutionMode %main LocalSize 1 1 1
9594 OpDecorate %var DescriptorSet 0
9595 OpDecorate %var Binding 0
9596 OpDecorate %block Block
9597 OpMemberDecorate %block 0 Offset 0
9598 OpMemberDecorate %block 0 MatrixStride 16
9599 OpDecorate %array ArrayStride 32
9600 OpDecorate %rta ArrayStride 64
9601 %void = OpTypeVoid
9602 %float = OpTypeFloat 32
9603 %int = OpTypeInt 32 0
9604 %int_2 = OpConstant %int 2
9605 %vec = OpTypeVector %float 2
9606 %mat = OpTypeMatrix %vec 2
9607 %array = OpTypeArray %mat %int_2
9608 %rta = OpTypeRuntimeArray %array
9609 %block = OpTypeStruct %rta
9610 %ptr = OpTypePointer StorageBuffer %block
9611 %var = OpVariable %ptr StorageBuffer
9612 %void_fn = OpTypeFunction %void
9613 %main = OpFunction %void None %void_fn
9614 %entry = OpLabel
9615 OpReturn
9616 OpFunctionEnd
9617 )";
9618
9619 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9620 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9621 EXPECT_THAT(
9622 getDiagnosticString(),
9623 HasSubstr(
9624 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9625 }
9626
TEST_F(ValidateDecorations,MatrixArrayArrayMissingStride)9627 TEST_F(ValidateDecorations, MatrixArrayArrayMissingStride) {
9628 const std::string spirv = R"(
9629 OpCapability Shader
9630 OpMemoryModel Logical GLSL450
9631 OpEntryPoint GLCompute %main "main"
9632 OpExecutionMode %main LocalSize 1 1 1
9633 OpDecorate %var DescriptorSet 0
9634 OpDecorate %var Binding 0
9635 OpDecorate %block Block
9636 OpMemberDecorate %block 0 Offset 0
9637 OpMemberDecorate %block 0 ColMajor
9638 OpDecorate %array ArrayStride 32
9639 OpDecorate %rta ArrayStride 64
9640 %void = OpTypeVoid
9641 %float = OpTypeFloat 32
9642 %int = OpTypeInt 32 0
9643 %int_2 = OpConstant %int 2
9644 %vec = OpTypeVector %float 2
9645 %mat = OpTypeMatrix %vec 2
9646 %array = OpTypeArray %mat %int_2
9647 %rta = OpTypeRuntimeArray %array
9648 %block = OpTypeStruct %rta
9649 %ptr = OpTypePointer StorageBuffer %block
9650 %var = OpVariable %ptr StorageBuffer
9651 %void_fn = OpTypeFunction %void
9652 %main = OpFunction %void None %void_fn
9653 %entry = OpLabel
9654 OpReturn
9655 OpFunctionEnd
9656 )";
9657
9658 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9659 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9660 EXPECT_THAT(
9661 getDiagnosticString(),
9662 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
9663 }
9664
TEST_F(ValidateDecorations,MatrixArrayArrayBadStride)9665 TEST_F(ValidateDecorations, MatrixArrayArrayBadStride) {
9666 const std::string spirv = R"(
9667 OpCapability Shader
9668 OpMemoryModel Logical GLSL450
9669 OpEntryPoint GLCompute %main "main"
9670 OpExecutionMode %main LocalSize 1 1 1
9671 OpDecorate %var DescriptorSet 0
9672 OpDecorate %var Binding 0
9673 OpDecorate %block Block
9674 OpMemberDecorate %block 0 Offset 0
9675 OpMemberDecorate %block 0 ColMajor
9676 OpMemberDecorate %block 0 MatrixStride 8
9677 OpDecorate %array ArrayStride 32
9678 OpDecorate %a ArrayStride 64
9679 %void = OpTypeVoid
9680 %float = OpTypeFloat 32
9681 %int = OpTypeInt 32 0
9682 %int_2 = OpConstant %int 2
9683 %vec = OpTypeVector %float 2
9684 %mat = OpTypeMatrix %vec 2
9685 %array = OpTypeArray %mat %int_2
9686 %a = OpTypeArray %array %int_2
9687 %block = OpTypeStruct %a
9688 %ptr = OpTypePointer Uniform %block
9689 %var = OpVariable %ptr Uniform
9690 %void_fn = OpTypeFunction %void
9691 %main = OpFunction %void None %void_fn
9692 %entry = OpLabel
9693 OpReturn
9694 OpFunctionEnd
9695 )";
9696
9697 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
9698 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
9699 EXPECT_THAT(
9700 getDiagnosticString(),
9701 HasSubstr("is a matrix with stride 8 not satisfying alignment to 16"));
9702 }
9703
TEST_F(ValidateDecorations,MultipleBuiltinsInputVertex)9704 TEST_F(ValidateDecorations, MultipleBuiltinsInputVertex) {
9705 const std::string body = R"(
9706 OpCapability Shader
9707 OpCapability DrawParameters
9708 OpMemoryModel Logical GLSL450
9709 OpEntryPoint Vertex %main "main" %_ %gl_BaseInstance1 %gl_BaseInstance2
9710 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
9711 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
9712 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
9713 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
9714 OpDecorate %gl_PerVertex Block
9715 OpDecorate %gl_BaseInstance1 BuiltIn BaseInstance
9716 OpDecorate %gl_BaseInstance2 BuiltIn BaseInstance
9717 %void = OpTypeVoid
9718 %3 = OpTypeFunction %void
9719 %float = OpTypeFloat 32
9720 %v4float = OpTypeVector %float 4
9721 %uint = OpTypeInt 32 0
9722 %uint_1 = OpConstant %uint 1
9723 %_arr_float_uint_1 = OpTypeArray %float %uint_1
9724 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
9725 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
9726 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
9727 %int = OpTypeInt 32 1
9728 %int_0 = OpConstant %int 0
9729 %float_0 = OpConstant %float 0
9730 %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
9731 %_ptr_Input_int = OpTypePointer Input %int
9732 %gl_BaseInstance1 = OpVariable %_ptr_Input_int Input
9733 %gl_BaseInstance2 = OpVariable %_ptr_Input_int Input
9734 %_ptr_Output_v4float = OpTypePointer Output %v4float
9735 %main = OpFunction %void None %3
9736 %5 = OpLabel
9737 %20 = OpLoad %int %gl_BaseInstance1
9738 %21 = OpConvertSToF %float %20
9739 %22 = OpVectorTimesScalar %v4float %17 %21
9740 %24 = OpAccessChain %_ptr_Output_v4float %_ %int_0
9741 OpStore %24 %22
9742 OpReturn
9743 OpFunctionEnd
9744 )";
9745
9746 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
9747 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
9748 EXPECT_THAT(getDiagnosticString(),
9749 HasSubstr("OpEntryPoint contains duplicate input variables with "
9750 "BaseInstance builtin"));
9751 EXPECT_THAT(getDiagnosticString(),
9752 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09658"));
9753 }
9754
TEST_F(ValidateDecorations,MultipleBuiltinsInputMesh)9755 TEST_F(ValidateDecorations, MultipleBuiltinsInputMesh) {
9756 const std::string body = R"(
9757 OpCapability DrawParameters
9758 OpCapability MeshShadingEXT
9759 OpExtension "SPV_EXT_mesh_shader"
9760 OpMemoryModel Logical GLSL450
9761 OpEntryPoint MeshEXT %main "main" %gl_DrawID_1 %gl_DrawID_2
9762 OpExecutionMode %main LocalSize 1 1 1
9763 OpExecutionMode %main OutputVertices 32
9764 OpExecutionMode %main OutputPrimitivesEXT 32
9765 OpExecutionMode %main OutputTrianglesEXT
9766 OpDecorate %gl_DrawID_1 BuiltIn DrawIndex
9767 OpDecorate %gl_DrawID_2 BuiltIn DrawIndex
9768 %void = OpTypeVoid
9769 %3 = OpTypeFunction %void
9770 %int = OpTypeInt 32 1
9771 %_ptr_Input_int = OpTypePointer Input %int
9772 %gl_DrawID_1 = OpVariable %_ptr_Input_int Input
9773 %gl_DrawID_2 = OpVariable %_ptr_Input_int Input
9774 %uint = OpTypeInt 32 0
9775 %main = OpFunction %void None %3
9776 %5 = OpLabel
9777 %9 = OpLoad %int %gl_DrawID_1
9778 %11 = OpBitcast %uint %9
9779 %12 = OpLoad %int %gl_DrawID_2
9780 %13 = OpBitcast %uint %12
9781 OpSetMeshOutputsEXT %11 %13
9782 OpReturn
9783 OpFunctionEnd
9784 )";
9785
9786 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
9787 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
9788 EXPECT_THAT(getDiagnosticString(),
9789 HasSubstr("OpEntryPoint contains duplicate input variables with "
9790 "DrawIndex builtin"));
9791 EXPECT_THAT(getDiagnosticString(),
9792 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09658"));
9793 }
9794
TEST_F(ValidateDecorations,MultipleBuiltinsInputCompute)9795 TEST_F(ValidateDecorations, MultipleBuiltinsInputCompute) {
9796 const std::string body = R"(
9797 OpCapability Shader
9798 OpMemoryModel Logical GLSL450
9799 OpEntryPoint GLCompute %main "main" %_ %gl_WorkGroupID_1 %gl_WorkGroupID_2
9800 OpExecutionMode %main LocalSize 1 1 1
9801 OpMemberDecorate %Buffers 0 Offset 0
9802 OpDecorate %Buffers Block
9803 OpDecorate %_ DescriptorSet 0
9804 OpDecorate %_ Binding 0
9805 OpDecorate %gl_WorkGroupID_1 BuiltIn WorkgroupId
9806 OpDecorate %gl_WorkGroupID_2 BuiltIn WorkgroupId
9807 %void = OpTypeVoid
9808 %3 = OpTypeFunction %void
9809 %uint = OpTypeInt 32 0
9810 %v3uint = OpTypeVector %uint 3
9811 %Buffers = OpTypeStruct %v3uint
9812 %_ptr_StorageBuffer_Buffers = OpTypePointer StorageBuffer %Buffers
9813 %_ = OpVariable %_ptr_StorageBuffer_Buffers StorageBuffer
9814 %int = OpTypeInt 32 1
9815 %int_0 = OpConstant %int 0
9816 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
9817 %gl_WorkGroupID_1 = OpVariable %_ptr_Input_v3uint Input
9818 %gl_WorkGroupID_2 = OpVariable %_ptr_Input_v3uint Input
9819 %_ptr_StorageBuffer_v3uint = OpTypePointer StorageBuffer %v3uint
9820 %main = OpFunction %void None %3
9821 %5 = OpLabel
9822 %15 = OpLoad %v3uint %gl_WorkGroupID_1
9823 %16 = OpLoad %v3uint %gl_WorkGroupID_2
9824 %17 = OpIAdd %v3uint %15 %16
9825 %19 = OpAccessChain %_ptr_StorageBuffer_v3uint %_ %int_0
9826 OpStore %19 %17
9827 OpReturn
9828 OpFunctionEnd
9829 )";
9830
9831 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
9832 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
9833 EXPECT_THAT(getDiagnosticString(),
9834 HasSubstr("OpEntryPoint contains duplicate input variables with "
9835 "WorkgroupId builtin"));
9836 EXPECT_THAT(getDiagnosticString(),
9837 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09658"));
9838 }
9839
TEST_F(ValidateDecorations,MultipleBuiltinsOutputFragment)9840 TEST_F(ValidateDecorations, MultipleBuiltinsOutputFragment) {
9841 const std::string body = R"(
9842 OpCapability Shader
9843 OpMemoryModel Logical GLSL450
9844 OpEntryPoint Fragment %main "main" %gl_FragDepth_1 %gl_FragDepth_2
9845 OpExecutionMode %main OriginUpperLeft
9846 OpExecutionMode %main DepthReplacing
9847 OpDecorate %gl_FragDepth_1 BuiltIn FragDepth
9848 OpDecorate %gl_FragDepth_2 BuiltIn FragDepth
9849 %void = OpTypeVoid
9850 %3 = OpTypeFunction %void
9851 %float = OpTypeFloat 32
9852 %_ptr_Output_float = OpTypePointer Output %float
9853 %gl_FragDepth_1 = OpVariable %_ptr_Output_float Output
9854 %gl_FragDepth_2 = OpVariable %_ptr_Output_float Output
9855 %float_1 = OpConstant %float 1
9856 %main = OpFunction %void None %3
9857 %5 = OpLabel
9858 OpStore %gl_FragDepth_1 %float_1
9859 %10 = OpLoad %float %gl_FragDepth_1
9860 %11 = OpFAdd %float %10 %float_1
9861 OpStore %gl_FragDepth_2 %11
9862 OpReturn
9863 OpFunctionEnd
9864 )";
9865
9866 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
9867 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
9868 EXPECT_THAT(getDiagnosticString(),
9869 HasSubstr("OpEntryPoint contains duplicate output variables with "
9870 "FragDepth builtin"));
9871 EXPECT_THAT(getDiagnosticString(),
9872 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09659"));
9873 }
9874
TEST_F(ValidateDecorations,MultipleBuiltinsRayTmaxKHR)9875 TEST_F(ValidateDecorations, MultipleBuiltinsRayTmaxKHR) {
9876 const std::string body = R"(
9877 OpCapability RayTracingKHR
9878 OpExtension "SPV_KHR_ray_tracing"
9879 OpMemoryModel Logical GLSL450
9880 OpEntryPoint AnyHitKHR %main "main" %gl_RayTmaxEXT %gl_HitTEXT %incomingPayload
9881 OpDecorate %gl_RayTmaxEXT BuiltIn RayTmaxKHR
9882 OpDecorate %gl_HitTEXT BuiltIn RayTmaxKHR
9883 %void = OpTypeVoid
9884 %3 = OpTypeFunction %void
9885 %float = OpTypeFloat 32
9886 %_ptr_Function_float = OpTypePointer Function %float
9887 %_ptr_Input_float = OpTypePointer Input %float
9888 %gl_RayTmaxEXT = OpVariable %_ptr_Input_float Input
9889 %gl_HitTEXT = OpVariable %_ptr_Input_float Input
9890 %v4float = OpTypeVector %float 4
9891 %_ptr_IncomingRayPayloadKHR_v4float = OpTypePointer IncomingRayPayloadKHR %v4float
9892 %incomingPayload = OpVariable %_ptr_IncomingRayPayloadKHR_v4float IncomingRayPayloadKHR
9893 %main = OpFunction %void None %3
9894 %5 = OpLabel
9895 %a = OpVariable %_ptr_Function_float Function
9896 %b = OpVariable %_ptr_Function_float Function
9897 %11 = OpLoad %float %gl_RayTmaxEXT
9898 OpStore %a %11
9899 %14 = OpLoad %float %gl_HitTEXT
9900 OpStore %b %14
9901 %18 = OpLoad %float %a
9902 %19 = OpLoad %float %b
9903 %22 = OpCompositeConstruct %v4float %18 %18 %19 %19
9904 OpStore %incomingPayload %22
9905 OpTerminateRayKHR
9906 OpFunctionEnd
9907 )";
9908
9909 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
9910 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
9911 EXPECT_THAT(
9912 getDiagnosticString(),
9913 HasSubstr(
9914 "OpEntryPoint contains duplicate input variables with RayTmax"));
9915 EXPECT_THAT(getDiagnosticString(),
9916 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09658"));
9917 }
9918
TEST_F(ValidateDecorations,MultipleBuiltinsBlock)9919 TEST_F(ValidateDecorations, MultipleBuiltinsBlock) {
9920 const std::string body = R"(
9921 OpCapability Shader
9922 OpMemoryModel Logical GLSL450
9923 OpEntryPoint Vertex %main "main" %var
9924 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
9925 OpMemberDecorate %gl_PerVertex 1 BuiltIn Position
9926 OpDecorate %gl_PerVertex Block
9927 %void = OpTypeVoid
9928 %3 = OpTypeFunction %void
9929 %float = OpTypeFloat 32
9930 %v4float = OpTypeVector %float 4
9931 %gl_PerVertex = OpTypeStruct %v4float %v4float
9932 %_ptr_gl_PerVertex = OpTypePointer Output %gl_PerVertex
9933 %var = OpVariable %_ptr_gl_PerVertex Output
9934 %int = OpTypeInt 32 1
9935 %int_0 = OpConstant %int 0
9936 %int_1 = OpConstant %int 1
9937 %float_0 = OpConstant %float 0
9938 %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
9939 %ptr_vec4 = OpTypePointer Output %v4float
9940 %main = OpFunction %void None %3
9941 %5 = OpLabel
9942 %19 = OpAccessChain %ptr_vec4 %var %int_0
9943 OpStore %19 %17
9944 %22 = OpAccessChain %ptr_vec4 %var %int_1
9945 OpStore %22 %17
9946 OpReturn
9947 OpFunctionEnd
9948 )";
9949
9950 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_0);
9951 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9952 EXPECT_THAT(
9953 getDiagnosticString(),
9954 HasSubstr(
9955 "OpEntryPoint contains duplicate output variables with Position"));
9956 EXPECT_THAT(getDiagnosticString(),
9957 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09659"));
9958 }
9959
TEST_F(ValidateDecorations,MultipleBuiltinsBlockMixed)9960 TEST_F(ValidateDecorations, MultipleBuiltinsBlockMixed) {
9961 const std::string body = R"(
9962 OpCapability Shader
9963 OpMemoryModel Logical GLSL450
9964 OpEntryPoint Vertex %main "main" %var %position
9965 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
9966 OpDecorate %gl_PerVertex Block
9967 OpDecorate %position BuiltIn Position
9968 %void = OpTypeVoid
9969 %3 = OpTypeFunction %void
9970 %float = OpTypeFloat 32
9971 %v4float = OpTypeVector %float 4
9972 %gl_PerVertex = OpTypeStruct %v4float
9973 %_ptr_gl_PerVertex = OpTypePointer Output %gl_PerVertex
9974 %var = OpVariable %_ptr_gl_PerVertex Output
9975 %int = OpTypeInt 32 1
9976 %int_0 = OpConstant %int 0
9977 %int_1 = OpConstant %int 1
9978 %float_0 = OpConstant %float 0
9979 %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
9980 %ptr_vec4 = OpTypePointer Output %v4float
9981 %position = OpVariable %ptr_vec4 Output
9982 %main = OpFunction %void None %3
9983 %5 = OpLabel
9984 %19 = OpAccessChain %ptr_vec4 %var %int_0
9985 OpStore %19 %17
9986 OpStore %position %17
9987 OpReturn
9988 OpFunctionEnd
9989 )";
9990
9991 CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_0);
9992 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9993 EXPECT_THAT(
9994 getDiagnosticString(),
9995 HasSubstr(
9996 "OpEntryPoint contains duplicate output variables with Position"));
9997 EXPECT_THAT(getDiagnosticString(),
9998 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-09659"));
9999 }
10000
TEST_F(ValidateDecorations,UntypedVariableWorkgroupRequiresStruct)10001 TEST_F(ValidateDecorations, UntypedVariableWorkgroupRequiresStruct) {
10002 const std::string spirv = R"(
10003 OpCapability Shader
10004 OpCapability UntypedPointersKHR
10005 OpCapability WorkgroupMemoryExplicitLayoutKHR
10006 OpExtension "SPV_KHR_untyped_pointers"
10007 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
10008 OpMemoryModel Logical GLSL450
10009 OpEntryPoint GLCompute %main "main" %var
10010 %void = OpTypeVoid
10011 %int = OpTypeInt 32 0
10012 %ptr = OpTypeUntypedPointerKHR Workgroup
10013 %var = OpUntypedVariableKHR %ptr Workgroup %int
10014 %void_fn = OpTypeFunction %void
10015 %main = OpFunction %void None %void_fn
10016 %entry = OpLabel
10017 OpReturn
10018 OpFunctionEnd
10019 )";
10020
10021 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
10022 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10023 EXPECT_THAT(getDiagnosticString(),
10024 HasSubstr("Untyped workgroup variables in shaders must be block "
10025 "decorated structs"));
10026 }
10027
TEST_F(ValidateDecorations,UntypedVariableWorkgroupRequiresBlockStruct)10028 TEST_F(ValidateDecorations, UntypedVariableWorkgroupRequiresBlockStruct) {
10029 const std::string spirv = R"(
10030 OpCapability Shader
10031 OpCapability UntypedPointersKHR
10032 OpCapability WorkgroupMemoryExplicitLayoutKHR
10033 OpExtension "SPV_KHR_untyped_pointers"
10034 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
10035 OpMemoryModel Logical GLSL450
10036 OpEntryPoint GLCompute %main "main" %var
10037 %void = OpTypeVoid
10038 %int = OpTypeInt 32 0
10039 %struct = OpTypeStruct %int
10040 %ptr = OpTypeUntypedPointerKHR Workgroup
10041 %var = OpUntypedVariableKHR %ptr Workgroup %struct
10042 %void_fn = OpTypeFunction %void
10043 %main = OpFunction %void None %void_fn
10044 %entry = OpLabel
10045 OpReturn
10046 OpFunctionEnd
10047 )";
10048
10049 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
10050 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
10051 EXPECT_THAT(getDiagnosticString(),
10052 HasSubstr("Untyped workgroup variables in shaders must be block "
10053 "decorated"));
10054 }
10055
TEST_F(ValidateDecorations,UntypedVariableStorageBufferMissingBlock)10056 TEST_F(ValidateDecorations, UntypedVariableStorageBufferMissingBlock) {
10057 const std::string spirv = R"(
10058 OpCapability Shader
10059 OpCapability UntypedPointersKHR
10060 OpExtension "SPV_KHR_untyped_pointers"
10061 OpExtension "SPV_KHR_storage_buffer_storage_class"
10062 OpMemoryModel Logical GLSL450
10063 OpEntryPoint GLCompute %main "main"
10064 OpExecutionMode %main LocalSize 1 1 1
10065 OpName %struct "struct"
10066 %void = OpTypeVoid
10067 %int = OpTypeInt 32 0
10068 %struct = OpTypeStruct %int
10069 %ptr = OpTypeUntypedPointerKHR StorageBuffer
10070 %var = OpUntypedVariableKHR %ptr StorageBuffer %struct
10071 %void_fn = OpTypeFunction %void
10072 %main = OpFunction %void None %void_fn
10073 %entry = OpLabel
10074 OpReturn
10075 OpFunctionEnd
10076 )";
10077
10078 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10079 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10080 EXPECT_THAT(getDiagnosticString(),
10081 HasSubstr("StorageBuffer id '2' is missing Block decoration"));
10082 }
10083
TEST_F(ValidateDecorations,UntypedVariableUniformMissingBlock)10084 TEST_F(ValidateDecorations, UntypedVariableUniformMissingBlock) {
10085 const std::string spirv = R"(
10086 OpCapability Shader
10087 OpCapability UntypedPointersKHR
10088 OpExtension "SPV_KHR_untyped_pointers"
10089 OpMemoryModel Logical GLSL450
10090 OpEntryPoint GLCompute %main "main"
10091 OpExecutionMode %main LocalSize 1 1 1
10092 OpName %struct "struct"
10093 %void = OpTypeVoid
10094 %int = OpTypeInt 32 0
10095 %struct = OpTypeStruct %int
10096 %ptr = OpTypeUntypedPointerKHR Uniform
10097 %var = OpUntypedVariableKHR %ptr Uniform %struct
10098 %void_fn = OpTypeFunction %void
10099 %main = OpFunction %void None %void_fn
10100 %entry = OpLabel
10101 OpReturn
10102 OpFunctionEnd
10103 )";
10104
10105 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10106 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10107 EXPECT_THAT(
10108 getDiagnosticString(),
10109 HasSubstr("Uniform id '2' is missing Block or BufferBlock decoration"));
10110 }
10111
TEST_F(ValidateDecorations,UntypedVariablePushConstantMissingBlock)10112 TEST_F(ValidateDecorations, UntypedVariablePushConstantMissingBlock) {
10113 const std::string spirv = R"(
10114 OpCapability Shader
10115 OpCapability UntypedPointersKHR
10116 OpExtension "SPV_KHR_untyped_pointers"
10117 OpMemoryModel Logical GLSL450
10118 OpEntryPoint GLCompute %main "main"
10119 OpExecutionMode %main LocalSize 1 1 1
10120 OpName %struct "struct"
10121 %void = OpTypeVoid
10122 %int = OpTypeInt 32 0
10123 %struct = OpTypeStruct %int
10124 %ptr = OpTypeUntypedPointerKHR PushConstant
10125 %var = OpUntypedVariableKHR %ptr PushConstant %struct
10126 %void_fn = OpTypeFunction %void
10127 %main = OpFunction %void None %void_fn
10128 %entry = OpLabel
10129 OpReturn
10130 OpFunctionEnd
10131 )";
10132
10133 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10134 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10135 EXPECT_THAT(getDiagnosticString(),
10136 HasSubstr("PushConstant id '2' is missing Block decoration"));
10137 }
10138
10139 using UntypedVariableSetAndBinding = spvtest::ValidateBase<std::string>;
10140
TEST_P(UntypedVariableSetAndBinding,MissingSet)10141 TEST_P(UntypedVariableSetAndBinding, MissingSet) {
10142 const auto sc = GetParam();
10143 const std::string spirv = R"(
10144 OpCapability Shader
10145 OpCapability UntypedPointersKHR
10146 OpExtension "SPV_KHR_untyped_pointers"
10147 OpExtension "SPV_KHR_storage_buffer_storage_class"
10148 OpMemoryModel Logical GLSL450
10149 OpEntryPoint GLCompute %main "main"
10150 OpExecutionMode %main LocalSize 1 1 1
10151 OpName %var "var"
10152 OpDecorate %struct Block
10153 OpMemberDecorate %struct 0 Offset 0
10154 OpDecorate %var Binding 0
10155 %void = OpTypeVoid
10156 %int = OpTypeInt 32 0
10157 %struct = OpTypeStruct %int
10158 %ptr = OpTypeUntypedPointerKHR )" +
10159 sc + R"(
10160 %var = OpUntypedVariableKHR %ptr )" + sc + R"( %struct
10161 %void_fn = OpTypeFunction %void
10162 %main = OpFunction %void None %void_fn
10163 %entry = OpLabel
10164 %load = OpLoad %struct %var
10165 OpReturn
10166 OpFunctionEnd
10167 )";
10168
10169 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10170 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10171 EXPECT_THAT(getDiagnosticString(),
10172 HasSubstr(sc + " id '2' is missing DescriptorSet decoration"));
10173 }
10174
TEST_P(UntypedVariableSetAndBinding,MissingBinding)10175 TEST_P(UntypedVariableSetAndBinding, MissingBinding) {
10176 const auto sc = GetParam();
10177 const std::string spirv = R"(
10178 OpCapability Shader
10179 OpCapability UntypedPointersKHR
10180 OpExtension "SPV_KHR_untyped_pointers"
10181 OpExtension "SPV_KHR_storage_buffer_storage_class"
10182 OpMemoryModel Logical GLSL450
10183 OpEntryPoint GLCompute %main "main"
10184 OpExecutionMode %main LocalSize 1 1 1
10185 OpName %var "var"
10186 OpDecorate %struct Block
10187 OpMemberDecorate %struct 0 Offset 0
10188 OpDecorate %var DescriptorSet 0
10189 %void = OpTypeVoid
10190 %int = OpTypeInt 32 0
10191 %struct = OpTypeStruct %int
10192 %ptr = OpTypeUntypedPointerKHR )" +
10193 sc + R"(
10194 %var = OpUntypedVariableKHR %ptr )" + sc + R"( %struct
10195 %void_fn = OpTypeFunction %void
10196 %main = OpFunction %void None %void_fn
10197 %entry = OpLabel
10198 %load = OpLoad %struct %var
10199 OpReturn
10200 OpFunctionEnd
10201 )";
10202
10203 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10204 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10205 EXPECT_THAT(getDiagnosticString(),
10206 HasSubstr(sc + " id '2' is missing Binding decoration"));
10207 }
10208
10209 INSTANTIATE_TEST_SUITE_P(ValidateUntypedVariableSetAndBinding,
10210 UntypedVariableSetAndBinding,
10211 Values("StorageBuffer", "Uniform"));
10212
10213 using UntypedPointerLayout =
10214 spvtest::ValidateBase<std::tuple<std::string, std::string>>;
10215
TEST_P(UntypedPointerLayout,BadOffset)10216 TEST_P(UntypedPointerLayout, BadOffset) {
10217 const auto sc = std::get<0>(GetParam());
10218 const auto op = std::get<1>(GetParam());
10219 const std::string set = (sc == "StorageBuffer" || sc == "Uniform"
10220 ? R"(OpDecorate %var DescriptorSet 0
10221 OpDecorate %var Binding 0
10222 )"
10223 : R"()");
10224 const std::string spirv = R"(
10225 OpCapability Shader
10226 OpCapability VariablePointers
10227 OpCapability UntypedPointersKHR
10228 OpCapability WorkgroupMemoryExplicitLayoutKHR
10229 OpExtension "SPV_KHR_untyped_pointers"
10230 OpExtension "SPV_KHR_variable_pointers"
10231 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
10232 OpExtension "SPV_KHR_storage_buffer_storage_class"
10233 OpMemoryModel Logical GLSL450
10234 OpEntryPoint GLCompute %main "main" %var
10235 OpExecutionMode %main LocalSize 1 1 1
10236 OpName %var "var"
10237 OpDecorate %struct Block
10238 OpMemberDecorate %struct 0 Offset 0
10239 OpMemberDecorate %struct 1 Offset 4
10240 )" + set + R"(OpMemberDecorate %test_type 0 Offset 0
10241 OpMemberDecorate %test_type 1 Offset 1
10242 %void = OpTypeVoid
10243 %int = OpTypeInt 32 0
10244 %int_0 = OpConstant %int 0
10245 %struct = OpTypeStruct %int %int
10246 %test_type = OpTypeStruct %int %int
10247 %test_val = OpConstantNull %test_type
10248 %ptr = OpTypeUntypedPointerKHR )" +
10249 sc + R"(
10250 %var = OpUntypedVariableKHR %ptr )" + sc + R"( %struct
10251 %void_fn = OpTypeFunction %void
10252 %main = OpFunction %void None %void_fn
10253 %entry = OpLabel
10254 )" + op + R"(
10255 OpReturn
10256 OpFunctionEnd
10257 )";
10258
10259 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
10260 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
10261 const bool read_only = sc == "Uniform" || sc == "PushConstant";
10262 if (!read_only || op.find("OpStore") == std::string::npos) {
10263 EXPECT_THAT(getDiagnosticString(),
10264 HasSubstr("member 1 at offset 1 is not aligned to"));
10265 }
10266 }
10267
TEST_P(UntypedPointerLayout,BadStride)10268 TEST_P(UntypedPointerLayout, BadStride) {
10269 const auto sc = std::get<0>(GetParam());
10270 const auto op = std::get<1>(GetParam());
10271 const std::string set = (sc == "StorageBuffer" || sc == "Uniform"
10272 ? R"(OpDecorate %var DescriptorSet 0
10273 OpDecorate %var Binding 0
10274 )"
10275 : R"()");
10276 const std::string spirv = R"(
10277 OpCapability Shader
10278 OpCapability VariablePointers
10279 OpCapability UntypedPointersKHR
10280 OpCapability WorkgroupMemoryExplicitLayoutKHR
10281 OpExtension "SPV_KHR_untyped_pointers"
10282 OpExtension "SPV_KHR_variable_pointers"
10283 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
10284 OpExtension "SPV_KHR_storage_buffer_storage_class"
10285 OpMemoryModel Logical GLSL450
10286 OpEntryPoint GLCompute %main "main" %var
10287 OpExecutionMode %main LocalSize 1 1 1
10288 OpName %var "var"
10289 OpDecorate %struct Block
10290 OpMemberDecorate %struct 0 Offset 0
10291 OpMemberDecorate %struct 1 Offset 4
10292 )" + set + R"(OpDecorate %test_type ArrayStride 4
10293 %void = OpTypeVoid
10294 %int = OpTypeInt 32 0
10295 %int_0 = OpConstant %int 0
10296 %int_4 = OpConstant %int 4
10297 %int4 = OpTypeVector %int 4
10298 %test_type = OpTypeArray %int4 %int_4
10299 %test_val = OpConstantNull %test_type
10300 %struct = OpTypeStruct %int %int
10301 %ptr = OpTypeUntypedPointerKHR )" +
10302 sc + R"(
10303 %var = OpUntypedVariableKHR %ptr )" + sc + R"( %struct
10304 %void_fn = OpTypeFunction %void
10305 %main = OpFunction %void None %void_fn
10306 %entry = OpLabel
10307 )" + op + R"(
10308 OpReturn
10309 OpFunctionEnd
10310 )";
10311
10312 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
10313 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
10314 const bool read_only = sc == "Uniform" || sc == "PushConstant";
10315 if (!read_only || op.find("OpStore") == std::string::npos) {
10316 EXPECT_THAT(
10317 getDiagnosticString(),
10318 HasSubstr("array with stride 4 not satisfying alignment to 16"));
10319 }
10320 }
10321
10322 INSTANTIATE_TEST_SUITE_P(
10323 ValidateUntypedPointerLayout, UntypedPointerLayout,
10324 Combine(Values("StorageBuffer", "Uniform", "PushConstant", "Workgroup"),
10325 Values("%gep = OpUntypedAccessChainKHR %ptr %test_type %var %int_0",
10326 "%gep = OpUntypedInBoundsAccessChainKHR %ptr %test_type "
10327 "%var %int_0",
10328 "%gep = OpUntypedPtrAccessChainKHR %ptr %test_type %var "
10329 "%int_0 %int_0",
10330 "%ld = OpLoad %test_type %var", "OpStore %var %test_val")));
10331
TEST_F(ValidateDecorations,UntypedArrayLengthMissingOffset)10332 TEST_F(ValidateDecorations, UntypedArrayLengthMissingOffset) {
10333 const std::string spirv = R"(
10334 OpCapability Shader
10335 OpCapability UntypedPointersKHR
10336 OpExtension "SPV_KHR_untyped_pointers"
10337 OpMemoryModel Logical GLSL450
10338 OpEntryPoint GLCompute %main "main"
10339 OpExecutionMode %main LocalSize 1 1 1
10340 OpDecorate %struct Block
10341 OpDecorate %block Block
10342 OpMemberDecorate %block 0 Offset 0
10343 OpDecorate %array ArrayStride 4
10344 OpDecorate %var DescriptorSet 0
10345 OpDecorate %var Binding 0
10346 %void = OpTypeVoid
10347 %int = OpTypeInt 32 0
10348 %array = OpTypeRuntimeArray %int
10349 %struct = OpTypeStruct %array
10350 %block = OpTypeStruct %array
10351 %ptr = OpTypeUntypedPointerKHR StorageBuffer
10352 %var = OpUntypedVariableKHR %ptr StorageBuffer %block
10353 %void_fn = OpTypeFunction %void
10354 %main = OpFunction %void None %void_fn
10355 %entry = OpLabel
10356 %len = OpUntypedArrayLengthKHR %int %struct %var 0
10357 OpReturn
10358 OpFunctionEnd
10359 )";
10360
10361 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
10362 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
10363 EXPECT_THAT(getDiagnosticString(),
10364 HasSubstr("member 0 is missing an Offset decoration"));
10365 }
10366
TEST_F(ValidateDecorations,ComponentMultipleArrays)10367 TEST_F(ValidateDecorations, ComponentMultipleArrays) {
10368 const std::string spirv = R"(
10369 OpCapability Tessellation
10370 %1 = OpExtInstImport "GLSL.std.450"
10371 OpMemoryModel Logical GLSL450
10372 OpEntryPoint TessellationEvaluation %main "main" %_ %FOO %FOO0
10373 OpExecutionMode %main Triangles
10374 OpExecutionMode %main SpacingEqual
10375 OpExecutionMode %main VertexOrderCcw
10376 OpSource GLSL 460
10377 OpSourceExtension "GL_EXT_nonuniform_qualifier"
10378 OpName %main "main"
10379 OpName %gl_PerVertex "gl_PerVertex"
10380 OpMemberName %gl_PerVertex 0 "gl_Position"
10381 OpMemberName %gl_PerVertex 1 "gl_PointSize"
10382 OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
10383 OpMemberName %gl_PerVertex 3 "gl_CullDistance"
10384 OpName %_ ""
10385 OpName %FOO "FOO"
10386 OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
10387 OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
10388 OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
10389 OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
10390 OpDecorate %gl_PerVertex Block
10391 OpDecorate %FOO Component 2
10392 OpDecorate %FOO Location 1
10393 OpDecorate %FOO0 Location 1
10394 OpDecorate %FOO0 Component 0
10395 %void = OpTypeVoid
10396 %3 = OpTypeFunction %void
10397 %float = OpTypeFloat 32
10398 %v4float = OpTypeVector %float 4
10399 %uint = OpTypeInt 32 0
10400 %uint_1 = OpConstant %uint 1
10401 %_arr_float_uint_1 = OpTypeArray %float %uint_1
10402 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
10403 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
10404 %_ = OpVariable %_ptr_Output_gl_PerVertex Output
10405 %int = OpTypeInt 32 1
10406 %int_0 = OpConstant %int 0
10407 %v2float = OpTypeVector %float 2
10408 %uint_2 = OpConstant %uint 2
10409 %_arr_v2float_uint_2 = OpTypeArray %v2float %uint_2
10410 %uint_32 = OpConstant %uint 32
10411 %_arr__arr_v2float_uint_2_uint_32 = OpTypeArray %_arr_v2float_uint_2 %uint_32
10412 %_ptr_Input__arr__arr_v2float_uint_2_uint_32 = OpTypePointer Input %_arr__arr_v2float_uint_2_uint_32
10413 %FOO = OpVariable %_ptr_Input__arr__arr_v2float_uint_2_uint_32 Input
10414 %FOO0 = OpVariable %_ptr_Input__arr__arr_v2float_uint_2_uint_32 Input
10415 %_ptr_Input_v2float = OpTypePointer Input %v2float
10416 %int_1 = OpConstant %int 1
10417 %uint_0 = OpConstant %uint 0
10418 %_ptr_Output_float = OpTypePointer Output %float
10419 %main = OpFunction %void None %3
10420 %5 = OpLabel
10421 %24 = OpAccessChain %_ptr_Input_v2float %FOO %int_0 %int_0
10422 %25 = OpLoad %v2float %24
10423 %27 = OpAccessChain %_ptr_Input_v2float %FOO0 %int_1 %int_1
10424 %28 = OpLoad %v2float %27
10425 %29 = OpFAdd %v2float %25 %28
10426 %32 = OpAccessChain %_ptr_Output_float %_ %int_0 %uint_0
10427 %33 = OpCompositeExtract %float %29 0
10428 OpStore %32 %33
10429 %34 = OpAccessChain %_ptr_Output_float %_ %int_0 %uint_1
10430 %35 = OpCompositeExtract %float %29 1
10431 OpStore %34 %35
10432 OpReturn
10433 OpFunctionEnd
10434 )";
10435
10436 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
10437 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
10438 }
10439
10440 } // namespace
10441 } // namespace val
10442 } // namespace spvtools
10443