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::__anon27113::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, VulkanUniformMissingDescriptorSetBad)3212 TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
3213 std::string spirv = R"(
3214 OpCapability Shader
3215 OpMemoryModel Logical GLSL450
3216 OpEntryPoint Fragment %1 "main"
3217 OpExecutionMode %1 OriginUpperLeft
3218
3219 OpDecorate %struct Block
3220 OpMemberDecorate %struct 0 Offset 0
3221 OpDecorate %var Binding 0
3222
3223 %void = OpTypeVoid
3224 %voidfn = OpTypeFunction %void
3225 %float = OpTypeFloat 32
3226 %struct = OpTypeStruct %float
3227 %ptr = OpTypePointer Uniform %struct
3228 %ptr_float = OpTypePointer Uniform %float
3229 %var = OpVariable %ptr Uniform
3230 %int = OpTypeInt 32 0
3231 %int_0 = OpConstant %int 0
3232
3233 %1 = OpFunction %void None %voidfn
3234 %label = OpLabel
3235 %2 = OpAccessChain %ptr_float %var %int_0
3236 %3 = OpLoad %float %2
3237 OpReturn
3238 OpFunctionEnd
3239 )";
3240
3241 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3242 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3243 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3244 EXPECT_THAT(getDiagnosticString(),
3245 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3246 EXPECT_THAT(getDiagnosticString(),
3247 HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n"
3248 "From Vulkan spec:\n"
3249 "These variables must have DescriptorSet and Binding "
3250 "decorations specified"));
3251 }
3252
TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad)3253 TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) {
3254 std::string spirv = R"(
3255 OpCapability Shader
3256 OpMemoryModel Logical GLSL450
3257 OpEntryPoint Fragment %1 "main"
3258 OpExecutionMode %1 OriginUpperLeft
3259
3260 OpDecorate %struct Block
3261 OpMemberDecorate %struct 0 Offset 0
3262 OpDecorate %var DescriptorSet 0
3263
3264 %void = OpTypeVoid
3265 %voidfn = OpTypeFunction %void
3266 %float = OpTypeFloat 32
3267 %struct = OpTypeStruct %float
3268 %ptr = OpTypePointer Uniform %struct
3269 %ptr_float = OpTypePointer Uniform %float
3270 %var = OpVariable %ptr Uniform
3271 %int = OpTypeInt 32 0
3272 %int_0 = OpConstant %int 0
3273
3274 %1 = OpFunction %void None %voidfn
3275 %label = OpLabel
3276 %2 = OpAccessChain %ptr_float %var %int_0
3277 %3 = OpLoad %float %2
3278 OpReturn
3279 OpFunctionEnd
3280 )";
3281
3282 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3283 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3284 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3285 EXPECT_THAT(getDiagnosticString(),
3286 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3287 EXPECT_THAT(getDiagnosticString(),
3288 HasSubstr("Uniform id '3' is missing Binding decoration.\n"
3289 "From Vulkan spec:\n"
3290 "These variables must have DescriptorSet and Binding "
3291 "decorations specified"));
3292 }
3293
TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad)3294 TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) {
3295 std::string spirv = R"(
3296 OpCapability Shader
3297 OpMemoryModel Logical GLSL450
3298 OpEntryPoint Fragment %1 "main"
3299 OpExecutionMode %1 OriginUpperLeft
3300
3301 OpDecorate %var Binding 0
3302
3303 %void = OpTypeVoid
3304 %voidfn = OpTypeFunction %void
3305 %sampler = OpTypeSampler
3306 %ptr = OpTypePointer UniformConstant %sampler
3307 %var = OpVariable %ptr UniformConstant
3308
3309 %1 = OpFunction %void None %voidfn
3310 %label = OpLabel
3311 %2 = OpLoad %sampler %var
3312 OpReturn
3313 OpFunctionEnd
3314 )";
3315
3316 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3317 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3318 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3319 EXPECT_THAT(getDiagnosticString(),
3320 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3321 EXPECT_THAT(
3322 getDiagnosticString(),
3323 HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n"
3324 "From Vulkan spec:\n"
3325 "These variables must have DescriptorSet and Binding "
3326 "decorations specified"));
3327 }
3328
TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad)3329 TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) {
3330 std::string spirv = R"(
3331 OpCapability Shader
3332 OpMemoryModel Logical GLSL450
3333 OpEntryPoint Fragment %1 "main"
3334 OpExecutionMode %1 OriginUpperLeft
3335
3336 OpDecorate %var DescriptorSet 0
3337
3338 %void = OpTypeVoid
3339 %voidfn = OpTypeFunction %void
3340 %sampler = OpTypeSampler
3341 %ptr = OpTypePointer UniformConstant %sampler
3342 %var = OpVariable %ptr UniformConstant
3343
3344 %1 = OpFunction %void None %voidfn
3345 %label = OpLabel
3346 %2 = OpLoad %sampler %var
3347 OpReturn
3348 OpFunctionEnd
3349 )";
3350
3351 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3352 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3353 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3354 EXPECT_THAT(getDiagnosticString(),
3355 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3356 EXPECT_THAT(
3357 getDiagnosticString(),
3358 HasSubstr("UniformConstant id '2' is missing Binding decoration.\n"
3359 "From Vulkan spec:\n"
3360 "These variables must have DescriptorSet and Binding "
3361 "decorations specified"));
3362 }
3363
TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad)3364 TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) {
3365 std::string spirv = R"(
3366 OpCapability Shader
3367 OpExtension "SPV_KHR_storage_buffer_storage_class"
3368 OpMemoryModel Logical GLSL450
3369 OpEntryPoint Fragment %1 "main"
3370 OpExecutionMode %1 OriginUpperLeft
3371
3372 OpDecorate %struct Block
3373 OpDecorate %var Binding 0
3374
3375 %void = OpTypeVoid
3376 %voidfn = OpTypeFunction %void
3377 %float = OpTypeFloat 32
3378 %struct = OpTypeStruct %float
3379 %ptr = OpTypePointer StorageBuffer %struct
3380 %var = OpVariable %ptr StorageBuffer
3381 %ptr_float = OpTypePointer StorageBuffer %float
3382 %int = OpTypeInt 32 0
3383 %int_0 = OpConstant %int 0
3384
3385 %1 = OpFunction %void None %voidfn
3386 %label = OpLabel
3387 %2 = OpAccessChain %ptr_float %var %int_0
3388 %3 = OpLoad %float %2
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("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3401 "From Vulkan spec:\n"
3402 "These variables must have DescriptorSet and Binding "
3403 "decorations specified"));
3404 }
3405
TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad)3406 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) {
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 DescriptorSet 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(getDiagnosticString(),
3441 HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n"
3442 "From Vulkan spec:\n"
3443 "These variables must have DescriptorSet and Binding "
3444 "decorations specified"));
3445 }
3446
TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetSubFunctionBad)3447 TEST_F(ValidateDecorations,
3448 VulkanStorageBufferMissingDescriptorSetSubFunctionBad) {
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 Binding 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 %call = OpFunctionCall %void %2
3472 OpReturn
3473 OpFunctionEnd
3474 %2 = OpFunction %void None %voidfn
3475 %label2 = OpLabel
3476 %3 = OpAccessChain %ptr_float %var %int_0
3477 %4 = OpLoad %float %3
3478 OpReturn
3479 OpFunctionEnd
3480 )";
3481
3482 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3483 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3484 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3485 EXPECT_THAT(getDiagnosticString(),
3486 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3487 EXPECT_THAT(
3488 getDiagnosticString(),
3489 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3490 "From Vulkan spec:\n"
3491 "These variables must have DescriptorSet and Binding "
3492 "decorations specified"));
3493 }
3494
TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorAndBindingUnusedGood)3495 TEST_F(ValidateDecorations,
3496 VulkanStorageBufferMissingDescriptorAndBindingUnusedGood) {
3497 std::string spirv = R"(
3498 OpCapability Shader
3499 OpExtension "SPV_KHR_storage_buffer_storage_class"
3500 OpMemoryModel Logical GLSL450
3501 OpEntryPoint Fragment %1 "main"
3502 OpExecutionMode %1 OriginUpperLeft
3503 OpDecorate %struct Block
3504 OpMemberDecorate %struct 0 Offset 0
3505
3506 %void = OpTypeVoid
3507 %voidfn = OpTypeFunction %void
3508 %float = OpTypeFloat 32
3509 %struct = OpTypeStruct %float
3510 %ptr = OpTypePointer StorageBuffer %struct
3511 %var = OpVariable %ptr StorageBuffer
3512
3513 %1 = OpFunction %void None %voidfn
3514 %label = OpLabel
3515 OpReturn
3516 OpFunctionEnd
3517 )";
3518
3519 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3520 EXPECT_EQ(SPV_SUCCESS,
3521 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3522 }
3523
TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood)3524 TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) {
3525 std::string spirv = R"(
3526 OpCapability Shader
3527 OpMemoryModel Logical GLSL450
3528 OpEntryPoint Fragment %1 "main"
3529 OpExecutionMode %1 OriginUpperLeft
3530
3531 OpDecorate %struct Block
3532 OpMemberDecorate %struct 0 Offset 0
3533 OpDecorate %var Binding 0
3534
3535 %void = OpTypeVoid
3536 %voidfn = OpTypeFunction %void
3537 %float = OpTypeFloat 32
3538 %struct = OpTypeStruct %float
3539 %ptr = OpTypePointer Uniform %struct
3540 %var = OpVariable %ptr Uniform
3541
3542 %1 = OpFunction %void None %voidfn
3543 %label = OpLabel
3544 OpReturn
3545 OpFunctionEnd
3546 )";
3547
3548 CompileSuccessfully(spirv);
3549 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3550 << getDiagnosticString();
3551 }
3552
TEST_F(ValidateDecorations, UniformMissingBindingGood)3553 TEST_F(ValidateDecorations, UniformMissingBindingGood) {
3554 std::string spirv = R"(
3555 OpCapability Shader
3556 OpMemoryModel Logical GLSL450
3557 OpEntryPoint Fragment %1 "main"
3558 OpExecutionMode %1 OriginUpperLeft
3559
3560 OpDecorate %struct Block
3561 OpMemberDecorate %struct 0 Offset 0
3562 OpDecorate %var DescriptorSet 0
3563
3564 %void = OpTypeVoid
3565 %voidfn = OpTypeFunction %void
3566 %float = OpTypeFloat 32
3567 %struct = OpTypeStruct %float
3568 %ptr = OpTypePointer Uniform %struct
3569 %var = OpVariable %ptr Uniform
3570
3571 %1 = OpFunction %void None %voidfn
3572 %label = OpLabel
3573 OpReturn
3574 OpFunctionEnd
3575 )";
3576
3577 CompileSuccessfully(spirv);
3578 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3579 << getDiagnosticString();
3580 }
3581
TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood)3582 TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) {
3583 std::string spirv = R"(
3584 OpCapability Shader
3585 OpMemoryModel Logical GLSL450
3586 OpEntryPoint Fragment %1 "main"
3587 OpExecutionMode %1 OriginUpperLeft
3588
3589 OpDecorate %var Binding 0
3590
3591 %void = OpTypeVoid
3592 %voidfn = OpTypeFunction %void
3593 %sampler = OpTypeSampler
3594 %ptr = OpTypePointer UniformConstant %sampler
3595 %var = OpVariable %ptr UniformConstant
3596
3597 %1 = OpFunction %void None %voidfn
3598 %label = OpLabel
3599 OpReturn
3600 OpFunctionEnd
3601 )";
3602
3603 CompileSuccessfully(spirv);
3604 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3605 << getDiagnosticString();
3606 }
3607
TEST_F(ValidateDecorations, UniformConstantMissingBindingGood)3608 TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) {
3609 std::string spirv = R"(
3610 OpCapability Shader
3611 OpMemoryModel Logical GLSL450
3612 OpEntryPoint Fragment %1 "main"
3613 OpExecutionMode %1 OriginUpperLeft
3614
3615 OpDecorate %var DescriptorSet 0
3616
3617 %void = OpTypeVoid
3618 %voidfn = OpTypeFunction %void
3619 %sampler = OpTypeSampler
3620 %ptr = OpTypePointer UniformConstant %sampler
3621 %var = OpVariable %ptr UniformConstant
3622
3623 %1 = OpFunction %void None %voidfn
3624 %label = OpLabel
3625 OpReturn
3626 OpFunctionEnd
3627 )";
3628
3629 CompileSuccessfully(spirv);
3630 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3631 << getDiagnosticString();
3632 }
3633
TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood)3634 TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) {
3635 std::string spirv = R"(
3636 OpCapability Shader
3637 OpExtension "SPV_KHR_storage_buffer_storage_class"
3638 OpMemoryModel Logical GLSL450
3639 OpEntryPoint Fragment %1 "main"
3640 OpExecutionMode %1 OriginUpperLeft
3641
3642 OpDecorate %struct BufferBlock
3643 OpDecorate %var Binding 0
3644
3645 %void = OpTypeVoid
3646 %voidfn = OpTypeFunction %void
3647 %float = OpTypeFloat 32
3648 %struct = OpTypeStruct %float
3649 %ptr = OpTypePointer StorageBuffer %struct
3650 %var = OpVariable %ptr StorageBuffer
3651
3652 %1 = OpFunction %void None %voidfn
3653 %label = OpLabel
3654 OpReturn
3655 OpFunctionEnd
3656 )";
3657
3658 CompileSuccessfully(spirv);
3659 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3660 << getDiagnosticString();
3661 }
3662
TEST_F(ValidateDecorations, StorageBufferMissingBindingGood)3663 TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) {
3664 std::string spirv = R"(
3665 OpCapability Shader
3666 OpExtension "SPV_KHR_storage_buffer_storage_class"
3667 OpMemoryModel Logical GLSL450
3668 OpEntryPoint Fragment %1 "main"
3669 OpExecutionMode %1 OriginUpperLeft
3670
3671 OpDecorate %struct BufferBlock
3672 OpDecorate %var DescriptorSet 0
3673
3674 %void = OpTypeVoid
3675 %voidfn = OpTypeFunction %void
3676 %float = OpTypeFloat 32
3677 %struct = OpTypeStruct %float
3678 %ptr = OpTypePointer StorageBuffer %struct
3679 %var = OpVariable %ptr StorageBuffer
3680
3681 %1 = OpFunction %void None %voidfn
3682 %label = OpLabel
3683 OpReturn
3684 OpFunctionEnd
3685 )";
3686
3687 CompileSuccessfully(spirv);
3688 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3689 << getDiagnosticString();
3690 }
3691
TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood)3692 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) {
3693 // Spot check buffer rules when using StorageBuffer storage class with Block
3694 // decoration.
3695 std::string spirv = R"(
3696 OpCapability Shader
3697 OpExtension "SPV_KHR_storage_buffer_storage_class"
3698 OpMemoryModel Logical GLSL450
3699 OpEntryPoint Vertex %main "main"
3700 OpSource GLSL 450
3701 OpDecorate %_arr_float_uint_2 ArrayStride 4
3702 OpMemberDecorate %S 0 Offset 0
3703 OpMemberDecorate %S 1 Offset 8
3704 OpDecorate %S Block
3705 OpDecorate %u DescriptorSet 0
3706 OpDecorate %u Binding 0
3707 %void = OpTypeVoid
3708 %3 = OpTypeFunction %void
3709 %float = OpTypeFloat 32
3710 %v2float = OpTypeVector %float 2
3711 %uint = OpTypeInt 32 0
3712 %uint_2 = OpConstant %uint 2
3713 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3714 %S = OpTypeStruct %v2float %_arr_float_uint_2
3715 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3716 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3717 %main = OpFunction %void None %3
3718 %5 = OpLabel
3719 OpReturn
3720 OpFunctionEnd
3721 )";
3722
3723 CompileSuccessfully(spirv);
3724 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
3725 << getDiagnosticString();
3726 }
3727
TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad)3728 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad) {
3729 // Like the previous test, but with offset 7.
3730 std::string spirv = R"(
3731 OpCapability Shader
3732 OpExtension "SPV_KHR_storage_buffer_storage_class"
3733 OpMemoryModel Logical GLSL450
3734 OpEntryPoint Vertex %main "main"
3735 OpSource GLSL 450
3736 OpDecorate %_arr_float_uint_2 ArrayStride 4
3737 OpMemberDecorate %S 0 Offset 0
3738 OpMemberDecorate %S 1 Offset 7
3739 OpDecorate %S Block
3740 OpDecorate %u DescriptorSet 0
3741 OpDecorate %u Binding 0
3742 %void = OpTypeVoid
3743 %3 = OpTypeFunction %void
3744 %float = OpTypeFloat 32
3745 %v2float = OpTypeVector %float 2
3746 %uint = OpTypeInt 32 0
3747 %uint_2 = OpConstant %uint 2
3748 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3749 %S = OpTypeStruct %v2float %_arr_float_uint_2
3750 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3751 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3752 %main = OpFunction %void None %3
3753 %5 = OpLabel
3754 OpReturn
3755 OpFunctionEnd
3756 )";
3757
3758 CompileSuccessfully(spirv);
3759 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3760 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3761 EXPECT_THAT(
3762 getDiagnosticString(),
3763 HasSubstr(
3764 "Structure id 3 decorated as Block for variable in StorageBuffer "
3765 "storage class must follow standard storage buffer layout rules: "
3766 "member 1 at offset 7 is not aligned to 4"));
3767 }
3768
TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout)3769 TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout) {
3770 std::string spirv = R"(
3771 OpCapability Shader
3772 %1 = OpExtInstImport "GLSL.std.450"
3773 OpMemoryModel Logical GLSL450
3774 OpEntryPoint GLCompute %main "main"
3775 OpExecutionMode %main LocalSize 1 1 1
3776 OpSource GLSL 430
3777 OpMemberDecorate %F 0 Offset 0
3778 OpMemberDecorate %F 1 Offset 8
3779 OpDecorate %_arr_float_uint_2 ArrayStride 4
3780 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3781 OpMemberDecorate %O 0 Offset 0
3782 OpMemberDecorate %O 1 Offset 16
3783 OpMemberDecorate %O 2 Offset 24
3784 OpMemberDecorate %O 3 Offset 32
3785 OpMemberDecorate %O 4 ColMajor
3786 OpMemberDecorate %O 4 Offset 48
3787 OpMemberDecorate %O 4 MatrixStride 16
3788 OpDecorate %_arr_O_uint_2 ArrayStride 144
3789 OpMemberDecorate %Output 0 Offset 0
3790 OpMemberDecorate %Output 1 Offset 8
3791 OpMemberDecorate %Output 2 Offset 16
3792 OpMemberDecorate %Output 3 Offset 32
3793 OpMemberDecorate %Output 4 Offset 48
3794 OpMemberDecorate %Output 5 Offset 52
3795 OpMemberDecorate %Output 6 ColMajor
3796 OpMemberDecorate %Output 6 Offset 64
3797 OpMemberDecorate %Output 6 MatrixStride 16
3798 OpMemberDecorate %Output 7 Offset 96
3799 OpDecorate %Output BufferBlock
3800 %void = OpTypeVoid
3801 %3 = OpTypeFunction %void
3802 %float = OpTypeFloat 32
3803 %v2float = OpTypeVector %float 2
3804 %v3float = OpTypeVector %float 3
3805 %int = OpTypeInt 32 1
3806 %uint = OpTypeInt 32 0
3807 %v2uint = OpTypeVector %uint 2
3808 %F = OpTypeStruct %int %v2uint
3809 %uint_2 = OpConstant %uint 2
3810 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3811 %mat2v3float = OpTypeMatrix %v3float 2
3812 %v3uint = OpTypeVector %uint 3
3813 %mat3v3float = OpTypeMatrix %v3float 3
3814 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3815 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3816 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3817 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3818 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3819 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3820 %main = OpFunction %void None %3
3821 %5 = OpLabel
3822 OpReturn
3823 OpFunctionEnd
3824 )";
3825
3826 CompileSuccessfully(spirv);
3827 EXPECT_EQ(SPV_SUCCESS,
3828 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3829 }
3830
TEST_F(ValidateDecorations, StorageBufferLayoutPermitsTightVec3ScalarPackingGood)3831 TEST_F(ValidateDecorations,
3832 StorageBufferLayoutPermitsTightVec3ScalarPackingGood) {
3833 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3834 std::string spirv = R"(
3835 OpCapability Shader
3836 OpExtension "SPV_KHR_storage_buffer_storage_class"
3837 OpMemoryModel Logical GLSL450
3838 OpEntryPoint Vertex %main "main"
3839 OpSource GLSL 450
3840 OpMemberDecorate %S 0 Offset 0
3841 OpMemberDecorate %S 1 Offset 12
3842 OpDecorate %S Block
3843 OpDecorate %B DescriptorSet 0
3844 OpDecorate %B Binding 0
3845 %void = OpTypeVoid
3846 %3 = OpTypeFunction %void
3847 %float = OpTypeFloat 32
3848 %v3float = OpTypeVector %float 3
3849 %S = OpTypeStruct %v3float %float
3850 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3851 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3852 %main = OpFunction %void None %3
3853 %5 = OpLabel
3854 OpReturn
3855 OpFunctionEnd
3856 )";
3857
3858 CompileSuccessfully(spirv);
3859 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
3860 << getDiagnosticString();
3861 }
3862
TEST_F(ValidateDecorations, StorageBufferLayoutForbidsTightScalarVec3PackingBad)3863 TEST_F(ValidateDecorations,
3864 StorageBufferLayoutForbidsTightScalarVec3PackingBad) {
3865 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3866 std::string spirv = R"(
3867 OpCapability Shader
3868 OpExtension "SPV_KHR_storage_buffer_storage_class"
3869 OpMemoryModel Logical GLSL450
3870 OpEntryPoint Vertex %main "main"
3871 OpSource GLSL 450
3872 OpMemberDecorate %S 0 Offset 0
3873 OpMemberDecorate %S 1 Offset 4
3874 OpDecorate %S Block
3875 OpDecorate %B DescriptorSet 0
3876 OpDecorate %B Binding 0
3877 %void = OpTypeVoid
3878 %3 = OpTypeFunction %void
3879 %float = OpTypeFloat 32
3880 %v3float = OpTypeVector %float 3
3881 %S = OpTypeStruct %float %v3float
3882 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3883 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3884 %main = OpFunction %void None %3
3885 %5 = OpLabel
3886 OpReturn
3887 OpFunctionEnd
3888 )";
3889
3890 CompileSuccessfully(spirv);
3891 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3892 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3893 EXPECT_THAT(
3894 getDiagnosticString(),
3895 HasSubstr(
3896 "Structure id 2 decorated as Block for variable in StorageBuffer "
3897 "storage class must follow standard storage buffer layout "
3898 "rules: member 1 at offset 4 is not aligned to 16"));
3899 }
3900
TEST_F(ValidateDecorations, BlockStandardUniformBufferLayoutIncorrectOffset0Bad)3901 TEST_F(ValidateDecorations,
3902 BlockStandardUniformBufferLayoutIncorrectOffset0Bad) {
3903 std::string spirv = R"(
3904 OpCapability Shader
3905 %1 = OpExtInstImport "GLSL.std.450"
3906 OpMemoryModel Logical GLSL450
3907 OpEntryPoint GLCompute %main "main"
3908 OpExecutionMode %main LocalSize 1 1 1
3909 OpSource GLSL 430
3910 OpMemberDecorate %F 0 Offset 0
3911 OpMemberDecorate %F 1 Offset 8
3912 OpDecorate %_arr_float_uint_2 ArrayStride 16
3913 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3914 OpMemberDecorate %O 0 Offset 0
3915 OpMemberDecorate %O 1 Offset 16
3916 OpMemberDecorate %O 2 Offset 24
3917 OpMemberDecorate %O 3 Offset 33
3918 OpMemberDecorate %O 4 ColMajor
3919 OpMemberDecorate %O 4 Offset 80
3920 OpMemberDecorate %O 4 MatrixStride 16
3921 OpDecorate %_arr_O_uint_2 ArrayStride 176
3922 OpMemberDecorate %Output 0 Offset 0
3923 OpMemberDecorate %Output 1 Offset 8
3924 OpMemberDecorate %Output 2 Offset 16
3925 OpMemberDecorate %Output 3 Offset 32
3926 OpMemberDecorate %Output 4 Offset 48
3927 OpMemberDecorate %Output 5 Offset 64
3928 OpMemberDecorate %Output 6 ColMajor
3929 OpMemberDecorate %Output 6 Offset 96
3930 OpMemberDecorate %Output 6 MatrixStride 16
3931 OpMemberDecorate %Output 7 Offset 128
3932 OpDecorate %Output Block
3933 %void = OpTypeVoid
3934 %3 = OpTypeFunction %void
3935 %float = OpTypeFloat 32
3936 %v2float = OpTypeVector %float 2
3937 %v3float = OpTypeVector %float 3
3938 %int = OpTypeInt 32 1
3939 %uint = OpTypeInt 32 0
3940 %v2uint = OpTypeVector %uint 2
3941 %F = OpTypeStruct %int %v2uint
3942 %uint_2 = OpConstant %uint 2
3943 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3944 %mat2v3float = OpTypeMatrix %v3float 2
3945 %v3uint = OpTypeVector %uint 3
3946 %mat3v3float = OpTypeMatrix %v3float 3
3947 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3948 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3949 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3950 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3951 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3952 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3953 %main = OpFunction %void None %3
3954 %5 = OpLabel
3955 OpReturn
3956 OpFunctionEnd
3957 )";
3958
3959 CompileSuccessfully(spirv);
3960 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3961 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
3962 EXPECT_THAT(
3963 getDiagnosticString(),
3964 HasSubstr("Structure id 6 decorated as Block for variable in Uniform "
3965 "storage class must follow standard uniform buffer layout "
3966 "rules: member 2 at offset 152 is not aligned to 16"));
3967 }
3968
TEST_F(ValidateDecorations, BlockStandardUniformBufferLayoutIncorrectOffset1Bad)3969 TEST_F(ValidateDecorations,
3970 BlockStandardUniformBufferLayoutIncorrectOffset1Bad) {
3971 std::string spirv = R"(
3972 OpCapability Shader
3973 %1 = OpExtInstImport "GLSL.std.450"
3974 OpMemoryModel Logical GLSL450
3975 OpEntryPoint GLCompute %main "main"
3976 OpExecutionMode %main LocalSize 1 1 1
3977 OpSource GLSL 430
3978 OpMemberDecorate %F 0 Offset 0
3979 OpMemberDecorate %F 1 Offset 8
3980 OpDecorate %_arr_float_uint_2 ArrayStride 16
3981 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3982 OpMemberDecorate %O 0 Offset 0
3983 OpMemberDecorate %O 1 Offset 16
3984 OpMemberDecorate %O 2 Offset 32
3985 OpMemberDecorate %O 3 Offset 64
3986 OpMemberDecorate %O 4 ColMajor
3987 OpMemberDecorate %O 4 Offset 80
3988 OpMemberDecorate %O 4 MatrixStride 16
3989 OpDecorate %_arr_O_uint_2 ArrayStride 176
3990 OpMemberDecorate %Output 0 Offset 0
3991 OpMemberDecorate %Output 1 Offset 8
3992 OpMemberDecorate %Output 2 Offset 16
3993 OpMemberDecorate %Output 3 Offset 32
3994 OpMemberDecorate %Output 4 Offset 48
3995 OpMemberDecorate %Output 5 Offset 71
3996 OpMemberDecorate %Output 6 ColMajor
3997 OpMemberDecorate %Output 6 Offset 96
3998 OpMemberDecorate %Output 6 MatrixStride 16
3999 OpMemberDecorate %Output 7 Offset 128
4000 OpDecorate %Output Block
4001 %void = OpTypeVoid
4002 %3 = OpTypeFunction %void
4003 %float = OpTypeFloat 32
4004 %v2float = OpTypeVector %float 2
4005 %v3float = OpTypeVector %float 3
4006 %int = OpTypeInt 32 1
4007 %uint = OpTypeInt 32 0
4008 %v2uint = OpTypeVector %uint 2
4009 %F = OpTypeStruct %int %v2uint
4010 %uint_2 = OpConstant %uint 2
4011 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4012 %mat2v3float = OpTypeMatrix %v3float 2
4013 %v3uint = OpTypeVector %uint 3
4014 %mat3v3float = OpTypeMatrix %v3float 3
4015 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
4016 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
4017 %_arr_O_uint_2 = OpTypeArray %O %uint_2
4018 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
4019 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4020 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4021 %main = OpFunction %void None %3
4022 %5 = OpLabel
4023 OpReturn
4024 OpFunctionEnd
4025 )";
4026
4027 CompileSuccessfully(spirv);
4028 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4029 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4030 EXPECT_THAT(
4031 getDiagnosticString(),
4032 HasSubstr("Structure id 8 decorated as Block for variable in Uniform "
4033 "storage class must follow standard uniform buffer layout "
4034 "rules: member 5 at offset 71 is not aligned to 16"));
4035 }
4036
TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad)4037 TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad) {
4038 std::string spirv = R"(
4039 OpCapability Shader
4040 %1 = OpExtInstImport "GLSL.std.450"
4041 OpMemoryModel Logical GLSL450
4042 OpEntryPoint GLCompute %main "main"
4043 OpExecutionMode %main LocalSize 1 1 1
4044 OpSource GLSL 430
4045 OpMemberDecorate %F 0 Offset 0
4046 OpMemberDecorate %F 1 Offset 8
4047 OpDecorate %_arr_float_uint_2 ArrayStride 16
4048 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 49
4049 OpMemberDecorate %O 0 Offset 0
4050 OpMemberDecorate %O 1 Offset 16
4051 OpMemberDecorate %O 2 Offset 32
4052 OpMemberDecorate %O 3 Offset 64
4053 OpMemberDecorate %O 4 ColMajor
4054 OpMemberDecorate %O 4 Offset 80
4055 OpMemberDecorate %O 4 MatrixStride 16
4056 OpDecorate %_arr_O_uint_2 ArrayStride 176
4057 OpMemberDecorate %Output 0 Offset 0
4058 OpMemberDecorate %Output 1 Offset 8
4059 OpMemberDecorate %Output 2 Offset 16
4060 OpMemberDecorate %Output 3 Offset 32
4061 OpMemberDecorate %Output 4 Offset 48
4062 OpMemberDecorate %Output 5 Offset 64
4063 OpMemberDecorate %Output 6 ColMajor
4064 OpMemberDecorate %Output 6 Offset 96
4065 OpMemberDecorate %Output 6 MatrixStride 16
4066 OpMemberDecorate %Output 7 Offset 128
4067 OpDecorate %Output Block
4068 %void = OpTypeVoid
4069 %3 = OpTypeFunction %void
4070 %float = OpTypeFloat 32
4071 %v2float = OpTypeVector %float 2
4072 %v3float = OpTypeVector %float 3
4073 %int = OpTypeInt 32 1
4074 %uint = OpTypeInt 32 0
4075 %v2uint = OpTypeVector %uint 2
4076 %F = OpTypeStruct %int %v2uint
4077 %uint_2 = OpConstant %uint 2
4078 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4079 %mat2v3float = OpTypeMatrix %v3float 2
4080 %v3uint = OpTypeVector %uint 3
4081 %mat3v3float = OpTypeMatrix %v3float 3
4082 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
4083 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
4084 %_arr_O_uint_2 = OpTypeArray %O %uint_2
4085 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
4086 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4087 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4088 %main = OpFunction %void None %3
4089 %5 = OpLabel
4090 OpReturn
4091 OpFunctionEnd
4092 )";
4093
4094 CompileSuccessfully(spirv);
4095 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4096 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4097 EXPECT_THAT(
4098 getDiagnosticString(),
4099 HasSubstr(
4100 "Structure id 6 decorated as Block for variable in Uniform storage "
4101 "class must follow standard uniform buffer layout rules: member 4 "
4102 "contains "
4103 "an array with stride 49 not satisfying alignment to 16"));
4104 }
4105
TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayoutImproperStraddleBad)4106 TEST_F(ValidateDecorations,
4107 BufferBlockStandardStorageBufferLayoutImproperStraddleBad) {
4108 std::string spirv = R"(
4109 OpCapability Shader
4110 %1 = OpExtInstImport "GLSL.std.450"
4111 OpMemoryModel Logical GLSL450
4112 OpEntryPoint GLCompute %main "main"
4113 OpExecutionMode %main LocalSize 1 1 1
4114 OpSource GLSL 430
4115 OpMemberDecorate %Output 0 Offset 0
4116 OpMemberDecorate %Output 1 Offset 8
4117 OpDecorate %Output BufferBlock
4118 %void = OpTypeVoid
4119 %3 = OpTypeFunction %void
4120 %float = OpTypeFloat 32
4121 %v3float = OpTypeVector %float 3
4122 %Output = OpTypeStruct %float %v3float
4123 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4124 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4125 %main = OpFunction %void None %3
4126 %5 = OpLabel
4127 OpReturn
4128 OpFunctionEnd
4129 )";
4130
4131 CompileSuccessfully(spirv);
4132 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4133 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4134 EXPECT_THAT(
4135 getDiagnosticString(),
4136 HasSubstr("Structure id 3 decorated as BufferBlock for variable in "
4137 "Uniform storage class must follow standard storage buffer "
4138 "layout rules: member 1 at offset 8 is not aligned to 16"));
4139 }
4140
TEST_F(ValidateDecorations, BlockUniformBufferLayoutOffsetInsideArrayPaddingBad)4141 TEST_F(ValidateDecorations,
4142 BlockUniformBufferLayoutOffsetInsideArrayPaddingBad) {
4143 // In this case the 2nd member fits entirely within the padding.
4144 std::string spirv = R"(
4145 OpCapability Shader
4146 %1 = OpExtInstImport "GLSL.std.450"
4147 OpMemoryModel Logical GLSL450
4148 OpEntryPoint GLCompute %main "main"
4149 OpExecutionMode %main LocalSize 1 1 1
4150 OpSource GLSL 430
4151 OpDecorate %_arr_float_uint_2 ArrayStride 16
4152 OpMemberDecorate %Output 0 Offset 0
4153 OpMemberDecorate %Output 1 Offset 20
4154 OpDecorate %Output Block
4155 %void = OpTypeVoid
4156 %3 = OpTypeFunction %void
4157 %float = OpTypeFloat 32
4158 %uint = OpTypeInt 32 0
4159 %v2uint = OpTypeVector %uint 2
4160 %uint_2 = OpConstant %uint 2
4161 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4162 %Output = OpTypeStruct %_arr_float_uint_2 %float
4163 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4164 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4165 %main = OpFunction %void None %3
4166 %5 = OpLabel
4167 OpReturn
4168 OpFunctionEnd
4169 )";
4170
4171 CompileSuccessfully(spirv);
4172 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4173 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4174 EXPECT_THAT(
4175 getDiagnosticString(),
4176 HasSubstr(
4177 "Structure id 4 decorated as Block for variable in Uniform storage "
4178 "class must follow standard uniform buffer layout rules: member 1 at "
4179 "offset 20 overlaps previous member ending at offset 31"));
4180 }
4181
TEST_F(ValidateDecorations, BlockUniformBufferLayoutOffsetInsideStructPaddingBad)4182 TEST_F(ValidateDecorations,
4183 BlockUniformBufferLayoutOffsetInsideStructPaddingBad) {
4184 // In this case the 2nd member fits entirely within the padding.
4185 std::string spirv = R"(
4186 OpCapability Shader
4187 OpMemoryModel Logical GLSL450
4188 OpEntryPoint GLCompute %1 "main"
4189 OpExecutionMode %1 LocalSize 1 1 1
4190 OpMemberDecorate %_struct_6 0 Offset 0
4191 OpMemberDecorate %_struct_2 0 Offset 0
4192 OpMemberDecorate %_struct_2 1 Offset 4
4193 OpDecorate %_struct_2 Block
4194 %void = OpTypeVoid
4195 %4 = OpTypeFunction %void
4196 %float = OpTypeFloat 32
4197 %_struct_6 = OpTypeStruct %float
4198 %_struct_2 = OpTypeStruct %_struct_6 %float
4199 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4200 %8 = OpVariable %_ptr_Uniform__struct_2 Uniform
4201 %1 = OpFunction %void None %4
4202 %9 = OpLabel
4203 OpReturn
4204 OpFunctionEnd
4205 )";
4206
4207 CompileSuccessfully(spirv);
4208 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4209 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4210 EXPECT_THAT(
4211 getDiagnosticString(),
4212 HasSubstr(
4213 "Structure id 3 decorated as Block for variable in Uniform storage "
4214 "class must follow standard uniform buffer layout rules: member 1 at "
4215 "offset 4 overlaps previous member ending at offset 15"));
4216 }
4217
TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0)4218 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0) {
4219 std::string spirv = R"(
4220 OpCapability Shader
4221 %1 = OpExtInstImport "GLSL.std.450"
4222 OpMemoryModel Logical GLSL450
4223 OpEntryPoint GLCompute %main "main"
4224 OpExecutionMode %main LocalSize 1 1 1
4225 OpMemberDecorate %Outer 0 Offset 4
4226 OpMemberDecorate %Outer 1 Offset 0
4227 OpDecorate %Outer Block
4228 OpDecorate %O DescriptorSet 0
4229 OpDecorate %O Binding 0
4230 %void = OpTypeVoid
4231 %3 = OpTypeFunction %void
4232 %uint = OpTypeInt 32 0
4233 %Outer = OpTypeStruct %uint %uint
4234 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4235 %O = OpVariable %_ptr_Uniform_Outer Uniform
4236 %main = OpFunction %void None %3
4237 %5 = OpLabel
4238 OpReturn
4239 OpFunctionEnd
4240 )";
4241
4242 CompileSuccessfully(spirv);
4243 EXPECT_EQ(SPV_SUCCESS,
4244 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
4245 }
4246
TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5)4247 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5) {
4248 std::string spirv = R"(
4249 OpCapability Shader
4250 %1 = OpExtInstImport "GLSL.std.450"
4251 OpMemoryModel Logical GLSL450
4252 OpEntryPoint GLCompute %main "main"
4253 OpExecutionMode %main LocalSize 1 1 1
4254 OpMemberDecorate %Outer 0 Offset 4
4255 OpMemberDecorate %Outer 1 Offset 0
4256 OpDecorate %Outer Block
4257 OpDecorate %O DescriptorSet 0
4258 OpDecorate %O Binding 0
4259 %void = OpTypeVoid
4260 %3 = OpTypeFunction %void
4261 %uint = OpTypeInt 32 0
4262 %Outer = OpTypeStruct %uint %uint
4263 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4264 %O = OpVariable %_ptr_Uniform_Outer Uniform
4265 %main = OpFunction %void None %3
4266 %5 = OpLabel
4267 OpReturn
4268 OpFunctionEnd
4269 )";
4270
4271 CompileSuccessfully(spirv);
4272 EXPECT_EQ(SPV_SUCCESS,
4273 ValidateAndRetrieveValidationState(SPV_ENV_OPENGL_4_5));
4274 }
4275
TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1)4276 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1) {
4277 std::string spirv = R"(
4278 OpCapability Shader
4279 %1 = OpExtInstImport "GLSL.std.450"
4280 OpMemoryModel Logical GLSL450
4281 OpEntryPoint GLCompute %main "main"
4282 OpExecutionMode %main LocalSize 1 1 1
4283 OpMemberDecorate %Outer 0 Offset 4
4284 OpMemberDecorate %Outer 1 Offset 0
4285 OpDecorate %Outer Block
4286 OpDecorate %O DescriptorSet 0
4287 OpDecorate %O Binding 0
4288 %void = OpTypeVoid
4289 %3 = OpTypeFunction %void
4290 %uint = OpTypeInt 32 0
4291 %Outer = OpTypeStruct %uint %uint
4292 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4293 %O = OpVariable %_ptr_Uniform_Outer Uniform
4294 %main = OpFunction %void None %3
4295 %5 = OpLabel
4296 OpReturn
4297 OpFunctionEnd
4298 )";
4299
4300 CompileSuccessfully(spirv);
4301 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
4302 << getDiagnosticString();
4303 EXPECT_THAT(getDiagnosticString(), Eq(""));
4304 }
4305
TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad)4306 TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad) {
4307 std::string spirv = R"(
4308 OpCapability Shader
4309 %1 = OpExtInstImport "GLSL.std.450"
4310 OpMemoryModel Logical GLSL450
4311 OpEntryPoint GLCompute %main "main"
4312 OpExecutionMode %main LocalSize 1 1 1
4313 OpMemberDecorate %Outer 0 Offset 0
4314 OpMemberDecorate %Outer 1 Offset 16
4315 OpMemberDecorate %Inner 0 Offset 0
4316 OpMemberDecorate %Inner 1 Offset 16
4317 OpDecorate %Outer Block
4318 OpDecorate %O DescriptorSet 0
4319 OpDecorate %O Binding 0
4320 %void = OpTypeVoid
4321 %3 = OpTypeFunction %void
4322 %uint = OpTypeInt 32 0
4323 %Inner = OpTypeStruct %uint %uint
4324 %Outer = OpTypeStruct %Inner %uint
4325 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4326 %O = OpVariable %_ptr_Uniform_Outer Uniform
4327 %main = OpFunction %void None %3
4328 %5 = OpLabel
4329 OpReturn
4330 OpFunctionEnd
4331 )";
4332
4333 CompileSuccessfully(spirv);
4334 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4335 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4336 EXPECT_THAT(
4337 getDiagnosticString(),
4338 HasSubstr(
4339 "Structure id 3 decorated as Block for variable in Uniform storage "
4340 "class must follow standard uniform buffer layout rules: member 1 at "
4341 "offset 16 overlaps previous member ending at offset 31"));
4342 }
4343
TEST_F(ValidateDecorations, BufferBlockEmptyStruct)4344 TEST_F(ValidateDecorations, BufferBlockEmptyStruct) {
4345 std::string spirv = R"(
4346 OpCapability Shader
4347 %1 = OpExtInstImport "GLSL.std.450"
4348 OpMemoryModel Logical GLSL450
4349 OpEntryPoint GLCompute %main "main"
4350 OpExecutionMode %main LocalSize 1 1 1
4351 OpSource GLSL 430
4352 OpMemberDecorate %Output 0 Offset 0
4353 OpDecorate %Output BufferBlock
4354 %void = OpTypeVoid
4355 %3 = OpTypeFunction %void
4356 %S = OpTypeStruct
4357 %Output = OpTypeStruct %S
4358 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4359 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4360 %main = OpFunction %void None %3
4361 %5 = OpLabel
4362 OpReturn
4363 OpFunctionEnd
4364 )";
4365
4366 CompileSuccessfully(spirv);
4367 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4368 }
4369
TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood)4370 TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood) {
4371 // Row major matrix rule:
4372 // A row-major matrix of C columns has a base alignment equal to
4373 // the base alignment of a vector of C matrix components.
4374 // Note: The "matrix component" is the scalar element type.
4375
4376 // The matrix has 3 columns and 2 rows (C=3, R=2).
4377 // So the base alignment of b is the same as a vector of 3 floats, which is 16
4378 // bytes. The matrix consists of two of these, and therefore occupies 2 x 16
4379 // bytes, or 32 bytes.
4380 //
4381 // So the offsets can be:
4382 // a -> 0
4383 // b -> 16
4384 // c -> 48
4385 // d -> 60 ; d fits at bytes 12-15 after offset of c. Tight (vec3;float)
4386 // packing
4387
4388 std::string spirv = R"(
4389 OpCapability Shader
4390 OpMemoryModel Logical GLSL450
4391 OpEntryPoint Vertex %1 "main"
4392 OpSource GLSL 450
4393 OpMemberDecorate %_struct_2 0 Offset 0
4394 OpMemberDecorate %_struct_2 1 RowMajor
4395 OpMemberDecorate %_struct_2 1 Offset 16
4396 OpMemberDecorate %_struct_2 1 MatrixStride 16
4397 OpMemberDecorate %_struct_2 2 Offset 48
4398 OpMemberDecorate %_struct_2 3 Offset 60
4399 OpDecorate %_struct_2 Block
4400 OpDecorate %3 DescriptorSet 0
4401 OpDecorate %3 Binding 0
4402 %void = OpTypeVoid
4403 %5 = OpTypeFunction %void
4404 %float = OpTypeFloat 32
4405 %v4float = OpTypeVector %float 4
4406 %v2float = OpTypeVector %float 2
4407 %mat3v2float = OpTypeMatrix %v2float 3
4408 %v3float = OpTypeVector %float 3
4409 %_struct_2 = OpTypeStruct %v4float %mat3v2float %v3float %float
4410 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4411 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4412 %1 = OpFunction %void None %5
4413 %12 = OpLabel
4414 OpReturn
4415 OpFunctionEnd
4416 )";
4417
4418 CompileSuccessfully(spirv);
4419 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
4420 << getDiagnosticString();
4421 }
4422
TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood)4423 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood) {
4424 // Like the previous case, but we have an array of arrays of matrices.
4425 // The RowMajor decoration goes on the struct member (surprisingly).
4426
4427 std::string spirv = R"(
4428 OpCapability Shader
4429 OpMemoryModel Logical GLSL450
4430 OpEntryPoint Vertex %1 "main"
4431 OpSource GLSL 450
4432 OpMemberDecorate %_struct_2 0 Offset 0
4433 OpMemberDecorate %_struct_2 1 RowMajor
4434 OpMemberDecorate %_struct_2 1 Offset 16
4435 OpMemberDecorate %_struct_2 1 MatrixStride 16
4436 OpMemberDecorate %_struct_2 2 Offset 80
4437 OpMemberDecorate %_struct_2 3 Offset 92
4438 OpDecorate %arr_mat ArrayStride 32
4439 OpDecorate %arr_arr_mat ArrayStride 32
4440 OpDecorate %_struct_2 Block
4441 OpDecorate %3 DescriptorSet 0
4442 OpDecorate %3 Binding 0
4443 %void = OpTypeVoid
4444 %5 = OpTypeFunction %void
4445 %float = OpTypeFloat 32
4446 %v4float = OpTypeVector %float 4
4447 %v2float = OpTypeVector %float 2
4448 %mat3v2float = OpTypeMatrix %v2float 3
4449 %uint = OpTypeInt 32 0
4450 %uint_1 = OpConstant %uint 1
4451 %uint_2 = OpConstant %uint 2
4452 %arr_mat = OpTypeArray %mat3v2float %uint_1
4453 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4454 %v3float = OpTypeVector %float 3
4455 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4456 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4457 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4458 %1 = OpFunction %void None %5
4459 %12 = OpLabel
4460 OpReturn
4461 OpFunctionEnd
4462 )";
4463
4464 CompileSuccessfully(spirv);
4465 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0))
4466 << getDiagnosticString();
4467 }
4468
TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad)4469 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad) {
4470 // Like the previous case, but the offset of member 2 overlaps the matrix.
4471 std::string spirv = R"(
4472 OpCapability Shader
4473 OpMemoryModel Logical GLSL450
4474 OpEntryPoint Vertex %1 "main"
4475 OpSource GLSL 450
4476 OpMemberDecorate %_struct_2 0 Offset 0
4477 OpMemberDecorate %_struct_2 1 RowMajor
4478 OpMemberDecorate %_struct_2 1 Offset 16
4479 OpMemberDecorate %_struct_2 1 MatrixStride 16
4480 OpMemberDecorate %_struct_2 2 Offset 64
4481 OpMemberDecorate %_struct_2 3 Offset 92
4482 OpDecorate %arr_mat ArrayStride 32
4483 OpDecorate %arr_arr_mat ArrayStride 32
4484 OpDecorate %_struct_2 Block
4485 OpDecorate %3 DescriptorSet 0
4486 OpDecorate %3 Binding 0
4487 %void = OpTypeVoid
4488 %5 = OpTypeFunction %void
4489 %float = OpTypeFloat 32
4490 %v4float = OpTypeVector %float 4
4491 %v2float = OpTypeVector %float 2
4492 %mat3v2float = OpTypeMatrix %v2float 3
4493 %uint = OpTypeInt 32 0
4494 %uint_1 = OpConstant %uint 1
4495 %uint_2 = OpConstant %uint 2
4496 %arr_mat = OpTypeArray %mat3v2float %uint_1
4497 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4498 %v3float = OpTypeVector %float 3
4499 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4500 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4501 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4502 %1 = OpFunction %void None %5
4503 %12 = OpLabel
4504 OpReturn
4505 OpFunctionEnd
4506 )";
4507
4508 CompileSuccessfully(spirv);
4509 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4510 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4511 EXPECT_THAT(
4512 getDiagnosticString(),
4513 HasSubstr(
4514 "Structure id 2 decorated as Block for variable in Uniform storage "
4515 "class must follow standard uniform buffer layout rules: member 2 at "
4516 "offset 64 overlaps previous member ending at offset 79"));
4517 }
4518
TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood)4519 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood) {
4520 // Original GLSL
4521
4522 // #version 450
4523 // layout (set=0,binding=0) buffer S {
4524 // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
4525 // uint i; // Can't have offset 60 = 3x16 + 12
4526 // } B;
4527 // void main() {}
4528
4529 std::string spirv = R"(
4530 OpCapability Shader
4531 OpMemoryModel Logical GLSL450
4532 OpEntryPoint Vertex %1 "main"
4533 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4534 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4535 OpMemberDecorate %_struct_4 0 Offset 0
4536 OpMemberDecorate %_struct_4 1 Offset 64
4537 OpDecorate %_struct_4 BufferBlock
4538 OpDecorate %5 DescriptorSet 0
4539 OpDecorate %5 Binding 0
4540 %void = OpTypeVoid
4541 %7 = OpTypeFunction %void
4542 %uint = OpTypeInt 32 0
4543 %v3uint = OpTypeVector %uint 3
4544 %uint_2 = OpConstant %uint 2
4545 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4546 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4547 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4548 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4549 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4550 %1 = OpFunction %void None %7
4551 %12 = OpLabel
4552 OpReturn
4553 OpFunctionEnd
4554 )";
4555
4556 CompileSuccessfully(spirv);
4557 EXPECT_EQ(SPV_SUCCESS,
4558 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4559 }
4560
TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGoodScalar)4561 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGoodScalar) {
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 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 60
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 options_->scalar_block_layout = true;
4599 CompileSuccessfully(spirv);
4600 EXPECT_EQ(SPV_SUCCESS,
4601 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4602 }
4603
TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad)4604 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) {
4605 // Like previous but, the offset of the second member is too small.
4606
4607 std::string spirv = R"(
4608 OpCapability Shader
4609 OpMemoryModel Logical GLSL450
4610 OpEntryPoint Vertex %1 "main"
4611 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4612 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4613 OpMemberDecorate %_struct_4 0 Offset 0
4614 OpMemberDecorate %_struct_4 1 Offset 60
4615 OpDecorate %_struct_4 BufferBlock
4616 OpDecorate %5 DescriptorSet 0
4617 OpDecorate %5 Binding 0
4618 %void = OpTypeVoid
4619 %7 = OpTypeFunction %void
4620 %uint = OpTypeInt 32 0
4621 %v3uint = OpTypeVector %uint 3
4622 %uint_2 = OpConstant %uint 2
4623 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4624 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4625 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4626 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4627 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4628 %1 = OpFunction %void None %7
4629 %12 = OpLabel
4630 OpReturn
4631 OpFunctionEnd
4632 )";
4633
4634 CompileSuccessfully(spirv);
4635 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4636 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4637 EXPECT_THAT(getDiagnosticString(),
4638 HasSubstr("Structure id 4 decorated as BufferBlock for variable "
4639 "in Uniform storage class must follow standard storage "
4640 "buffer layout rules: member 1 at offset 60 overlaps "
4641 "previous member ending at offset 63"));
4642 }
4643
TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood)4644 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) {
4645 // Like the corresponding buffer block case, but the array padding must
4646 // count for the last element as well, and so the offset of the second
4647 // member must be at least 64.
4648 std::string spirv = R"(
4649 OpCapability Shader
4650 OpMemoryModel Logical GLSL450
4651 OpEntryPoint Vertex %1 "main"
4652 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4653 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4654 OpMemberDecorate %_struct_4 0 Offset 0
4655 OpMemberDecorate %_struct_4 1 Offset 64
4656 OpDecorate %_struct_4 Block
4657 OpDecorate %5 DescriptorSet 0
4658 OpDecorate %5 Binding 0
4659 %void = OpTypeVoid
4660 %7 = OpTypeFunction %void
4661 %uint = OpTypeInt 32 0
4662 %v3uint = OpTypeVector %uint 3
4663 %uint_2 = OpConstant %uint 2
4664 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4665 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4666 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4667 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4668 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4669 %1 = OpFunction %void None %7
4670 %12 = OpLabel
4671 OpReturn
4672 OpFunctionEnd
4673 )";
4674
4675 CompileSuccessfully(spirv);
4676 EXPECT_EQ(SPV_SUCCESS,
4677 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4678 }
4679
TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad)4680 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) {
4681 // Like previous but, the offset of the second member is too small.
4682
4683 std::string spirv = R"(
4684 OpCapability Shader
4685 OpMemoryModel Logical GLSL450
4686 OpEntryPoint Vertex %1 "main"
4687 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4688 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4689 OpMemberDecorate %_struct_4 0 Offset 0
4690 OpMemberDecorate %_struct_4 1 Offset 60
4691 OpDecorate %_struct_4 Block
4692 OpDecorate %5 DescriptorSet 0
4693 OpDecorate %5 Binding 0
4694 %void = OpTypeVoid
4695 %7 = OpTypeFunction %void
4696 %uint = OpTypeInt 32 0
4697 %v3uint = OpTypeVector %uint 3
4698 %uint_2 = OpConstant %uint 2
4699 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4700 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4701 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4702 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4703 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4704 %1 = OpFunction %void None %7
4705 %12 = OpLabel
4706 OpReturn
4707 OpFunctionEnd
4708 )";
4709
4710 CompileSuccessfully(spirv);
4711 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4712 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4713 EXPECT_THAT(
4714 getDiagnosticString(),
4715 HasSubstr(
4716 "Structure id 4 decorated as Block for variable in Uniform storage "
4717 "class must follow standard uniform buffer layout rules: member 1 at "
4718 "offset 60 overlaps previous member ending at offset 63"));
4719 }
4720
TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout)4721 TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) {
4722 // Checks that block layout is not verified in skipping block layout mode.
4723 // Even for obviously wrong layout.
4724 std::string spirv = R"(
4725 OpCapability Shader
4726 OpMemoryModel Logical GLSL450
4727 OpEntryPoint Vertex %main "main"
4728 OpSource GLSL 450
4729 OpMemberDecorate %S 0 Offset 3 ; wrong alignment
4730 OpMemberDecorate %S 1 Offset 3 ; same offset as before!
4731 OpDecorate %S Block
4732 OpDecorate %B DescriptorSet 0
4733 OpDecorate %B Binding 0
4734 %void = OpTypeVoid
4735 %3 = OpTypeFunction %void
4736 %float = OpTypeFloat 32
4737 %v3float = OpTypeVector %float 3
4738 %S = OpTypeStruct %float %v3float
4739 %_ptr_Uniform_S = OpTypePointer Uniform %S
4740 %B = OpVariable %_ptr_Uniform_S Uniform
4741 %main = OpFunction %void None %3
4742 %5 = OpLabel
4743 OpReturn
4744 OpFunctionEnd
4745 )";
4746
4747 CompileSuccessfully(spirv);
4748 spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true);
4749 EXPECT_EQ(SPV_SUCCESS,
4750 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4751 EXPECT_THAT(getDiagnosticString(), Eq(""));
4752 }
4753
TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass)4754 TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) {
4755 const std::string spirv = R"(
4756 OpCapability Shader
4757 OpMemoryModel Logical GLSL450
4758 OpEntryPoint Fragment %1 "func" %var
4759 OpExecutionMode %1 OriginUpperLeft
4760 %void = OpTypeVoid
4761 %int = OpTypeInt 32 0
4762 %ptr_int_Workgroup = OpTypePointer Workgroup %int
4763 %var = OpVariable %ptr_int_Workgroup Workgroup
4764 %func_ty = OpTypeFunction %void
4765 %1 = OpFunction %void None %func_ty
4766 %2 = OpLabel
4767 OpReturn
4768 OpFunctionEnd
4769 )";
4770
4771 CompileSuccessfully(spirv);
4772 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4773 EXPECT_THAT(getDiagnosticString(),
4774 HasSubstr("OpEntryPoint interfaces must be OpVariables with "
4775 "Storage Class of Input(1) or Output(3). Found Storage "
4776 "Class 4 for Entry Point id 1."));
4777 }
4778
TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent)4779 TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent) {
4780 const std::string spirv = R"(
4781 OpCapability Shader
4782 OpCapability VulkanMemoryModelKHR
4783 OpCapability Linkage
4784 OpExtension "SPV_KHR_vulkan_memory_model"
4785 OpExtension "SPV_KHR_storage_buffer_storage_class"
4786 OpMemoryModel Logical VulkanKHR
4787 OpDecorate %1 Coherent
4788 %2 = OpTypeInt 32 0
4789 %3 = OpTypePointer StorageBuffer %2
4790 %1 = OpVariable %3 StorageBuffer
4791 )";
4792
4793 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4794 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4795 EXPECT_THAT(getDiagnosticString(),
4796 HasSubstr("Coherent decoration targeting '1[%1]' is "
4797 "banned when using the Vulkan memory model."));
4798 }
4799
TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember)4800 TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember) {
4801 const std::string spirv = R"(
4802 OpCapability Shader
4803 OpCapability VulkanMemoryModelKHR
4804 OpCapability Linkage
4805 OpExtension "SPV_KHR_vulkan_memory_model"
4806 OpMemoryModel Logical VulkanKHR
4807 OpMemberDecorate %1 0 Coherent
4808 %2 = OpTypeInt 32 0
4809 %1 = OpTypeStruct %2 %2
4810 )";
4811
4812 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4813 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4814 EXPECT_THAT(
4815 getDiagnosticString(),
4816 HasSubstr(
4817 "Coherent decoration targeting '1[%_struct_1]' (member index 0) "
4818 "is banned when using the Vulkan memory model."));
4819 }
4820
TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile)4821 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) {
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 Volatile
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("Volatile decoration targeting '1[%1]' is banned when "
4839 "using the Vulkan memory model."));
4840 }
4841
TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember)4842 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember) {
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 1 Volatile
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(getDiagnosticString(),
4857 HasSubstr("Volatile decoration targeting '1[%_struct_1]' (member "
4858 "index 1) is banned when using the Vulkan memory "
4859 "model."));
4860 }
4861
TEST_F(ValidateDecorations, FPRoundingModeGood)4862 TEST_F(ValidateDecorations, FPRoundingModeGood) {
4863 std::string spirv = R"(
4864 OpCapability Shader
4865 OpCapability Linkage
4866 OpCapability StorageBuffer16BitAccess
4867 OpExtension "SPV_KHR_storage_buffer_storage_class"
4868 OpExtension "SPV_KHR_variable_pointers"
4869 OpExtension "SPV_KHR_16bit_storage"
4870 OpMemoryModel Logical GLSL450
4871 OpEntryPoint GLCompute %main "main"
4872 OpDecorate %_ FPRoundingMode RTE
4873 %half = OpTypeFloat 16
4874 %float = OpTypeFloat 32
4875 %float_1_25 = OpConstant %float 1.25
4876 %half_ptr = OpTypePointer StorageBuffer %half
4877 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4878 %void = OpTypeVoid
4879 %func = OpTypeFunction %void
4880 %main = OpFunction %void None %func
4881 %main_entry = OpLabel
4882 %_ = OpFConvert %half %float_1_25
4883 OpStore %half_ptr_var %_
4884 OpReturn
4885 OpFunctionEnd
4886 )";
4887
4888 CompileSuccessfully(spirv);
4889 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4890 }
4891
TEST_F(ValidateDecorations, FPRoundingModeVectorGood)4892 TEST_F(ValidateDecorations, FPRoundingModeVectorGood) {
4893 std::string spirv = R"(
4894 OpCapability Shader
4895 OpCapability Linkage
4896 OpCapability StorageBuffer16BitAccess
4897 OpExtension "SPV_KHR_storage_buffer_storage_class"
4898 OpExtension "SPV_KHR_variable_pointers"
4899 OpExtension "SPV_KHR_16bit_storage"
4900 OpMemoryModel Logical GLSL450
4901 OpEntryPoint GLCompute %main "main"
4902 OpDecorate %_ FPRoundingMode RTE
4903 %half = OpTypeFloat 16
4904 %float = OpTypeFloat 32
4905 %v2half = OpTypeVector %half 2
4906 %v2float = OpTypeVector %float 2
4907 %float_1_25 = OpConstant %float 1.25
4908 %floats = OpConstantComposite %v2float %float_1_25 %float_1_25
4909 %halfs_ptr = OpTypePointer StorageBuffer %v2half
4910 %halfs_ptr_var = OpVariable %halfs_ptr StorageBuffer
4911 %void = OpTypeVoid
4912 %func = OpTypeFunction %void
4913 %main = OpFunction %void None %func
4914 %main_entry = OpLabel
4915 %_ = OpFConvert %v2half %floats
4916 OpStore %halfs_ptr_var %_
4917 OpReturn
4918 OpFunctionEnd
4919 )";
4920
4921 CompileSuccessfully(spirv);
4922 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4923 }
4924
TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert)4925 TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert) {
4926 std::string spirv = R"(
4927 OpCapability Shader
4928 OpCapability Linkage
4929 OpCapability StorageBuffer16BitAccess
4930 OpExtension "SPV_KHR_storage_buffer_storage_class"
4931 OpExtension "SPV_KHR_variable_pointers"
4932 OpExtension "SPV_KHR_16bit_storage"
4933 OpMemoryModel Logical GLSL450
4934 OpEntryPoint GLCompute %main "main"
4935 OpDecorate %_ FPRoundingMode RTE
4936 %short = OpTypeInt 16 1
4937 %int = OpTypeInt 32 1
4938 %int_17 = OpConstant %int 17
4939 %short_ptr = OpTypePointer StorageBuffer %short
4940 %short_ptr_var = OpVariable %short_ptr StorageBuffer
4941 %void = OpTypeVoid
4942 %func = OpTypeFunction %void
4943 %main = OpFunction %void None %func
4944 %main_entry = OpLabel
4945 %_ = OpSConvert %short %int_17
4946 OpStore %short_ptr_var %_
4947 OpReturn
4948 OpFunctionEnd
4949 )";
4950
4951 CompileSuccessfully(spirv);
4952 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4953 EXPECT_THAT(getDiagnosticString(),
4954 HasSubstr("FPRoundingMode decoration can be applied only to a "
4955 "width-only conversion instruction for floating-point "
4956 "object."));
4957 }
4958
TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood)4959 TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood) {
4960 std::string spirv = R"(
4961 OpCapability Shader
4962 OpCapability Linkage
4963 OpCapability StorageBuffer16BitAccess
4964 OpExtension "SPV_KHR_storage_buffer_storage_class"
4965 OpExtension "SPV_KHR_variable_pointers"
4966 OpExtension "SPV_KHR_16bit_storage"
4967 OpMemoryModel Logical GLSL450
4968 OpEntryPoint GLCompute %main "main"
4969 OpDecorate %_ FPRoundingMode RTE
4970 %half = OpTypeFloat 16
4971 %float = OpTypeFloat 32
4972 %float_1_25 = OpConstant %float 1.25
4973 %half_ptr = OpTypePointer StorageBuffer %half
4974 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4975 %void = OpTypeVoid
4976 %func = OpTypeFunction %void
4977 %main = OpFunction %void None %func
4978 %main_entry = OpLabel
4979 %_ = OpFConvert %half %float_1_25
4980 OpReturn
4981 OpFunctionEnd
4982 )";
4983
4984 CompileSuccessfully(spirv);
4985 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4986 }
4987
TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good)4988 TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good) {
4989 std::string spirv = R"(
4990 OpCapability Shader
4991 OpCapability Linkage
4992 OpCapability StorageBuffer16BitAccess
4993 OpCapability Float64
4994 OpExtension "SPV_KHR_storage_buffer_storage_class"
4995 OpExtension "SPV_KHR_variable_pointers"
4996 OpExtension "SPV_KHR_16bit_storage"
4997 OpMemoryModel Logical GLSL450
4998 OpEntryPoint GLCompute %main "main"
4999 OpDecorate %_ FPRoundingMode RTE
5000 %half = OpTypeFloat 16
5001 %double = OpTypeFloat 64
5002 %double_1_25 = OpConstant %double 1.25
5003 %half_ptr = OpTypePointer StorageBuffer %half
5004 %half_ptr_var = OpVariable %half_ptr StorageBuffer
5005 %void = OpTypeVoid
5006 %func = OpTypeFunction %void
5007 %main = OpFunction %void None %func
5008 %main_entry = OpLabel
5009 %_ = OpFConvert %half %double_1_25
5010 OpStore %half_ptr_var %_
5011 OpReturn
5012 OpFunctionEnd
5013 )";
5014
5015 CompileSuccessfully(spirv);
5016 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5017 }
5018
TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16)5019 TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16) {
5020 std::string spirv = R"(
5021 OpCapability Shader
5022 OpCapability Linkage
5023 OpCapability StorageBuffer16BitAccess
5024 OpCapability Float64
5025 OpExtension "SPV_KHR_storage_buffer_storage_class"
5026 OpExtension "SPV_KHR_variable_pointers"
5027 OpExtension "SPV_KHR_16bit_storage"
5028 OpMemoryModel Logical GLSL450
5029 OpEntryPoint GLCompute %main "main"
5030 OpDecorate %_ FPRoundingMode RTE
5031 %float = OpTypeFloat 32
5032 %double = OpTypeFloat 64
5033 %double_1_25 = OpConstant %double 1.25
5034 %float_ptr = OpTypePointer StorageBuffer %float
5035 %float_ptr_var = OpVariable %float_ptr StorageBuffer
5036 %void = OpTypeVoid
5037 %func = OpTypeFunction %void
5038 %main = OpFunction %void None %func
5039 %main_entry = OpLabel
5040 %_ = OpFConvert %float %double_1_25
5041 OpStore %float_ptr_var %_
5042 OpReturn
5043 OpFunctionEnd
5044 )";
5045
5046 CompileSuccessfully(spirv);
5047 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5048 EXPECT_THAT(
5049 getDiagnosticString(),
5050 HasSubstr("FPRoundingMode decoration can be applied only to the "
5051 "Object operand of an OpStore storing through a "
5052 "pointer to a 16-bit floating-point scalar or vector object."));
5053 }
5054
TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood)5055 TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood) {
5056 std::string spirv = R"(
5057 OpCapability Shader
5058 OpCapability Linkage
5059 OpCapability StorageBuffer16BitAccess
5060 OpExtension "SPV_KHR_storage_buffer_storage_class"
5061 OpExtension "SPV_KHR_variable_pointers"
5062 OpExtension "SPV_KHR_16bit_storage"
5063 OpMemoryModel Logical GLSL450
5064 OpEntryPoint GLCompute %main "main"
5065 OpDecorate %_ FPRoundingMode RTE
5066 %half = OpTypeFloat 16
5067 %float = OpTypeFloat 32
5068 %float_1_25 = OpConstant %float 1.25
5069 %half_ptr = OpTypePointer StorageBuffer %half
5070 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
5071 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
5072 %half_ptr_var_2 = OpVariable %half_ptr StorageBuffer
5073 %void = OpTypeVoid
5074 %func = OpTypeFunction %void
5075 %main = OpFunction %void None %func
5076 %main_entry = OpLabel
5077 %_ = OpFConvert %half %float_1_25
5078 OpStore %half_ptr_var_0 %_
5079 OpStore %half_ptr_var_1 %_
5080 OpStore %half_ptr_var_2 %_
5081 OpReturn
5082 OpFunctionEnd
5083 )";
5084
5085 CompileSuccessfully(spirv);
5086 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5087 }
5088
TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad)5089 TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad) {
5090 std::string spirv = R"(
5091 OpCapability Shader
5092 OpCapability Linkage
5093 OpCapability StorageBuffer16BitAccess
5094 OpExtension "SPV_KHR_storage_buffer_storage_class"
5095 OpExtension "SPV_KHR_variable_pointers"
5096 OpExtension "SPV_KHR_16bit_storage"
5097 OpMemoryModel Logical GLSL450
5098 OpEntryPoint GLCompute %main "main"
5099 OpDecorate %_ FPRoundingMode RTE
5100 %half = OpTypeFloat 16
5101 %float = OpTypeFloat 32
5102 %float_1_25 = OpConstant %float 1.25
5103 %half_ptr = OpTypePointer StorageBuffer %half
5104 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
5105 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
5106 %void = OpTypeVoid
5107 %func = OpTypeFunction %void
5108 %main = OpFunction %void None %func
5109 %main_entry = OpLabel
5110 %_ = OpFConvert %half %float_1_25
5111 OpStore %half_ptr_var_0 %_
5112 %result = OpFAdd %half %_ %_
5113 OpStore %half_ptr_var_1 %_
5114 OpReturn
5115 OpFunctionEnd
5116 )";
5117
5118 CompileSuccessfully(spirv);
5119 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5120 EXPECT_THAT(getDiagnosticString(),
5121 HasSubstr("FPRoundingMode decoration can be applied only to the "
5122 "Object operand of an OpStore."));
5123 }
5124
TEST_F(ValidateDecorations, VulkanFPRoundingModeGood)5125 TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
5126 std::string spirv = R"(
5127 OpCapability Shader
5128 OpCapability StorageBuffer16BitAccess
5129 %1 = OpExtInstImport "GLSL.std.450"
5130 OpMemoryModel Logical GLSL450
5131 OpEntryPoint GLCompute %main "main" %_
5132 OpExecutionMode %main LocalSize 1 1 1
5133 OpMemberDecorate %ssbo 0 Offset 0
5134 OpDecorate %ssbo Block
5135 OpDecorate %_ DescriptorSet 0
5136 OpDecorate %_ Binding 0
5137 OpDecorate %17 FPRoundingMode RTE
5138 %void = OpTypeVoid
5139 %3 = OpTypeFunction %void
5140 %float = OpTypeFloat 32
5141 %_ptr_Function_float = OpTypePointer Function %float
5142 %float_1 = OpConstant %float 1
5143 %half = OpTypeFloat 16
5144 %ssbo = OpTypeStruct %half
5145 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
5146 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
5147 %int = OpTypeInt 32 1
5148 %int_0 = OpConstant %int 0
5149 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
5150 %main = OpFunction %void None %3
5151 %5 = OpLabel
5152 %b = OpVariable %_ptr_Function_float Function
5153 OpStore %b %float_1
5154 %16 = OpLoad %float %b
5155 %17 = OpFConvert %half %16
5156 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
5157 OpStore %19 %17
5158 OpReturn
5159 OpFunctionEnd
5160 )";
5161
5162 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5163 EXPECT_EQ(SPV_SUCCESS,
5164 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5165 }
5166
TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode)5167 TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
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 RTP
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_ERROR_INVALID_ID,
5206 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5207 EXPECT_THAT(getDiagnosticString(),
5208 AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
5209 EXPECT_THAT(
5210 getDiagnosticString(),
5211 HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
5212 }
5213
TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup)5214 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
5215 std::string spirv = R"(
5216 OpCapability Shader
5217 OpCapability Linkage
5218 OpMemoryModel Logical GLSL450
5219 %1 = OpDecorationGroup
5220 OpGroupDecorate %1 %1
5221 )";
5222
5223 CompileSuccessfully(spirv);
5224 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5225 EXPECT_THAT(getDiagnosticString(),
5226 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5227 "'1[%1]'"));
5228 }
5229
TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2)5230 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2) {
5231 std::string spirv = R"(
5232 OpCapability Shader
5233 OpCapability Linkage
5234 OpMemoryModel Logical GLSL450
5235 %1 = OpDecorationGroup
5236 OpGroupDecorate %1 %2 %1
5237 %2 = OpTypeVoid
5238 )";
5239
5240 CompileSuccessfully(spirv);
5241 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5242 EXPECT_THAT(getDiagnosticString(),
5243 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5244 "'1[%1]'"));
5245 }
5246
TEST_F(ValidateDecorations, RecurseThroughRuntimeArray)5247 TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) {
5248 const std::string spirv = R"(
5249 OpCapability Shader
5250 OpExtension "SPV_KHR_storage_buffer_storage_class"
5251 OpMemoryModel Logical GLSL450
5252 OpEntryPoint GLCompute %main "main"
5253 OpExecutionMode %main LocalSize 1 1 1
5254 OpDecorate %outer Block
5255 OpMemberDecorate %inner 0 Offset 0
5256 OpMemberDecorate %inner 1 Offset 1
5257 OpDecorate %runtime ArrayStride 16
5258 OpMemberDecorate %outer 0 Offset 0
5259 %int = OpTypeInt 32 0
5260 %inner = OpTypeStruct %int %int
5261 %runtime = OpTypeRuntimeArray %inner
5262 %outer = OpTypeStruct %runtime
5263 %outer_ptr = OpTypePointer StorageBuffer %outer
5264 %var = OpVariable %outer_ptr StorageBuffer
5265 %void = OpTypeVoid
5266 %void_fn = OpTypeFunction %void
5267 %main = OpFunction %void None %void_fn
5268 %entry = OpLabel
5269 OpReturn
5270 OpFunctionEnd
5271 )";
5272
5273 CompileSuccessfully(spirv);
5274 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5275 EXPECT_THAT(
5276 getDiagnosticString(),
5277 HasSubstr(
5278 "Structure id 3 decorated as Block for variable in StorageBuffer "
5279 "storage class must follow standard storage buffer layout "
5280 "rules: member 1 at offset 1 is not aligned to 4"));
5281 }
5282
TEST_F(ValidateDecorations, VulkanStructWithoutDecorationWithRuntimeArray)5283 TEST_F(ValidateDecorations, VulkanStructWithoutDecorationWithRuntimeArray) {
5284 std::string str = R"(
5285 OpCapability Shader
5286 OpMemoryModel Logical GLSL450
5287 OpEntryPoint Fragment %func "func"
5288 OpExecutionMode %func OriginUpperLeft
5289 OpDecorate %array_t ArrayStride 4
5290 OpMemberDecorate %struct_t 0 Offset 0
5291 OpMemberDecorate %struct_t 1 Offset 4
5292 %uint_t = OpTypeInt 32 0
5293 %array_t = OpTypeRuntimeArray %uint_t
5294 %struct_t = OpTypeStruct %uint_t %array_t
5295 %struct_ptr = OpTypePointer StorageBuffer %struct_t
5296 %2 = OpVariable %struct_ptr StorageBuffer
5297 %void = OpTypeVoid
5298 %func_t = OpTypeFunction %void
5299 %func = OpFunction %void None %func_t
5300 %1 = OpLabel
5301 OpReturn
5302 OpFunctionEnd
5303 )";
5304
5305 CompileSuccessfully(str.c_str(), SPV_ENV_VULKAN_1_1);
5306 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5307 EXPECT_THAT(getDiagnosticString(),
5308 AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
5309 EXPECT_THAT(getDiagnosticString(),
5310 HasSubstr("Vulkan, OpTypeStruct containing an OpTypeRuntimeArray "
5311 "must be decorated with Block or BufferBlock."));
5312 }
5313
TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood)5314 TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) {
5315 const std::string spirv = R"(
5316 OpCapability Shader
5317 OpMemoryModel Logical GLSL450
5318 OpEntryPoint GLCompute %main "main"
5319 OpExecutionMode %main LocalSize 1 1 1
5320 OpDecorate %struct Block
5321 OpMemberDecorate %struct 0 Offset 0
5322 OpMemberDecorate %struct 1 Offset 16
5323 OpDecorate %var DescriptorSet 0
5324 OpDecorate %var Binding 0
5325 %void = OpTypeVoid
5326 %float = OpTypeFloat 32
5327 %empty = OpTypeStruct
5328 %struct = OpTypeStruct %float %empty
5329 %ptr_struct_ubo = OpTypePointer Uniform %struct
5330 %var = OpVariable %ptr_struct_ubo Uniform
5331 %voidfn = OpTypeFunction %void
5332 %main = OpFunction %void None %voidfn
5333 %entry = OpLabel
5334 OpReturn
5335 OpFunctionEnd
5336 )";
5337
5338 CompileSuccessfully(spirv);
5339 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5340 }
5341
5342 // Uniform and UniformId decorations
5343
TEST_F(ValidateDecorations, UniformDecorationGood)5344 TEST_F(ValidateDecorations, UniformDecorationGood) {
5345 const std::string spirv = R"(
5346 OpCapability Shader
5347 OpMemoryModel Logical Simple
5348 OpEntryPoint GLCompute %main "main"
5349 OpExecutionMode %main LocalSize 1 1 1
5350 OpDecorate %int0 Uniform
5351 OpDecorate %var Uniform
5352 OpDecorate %val Uniform
5353 %void = OpTypeVoid
5354 %int = OpTypeInt 32 1
5355 %int0 = OpConstantNull %int
5356 %intptr = OpTypePointer Private %int
5357 %var = OpVariable %intptr Private
5358 %fn = OpTypeFunction %void
5359 %main = OpFunction %void None %fn
5360 %entry = OpLabel
5361 %val = OpLoad %int %var
5362 OpReturn
5363 OpFunctionEnd
5364 )";
5365
5366 CompileSuccessfully(spirv);
5367 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5368 EXPECT_THAT(getDiagnosticString(), Eq(""));
5369 }
5370
5371 // Returns SPIR-V assembly for a shader that uses a given decoration
5372 // instruction.
ShaderWithUniformLikeDecoration(const std::string& inst)5373 std::string ShaderWithUniformLikeDecoration(const std::string& inst) {
5374 return std::string(R"(
5375 OpCapability Shader
5376 OpMemoryModel Logical Simple
5377 OpEntryPoint GLCompute %main "main"
5378 OpExecutionMode %main LocalSize 1 1 1
5379 OpName %subgroupscope "subgroupscope"
5380 OpName %call "call"
5381 OpName %myfunc "myfunc"
5382 OpName %int0 "int0"
5383 OpName %float0 "float0"
5384 OpName %fn "fn"
5385 )") + inst +
5386 R"(
5387 %void = OpTypeVoid
5388 %float = OpTypeFloat 32
5389 %int = OpTypeInt 32 1
5390 %int0 = OpConstantNull %int
5391 %int_99 = OpConstant %int 99
5392 %subgroupscope = OpConstant %int 3
5393 %float0 = OpConstantNull %float
5394 %fn = OpTypeFunction %void
5395 %myfunc = OpFunction %void None %fn
5396 %myfuncentry = OpLabel
5397 OpReturn
5398 OpFunctionEnd
5399 %main = OpFunction %void None %fn
5400 %entry = OpLabel
5401 %call = OpFunctionCall %void %myfunc
5402 OpReturn
5403 OpFunctionEnd
5404 )";
5405 }
5406
TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad)5407 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad) {
5408 const std::string spirv = ShaderWithUniformLikeDecoration(
5409 "OpDecorateId %int0 UniformId %subgroupscope");
5410 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5411 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5412 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5413 EXPECT_THAT(getDiagnosticString(),
5414 HasSubstr("requires SPIR-V version 1.4 or later\n"
5415 " OpDecorateId %int0 UniformId %subgroupscope"))
5416 << spirv;
5417 }
5418
TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14)5419 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14) {
5420 const std::string spirv = ShaderWithUniformLikeDecoration(
5421 "OpDecorateId %int0 UniformId %subgroupscope");
5422 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5423 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5424 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5425 EXPECT_THAT(getDiagnosticString(),
5426 HasSubstr("requires SPIR-V version 1.4 or later"));
5427 }
5428
TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good)5429 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good) {
5430 const std::string spirv = ShaderWithUniformLikeDecoration(
5431 "OpDecorateId %int0 UniformId %subgroupscope");
5432 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5433 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5434 EXPECT_THAT(getDiagnosticString(), Eq(""));
5435 }
5436
TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad)5437 TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad) {
5438 const std::string spirv =
5439 ShaderWithUniformLikeDecoration("OpDecorate %fn Uniform");
5440
5441 CompileSuccessfully(spirv);
5442 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5443 EXPECT_THAT(getDiagnosticString(),
5444 HasSubstr("Uniform decoration applied to a non-object"));
5445 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5446 }
5447
TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad)5448 TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad) {
5449 const std::string spirv = ShaderWithUniformLikeDecoration(
5450 "OpDecorateId %fn UniformId %subgroupscope");
5451
5452 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5453 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5454 EXPECT_THAT(getDiagnosticString(),
5455 HasSubstr("UniformId decoration applied to a non-object"));
5456 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5457 }
5458
TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad)5459 TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad) {
5460 const std::string spirv =
5461 ShaderWithUniformLikeDecoration("OpDecorate %call Uniform");
5462
5463 CompileSuccessfully(spirv);
5464 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5465 EXPECT_THAT(getDiagnosticString(),
5466 HasSubstr("Uniform decoration applied to a value with void type\n"
5467 " %call = OpFunctionCall %void %myfunc"));
5468 }
5469
TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad)5470 TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad) {
5471 const std::string spirv = ShaderWithUniformLikeDecoration(
5472 "OpDecorateId %call UniformId %subgroupscope");
5473
5474 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5475 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4))
5476 << spirv;
5477 EXPECT_THAT(
5478 getDiagnosticString(),
5479 HasSubstr("UniformId decoration applied to a value with void type\n"
5480 " %call = OpFunctionCall %void %myfunc"));
5481 }
5482
TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14IdIsFloatValueIsBad)5483 TEST_F(ValidateDecorations,
5484 UniformDecorationWithScopeIdV14IdIsFloatValueIsBad) {
5485 const std::string spirv =
5486 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %float0");
5487
5488 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5489 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5490 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5491 EXPECT_THAT(getDiagnosticString(),
5492 HasSubstr("ConstantNull: expected scope to be a 32-bit int"));
5493 }
5494
TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad)5495 TEST_F(ValidateDecorations,
5496 UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad) {
5497 const std::string spirv =
5498 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int_99");
5499
5500 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5501 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5502 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5503 EXPECT_THAT(
5504 getDiagnosticString(),
5505 HasSubstr("Invalid scope value:\n %int_99 = OpConstant %int 99\n"));
5506 }
5507
TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv)5508 TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
5509 const std::string spirv =
5510 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int0");
5511
5512 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
5513 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5514 ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
5515 EXPECT_THAT(getDiagnosticString(),
5516 AnyVUID("VUID-StandaloneSpirv-None-04636"));
5517 EXPECT_THAT(getDiagnosticString(),
5518 HasSubstr(": in Vulkan environment Execution Scope is limited to "
5519 "Workgroup and Subgroup"));
5520 }
5521
TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad)5522 TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) {
5523 const std::string spirv =
5524 ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform");
5525
5526 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
5527 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
5528 EXPECT_THAT(getDiagnosticString(),
5529 HasSubstr("Decorations that don't take ID parameters may not be "
5530 "used with OpDecorateId\n"
5531 " OpDecorateId %int0 Uniform"));
5532 }
5533
TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad)5534 TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) {
5535 const std::string spirv = ShaderWithUniformLikeDecoration(
5536 "OpDecorate %int0 UniformId %subgroupscope");
5537
5538 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5539 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5540 EXPECT_THAT(
5541 getDiagnosticString(),
5542 HasSubstr(
5543 "Decorations taking ID parameters may not be used with OpDecorateId\n"
5544 " OpDecorate %int0 UniformId %subgroupscope"));
5545 }
5546
TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID)5547 TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) {
5548 std::string spirv = R"(
5549 OpCapability Shader
5550 OpMemoryModel Logical GLSL450
5551 OpEntryPoint Fragment %1 "main"
5552 OpExecutionMode %1 OriginUpperLeft
5553
5554 OpMemberDecorate %struct 0 Offset 0
5555 OpMemberDecorate %struct 0 Offset 0
5556
5557 %void = OpTypeVoid
5558 %voidfn = OpTypeFunction %void
5559 %float = OpTypeFloat 32
5560 %struct = OpTypeStruct %float
5561
5562 %1 = OpFunction %void None %voidfn
5563 %label = OpLabel
5564 OpReturn
5565 OpFunctionEnd
5566 )";
5567
5568 CompileSuccessfully(spirv);
5569 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5570 EXPECT_THAT(getDiagnosticString(),
5571 HasSubstr("ID '2', member '0' decorated with Offset multiple "
5572 "times is not allowed."));
5573 }
5574
TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID)5575 TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) {
5576 std::string spirv = R"(
5577 OpCapability Shader
5578 OpMemoryModel Logical GLSL450
5579 OpEntryPoint Fragment %1 "main"
5580 OpExecutionMode %1 OriginUpperLeft
5581
5582 OpDecorate %array ArrayStride 4
5583 OpDecorate %array ArrayStride 4
5584
5585 %void = OpTypeVoid
5586 %voidfn = OpTypeFunction %void
5587 %float = OpTypeFloat 32
5588 %uint = OpTypeInt 32 0
5589 %uint_4 = OpConstant %uint 4
5590 %array = OpTypeArray %float %uint_4
5591
5592 %1 = OpFunction %void None %voidfn
5593 %label = OpLabel
5594 OpReturn
5595 OpFunctionEnd
5596 )";
5597
5598 CompileSuccessfully(spirv);
5599 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5600 EXPECT_THAT(getDiagnosticString(),
5601 HasSubstr("ID '2' decorated with ArrayStride multiple "
5602 "times is not allowed."));
5603 }
5604
TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID)5605 TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) {
5606 std::string spirv = R"(
5607 OpCapability Shader
5608 OpMemoryModel Logical GLSL450
5609 OpEntryPoint Fragment %1 "main"
5610 OpExecutionMode %1 OriginUpperLeft
5611
5612 OpMemberDecorate %struct 0 Offset 0
5613 OpMemberDecorate %struct 0 ColMajor
5614 OpMemberDecorate %struct 0 MatrixStride 16
5615 OpMemberDecorate %struct 0 MatrixStride 16
5616
5617 %void = OpTypeVoid
5618 %voidfn = OpTypeFunction %void
5619 %float = OpTypeFloat 32
5620 %fvec4 = OpTypeVector %float 4
5621 %fmat4 = OpTypeMatrix %fvec4 4
5622 %struct = OpTypeStruct %fmat4
5623
5624 %1 = OpFunction %void None %voidfn
5625 %label = OpLabel
5626 OpReturn
5627 OpFunctionEnd
5628 )";
5629
5630 CompileSuccessfully(spirv);
5631 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5632 EXPECT_THAT(getDiagnosticString(),
5633 HasSubstr("ID '2', member '0' decorated with MatrixStride "
5634 "multiple times is not allowed."));
5635 }
5636
TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID)5637 TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) {
5638 std::string spirv = R"(
5639 OpCapability Shader
5640 OpMemoryModel Logical GLSL450
5641 OpEntryPoint Fragment %1 "main"
5642 OpExecutionMode %1 OriginUpperLeft
5643
5644 OpMemberDecorate %struct 0 Offset 0
5645 OpMemberDecorate %struct 0 MatrixStride 16
5646 OpMemberDecorate %struct 0 RowMajor
5647 OpMemberDecorate %struct 0 RowMajor
5648
5649 %void = OpTypeVoid
5650 %voidfn = OpTypeFunction %void
5651 %float = OpTypeFloat 32
5652 %fvec4 = OpTypeVector %float 4
5653 %fmat4 = OpTypeMatrix %fvec4 4
5654 %struct = OpTypeStruct %fmat4
5655
5656 %1 = OpFunction %void None %voidfn
5657 %label = OpLabel
5658 OpReturn
5659 OpFunctionEnd
5660 )";
5661
5662 CompileSuccessfully(spirv);
5663 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5664 EXPECT_THAT(getDiagnosticString(),
5665 HasSubstr("ID '2', member '0' decorated with RowMajor multiple "
5666 "times is not allowed."));
5667 }
5668
TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID)5669 TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) {
5670 std::string spirv = R"(
5671 OpCapability Shader
5672 OpMemoryModel Logical GLSL450
5673 OpEntryPoint Fragment %1 "main"
5674 OpExecutionMode %1 OriginUpperLeft
5675
5676 OpMemberDecorate %struct 0 Offset 0
5677 OpMemberDecorate %struct 0 MatrixStride 16
5678 OpMemberDecorate %struct 0 ColMajor
5679 OpMemberDecorate %struct 0 ColMajor
5680
5681 %void = OpTypeVoid
5682 %voidfn = OpTypeFunction %void
5683 %float = OpTypeFloat 32
5684 %fvec4 = OpTypeVector %float 4
5685 %fmat4 = OpTypeMatrix %fvec4 4
5686 %struct = OpTypeStruct %fmat4
5687
5688 %1 = OpFunction %void None %voidfn
5689 %label = OpLabel
5690 OpReturn
5691 OpFunctionEnd
5692 )";
5693
5694 CompileSuccessfully(spirv);
5695 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5696 EXPECT_THAT(getDiagnosticString(),
5697 HasSubstr("ID '2', member '0' decorated with ColMajor multiple "
5698 "times is not allowed."));
5699 }
5700
TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID)5701 TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) {
5702 std::string spirv = R"(
5703 OpCapability Shader
5704 OpMemoryModel Logical GLSL450
5705 OpEntryPoint Fragment %1 "main"
5706 OpExecutionMode %1 OriginUpperLeft
5707
5708 OpMemberDecorate %struct 0 Offset 0
5709 OpMemberDecorate %struct 0 MatrixStride 16
5710 OpMemberDecorate %struct 0 ColMajor
5711 OpMemberDecorate %struct 0 RowMajor
5712
5713 %void = OpTypeVoid
5714 %voidfn = OpTypeFunction %void
5715 %float = OpTypeFloat 32
5716 %fvec4 = OpTypeVector %float 4
5717 %fmat4 = OpTypeMatrix %fvec4 4
5718 %struct = OpTypeStruct %fmat4
5719
5720 %1 = OpFunction %void None %voidfn
5721 %label = OpLabel
5722 OpReturn
5723 OpFunctionEnd
5724 )";
5725
5726 CompileSuccessfully(spirv);
5727 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5728 EXPECT_THAT(getDiagnosticString(),
5729 HasSubstr("ID '2', member '0' decorated with both RowMajor and "
5730 "ColMajor is not allowed."));
5731 }
5732
TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID)5733 TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
5734 std::string spirv = R"(
5735 OpCapability Shader
5736 OpMemoryModel Logical GLSL450
5737 OpEntryPoint Fragment %1 "main"
5738 OpExecutionMode %1 OriginUpperLeft
5739
5740 OpDecorate %struct Block
5741 OpDecorate %struct BufferBlock
5742 OpMemberDecorate %struct 0 Offset 0
5743 OpMemberDecorate %struct 0 MatrixStride 16
5744 OpMemberDecorate %struct 0 RowMajor
5745
5746 %void = OpTypeVoid
5747 %voidfn = OpTypeFunction %void
5748 %float = OpTypeFloat 32
5749 %fvec4 = OpTypeVector %float 4
5750 %fmat4 = OpTypeMatrix %fvec4 4
5751 %struct = OpTypeStruct %fmat4
5752
5753 %1 = OpFunction %void None %voidfn
5754 %label = OpLabel
5755 OpReturn
5756 OpFunctionEnd
5757 )";
5758
5759 CompileSuccessfully(spirv);
5760 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5761 EXPECT_THAT(
5762 getDiagnosticString(),
5763 HasSubstr(
5764 "ID '2' decorated with both BufferBlock and Block is not allowed."));
5765 }
5766
MakeIntegerShader( const std::string& decoration, const std::string& inst, const std::string& extension = �)5767 std::string MakeIntegerShader(
5768 const std::string& decoration, const std::string& inst,
5769 const std::string& extension =
5770 "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
5771 return R"(
5772 OpCapability Shader
5773 OpCapability Linkage
5774 )" + extension +
5775 R"(
5776 %glsl = OpExtInstImport "GLSL.std.450"
5777 %opencl = OpExtInstImport "OpenCL.std"
5778 OpMemoryModel Logical GLSL450
5779 OpEntryPoint GLCompute %main "main"
5780 OpName %entry "entry"
5781 )" + decoration +
5782 R"(
5783 %void = OpTypeVoid
5784 %voidfn = OpTypeFunction %void
5785 %int = OpTypeInt 32 1
5786 %zero = OpConstantNull %int
5787 %float = OpTypeFloat 32
5788 %float0 = OpConstantNull %float
5789 %main = OpFunction %void None %voidfn
5790 %entry = OpLabel
5791 )" + inst +
5792 R"(
5793 OpReturn
5794 OpFunctionEnd)";
5795 }
5796
5797 // NoSignedWrap
5798
TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad)5799 TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
5800 std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
5801
5802 CompileSuccessfully(spirv);
5803 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5804 EXPECT_THAT(
5805 getDiagnosticString(),
5806 HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
5807 }
5808
TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad)5809 TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
5810 std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
5811
5812 CompileSuccessfully(spirv);
5813 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5814 EXPECT_THAT(getDiagnosticString(),
5815 HasSubstr("NoSignedWrap decoration may not be applied to Label"));
5816 }
5817
TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad)5818 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
5819 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5820 "%val = OpIAdd %int %zero %zero", "");
5821
5822 CompileSuccessfully(spirv);
5823 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5824 EXPECT_THAT(getDiagnosticString(),
5825 HasSubstr("requires one of these extensions: "
5826 "SPV_KHR_no_integer_wrap_decoration"));
5827 }
5828
TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad)5829 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) {
5830 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5831 "%val = OpIAdd %int %zero %zero", "");
5832
5833 CompileSuccessfully(spirv);
5834 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5835 EXPECT_THAT(getDiagnosticString(),
5836 HasSubstr("requires one of these extensions: "
5837 "SPV_KHR_no_integer_wrap_decoration"));
5838 }
5839
TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good)5840 TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) {
5841 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5842 "%val = OpIAdd %int %zero %zero", "");
5843
5844 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5845 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5846 EXPECT_THAT(getDiagnosticString(), Eq(""));
5847 }
5848
TEST_F(ValidateDecorations, NoSignedWrapIAddGood)5849 TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
5850 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5851 "%val = OpIAdd %int %zero %zero");
5852
5853 CompileSuccessfully(spirv);
5854 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5855 EXPECT_THAT(getDiagnosticString(), Eq(""));
5856 }
5857
TEST_F(ValidateDecorations, NoSignedWrapISubGood)5858 TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
5859 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5860 "%val = OpISub %int %zero %zero");
5861
5862 CompileSuccessfully(spirv);
5863 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5864 EXPECT_THAT(getDiagnosticString(), Eq(""));
5865 }
5866
TEST_F(ValidateDecorations, NoSignedWrapIMulGood)5867 TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
5868 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5869 "%val = OpIMul %int %zero %zero");
5870
5871 CompileSuccessfully(spirv);
5872 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5873 EXPECT_THAT(getDiagnosticString(), Eq(""));
5874 }
5875
TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood)5876 TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
5877 std::string spirv =
5878 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5879 "%val = OpShiftLeftLogical %int %zero %zero");
5880
5881 CompileSuccessfully(spirv);
5882 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5883 EXPECT_THAT(getDiagnosticString(), Eq(""));
5884 }
5885
TEST_F(ValidateDecorations, NoSignedWrapSNegateGood)5886 TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
5887 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5888 "%val = OpSNegate %int %zero");
5889
5890 CompileSuccessfully(spirv);
5891 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5892 EXPECT_THAT(getDiagnosticString(), Eq(""));
5893 }
5894
TEST_F(ValidateDecorations, NoSignedWrapSRemBad)5895 TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
5896 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5897 "%val = OpSRem %int %zero %zero");
5898
5899 CompileSuccessfully(spirv);
5900 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5901 EXPECT_THAT(getDiagnosticString(),
5902 HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
5903 }
5904
TEST_F(ValidateDecorations, NoSignedWrapFAddBad)5905 TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
5906 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5907 "%val = OpFAdd %float %float0 %float0");
5908
5909 CompileSuccessfully(spirv);
5910 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5911 EXPECT_THAT(getDiagnosticString(),
5912 HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
5913 }
5914
TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood)5915 TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
5916 std::string spirv =
5917 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5918 "%val = OpExtInst %int %opencl s_abs %zero");
5919
5920 CompileSuccessfully(spirv);
5921 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5922 EXPECT_THAT(getDiagnosticString(), Eq(""));
5923 }
5924
TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood)5925 TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
5926 std::string spirv = MakeIntegerShader(
5927 "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
5928
5929 CompileSuccessfully(spirv);
5930 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5931 EXPECT_THAT(getDiagnosticString(), Eq(""));
5932 }
5933
5934 // TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
5935 // "OpExtInst for instruction numbers specified in the extended
5936 // instruction-set specifications as accepting this decoration."
5937
5938 // NoUnignedWrap
5939
TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad)5940 TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
5941 std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
5942
5943 CompileSuccessfully(spirv);
5944 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5945 EXPECT_THAT(
5946 getDiagnosticString(),
5947 HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
5948 }
5949
TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad)5950 TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
5951 std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
5952
5953 CompileSuccessfully(spirv);
5954 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5955 EXPECT_THAT(
5956 getDiagnosticString(),
5957 HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
5958 }
5959
TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad)5960 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
5961 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5962 "%val = OpIAdd %int %zero %zero", "");
5963
5964 CompileSuccessfully(spirv);
5965 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5966 EXPECT_THAT(getDiagnosticString(),
5967 HasSubstr("requires one of these extensions: "
5968 "SPV_KHR_no_integer_wrap_decoration"));
5969 }
5970
TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad)5971 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) {
5972 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5973 "%val = OpIAdd %int %zero %zero", "");
5974
5975 CompileSuccessfully(spirv);
5976 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5977 EXPECT_THAT(getDiagnosticString(),
5978 HasSubstr("requires one of these extensions: "
5979 "SPV_KHR_no_integer_wrap_decoration"));
5980 }
5981
TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good)5982 TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) {
5983 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5984 "%val = OpIAdd %int %zero %zero", "");
5985
5986 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5987 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5988 EXPECT_THAT(getDiagnosticString(), Eq(""));
5989 }
5990
TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood)5991 TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
5992 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5993 "%val = OpIAdd %int %zero %zero");
5994
5995 CompileSuccessfully(spirv);
5996 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5997 EXPECT_THAT(getDiagnosticString(), Eq(""));
5998 }
5999
TEST_F(ValidateDecorations, NoUnsignedWrapISubGood)6000 TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
6001 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6002 "%val = OpISub %int %zero %zero");
6003
6004 CompileSuccessfully(spirv);
6005 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6006 EXPECT_THAT(getDiagnosticString(), Eq(""));
6007 }
6008
TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood)6009 TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
6010 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6011 "%val = OpIMul %int %zero %zero");
6012
6013 CompileSuccessfully(spirv);
6014 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6015 EXPECT_THAT(getDiagnosticString(), Eq(""));
6016 }
6017
TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood)6018 TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
6019 std::string spirv =
6020 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6021 "%val = OpShiftLeftLogical %int %zero %zero");
6022
6023 CompileSuccessfully(spirv);
6024 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6025 EXPECT_THAT(getDiagnosticString(), Eq(""));
6026 }
6027
TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood)6028 TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
6029 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6030 "%val = OpSNegate %int %zero");
6031
6032 CompileSuccessfully(spirv);
6033 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6034 EXPECT_THAT(getDiagnosticString(), Eq(""));
6035 }
6036
TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad)6037 TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
6038 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6039 "%val = OpSRem %int %zero %zero");
6040
6041 CompileSuccessfully(spirv);
6042 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6043 EXPECT_THAT(
6044 getDiagnosticString(),
6045 HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
6046 }
6047
TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad)6048 TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
6049 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6050 "%val = OpFAdd %float %float0 %float0");
6051
6052 CompileSuccessfully(spirv);
6053 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6054 EXPECT_THAT(
6055 getDiagnosticString(),
6056 HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
6057 }
6058
TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood)6059 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
6060 std::string spirv =
6061 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6062 "%val = OpExtInst %int %opencl s_abs %zero");
6063
6064 CompileSuccessfully(spirv);
6065 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6066 EXPECT_THAT(getDiagnosticString(), Eq(""));
6067 }
6068
TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood)6069 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
6070 std::string spirv =
6071 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
6072 "%val = OpExtInst %int %glsl SAbs %zero");
6073
6074 CompileSuccessfully(spirv);
6075 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6076 EXPECT_THAT(getDiagnosticString(), Eq(""));
6077 }
6078
TEST_F(ValidateDecorations, AliasedandRestrictBad)6079 TEST_F(ValidateDecorations, AliasedandRestrictBad) {
6080 const std::string body = R"(
6081 OpCapability Shader
6082 %1 = OpExtInstImport "GLSL.std.450"
6083 OpMemoryModel Logical GLSL450
6084 OpEntryPoint GLCompute %main "main"
6085 OpExecutionMode %main LocalSize 1 1 1
6086 OpSource GLSL 430
6087 OpMemberDecorate %Output 0 Offset 0
6088 OpDecorate %Output BufferBlock
6089 OpDecorate %dataOutput Restrict
6090 OpDecorate %dataOutput Aliased
6091 %void = OpTypeVoid
6092 %3 = OpTypeFunction %void
6093 %float = OpTypeFloat 32
6094 %Output = OpTypeStruct %float
6095 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
6096 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
6097 %main = OpFunction %void None %3
6098 %5 = OpLabel
6099 OpReturn
6100 OpFunctionEnd
6101 )";
6102
6103 CompileSuccessfully(body.c_str());
6104 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6105 EXPECT_THAT(
6106 getDiagnosticString(),
6107 HasSubstr("decorated with both Aliased and Restrict is not allowed"));
6108 }
6109
6110 // TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
6111 // "OpExtInst for instruction numbers specified in the extended
6112 // instruction-set specifications as accepting this decoration."
6113
TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess)6114 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
6115 const std::string body = R"(
6116 OpCapability PhysicalStorageBufferAddresses
6117 OpCapability Int64
6118 OpCapability Shader
6119 OpExtension "SPV_EXT_physical_storage_buffer"
6120 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6121 OpEntryPoint Fragment %main "main"
6122 OpExecutionMode %main OriginUpperLeft
6123 OpDecorate %val1 RestrictPointer
6124 %uint64 = OpTypeInt 64 0
6125 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6126 %pptr_f = OpTypePointer Function %ptr
6127 %void = OpTypeVoid
6128 %voidfn = OpTypeFunction %void
6129 %main = OpFunction %void None %voidfn
6130 %entry = OpLabel
6131 %val1 = OpVariable %pptr_f Function
6132 OpReturn
6133 OpFunctionEnd
6134 )";
6135
6136 CompileSuccessfully(body.c_str());
6137 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6138 }
6139
TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing)6140 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) {
6141 const std::string body = R"(
6142 OpCapability PhysicalStorageBufferAddresses
6143 OpCapability Int64
6144 OpCapability Shader
6145 OpExtension "SPV_EXT_physical_storage_buffer"
6146 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6147 OpEntryPoint Fragment %main "main"
6148 OpExecutionMode %main OriginUpperLeft
6149 %uint64 = OpTypeInt 64 0
6150 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6151 %pptr_f = OpTypePointer Function %ptr
6152 %void = OpTypeVoid
6153 %voidfn = OpTypeFunction %void
6154 %main = OpFunction %void None %voidfn
6155 %entry = OpLabel
6156 %val1 = OpVariable %pptr_f Function
6157 OpReturn
6158 OpFunctionEnd
6159 )";
6160
6161 CompileSuccessfully(body.c_str());
6162 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6163 EXPECT_THAT(getDiagnosticString(),
6164 HasSubstr("expected AliasedPointer or RestrictPointer for "
6165 "PhysicalStorageBuffer pointer"));
6166 }
6167
TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth)6168 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) {
6169 const std::string body = R"(
6170 OpCapability PhysicalStorageBufferAddresses
6171 OpCapability Int64
6172 OpCapability Shader
6173 OpExtension "SPV_EXT_physical_storage_buffer"
6174 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6175 OpEntryPoint Fragment %main "main"
6176 OpExecutionMode %main OriginUpperLeft
6177 OpDecorate %val1 RestrictPointer
6178 OpDecorate %val1 AliasedPointer
6179 %uint64 = OpTypeInt 64 0
6180 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6181 %pptr_f = OpTypePointer Function %ptr
6182 %void = OpTypeVoid
6183 %voidfn = OpTypeFunction %void
6184 %main = OpFunction %void None %voidfn
6185 %entry = OpLabel
6186 %val1 = OpVariable %pptr_f Function
6187 OpReturn
6188 OpFunctionEnd
6189 )";
6190
6191 CompileSuccessfully(body.c_str());
6192 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6193 EXPECT_THAT(getDiagnosticString(),
6194 HasSubstr("can't specify both AliasedPointer and RestrictPointer "
6195 "for PhysicalStorageBuffer pointer"));
6196 }
6197
TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess)6198 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) {
6199 const std::string body = R"(
6200 OpCapability PhysicalStorageBufferAddresses
6201 OpCapability Int64
6202 OpCapability Shader
6203 OpExtension "SPV_EXT_physical_storage_buffer"
6204 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6205 OpEntryPoint Fragment %main "main"
6206 OpExecutionMode %main OriginUpperLeft
6207 OpDecorate %fparam Restrict
6208 %uint64 = OpTypeInt 64 0
6209 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6210 %void = OpTypeVoid
6211 %voidfn = OpTypeFunction %void
6212 %fnptr = OpTypeFunction %void %ptr
6213 %main = OpFunction %void None %voidfn
6214 %entry = OpLabel
6215 OpReturn
6216 OpFunctionEnd
6217 %fn = OpFunction %void None %fnptr
6218 %fparam = OpFunctionParameter %ptr
6219 %lab = OpLabel
6220 OpReturn
6221 OpFunctionEnd
6222 )";
6223
6224 CompileSuccessfully(body.c_str());
6225 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6226 }
6227
TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing)6228 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) {
6229 const std::string body = R"(
6230 OpCapability PhysicalStorageBufferAddresses
6231 OpCapability Int64
6232 OpCapability Shader
6233 OpExtension "SPV_EXT_physical_storage_buffer"
6234 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6235 OpEntryPoint Fragment %main "main"
6236 OpExecutionMode %main OriginUpperLeft
6237 %uint64 = OpTypeInt 64 0
6238 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6239 %void = OpTypeVoid
6240 %voidfn = OpTypeFunction %void
6241 %fnptr = OpTypeFunction %void %ptr
6242 %main = OpFunction %void None %voidfn
6243 %entry = OpLabel
6244 OpReturn
6245 OpFunctionEnd
6246 %fn = OpFunction %void None %fnptr
6247 %fparam = OpFunctionParameter %ptr
6248 %lab = OpLabel
6249 OpReturn
6250 OpFunctionEnd
6251 )";
6252
6253 CompileSuccessfully(body.c_str());
6254 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6255 EXPECT_THAT(getDiagnosticString(),
6256 HasSubstr("expected Aliased or Restrict for "
6257 "PhysicalStorageBuffer pointer"));
6258 }
6259
TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth)6260 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
6261 const std::string body = R"(
6262 OpCapability PhysicalStorageBufferAddresses
6263 OpCapability Int64
6264 OpCapability Shader
6265 OpExtension "SPV_EXT_physical_storage_buffer"
6266 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6267 OpEntryPoint Fragment %main "main"
6268 OpExecutionMode %main OriginUpperLeft
6269 OpDecorate %fparam Restrict
6270 OpDecorate %fparam Aliased
6271 %uint64 = OpTypeInt 64 0
6272 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6273 %void = OpTypeVoid
6274 %voidfn = OpTypeFunction %void
6275 %fnptr = OpTypeFunction %void %ptr
6276 %main = OpFunction %void None %voidfn
6277 %entry = OpLabel
6278 OpReturn
6279 OpFunctionEnd
6280 %fn = OpFunction %void None %fnptr
6281 %fparam = OpFunctionParameter %ptr
6282 %lab = OpLabel
6283 OpReturn
6284 OpFunctionEnd
6285 )";
6286
6287 CompileSuccessfully(body.c_str());
6288 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6289 EXPECT_THAT(getDiagnosticString(),
6290 HasSubstr("can't specify both Aliased and Restrict for "
6291 "PhysicalStorageBuffer pointer"));
6292 }
6293
TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess)6294 TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) {
6295 std::string spirv = R"(
6296 OpCapability PhysicalStorageBufferAddresses
6297 OpCapability Shader
6298 OpCapability Linkage
6299 OpCapability StorageBuffer16BitAccess
6300 OpExtension "SPV_EXT_physical_storage_buffer"
6301 OpExtension "SPV_KHR_storage_buffer_storage_class"
6302 OpExtension "SPV_KHR_variable_pointers"
6303 OpExtension "SPV_KHR_16bit_storage"
6304 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6305 OpEntryPoint GLCompute %main "main"
6306 OpDecorate %_ FPRoundingMode RTE
6307 OpDecorate %half_ptr_var AliasedPointer
6308 %half = OpTypeFloat 16
6309 %float = OpTypeFloat 32
6310 %float_1_25 = OpConstant %float 1.25
6311 %half_ptr = OpTypePointer PhysicalStorageBuffer %half
6312 %half_pptr_f = OpTypePointer Function %half_ptr
6313 %void = OpTypeVoid
6314 %func = OpTypeFunction %void
6315 %main = OpFunction %void None %func
6316 %main_entry = OpLabel
6317 %half_ptr_var = OpVariable %half_pptr_f Function
6318 %val1 = OpLoad %half_ptr %half_ptr_var
6319 %_ = OpFConvert %half %float_1_25
6320 OpStore %val1 %_ Aligned 2
6321 OpReturn
6322 OpFunctionEnd
6323 )";
6324
6325 CompileSuccessfully(spirv);
6326 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6327 }
6328
TEST_F(ValidateDecorations, InvalidStraddle)6329 TEST_F(ValidateDecorations, InvalidStraddle) {
6330 const std::string spirv = R"(
6331 OpCapability Shader
6332 OpMemoryModel Logical GLSL450
6333 OpEntryPoint GLCompute %main "main"
6334 OpExecutionMode %main LocalSize 1 1 1
6335 OpMemberDecorate %inner_struct 0 Offset 0
6336 OpMemberDecorate %inner_struct 1 Offset 4
6337 OpDecorate %outer_struct Block
6338 OpMemberDecorate %outer_struct 0 Offset 0
6339 OpMemberDecorate %outer_struct 1 Offset 8
6340 OpDecorate %var DescriptorSet 0
6341 OpDecorate %var Binding 0
6342 %void = OpTypeVoid
6343 %float = OpTypeFloat 32
6344 %float2 = OpTypeVector %float 2
6345 %inner_struct = OpTypeStruct %float %float2
6346 %outer_struct = OpTypeStruct %float2 %inner_struct
6347 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct
6348 %var = OpVariable %ptr_ssbo_outer StorageBuffer
6349 %void_fn = OpTypeFunction %void
6350 %main = OpFunction %void None %void_fn
6351 %entry = OpLabel
6352 OpReturn
6353 OpFunctionEnd
6354 )";
6355
6356 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6357 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6358 EXPECT_THAT(getDiagnosticString(),
6359 HasSubstr("Structure id 2 decorated as Block for variable in "
6360 "StorageBuffer storage class must follow relaxed "
6361 "storage buffer layout rules: member 1 is an "
6362 "improperly straddling vector at offset 12"));
6363 }
6364
TEST_F(ValidateDecorations, DescriptorArray)6365 TEST_F(ValidateDecorations, DescriptorArray) {
6366 const std::string spirv = R"(
6367 OpCapability Shader
6368 OpExtension "SPV_KHR_storage_buffer_storage_class"
6369 OpMemoryModel Logical GLSL450
6370 OpEntryPoint GLCompute %main "main"
6371 OpExecutionMode %main LocalSize 1 1 1
6372 OpDecorate %struct Block
6373 OpMemberDecorate %struct 0 Offset 0
6374 OpMemberDecorate %struct 1 Offset 1
6375 OpDecorate %var DescriptorSet 0
6376 OpDecorate %var Binding 0
6377 %void = OpTypeVoid
6378 %float = OpTypeFloat 32
6379 %int = OpTypeInt 32 0
6380 %int_2 = OpConstant %int 2
6381 %float2 = OpTypeVector %float 2
6382 %struct = OpTypeStruct %float %float2
6383 %struct_array = OpTypeArray %struct %int_2
6384 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6385 %var = OpVariable %ptr_ssbo_array StorageBuffer
6386 %void_fn = OpTypeFunction %void
6387 %main = OpFunction %void None %void_fn
6388 %entry = OpLabel
6389 OpReturn
6390 OpFunctionEnd
6391 )";
6392
6393 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6394 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6395 EXPECT_THAT(getDiagnosticString(),
6396 HasSubstr("Structure id 2 decorated as Block for variable in "
6397 "StorageBuffer storage class must follow standard "
6398 "storage buffer layout rules: member 1 at offset 1 is "
6399 "not aligned to 8"));
6400 }
6401
TEST_F(ValidateDecorations, DescriptorRuntimeArray)6402 TEST_F(ValidateDecorations, DescriptorRuntimeArray) {
6403 const std::string spirv = R"(
6404 OpCapability Shader
6405 OpCapability RuntimeDescriptorArrayEXT
6406 OpExtension "SPV_KHR_storage_buffer_storage_class"
6407 OpExtension "SPV_EXT_descriptor_indexing"
6408 OpMemoryModel Logical GLSL450
6409 OpEntryPoint GLCompute %main "main"
6410 OpExecutionMode %main LocalSize 1 1 1
6411 OpDecorate %struct Block
6412 OpMemberDecorate %struct 0 Offset 0
6413 OpMemberDecorate %struct 1 Offset 1
6414 OpDecorate %var DescriptorSet 0
6415 OpDecorate %var Binding 0
6416 %void = OpTypeVoid
6417 %float = OpTypeFloat 32
6418 %int = OpTypeInt 32 0
6419 %float2 = OpTypeVector %float 2
6420 %struct = OpTypeStruct %float %float2
6421 %struct_array = OpTypeRuntimeArray %struct
6422 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6423 %var = OpVariable %ptr_ssbo_array StorageBuffer
6424 %void_fn = OpTypeFunction %void
6425 %main = OpFunction %void None %void_fn
6426 %entry = OpLabel
6427 OpReturn
6428 OpFunctionEnd
6429 )";
6430
6431 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6432 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6433 EXPECT_THAT(getDiagnosticString(),
6434 HasSubstr("Structure id 2 decorated as Block for variable in "
6435 "StorageBuffer storage class must follow standard "
6436 "storage buffer layout rules: member 1 at offset 1 is "
6437 "not aligned to 8"));
6438 }
6439
TEST_F(ValidateDecorations, MultiDimensionalArray)6440 TEST_F(ValidateDecorations, MultiDimensionalArray) {
6441 const std::string spirv = R"(
6442 OpCapability Shader
6443 OpMemoryModel Logical GLSL450
6444 OpEntryPoint GLCompute %main "main"
6445 OpExecutionMode %main LocalSize 1 1 1
6446 OpDecorate %struct Block
6447 OpMemberDecorate %struct 0 Offset 0
6448 OpDecorate %array_4 ArrayStride 4
6449 OpDecorate %array_3 ArrayStride 48
6450 OpDecorate %var DescriptorSet 0
6451 OpDecorate %var Binding 0
6452 %void = OpTypeVoid
6453 %int = OpTypeInt 32 0
6454 %int_3 = OpConstant %int 3
6455 %int_4 = OpConstant %int 4
6456 %array_4 = OpTypeArray %int %int_4
6457 %array_3 = OpTypeArray %array_4 %int_3
6458 %struct = OpTypeStruct %array_3
6459 %ptr_struct = OpTypePointer Uniform %struct
6460 %var = OpVariable %ptr_struct Uniform
6461 %void_fn = OpTypeFunction %void
6462 %main = OpFunction %void None %void_fn
6463 %entry = OpLabel
6464 OpReturn
6465 OpFunctionEnd
6466 )";
6467
6468 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6469 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6470 EXPECT_THAT(getDiagnosticString(),
6471 HasSubstr("Structure id 2 decorated as Block for variable in "
6472 "Uniform storage class must follow standard uniform "
6473 "buffer layout rules: member 0 contains an array with "
6474 "stride 4 not satisfying alignment to 16"));
6475 }
6476
TEST_F(ValidateDecorations, ImproperStraddleInArray)6477 TEST_F(ValidateDecorations, ImproperStraddleInArray) {
6478 const std::string spirv = R"(
6479 OpCapability Shader
6480 OpMemoryModel Logical GLSL450
6481 OpEntryPoint GLCompute %main "main"
6482 OpExecutionMode %main LocalSize 1 1 1
6483 OpDecorate %struct Block
6484 OpMemberDecorate %struct 0 Offset 0
6485 OpDecorate %array ArrayStride 24
6486 OpMemberDecorate %inner 0 Offset 0
6487 OpMemberDecorate %inner 1 Offset 4
6488 OpMemberDecorate %inner 2 Offset 12
6489 OpMemberDecorate %inner 3 Offset 16
6490 OpDecorate %var DescriptorSet 0
6491 OpDecorate %var Binding 0
6492 %void = OpTypeVoid
6493 %int = OpTypeInt 32 0
6494 %int_2 = OpConstant %int 2
6495 %int2 = OpTypeVector %int 2
6496 %inner = OpTypeStruct %int %int2 %int %int
6497 %array = OpTypeArray %inner %int_2
6498 %struct = OpTypeStruct %array
6499 %ptr_struct = OpTypePointer StorageBuffer %struct
6500 %var = OpVariable %ptr_struct StorageBuffer
6501 %void_fn = OpTypeFunction %void
6502 %main = OpFunction %void None %void_fn
6503 %entry = OpLabel
6504 OpReturn
6505 OpFunctionEnd
6506 )";
6507
6508 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6509 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6510 EXPECT_THAT(getDiagnosticString(),
6511 HasSubstr("Structure id 4 decorated as Block for variable in "
6512 "StorageBuffer storage class must follow relaxed "
6513 "storage buffer layout rules: member 1 is an "
6514 "improperly straddling vector at offset 28"));
6515 }
6516
TEST_F(ValidateDecorations, LargeArray)6517 TEST_F(ValidateDecorations, LargeArray) {
6518 const std::string spirv = R"(
6519 OpCapability Shader
6520 OpMemoryModel Logical GLSL450
6521 OpEntryPoint GLCompute %main "main"
6522 OpExecutionMode %main LocalSize 1 1 1
6523 OpDecorate %struct Block
6524 OpMemberDecorate %struct 0 Offset 0
6525 OpDecorate %array ArrayStride 24
6526 OpMemberDecorate %inner 0 Offset 0
6527 OpMemberDecorate %inner 1 Offset 8
6528 OpMemberDecorate %inner 2 Offset 16
6529 OpMemberDecorate %inner 3 Offset 20
6530 OpDecorate %var DescriptorSet 0
6531 OpDecorate %var Binding 0
6532 %void = OpTypeVoid
6533 %int = OpTypeInt 32 0
6534 %int_2000000 = OpConstant %int 2000000
6535 %int2 = OpTypeVector %int 2
6536 %inner = OpTypeStruct %int %int2 %int %int
6537 %array = OpTypeArray %inner %int_2000000
6538 %struct = OpTypeStruct %array
6539 %ptr_struct = OpTypePointer StorageBuffer %struct
6540 %var = OpVariable %ptr_struct StorageBuffer
6541 %void_fn = OpTypeFunction %void
6542 %main = OpFunction %void None %void_fn
6543 %entry = OpLabel
6544 OpReturn
6545 OpFunctionEnd
6546 )";
6547
6548 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6549 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6550 }
6551
6552 // NonWritable
6553
6554 // Returns a SPIR-V shader module with variables in various storage classes,
6555 // parameterizable by which ID should be decorated as NonWritable.
ShaderWithNonWritableTarget(const std::string& target, bool member_decorate = false)6556 std::string ShaderWithNonWritableTarget(const std::string& target,
6557 bool member_decorate = false) {
6558 const std::string decoration_inst =
6559 std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") +
6560 target + (member_decorate ? " 0" : "");
6561
6562 return std::string(R"(
6563 OpCapability Shader
6564 OpCapability RuntimeDescriptorArrayEXT
6565 OpExtension "SPV_EXT_descriptor_indexing"
6566 OpExtension "SPV_KHR_storage_buffer_storage_class"
6567 OpMemoryModel Logical GLSL450
6568 OpEntryPoint Vertex %main "main"
6569 OpName %label "label"
6570 OpName %param_f "param_f"
6571 OpName %param_p "param_p"
6572 OpName %_ptr_imstor "_ptr_imstor"
6573 OpName %_ptr_imsam "_ptr_imsam"
6574 OpName %var_wg "var_wg"
6575 OpName %var_imsam "var_imsam"
6576 OpName %var_priv "var_priv"
6577 OpName %var_func "var_func"
6578 OpName %simple_struct "simple_struct"
6579
6580 OpDecorate %struct_b Block
6581 OpDecorate %struct_b_rtarr Block
6582 OpMemberDecorate %struct_b 0 Offset 0
6583 OpMemberDecorate %struct_b_rtarr 0 Offset 0
6584 OpDecorate %rtarr ArrayStride 4
6585 )") + decoration_inst +
6586
6587 R"( NonWritable
6588
6589 %void = OpTypeVoid
6590 %void_fn = OpTypeFunction %void
6591 %float = OpTypeFloat 32
6592 %float_0 = OpConstant %float 0
6593 %int = OpTypeInt 32 0
6594 %int_2 = OpConstant %int 2
6595 %struct_b = OpTypeStruct %float
6596 %rtarr = OpTypeRuntimeArray %float
6597 %struct_b_rtarr = OpTypeStruct %rtarr
6598 %simple_struct = OpTypeStruct %float
6599 ; storage image
6600 %imstor = OpTypeImage %float 2D 0 0 0 2 R32f
6601 ; sampled image
6602 %imsam = OpTypeImage %float 2D 0 0 0 1 R32f
6603 %array_imstor = OpTypeArray %imstor %int_2
6604 %rta_imstor = OpTypeRuntimeArray %imstor
6605
6606 %_ptr_Uniform_stb = OpTypePointer Uniform %struct_b
6607 %_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b
6608 %_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr
6609 %_ptr_Workgroup = OpTypePointer Workgroup %float
6610 %_ptr_Private = OpTypePointer Private %float
6611 %_ptr_Function = OpTypePointer Function %float
6612 %_ptr_imstor = OpTypePointer UniformConstant %imstor
6613 %_ptr_imsam = OpTypePointer UniformConstant %imsam
6614 %_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor
6615 %_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor
6616
6617 %extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor
6618
6619 %var_ubo = OpVariable %_ptr_Uniform_stb Uniform
6620 %var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer
6621 %var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer
6622 %var_wg = OpVariable %_ptr_Workgroup Workgroup
6623 %var_priv = OpVariable %_ptr_Private Private
6624 %var_imstor = OpVariable %_ptr_imstor UniformConstant
6625 %var_imsam = OpVariable %_ptr_imsam UniformConstant
6626 %var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant
6627 %var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant
6628
6629 %helper = OpFunction %void None %extra_fn
6630 %param_f = OpFunctionParameter %float
6631 %param_p = OpFunctionParameter %_ptr_Private
6632 %param_pimstor = OpFunctionParameter %_ptr_imstor
6633 %helper_label = OpLabel
6634 %helper_func_var = OpVariable %_ptr_Function Function
6635 OpReturn
6636 OpFunctionEnd
6637
6638 %main = OpFunction %void None %void_fn
6639 %label = OpLabel
6640 %var_func = OpVariable %_ptr_Function Function
6641 OpReturn
6642 OpFunctionEnd
6643 )";
6644 }
6645
TEST_F(ValidateDecorations, NonWritableLabelTargetBad)6646 TEST_F(ValidateDecorations, NonWritableLabelTargetBad) {
6647 std::string spirv = ShaderWithNonWritableTarget("%label");
6648
6649 CompileSuccessfully(spirv);
6650 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6651 EXPECT_THAT(getDiagnosticString(),
6652 HasSubstr("must be a memory object declaration"));
6653 }
6654
TEST_F(ValidateDecorations, NonWritableTypeTargetBad)6655 TEST_F(ValidateDecorations, NonWritableTypeTargetBad) {
6656 std::string spirv = ShaderWithNonWritableTarget("%void");
6657
6658 CompileSuccessfully(spirv);
6659 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6660 EXPECT_THAT(getDiagnosticString(),
6661 HasSubstr("must be a memory object declaration"));
6662 }
6663
TEST_F(ValidateDecorations, NonWritableValueTargetBad)6664 TEST_F(ValidateDecorations, NonWritableValueTargetBad) {
6665 std::string spirv = ShaderWithNonWritableTarget("%float_0");
6666
6667 CompileSuccessfully(spirv);
6668 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6669 EXPECT_THAT(getDiagnosticString(),
6670 HasSubstr("must be a memory object declaration"));
6671 }
6672
TEST_F(ValidateDecorations, NonWritableValueParamBad)6673 TEST_F(ValidateDecorations, NonWritableValueParamBad) {
6674 std::string spirv = ShaderWithNonWritableTarget("%param_f");
6675
6676 CompileSuccessfully(spirv);
6677 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6678 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
6679 }
6680
TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad)6681 TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) {
6682 std::string spirv = ShaderWithNonWritableTarget("%param_p");
6683
6684 CompileSuccessfully(spirv);
6685 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6686 EXPECT_THAT(
6687 getDiagnosticString(),
6688 HasSubstr(
6689 "Target of NonWritable decoration is invalid: must "
6690 "point to a storage image, uniform block, or storage "
6691 "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float"));
6692 }
6693
TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood)6694 TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) {
6695 std::string spirv = ShaderWithNonWritableTarget("%param_pimstor");
6696
6697 CompileSuccessfully(spirv);
6698 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6699 EXPECT_THAT(getDiagnosticString(), Eq(""));
6700 }
6701
TEST_F(ValidateDecorations, NonWritableVarStorageImageGood)6702 TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) {
6703 std::string spirv = ShaderWithNonWritableTarget("%var_imstor");
6704
6705 CompileSuccessfully(spirv);
6706 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6707 EXPECT_THAT(getDiagnosticString(), Eq(""));
6708 }
6709
TEST_F(ValidateDecorations, NonWritableVarSampledImageBad)6710 TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) {
6711 std::string spirv = ShaderWithNonWritableTarget("%var_imsam");
6712
6713 CompileSuccessfully(spirv);
6714 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6715 EXPECT_THAT(getDiagnosticString(),
6716 HasSubstr("Target of NonWritable decoration is invalid: must "
6717 "point to a storage image, uniform block, or storage "
6718 "buffer\n %var_imsam"));
6719 }
6720
TEST_F(ValidateDecorations, NonWritableVarUboGood)6721 TEST_F(ValidateDecorations, NonWritableVarUboGood) {
6722 std::string spirv = ShaderWithNonWritableTarget("%var_ubo");
6723
6724 CompileSuccessfully(spirv);
6725 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6726 EXPECT_THAT(getDiagnosticString(), Eq(""));
6727 }
6728
TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood)6729 TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) {
6730 const std::string spirv = R"(
6731 OpCapability Shader
6732 OpMemoryModel Logical GLSL450
6733 OpEntryPoint Vertex %main "main"
6734 OpDecorate %struct_bb BufferBlock
6735 OpMemberDecorate %struct_bb 0 Offset 0
6736 OpDecorate %var_ssbo_u NonWritable
6737 %void = OpTypeVoid
6738 %void_fn = OpTypeFunction %void
6739 %float = OpTypeFloat 32
6740 %struct_bb = OpTypeStruct %float
6741 %_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb
6742 %var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform
6743 %main = OpFunction %void None %void_fn
6744 %label = OpLabel
6745 OpReturn
6746 OpFunctionEnd
6747 )";
6748
6749 CompileSuccessfully(spirv);
6750 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6751 EXPECT_THAT(getDiagnosticString(), Eq(""));
6752 }
6753
TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood)6754 TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) {
6755 std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb");
6756
6757 CompileSuccessfully(spirv);
6758 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6759 EXPECT_THAT(getDiagnosticString(), Eq(""));
6760 }
6761
TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood)6762 TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) {
6763 std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true);
6764
6765 CompileSuccessfully(spirv);
6766 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6767 EXPECT_THAT(getDiagnosticString(), Eq(""));
6768 }
6769
TEST_F(ValidateDecorations, NonWritableMemberOfStructGood)6770 TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) {
6771 std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true);
6772
6773 CompileSuccessfully(spirv);
6774 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6775 }
6776
TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad)6777 TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) {
6778 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6779
6780 CompileSuccessfully(spirv);
6781 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6782 EXPECT_THAT(getDiagnosticString(),
6783 HasSubstr("Target of NonWritable decoration is invalid: must "
6784 "point to a storage image, uniform block, or storage "
6785 "buffer\n %var_wg"));
6786 }
6787
TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad)6788 TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) {
6789 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6790
6791 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6792 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6793 EXPECT_THAT(getDiagnosticString(),
6794 HasSubstr("Target of NonWritable decoration is invalid: must "
6795 "point to a storage image, uniform block, storage "
6796 "buffer, or variable in Private or Function storage "
6797 "class\n %var_wg"));
6798 }
6799
TEST_F(ValidateDecorations, NonWritableVarPrivateBad)6800 TEST_F(ValidateDecorations, NonWritableVarPrivateBad) {
6801 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6802
6803 CompileSuccessfully(spirv);
6804 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6805 EXPECT_THAT(getDiagnosticString(),
6806 HasSubstr("Target of NonWritable decoration is invalid: must "
6807 "point to a storage image, uniform block, or storage "
6808 "buffer\n %var_priv"));
6809 }
6810
TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad)6811 TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) {
6812 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6813
6814 CompileSuccessfully(spirv);
6815 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6816 EXPECT_THAT(getDiagnosticString(),
6817 HasSubstr("Target of NonWritable decoration is invalid: must "
6818 "point to a storage image, uniform block, or storage "
6819 "buffer\n %var_priv"));
6820 }
6821
TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good)6822 TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) {
6823 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6824
6825 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6826 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6827 EXPECT_THAT(getDiagnosticString(), Eq(""));
6828 }
6829
TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad)6830 TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) {
6831 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6832
6833 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
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, or storage "
6838 "buffer\n %var_priv"));
6839 }
6840
TEST_F(ValidateDecorations, NonWritableVarFunctionBad)6841 TEST_F(ValidateDecorations, NonWritableVarFunctionBad) {
6842 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6843
6844 CompileSuccessfully(spirv);
6845 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6846 EXPECT_THAT(getDiagnosticString(),
6847 HasSubstr("Target of NonWritable decoration is invalid: must "
6848 "point to a storage image, uniform block, or storage "
6849 "buffer\n %var_func"));
6850 }
6851
TEST_F(ValidateDecorations, NonWritableArrayGood)6852 TEST_F(ValidateDecorations, NonWritableArrayGood) {
6853 std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor");
6854
6855 CompileSuccessfully(spirv);
6856 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6857 }
6858
TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood)6859 TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) {
6860 std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor");
6861
6862 CompileSuccessfully(spirv);
6863 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6864 }
6865
TEST_P(ValidateVulkanCombineDecorationResult, Decorate)6866 TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
6867 const char* const decoration = std::get<0>(GetParam());
6868 const char* const vuid = std::get<1>(GetParam());
6869 const TestResult& test_result = std::get<2>(GetParam());
6870
6871 CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
6872 generator.before_types_ = "OpDecorate %u32 ";
6873 generator.before_types_ += decoration;
6874 generator.before_types_ += "\n";
6875
6876 EntryPoint entry_point;
6877 entry_point.name = "main";
6878 entry_point.execution_model = "Vertex";
6879 generator.entry_points_.push_back(std::move(entry_point));
6880
6881 CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
6882 ASSERT_EQ(test_result.validation_result,
6883 ValidateInstructions(SPV_ENV_VULKAN_1_0));
6884 if (!test_result.error_str.empty()) {
6885 EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
6886 }
6887 if (vuid) {
6888 EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
6889 }
6890 }
6891
6892 INSTANTIATE_TEST_SUITE_P(
6893 DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
6894 Combine(Values("GLSLShared", "GLSLPacked"),
6895 Values("VUID-StandaloneSpirv-GLSLShared-04669"),
6896 Values(TestResult(
6897 SPV_ERROR_INVALID_ID,
6898 "is not valid for the Vulkan execution environment."))));
6899
TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad)6900 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
6901 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6902
6903 CompileSuccessfully(spirv);
6904 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6905 EXPECT_THAT(getDiagnosticString(),
6906 HasSubstr("Target of NonWritable decoration is invalid: must "
6907 "point to a storage image, uniform block, or storage "
6908 "buffer\n %var_func"));
6909 }
6910
TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good)6911 TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) {
6912 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6913
6914 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6915 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6916 EXPECT_THAT(getDiagnosticString(), Eq(""));
6917 }
6918
TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad)6919 TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) {
6920 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6921
6922 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6923 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6924 EXPECT_THAT(getDiagnosticString(),
6925 HasSubstr("Target of NonWritable decoration is invalid: must "
6926 "point to a storage image, uniform block, or storage "
6927 "buffer\n %var_func"));
6928 }
6929
TEST_F(ValidateDecorations, BufferBlockV13ValV14Good)6930 TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) {
6931 std::string spirv = R"(
6932 OpCapability Shader
6933 OpCapability Linkage
6934 OpMemoryModel Logical GLSL450
6935 OpDecorate %1 BufferBlock
6936 %1 = OpTypeStruct
6937 )";
6938
6939 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6940 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6941 }
6942
TEST_F(ValidateDecorations, BufferBlockV14Bad)6943 TEST_F(ValidateDecorations, BufferBlockV14Bad) {
6944 std::string spirv = R"(
6945 OpCapability Shader
6946 OpCapability Linkage
6947 OpMemoryModel Logical GLSL450
6948 OpDecorate %1 BufferBlock
6949 %1 = OpTypeStruct
6950 )";
6951
6952 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6953 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
6954 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6955 EXPECT_THAT(getDiagnosticString(),
6956 HasSubstr("2nd operand of Decorate: operand BufferBlock(3) "
6957 "requires SPIR-V version 1.3 or earlier"));
6958 }
6959
6960 // Component
6961
TEST_F(ValidateDecorations, ComponentDecorationBadTarget)6962 TEST_F(ValidateDecorations, ComponentDecorationBadTarget) {
6963 std::string spirv = R"(
6964 OpCapability Shader
6965 OpMemoryModel Logical GLSL450
6966 OpEntryPoint Vertex %main "main"
6967 OpDecorate %t Component 0
6968 %void = OpTypeVoid
6969 %3 = OpTypeFunction %void
6970 %float = OpTypeFloat 32
6971 %t = OpTypeVector %float 2
6972 %main = OpFunction %void None %3
6973 %5 = OpLabel
6974 OpReturn
6975 OpFunctionEnd
6976 )";
6977
6978 CompileSuccessfully(spirv);
6979 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6980 EXPECT_THAT(getDiagnosticString(),
6981 HasSubstr("must be a memory object declaration"));
6982 }
6983
TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass)6984 TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) {
6985 std::string spirv = R"(
6986 OpCapability Shader
6987 OpMemoryModel Logical GLSL450
6988 OpEntryPoint Vertex %main "main"
6989 OpDecorate %v Component 0
6990 %void = OpTypeVoid
6991 %3 = OpTypeFunction %void
6992 %float = OpTypeFloat 32
6993 %t = OpTypeVector %float 2
6994 %ptr_private = OpTypePointer Private %t
6995 %v = OpVariable %ptr_private Private
6996 %main = OpFunction %void None %3
6997 %5 = OpLabel
6998 OpReturn
6999 OpFunctionEnd
7000 )";
7001
7002 CompileSuccessfully(spirv);
7003 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7004 EXPECT_THAT(getDiagnosticString(),
7005 HasSubstr("Target of Component decoration is invalid: must "
7006 "point to a Storage Class of Input(1) or Output(3)"));
7007 }
7008
TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan)7009 TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) {
7010 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7011 std::string spirv = R"(
7012 OpCapability Shader
7013 OpCapability Matrix
7014 OpMemoryModel Logical GLSL450
7015 OpEntryPoint Vertex %main "main"
7016 OpDecorate %v Component 0
7017 %void = OpTypeVoid
7018 %3 = OpTypeFunction %void
7019 %float = OpTypeFloat 32
7020 %vtype = OpTypeVector %float 4
7021 %t = OpTypeMatrix %vtype 4
7022 %ptr_input = OpTypePointer Input %t
7023 %v = OpVariable %ptr_input Input
7024 %main = OpFunction %void None %3
7025 %5 = OpLabel
7026 OpReturn
7027 OpFunctionEnd
7028 )";
7029
7030 CompileSuccessfully(spirv, env);
7031 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7032 EXPECT_THAT(getDiagnosticString(),
7033 AnyVUID("VUID-StandaloneSpirv-Component-04924"));
7034 EXPECT_THAT(getDiagnosticString(),
7035 HasSubstr("Component decoration specified for type"));
7036 EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
7037 }
7038
ShaderWithComponentDecoration(const std::string& type, const std::string& decoration)7039 std::string ShaderWithComponentDecoration(const std::string& type,
7040 const std::string& decoration) {
7041 return R"(
7042 OpCapability Shader
7043 OpCapability Int64
7044 OpMemoryModel Logical GLSL450
7045 OpEntryPoint Fragment %main "main" %entryPointOutput
7046 OpExecutionMode %main OriginUpperLeft
7047 OpDecorate %entryPointOutput Location 0
7048 OpDecorate %entryPointOutput )" +
7049 decoration + R"(
7050 %void = OpTypeVoid
7051 %3 = OpTypeFunction %void
7052 %float = OpTypeFloat 32
7053 %v3float = OpTypeVector %float 3
7054 %v4float = OpTypeVector %float 4
7055 %uint = OpTypeInt 32 0
7056 %uint64 = OpTypeInt 64 0
7057 %v2uint64 = OpTypeVector %uint64 2
7058 %v3uint64 = OpTypeVector %uint64 3
7059 %uint_2 = OpConstant %uint 2
7060 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
7061 %float_0 = OpConstant %float 0
7062 %_ptr_Output_type = OpTypePointer Output %)" + type + R"(
7063 %entryPointOutput = OpVariable %_ptr_Output_type Output
7064 %main = OpFunction %void None %3
7065 %5 = OpLabel
7066 OpReturn
7067 OpFunctionEnd
7068 )";
7069 }
7070
TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan)7071 TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
7072 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7073 std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
7074
7075 CompileSuccessfully(spirv, env);
7076 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7077 EXPECT_THAT(getDiagnosticString(), Eq(""));
7078 }
7079
TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan)7080 TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
7081 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7082 std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
7083
7084 CompileSuccessfully(spirv, env);
7085 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7086 EXPECT_THAT(getDiagnosticString(), Eq(""));
7087 }
7088
TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan)7089 TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
7090 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7091 std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
7092
7093 CompileSuccessfully(spirv, env);
7094 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7095 EXPECT_THAT(getDiagnosticString(), Eq(""));
7096 }
7097
TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan)7098 TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
7099 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7100 std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
7101
7102 CompileSuccessfully(spirv, env);
7103 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7104 EXPECT_THAT(getDiagnosticString(), Eq(""));
7105 }
7106
TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan)7107 TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
7108 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7109 std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
7110
7111 CompileSuccessfully(spirv, env);
7112 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7113 EXPECT_THAT(getDiagnosticString(),
7114 AnyVUID("VUID-StandaloneSpirv-Component-04920"));
7115 EXPECT_THAT(
7116 getDiagnosticString(),
7117 HasSubstr("Component decoration value must not be greater than 3"));
7118 }
7119
TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan)7120 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
7121 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7122 std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
7123
7124 CompileSuccessfully(spirv, env);
7125 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7126 EXPECT_THAT(getDiagnosticString(), Eq(""));
7127 }
7128
TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan)7129 TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
7130 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7131 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
7132
7133 CompileSuccessfully(spirv, env);
7134 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7135 EXPECT_THAT(getDiagnosticString(), Eq(""));
7136 }
7137
TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan)7138 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
7139 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7140 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
7141
7142 CompileSuccessfully(spirv, env);
7143 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7144 EXPECT_THAT(getDiagnosticString(),
7145 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7146 EXPECT_THAT(getDiagnosticString(),
7147 HasSubstr("Sequence of components starting with 1 "
7148 "and ending with 4 gets larger than 3"));
7149 }
7150
TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan)7151 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
7152 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7153 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
7154
7155 CompileSuccessfully(spirv, env);
7156 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7157 EXPECT_THAT(getDiagnosticString(),
7158 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7159 EXPECT_THAT(getDiagnosticString(),
7160 HasSubstr("Sequence of components starting with 3 "
7161 "and ending with 6 gets larger than 3"));
7162 }
7163
TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan)7164 TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
7165 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7166 std::string spirv =
7167 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
7168
7169 CompileSuccessfully(spirv, env);
7170 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7171 EXPECT_THAT(getDiagnosticString(), Eq(""));
7172 }
7173
TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan)7174 TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
7175 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7176 std::string spirv =
7177 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
7178
7179 CompileSuccessfully(spirv, env);
7180 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7181 EXPECT_THAT(getDiagnosticString(),
7182 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7183 EXPECT_THAT(getDiagnosticString(),
7184 HasSubstr("Sequence of components starting with 2 "
7185 "and ending with 4 gets larger than 3"));
7186 }
7187
TEST_F(ValidateDecorations, ComponentDecoration64ScalarGoodVulkan)7188 TEST_F(ValidateDecorations, ComponentDecoration64ScalarGoodVulkan) {
7189 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7190 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 0");
7191
7192 CompileSuccessfully(spirv, env);
7193 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7194 }
7195
TEST_F(ValidateDecorations, ComponentDecoration64Scalar1BadVulkan)7196 TEST_F(ValidateDecorations, ComponentDecoration64Scalar1BadVulkan) {
7197 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7198 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 1");
7199
7200 CompileSuccessfully(spirv, env);
7201 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7202 EXPECT_THAT(getDiagnosticString(),
7203 AnyVUID("VUID-StandaloneSpirv-Component-04923"));
7204 EXPECT_THAT(getDiagnosticString(),
7205 HasSubstr("Component decoration value must not be 1 or 3 for "
7206 "64-bit data types"));
7207 }
7208
TEST_F(ValidateDecorations, ComponentDecoration64Scalar2GoodVulkan)7209 TEST_F(ValidateDecorations, ComponentDecoration64Scalar2GoodVulkan) {
7210 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7211 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 2");
7212
7213 CompileSuccessfully(spirv, env);
7214 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7215 }
7216
TEST_F(ValidateDecorations, ComponentDecoration64Scalar3BadVulkan)7217 TEST_F(ValidateDecorations, ComponentDecoration64Scalar3BadVulkan) {
7218 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7219 std::string spirv = ShaderWithComponentDecoration("uint64", "Component 3");
7220
7221 CompileSuccessfully(spirv, env);
7222 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7223 EXPECT_THAT(getDiagnosticString(),
7224 AnyVUID("VUID-StandaloneSpirv-Component-04923"));
7225 EXPECT_THAT(getDiagnosticString(),
7226 HasSubstr("Component decoration value must not be 1 or 3 for "
7227 "64-bit data types"));
7228 }
7229
TEST_F(ValidateDecorations, ComponentDecoration64Vec0GoodVulkan)7230 TEST_F(ValidateDecorations, ComponentDecoration64Vec0GoodVulkan) {
7231 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7232 std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 0");
7233
7234 CompileSuccessfully(spirv, env);
7235 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7236 }
7237
TEST_F(ValidateDecorations, ComponentDecoration64Vec1BadVulkan)7238 TEST_F(ValidateDecorations, ComponentDecoration64Vec1BadVulkan) {
7239 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7240 std::string spirv = ShaderWithComponentDecoration("v2uint64", "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, ComponentDecoration64Vec2BadVulkan)7251 TEST_F(ValidateDecorations, ComponentDecoration64Vec2BadVulkan) {
7252 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7253 std::string spirv = ShaderWithComponentDecoration("v2uint64", "Component 2");
7254
7255 CompileSuccessfully(spirv, env);
7256 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7257 EXPECT_THAT(getDiagnosticString(),
7258 AnyVUID("VUID-StandaloneSpirv-Component-04922"));
7259 HasSubstr(
7260 "Sequence of components starting with 2 "
7261 "and ending with 6 gets larger than 3");
7262 }
7263
TEST_F(ValidateDecorations, ComponentDecoration64VecWideBadVulkan)7264 TEST_F(ValidateDecorations, ComponentDecoration64VecWideBadVulkan) {
7265 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7266 std::string spirv = ShaderWithComponentDecoration("v3uint64", "Component 0");
7267
7268 CompileSuccessfully(spirv, env);
7269 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7270 EXPECT_THAT(getDiagnosticString(),
7271 AnyVUID("VUID-StandaloneSpirv-Component-07703"));
7272 EXPECT_THAT(getDiagnosticString(),
7273 HasSubstr("Component decoration only allowed on 64-bit scalar "
7274 "and 2-component vector"));
7275 }
7276
TEST_F(ValidateDecorations, ComponentDecorationBlockGood)7277 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
7278 std::string spirv = R"(
7279 OpCapability Shader
7280 OpMemoryModel Logical GLSL450
7281 OpEntryPoint Fragment %4 "main" %9 %12
7282 OpExecutionMode %4 OriginUpperLeft
7283 OpDecorate %9 Location 0
7284 OpMemberDecorate %block 0 Location 2
7285 OpMemberDecorate %block 0 Component 1
7286 OpDecorate %block Block
7287 %2 = OpTypeVoid
7288 %3 = OpTypeFunction %2
7289 %float = OpTypeFloat 32
7290 %vec3 = OpTypeVector %float 3
7291 %8 = OpTypePointer Output %vec3
7292 %9 = OpVariable %8 Output
7293 %block = OpTypeStruct %vec3
7294 %11 = OpTypePointer Input %block
7295 %12 = OpVariable %11 Input
7296 %int = OpTypeInt 32 1
7297 %14 = OpConstant %int 0
7298 %15 = OpTypePointer Input %vec3
7299 %4 = OpFunction %2 None %3
7300 %5 = OpLabel
7301 %16 = OpAccessChain %15 %12 %14
7302 %17 = OpLoad %vec3 %16
7303 OpStore %9 %17
7304 OpReturn
7305 OpFunctionEnd
7306 )";
7307
7308 CompileSuccessfully(spirv);
7309 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7310 EXPECT_THAT(getDiagnosticString(), Eq(""));
7311 }
7312
TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan)7313 TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) {
7314 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7315 std::string spirv = R"(
7316 OpCapability Shader
7317 OpMemoryModel Logical GLSL450
7318 OpEntryPoint Fragment %4 "main" %9 %12
7319 OpExecutionMode %4 OriginUpperLeft
7320 OpDecorate %9 Location 0
7321 OpMemberDecorate %block 0 Location 2
7322 OpMemberDecorate %block 0 Component 2
7323 OpDecorate %block Block
7324 %2 = OpTypeVoid
7325 %3 = OpTypeFunction %2
7326 %float = OpTypeFloat 32
7327 %vec3 = OpTypeVector %float 3
7328 %8 = OpTypePointer Output %vec3
7329 %9 = OpVariable %8 Output
7330 %block = OpTypeStruct %vec3
7331 %11 = OpTypePointer Input %block
7332 %12 = OpVariable %11 Input
7333 %int = OpTypeInt 32 1
7334 %14 = OpConstant %int 0
7335 %15 = OpTypePointer Input %vec3
7336 %4 = OpFunction %2 None %3
7337 %5 = OpLabel
7338 %16 = OpAccessChain %15 %12 %14
7339 %17 = OpLoad %vec3 %16
7340 OpStore %9 %17
7341 OpReturn
7342 OpFunctionEnd
7343 )";
7344
7345 CompileSuccessfully(spirv, env);
7346 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7347 EXPECT_THAT(getDiagnosticString(),
7348 AnyVUID("VUID-StandaloneSpirv-Component-04921"));
7349 EXPECT_THAT(getDiagnosticString(),
7350 HasSubstr("Sequence of components starting with 2 "
7351 "and ending with 4 gets larger than 3"));
7352 }
7353
TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter)7354 TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
7355 std::string spirv = R"(
7356 OpCapability Shader
7357 OpMemoryModel Logical GLSL450
7358 OpEntryPoint Vertex %main "main"
7359
7360 OpDecorate %param_f Component 0
7361
7362 %void = OpTypeVoid
7363 %void_fn = OpTypeFunction %void
7364 %float = OpTypeFloat 32
7365 %float_0 = OpConstant %float 0
7366 %int = OpTypeInt 32 0
7367 %int_2 = OpConstant %int 2
7368 %struct_b = OpTypeStruct %float
7369
7370 %extra_fn = OpTypeFunction %void %float
7371
7372 %helper = OpFunction %void None %extra_fn
7373 %param_f = OpFunctionParameter %float
7374 %helper_label = OpLabel
7375 OpReturn
7376 OpFunctionEnd
7377
7378 %main = OpFunction %void None %void_fn
7379 %label = OpLabel
7380 OpReturn
7381 OpFunctionEnd
7382 )";
7383
7384 CompileSuccessfully(spirv);
7385 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7386 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
7387 }
7388
TEST_F(ValidateDecorations, VulkanStorageBufferBlock)7389 TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
7390 const std::string spirv = R"(
7391 OpCapability Shader
7392 OpExtension "SPV_KHR_storage_buffer_storage_class"
7393 OpMemoryModel Logical GLSL450
7394 OpEntryPoint GLCompute %main "main"
7395 OpExecutionMode %main LocalSize 1 1 1
7396 OpDecorate %struct Block
7397 OpMemberDecorate %struct 0 Offset 0
7398 %void = OpTypeVoid
7399 %uint = OpTypeInt 32 0
7400 %struct = OpTypeStruct %uint
7401 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7402 %var = OpVariable %ptr_ssbo StorageBuffer
7403 %void_fn = OpTypeFunction %void
7404 %main = OpFunction %void None %void_fn
7405 %entry = OpLabel
7406 OpReturn
7407 OpFunctionEnd
7408 )";
7409
7410 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7411 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7412 }
7413
TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock)7414 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
7415 const std::string spirv = R"(
7416 OpCapability Shader
7417 OpExtension "SPV_KHR_storage_buffer_storage_class"
7418 OpMemoryModel Logical GLSL450
7419 OpEntryPoint GLCompute %main "main"
7420 OpExecutionMode %main LocalSize 1 1 1
7421 %void = OpTypeVoid
7422 %uint = OpTypeInt 32 0
7423 %struct = OpTypeStruct %uint
7424 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7425 %var = OpVariable %ptr_ssbo StorageBuffer
7426 %void_fn = OpTypeFunction %void
7427 %main = OpFunction %void None %void_fn
7428 %entry = OpLabel
7429 OpReturn
7430 OpFunctionEnd
7431 )";
7432
7433 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7434 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7435 EXPECT_THAT(getDiagnosticString(),
7436 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7437 EXPECT_THAT(getDiagnosticString(),
7438 HasSubstr("From Vulkan spec:\nSuch variables "
7439 "must be identified with a Block decoration"));
7440 }
7441
TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock)7442 TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
7443 const std::string spirv = R"(
7444 OpCapability Shader
7445 OpExtension "SPV_KHR_storage_buffer_storage_class"
7446 OpMemoryModel Logical GLSL450
7447 OpEntryPoint GLCompute %main "main"
7448 OpExecutionMode %main LocalSize 1 1 1
7449 %void = OpTypeVoid
7450 %uint = OpTypeInt 32 0
7451 %uint_4 = OpConstant %uint 4
7452 %struct = OpTypeStruct %uint
7453 %array = OpTypeArray %struct %uint_4
7454 %ptr_ssbo = OpTypePointer StorageBuffer %array
7455 %var = OpVariable %ptr_ssbo StorageBuffer
7456 %void_fn = OpTypeFunction %void
7457 %main = OpFunction %void None %void_fn
7458 %entry = OpLabel
7459 OpReturn
7460 OpFunctionEnd
7461 )";
7462
7463 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7464 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7465 EXPECT_THAT(getDiagnosticString(),
7466 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7467 EXPECT_THAT(getDiagnosticString(),
7468 HasSubstr("From Vulkan spec:\nSuch variables "
7469 "must be identified with a Block decoration"));
7470 }
7471
TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock)7472 TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
7473 const std::string spirv = R"(
7474 OpCapability Shader
7475 OpCapability RuntimeDescriptorArrayEXT
7476 OpExtension "SPV_EXT_descriptor_indexing"
7477 OpExtension "SPV_KHR_storage_buffer_storage_class"
7478 OpMemoryModel Logical GLSL450
7479 OpEntryPoint GLCompute %main "main"
7480 OpExecutionMode %main LocalSize 1 1 1
7481 %void = OpTypeVoid
7482 %uint = OpTypeInt 32 0
7483 %struct = OpTypeStruct %uint
7484 %array = OpTypeRuntimeArray %struct
7485 %ptr_ssbo = OpTypePointer StorageBuffer %array
7486 %var = OpVariable %ptr_ssbo StorageBuffer
7487 %void_fn = OpTypeFunction %void
7488 %main = OpFunction %void None %void_fn
7489 %entry = OpLabel
7490 OpReturn
7491 OpFunctionEnd
7492 )";
7493
7494 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7495 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7496 EXPECT_THAT(getDiagnosticString(),
7497 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7498 EXPECT_THAT(getDiagnosticString(),
7499 HasSubstr("From Vulkan spec:\nSuch variables "
7500 "must be identified with a Block decoration"));
7501 }
7502
TEST_F(ValidateDecorations, VulkanUniformBlock)7503 TEST_F(ValidateDecorations, VulkanUniformBlock) {
7504 const std::string spirv = R"(
7505 OpCapability Shader
7506 OpMemoryModel Logical GLSL450
7507 OpEntryPoint GLCompute %main "main"
7508 OpExecutionMode %main LocalSize 1 1 1
7509 OpDecorate %struct Block
7510 OpMemberDecorate %struct 0 Offset 0
7511 %void = OpTypeVoid
7512 %uint = OpTypeInt 32 0
7513 %struct = OpTypeStruct %uint
7514 %ptr_ubo = OpTypePointer Uniform %struct
7515 %var = OpVariable %ptr_ubo Uniform
7516 %void_fn = OpTypeFunction %void
7517 %main = OpFunction %void None %void_fn
7518 %entry = OpLabel
7519 OpReturn
7520 OpFunctionEnd
7521 )";
7522
7523 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7524 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7525 }
7526
TEST_F(ValidateDecorations, VulkanUniformBufferBlock)7527 TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
7528 const std::string spirv = R"(
7529 OpCapability Shader
7530 OpMemoryModel Logical GLSL450
7531 OpEntryPoint GLCompute %main "main"
7532 OpExecutionMode %main LocalSize 1 1 1
7533 OpDecorate %struct BufferBlock
7534 OpMemberDecorate %struct 0 Offset 0
7535 %void = OpTypeVoid
7536 %uint = OpTypeInt 32 0
7537 %struct = OpTypeStruct %uint
7538 %ptr_ubo = OpTypePointer Uniform %struct
7539 %var = OpVariable %ptr_ubo Uniform
7540 %void_fn = OpTypeFunction %void
7541 %main = OpFunction %void None %void_fn
7542 %entry = OpLabel
7543 OpReturn
7544 OpFunctionEnd
7545 )";
7546
7547 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7548 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7549 }
7550
TEST_F(ValidateDecorations, VulkanUniformMissingBlock)7551 TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
7552 const std::string spirv = R"(
7553 OpCapability Shader
7554 OpMemoryModel Logical GLSL450
7555 OpEntryPoint GLCompute %main "main"
7556 OpExecutionMode %main LocalSize 1 1 1
7557 %void = OpTypeVoid
7558 %uint = OpTypeInt 32 0
7559 %struct = OpTypeStruct %uint
7560 %ptr_ubo = OpTypePointer Uniform %struct
7561 %var = OpVariable %ptr_ubo Uniform
7562 %void_fn = OpTypeFunction %void
7563 %main = OpFunction %void None %void_fn
7564 %entry = OpLabel
7565 OpReturn
7566 OpFunctionEnd
7567 )";
7568
7569 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7570 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7571 EXPECT_THAT(getDiagnosticString(),
7572 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7573 EXPECT_THAT(getDiagnosticString(),
7574 HasSubstr("From Vulkan spec:\nSuch variables must be "
7575 "identified with a Block or BufferBlock decoration"));
7576 }
7577
TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock)7578 TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
7579 const std::string spirv = R"(
7580 OpCapability Shader
7581 OpMemoryModel Logical GLSL450
7582 OpEntryPoint GLCompute %main "main"
7583 OpExecutionMode %main LocalSize 1 1 1
7584 %void = OpTypeVoid
7585 %uint = OpTypeInt 32 0
7586 %uint_4 = OpConstant %uint 4
7587 %struct = OpTypeStruct %uint
7588 %array = OpTypeArray %struct %uint_4
7589 %ptr_ubo = OpTypePointer Uniform %array
7590 %var = OpVariable %ptr_ubo Uniform
7591 %void_fn = OpTypeFunction %void
7592 %main = OpFunction %void None %void_fn
7593 %entry = OpLabel
7594 OpReturn
7595 OpFunctionEnd
7596 )";
7597
7598 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7599 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7600 EXPECT_THAT(getDiagnosticString(),
7601 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7602 EXPECT_THAT(getDiagnosticString(),
7603 HasSubstr("From Vulkan spec:\nSuch variables must be "
7604 "identified with a Block or BufferBlock decoration"));
7605 }
7606
TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock)7607 TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
7608 const std::string spirv = R"(
7609 OpCapability Shader
7610 OpCapability RuntimeDescriptorArrayEXT
7611 OpExtension "SPV_EXT_descriptor_indexing"
7612 OpMemoryModel Logical GLSL450
7613 OpEntryPoint GLCompute %main "main"
7614 OpExecutionMode %main LocalSize 1 1 1
7615 %void = OpTypeVoid
7616 %uint = OpTypeInt 32 0
7617 %struct = OpTypeStruct %uint
7618 %array = OpTypeRuntimeArray %struct
7619 %ptr_ubo = OpTypePointer Uniform %array
7620 %var = OpVariable %ptr_ubo Uniform
7621 %void_fn = OpTypeFunction %void
7622 %main = OpFunction %void None %void_fn
7623 %entry = OpLabel
7624 OpReturn
7625 OpFunctionEnd
7626 )";
7627
7628 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7629 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7630 EXPECT_THAT(getDiagnosticString(),
7631 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7632 EXPECT_THAT(getDiagnosticString(),
7633 HasSubstr("From Vulkan spec:\nSuch variables must be "
7634 "identified with a Block or BufferBlock decoration"));
7635 }
7636
TEST_F(ValidateDecorations, VulkanArrayStrideZero)7637 TEST_F(ValidateDecorations, VulkanArrayStrideZero) {
7638 const std::string spirv = R"(
7639 OpCapability Shader
7640 OpMemoryModel Logical GLSL450
7641 OpEntryPoint GLCompute %main "main"
7642 OpExecutionMode %main LocalSize 1 1 1
7643 OpDecorate %var DescriptorSet 0
7644 OpDecorate %var Binding 0
7645 OpDecorate %struct Block
7646 OpMemberDecorate %struct 0 Offset 0
7647 OpDecorate %array ArrayStride 0
7648 %void = OpTypeVoid
7649 %int = OpTypeInt 32 0
7650 %int_4 = OpConstant %int 4
7651 %array = OpTypeArray %int %int_4
7652 %struct = OpTypeStruct %array
7653 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7654 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7655 %void_fn = OpTypeFunction %void
7656 %main = OpFunction %void None %void_fn
7657 %entry = OpLabel
7658 OpReturn
7659 OpFunctionEnd
7660 )";
7661
7662 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7663 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7664 EXPECT_THAT(getDiagnosticString(),
7665 HasSubstr("contains an array with stride 0"));
7666 }
7667
TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall)7668 TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) {
7669 const std::string spirv = R"(
7670 OpCapability Shader
7671 OpMemoryModel Logical GLSL450
7672 OpEntryPoint GLCompute %main "main"
7673 OpExecutionMode %main LocalSize 1 1 1
7674 OpDecorate %var DescriptorSet 0
7675 OpDecorate %var Binding 0
7676 OpDecorate %struct Block
7677 OpMemberDecorate %struct 0 Offset 0
7678 OpDecorate %inner ArrayStride 4
7679 OpDecorate %outer ArrayStride 4
7680 %void = OpTypeVoid
7681 %int = OpTypeInt 32 0
7682 %int_4 = OpConstant %int 4
7683 %inner = OpTypeArray %int %int_4
7684 %outer = OpTypeArray %inner %int_4
7685 %struct = OpTypeStruct %outer
7686 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7687 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7688 %void_fn = OpTypeFunction %void
7689 %main = OpFunction %void None %void_fn
7690 %entry = OpLabel
7691 OpReturn
7692 OpFunctionEnd
7693 )";
7694
7695 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7696 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7697 EXPECT_THAT(
7698 getDiagnosticString(),
7699 HasSubstr(
7700 "contains an array with stride 4, but with an element size of 16"));
7701 }
7702
TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate)7703 TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate) {
7704 std::string spirv = R"(
7705 OpCapability Addresses
7706 OpCapability Linkage
7707 OpCapability Kernel
7708 OpCapability Int8
7709 %1 = OpExtInstImport "OpenCL.std"
7710 OpMemoryModel Physical32 OpenCL
7711 OpName %foo "foo"
7712 OpName %entry "entry"
7713 OpName %bar "bar"
7714 OpName %entry_0 "entry"
7715 OpName %k "k"
7716 OpName %entry_1 "entry"
7717 OpName %b "b"
7718 OpDecorate %28 FuncParamAttr Zext
7719 %28 = OpDecorationGroup
7720 OpDecorate %k LinkageAttributes "k" Export
7721 OpDecorate %foo LinkageAttributes "foo" Export
7722 OpDecorate %bar LinkageAttributes "bar" Export
7723 OpDecorate %b Alignment 1
7724 OpGroupDecorate %28 %foo %bar
7725 %uchar = OpTypeInt 8 0
7726 %bool = OpTypeBool
7727 %3 = OpTypeFunction %bool
7728 %void = OpTypeVoid
7729 %10 = OpTypeFunction %void
7730 %_ptr_Function_uchar = OpTypePointer Function %uchar
7731 %true = OpConstantTrue %bool
7732 %foo = OpFunction %bool DontInline %3
7733 %entry = OpLabel
7734 OpReturnValue %true
7735 OpFunctionEnd
7736 %bar = OpFunction %bool DontInline %3
7737 %entry_0 = OpLabel
7738 OpReturnValue %true
7739 OpFunctionEnd
7740 %k = OpFunction %void DontInline %10
7741 %entry_1 = OpLabel
7742 %b = OpVariable %_ptr_Function_uchar Function
7743 OpReturn
7744 OpFunctionEnd
7745 )";
7746 CompileSuccessfully(spirv);
7747 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7748 }
7749
TEST_F(ValidateDecorations, LocationVariableGood)7750 TEST_F(ValidateDecorations, LocationVariableGood) {
7751 const std::string spirv = R"(
7752 OpCapability Shader
7753 OpCapability Linkage
7754 OpMemoryModel Logical GLSL450
7755 OpDecorate %in_var Location 0
7756 %float = OpTypeFloat 32
7757 %ptr_input_float = OpTypePointer Input %float
7758 %in_var = OpVariable %ptr_input_float Input
7759 )";
7760
7761 CompileSuccessfully(spirv);
7762 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7763 }
7764
TEST_F(ValidateDecorations, LocationStructMemberGood)7765 TEST_F(ValidateDecorations, LocationStructMemberGood) {
7766 const std::string spirv = R"(
7767 OpCapability Shader
7768 OpCapability Linkage
7769 OpMemoryModel Logical GLSL450
7770 OpMemberDecorate %struct 0 Location 0
7771 %float = OpTypeFloat 32
7772 %struct = OpTypeStruct %float
7773 )";
7774
7775 CompileSuccessfully(spirv);
7776 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7777 }
7778
TEST_F(ValidateDecorations, LocationStructBad)7779 TEST_F(ValidateDecorations, LocationStructBad) {
7780 const std::string spirv = R"(
7781 OpCapability Shader
7782 OpCapability Linkage
7783 OpMemoryModel Logical GLSL450
7784 OpDecorate %struct Location 0
7785 %float = OpTypeFloat 32
7786 %struct = OpTypeStruct %float
7787 )";
7788
7789 CompileSuccessfully(spirv);
7790 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7791 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7792 }
7793
TEST_F(ValidateDecorations, LocationFloatBad)7794 TEST_F(ValidateDecorations, LocationFloatBad) {
7795 const std::string spirv = R"(
7796 OpCapability Shader
7797 OpCapability Linkage
7798 OpMemoryModel Logical GLSL450
7799 OpDecorate %float Location 0
7800 %float = OpTypeFloat 32
7801 )";
7802
7803 CompileSuccessfully(spirv);
7804 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7805 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7806 }
7807
TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable)7808 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable) {
7809 std::string spirv = R"(
7810 OpCapability Shader
7811 OpCapability WorkgroupMemoryExplicitLayoutKHR
7812 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7813 OpMemoryModel Logical GLSL450
7814 OpEntryPoint GLCompute %main "main" %_
7815 OpExecutionMode %main LocalSize 8 1 1
7816 OpMemberDecorate %first 0 Offset 0
7817 OpDecorate %first Block
7818 %void = OpTypeVoid
7819 %3 = OpTypeFunction %void
7820 %int = OpTypeInt 32 1
7821 %first = OpTypeStruct %int
7822 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7823 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7824 %int_0 = OpConstant %int 0
7825 %int_2 = OpConstant %int 2
7826 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7827 %main = OpFunction %void None %3
7828 %5 = OpLabel
7829 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7830 OpStore %13 %int_2
7831 OpReturn
7832 OpFunctionEnd
7833 )";
7834
7835 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7836 EXPECT_EQ(SPV_SUCCESS,
7837 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7838 }
7839
TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14)7840 TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14) {
7841 std::string spirv = R"(
7842 OpCapability Shader
7843 OpCapability WorkgroupMemoryExplicitLayoutKHR
7844 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7845 OpMemoryModel Logical GLSL450
7846 OpEntryPoint GLCompute %main "main" %_
7847 OpExecutionMode %main LocalSize 8 1 1
7848 OpMemberDecorate %first 0 Offset 0
7849 OpDecorate %first Block
7850 %void = OpTypeVoid
7851 %3 = OpTypeFunction %void
7852 %int = OpTypeInt 32 1
7853 %first = OpTypeStruct %int
7854 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7855 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7856 %int_0 = OpConstant %int 0
7857 %int_2 = OpConstant %int 2
7858 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7859 %main = OpFunction %void None %3
7860 %5 = OpLabel
7861 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7862 OpStore %13 %int_2
7863 OpReturn
7864 OpFunctionEnd
7865 )";
7866
7867 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7868 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
7869 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7870 EXPECT_THAT(getDiagnosticString(),
7871 HasSubstr("requires SPIR-V version 1.4 or later"));
7872 }
7873
TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable)7874 TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable) {
7875 std::string spirv = R"(
7876 OpCapability Shader
7877 OpMemoryModel Logical GLSL450
7878 OpEntryPoint GLCompute %main "main" %a
7879 OpExecutionMode %main LocalSize 8 1 1
7880 %void = OpTypeVoid
7881 %3 = OpTypeFunction %void
7882 %int = OpTypeInt 32 1
7883 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7884 %a = OpVariable %_ptr_Workgroup_int Workgroup
7885 %int_2 = OpConstant %int 2
7886 %main = OpFunction %void None %3
7887 %5 = OpLabel
7888 OpStore %a %int_2
7889 OpReturn
7890 OpFunctionEnd
7891 )";
7892
7893 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7894 EXPECT_EQ(SPV_SUCCESS,
7895 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7896 }
7897
TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable)7898 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable) {
7899 std::string spirv = R"(
7900 OpCapability Shader
7901 OpCapability WorkgroupMemoryExplicitLayoutKHR
7902 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7903 OpMemoryModel Logical GLSL450
7904 OpEntryPoint GLCompute %main "main" %_ %__0
7905 OpExecutionMode %main LocalSize 8 1 1
7906 OpMemberDecorate %first 0 Offset 0
7907 OpDecorate %first Block
7908 OpMemberDecorate %second 0 Offset 0
7909 OpDecorate %second Block
7910 OpDecorate %_ Aliased
7911 OpDecorate %__0 Aliased
7912 %void = OpTypeVoid
7913 %3 = OpTypeFunction %void
7914 %int = OpTypeInt 32 1
7915 %first = OpTypeStruct %int
7916 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7917 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7918 %int_0 = OpConstant %int 0
7919 %int_2 = OpConstant %int 2
7920 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7921 %second = OpTypeStruct %int
7922 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7923 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7924 %int_3 = OpConstant %int 3
7925 %main = OpFunction %void None %3
7926 %5 = OpLabel
7927 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7928 OpStore %13 %int_2
7929 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7930 OpStore %18 %int_3
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, WorkgroupBlockVariableWith8BitType)7940 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith8BitType) {
7941 std::string spirv = R"(
7942 OpCapability Shader
7943 OpCapability Int8
7944 OpCapability WorkgroupMemoryExplicitLayout8BitAccessKHR
7945 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7946 OpMemoryModel Logical GLSL450
7947 OpEntryPoint GLCompute %main "main" %_
7948 OpExecutionMode %main LocalSize 2 1 1
7949 OpMemberDecorate %first 0 Offset 0
7950 OpDecorate %first Block
7951 %void = OpTypeVoid
7952 %3 = OpTypeFunction %void
7953 %char = OpTypeInt 8 1
7954 %first = OpTypeStruct %char
7955 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7956 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7957 %int = OpTypeInt 32 1
7958 %int_0 = OpConstant %int 0
7959 %char_2 = OpConstant %char 2
7960 %_ptr_Workgroup_char = OpTypePointer Workgroup %char
7961 %main = OpFunction %void None %3
7962 %5 = OpLabel
7963 %14 = OpAccessChain %_ptr_Workgroup_char %_ %int_0
7964 OpStore %14 %char_2
7965 OpReturn
7966 OpFunctionEnd
7967 )";
7968
7969 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7970 EXPECT_EQ(SPV_SUCCESS,
7971 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7972 }
7973
TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable)7974 TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable) {
7975 std::string spirv = R"(
7976 OpCapability Shader
7977 OpMemoryModel Logical GLSL450
7978 OpEntryPoint GLCompute %main "main" %a %b
7979 OpExecutionMode %main LocalSize 8 1 1
7980 %void = OpTypeVoid
7981 %3 = OpTypeFunction %void
7982 %int = OpTypeInt 32 1
7983 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7984 %a = OpVariable %_ptr_Workgroup_int Workgroup
7985 %int_2 = OpConstant %int 2
7986 %b = OpVariable %_ptr_Workgroup_int Workgroup
7987 %int_3 = OpConstant %int 3
7988 %main = OpFunction %void None %3
7989 %5 = OpLabel
7990 OpStore %a %int_2
7991 OpStore %b %int_3
7992 OpReturn
7993 OpFunctionEnd
7994 )";
7995
7996 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7997 EXPECT_EQ(SPV_SUCCESS,
7998 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7999 }
8000
TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType)8001 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType) {
8002 std::string spirv = R"(
8003 OpCapability Shader
8004 OpCapability Float16
8005 OpCapability Int16
8006 OpCapability WorkgroupMemoryExplicitLayoutKHR
8007 OpCapability WorkgroupMemoryExplicitLayout16BitAccessKHR
8008 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8009 OpMemoryModel Logical GLSL450
8010 OpEntryPoint GLCompute %main "main" %_
8011 OpExecutionMode %main LocalSize 2 1 1
8012 OpMemberDecorate %first 0 Offset 0
8013 OpMemberDecorate %first 1 Offset 2
8014 OpDecorate %first Block
8015 %void = OpTypeVoid
8016 %3 = OpTypeFunction %void
8017 %short = OpTypeInt 16 1
8018 %half = OpTypeFloat 16
8019 %first = OpTypeStruct %short %half
8020 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8021 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8022 %int = OpTypeInt 32 1
8023 %int_0 = OpConstant %int 0
8024 %short_3 = OpConstant %short 3
8025 %_ptr_Workgroup_short = OpTypePointer Workgroup %short
8026 %int_1 = OpConstant %int 1
8027 %half_0x1_898p_3 = OpConstant %half 0x1.898p+3
8028 %_ptr_Workgroup_half = OpTypePointer Workgroup %half
8029 %main = OpFunction %void None %3
8030 %5 = OpLabel
8031 %15 = OpAccessChain %_ptr_Workgroup_short %_ %int_0
8032 OpStore %15 %short_3
8033 %19 = OpAccessChain %_ptr_Workgroup_half %_ %int_1
8034 OpStore %19 %half_0x1_898p_3
8035 OpReturn
8036 OpFunctionEnd
8037 )";
8038
8039 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8040 EXPECT_EQ(SPV_SUCCESS,
8041 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8042 }
8043
TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout)8044 TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout) {
8045 std::string spirv = R"(
8046 OpCapability Shader
8047 OpCapability WorkgroupMemoryExplicitLayoutKHR
8048 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8049 OpMemoryModel Logical GLSL450
8050 OpEntryPoint Vertex %main "main" %B
8051 OpSource GLSL 450
8052 OpMemberDecorate %S 0 Offset 0
8053 OpMemberDecorate %S 1 Offset 4
8054 OpMemberDecorate %S 2 Offset 16
8055 OpMemberDecorate %S 3 Offset 28
8056 OpDecorate %S Block
8057 OpDecorate %B Aliased
8058 %void = OpTypeVoid
8059 %3 = OpTypeFunction %void
8060 %float = OpTypeFloat 32
8061 %v3float = OpTypeVector %float 3
8062 %S = OpTypeStruct %float %v3float %v3float %v3float
8063 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
8064 %B = OpVariable %_ptr_Workgroup_S Workgroup
8065 %main = OpFunction %void None %3
8066 %5 = OpLabel
8067 OpReturn
8068 OpFunctionEnd
8069 )";
8070
8071 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8072 spvValidatorOptionsSetWorkgroupScalarBlockLayout(getValidatorOptions(), true);
8073 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4))
8074 << getDiagnosticString();
8075 }
8076
TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad)8077 TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad) {
8078 std::string spirv = R"(
8079 OpCapability Shader
8080 OpCapability WorkgroupMemoryExplicitLayoutKHR
8081 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8082 OpMemoryModel Logical GLSL450
8083 OpEntryPoint GLCompute %main "main" %_ %b
8084 OpExecutionMode %main LocalSize 8 1 1
8085 OpMemberDecorate %first 0 Offset 0
8086 OpDecorate %first Block
8087 OpDecorate %_ Aliased
8088 OpDecorate %b Aliased
8089 %void = OpTypeVoid
8090 %3 = OpTypeFunction %void
8091 %int = OpTypeInt 32 1
8092 %first = OpTypeStruct %int
8093 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8094 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8095 %int_0 = OpConstant %int 0
8096 %int_2 = OpConstant %int 2
8097 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8098 %b = OpVariable %_ptr_Workgroup_int Workgroup
8099 %int_3 = OpConstant %int 3
8100 %main = OpFunction %void None %3
8101 %5 = OpLabel
8102 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8103 OpStore %13 %int_2
8104 OpStore %b %int_3
8105 OpReturn
8106 OpFunctionEnd
8107 )";
8108
8109 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8110 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8111 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8112 EXPECT_THAT(
8113 getDiagnosticString(),
8114 HasSubstr("either all or none of the Workgroup Storage Class variables "
8115 "in the entry point interface must point to struct types "
8116 "decorated with Block"));
8117 }
8118
TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased)8119 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased) {
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" %_ %__0
8126 OpExecutionMode %main LocalSize 8 1 1
8127 OpMemberDecorate %first 0 Offset 0
8128 OpDecorate %first Block
8129 OpMemberDecorate %second 0 Offset 0
8130 OpDecorate %second Block
8131 OpDecorate %_ Aliased
8132 %void = OpTypeVoid
8133 %3 = OpTypeFunction %void
8134 %int = OpTypeInt 32 1
8135 %first = OpTypeStruct %int
8136 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8137 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8138 %int_0 = OpConstant %int 0
8139 %int_2 = OpConstant %int 2
8140 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8141 %second = OpTypeStruct %int
8142 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
8143 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
8144 %int_3 = OpConstant %int 3
8145 %main = OpFunction %void None %3
8146 %5 = OpLabel
8147 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8148 OpStore %13 %int_2
8149 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
8150 OpStore %18 %int_3
8151 OpReturn
8152 OpFunctionEnd
8153 )";
8154
8155 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8156 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8157 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8158 EXPECT_THAT(
8159 getDiagnosticString(),
8160 HasSubstr("more than one Workgroup Storage Class variable in the "
8161 "entry point interface point to a type decorated with Block, "
8162 "all of them must be decorated with Aliased"));
8163 }
8164
TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct)8165 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct) {
8166 std::string spirv = R"(
8167 OpCapability Shader
8168 OpCapability WorkgroupMemoryExplicitLayoutKHR
8169 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8170 OpMemoryModel Logical GLSL450
8171 OpEntryPoint GLCompute %main "main" %_
8172 OpExecutionMode %main LocalSize 8 1 1
8173 OpDecorate %first Block
8174 %void = OpTypeVoid
8175 %3 = OpTypeFunction %void
8176 %int = OpTypeInt 32 1
8177 %int_3 = OpConstant %int 3
8178 %first = OpTypeArray %int %int_3
8179 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8180 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8181 %int_0 = OpConstant %int 0
8182 %int_2 = OpConstant %int 2
8183 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8184 %main = OpFunction %void None %3
8185 %5 = OpLabel
8186 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8187 OpStore %13 %int_2
8188 OpReturn
8189 OpFunctionEnd
8190 )";
8191
8192 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8193 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8194 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8195 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
8196 }
8197
TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout)8198 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout) {
8199 std::string spirv = R"(
8200 OpCapability Shader
8201 OpCapability WorkgroupMemoryExplicitLayoutKHR
8202 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8203 OpMemoryModel Logical GLSL450
8204 OpEntryPoint GLCompute %main "main" %_
8205 OpExecutionMode %main LocalSize 8 1 1
8206 OpDecorate %first Block
8207 %void = OpTypeVoid
8208 %3 = OpTypeFunction %void
8209 %int = OpTypeInt 32 1
8210 %first = OpTypeStruct %int
8211 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8212 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8213 %int_0 = OpConstant %int 0
8214 %int_2 = OpConstant %int 2
8215 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8216 %main = OpFunction %void None %3
8217 %5 = OpLabel
8218 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8219 OpStore %13 %int_2
8220 OpReturn
8221 OpFunctionEnd
8222 )";
8223
8224 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8225 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8226 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8227 EXPECT_THAT(
8228 getDiagnosticString(),
8229 HasSubstr("Block must be explicitly laid out with Offset decorations"));
8230 }
8231
TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout)8232 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout) {
8233 std::string spirv = R"(
8234 OpCapability Shader
8235 OpCapability WorkgroupMemoryExplicitLayoutKHR
8236 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
8237 OpMemoryModel Logical GLSL450
8238 OpEntryPoint GLCompute %main "main" %_
8239 OpExecutionMode %main LocalSize 8 1 1
8240 OpMemberDecorate %first 0 Offset 1
8241 OpDecorate %first Block
8242 %void = OpTypeVoid
8243 %3 = OpTypeFunction %void
8244 %int = OpTypeInt 32 1
8245 %first = OpTypeStruct %int
8246 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
8247 %_ = OpVariable %_ptr_Workgroup_first Workgroup
8248 %int_0 = OpConstant %int 0
8249 %int_2 = OpConstant %int 2
8250 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8251 %main = OpFunction %void None %3
8252 %5 = OpLabel
8253 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8254 OpStore %13 %int_2
8255 OpReturn
8256 OpFunctionEnd
8257 )";
8258
8259 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8260 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8261 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8262 EXPECT_THAT(
8263 getDiagnosticString(),
8264 HasSubstr("Block for variable in Workgroup storage class must follow "
8265 "relaxed storage buffer layout rules: "
8266 "member 0 at offset 1 is not aligned to 4"));
8267 }
8268
TEST_F(ValidateDecorations, WorkgroupBlockNoCapability)8269 TEST_F(ValidateDecorations, WorkgroupBlockNoCapability) {
8270 std::string spirv = R"(
8271 OpCapability Shader
8272 OpMemoryModel Logical GLSL450
8273 OpEntryPoint GLCompute %main "main" %_
8274 OpExecutionMode %main LocalSize 1 1 1
8275 OpMemberDecorate %struct 0 Offset 0
8276 OpMemberDecorate %struct 1 Offset 4
8277 OpDecorate %struct Block
8278 %void = OpTypeVoid
8279 %3 = OpTypeFunction %void
8280 %int = OpTypeInt 32 1
8281 %struct = OpTypeStruct %int %int
8282 %ptr_workgroup = OpTypePointer Workgroup %struct
8283 %_ = OpVariable %ptr_workgroup Workgroup
8284 %main = OpFunction %void None %3
8285 %5 = OpLabel
8286 OpReturn
8287 OpFunctionEnd
8288 )";
8289
8290 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8291 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
8292 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
8293 EXPECT_THAT(
8294 getDiagnosticString(),
8295 HasSubstr(
8296 "Workgroup Storage Class variables can't be decorated with Block "
8297 "unless declaring the WorkgroupMemoryExplicitLayoutKHR capability"));
8298 }
8299
TEST_F(ValidateDecorations, BadMatrixStrideUniform)8300 TEST_F(ValidateDecorations, BadMatrixStrideUniform) {
8301 const std::string spirv = R"(
8302 OpCapability Shader
8303 OpMemoryModel Logical GLSL450
8304 OpEntryPoint GLCompute %main "main"
8305 OpExecutionMode %main LocalSize 1 1 1
8306 OpDecorate %block Block
8307 OpMemberDecorate %block 0 Offset 0
8308 OpMemberDecorate %block 0 MatrixStride 3
8309 OpMemberDecorate %block 0 ColMajor
8310 OpDecorate %var DescriptorSet 0
8311 OpDecorate %var Binding 0
8312 %void = OpTypeVoid
8313 %float = OpTypeFloat 32
8314 %float4 = OpTypeVector %float 4
8315 %matrix4x4 = OpTypeMatrix %float4 4
8316 %block = OpTypeStruct %matrix4x4
8317 %block_ptr = OpTypePointer Uniform %block
8318 %var = OpVariable %block_ptr Uniform
8319 %void_fn = OpTypeFunction %void
8320 %main = OpFunction %void None %void_fn
8321 %entry = OpLabel
8322 OpReturn
8323 OpFunctionEnd
8324 )";
8325
8326 CompileSuccessfully(spirv);
8327 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8328 EXPECT_THAT(
8329 getDiagnosticString(),
8330 HasSubstr(
8331 "Structure id 2 decorated as Block for variable in Uniform storage "
8332 "class must follow standard uniform buffer layout rules: member 0 is "
8333 "a matrix with stride 3 not satisfying alignment to 16"));
8334 }
8335
TEST_F(ValidateDecorations, BadMatrixStrideStorageBuffer)8336 TEST_F(ValidateDecorations, BadMatrixStrideStorageBuffer) {
8337 const std::string spirv = R"(
8338 OpCapability Shader
8339 OpExtension "SPV_KHR_storage_buffer_storage_class"
8340 OpMemoryModel Logical GLSL450
8341 OpEntryPoint GLCompute %main "main"
8342 OpExecutionMode %main LocalSize 1 1 1
8343 OpDecorate %block Block
8344 OpMemberDecorate %block 0 Offset 0
8345 OpMemberDecorate %block 0 MatrixStride 3
8346 OpMemberDecorate %block 0 ColMajor
8347 OpDecorate %var DescriptorSet 0
8348 OpDecorate %var Binding 0
8349 %void = OpTypeVoid
8350 %float = OpTypeFloat 32
8351 %float4 = OpTypeVector %float 4
8352 %matrix4x4 = OpTypeMatrix %float4 4
8353 %block = OpTypeStruct %matrix4x4
8354 %block_ptr = OpTypePointer StorageBuffer %block
8355 %var = OpVariable %block_ptr StorageBuffer
8356 %void_fn = OpTypeFunction %void
8357 %main = OpFunction %void None %void_fn
8358 %entry = OpLabel
8359 OpReturn
8360 OpFunctionEnd
8361 )";
8362
8363 CompileSuccessfully(spirv);
8364 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8365 EXPECT_THAT(
8366 getDiagnosticString(),
8367 HasSubstr(
8368 "Structure id 2 decorated as Block for variable in StorageBuffer "
8369 "storage class must follow standard storage buffer layout rules: "
8370 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8371 }
8372
TEST_F(ValidateDecorations, BadMatrixStridePushConstant)8373 TEST_F(ValidateDecorations, BadMatrixStridePushConstant) {
8374 const std::string spirv = R"(
8375 OpCapability Shader
8376 OpMemoryModel Logical GLSL450
8377 OpEntryPoint GLCompute %main "main"
8378 OpExecutionMode %main LocalSize 1 1 1
8379 OpDecorate %block Block
8380 OpMemberDecorate %block 0 Offset 0
8381 OpMemberDecorate %block 0 MatrixStride 3
8382 OpMemberDecorate %block 0 ColMajor
8383 %void = OpTypeVoid
8384 %float = OpTypeFloat 32
8385 %float4 = OpTypeVector %float 4
8386 %matrix4x4 = OpTypeMatrix %float4 4
8387 %block = OpTypeStruct %matrix4x4
8388 %block_ptr = OpTypePointer PushConstant %block
8389 %var = OpVariable %block_ptr PushConstant
8390 %void_fn = OpTypeFunction %void
8391 %main = OpFunction %void None %void_fn
8392 %entry = OpLabel
8393 OpReturn
8394 OpFunctionEnd
8395 )";
8396
8397 CompileSuccessfully(spirv);
8398 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8399 EXPECT_THAT(
8400 getDiagnosticString(),
8401 HasSubstr(
8402 "Structure id 2 decorated as Block for variable in PushConstant "
8403 "storage class must follow standard storage buffer layout rules: "
8404 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8405 }
8406
TEST_F(ValidateDecorations, BadMatrixStrideStorageBufferScalarLayout)8407 TEST_F(ValidateDecorations, BadMatrixStrideStorageBufferScalarLayout) {
8408 const std::string spirv = R"(
8409 OpCapability Shader
8410 OpExtension "SPV_KHR_storage_buffer_storage_class"
8411 OpMemoryModel Logical GLSL450
8412 OpEntryPoint GLCompute %main "main"
8413 OpExecutionMode %main LocalSize 1 1 1
8414 OpDecorate %block Block
8415 OpMemberDecorate %block 0 Offset 0
8416 OpMemberDecorate %block 0 MatrixStride 3
8417 OpMemberDecorate %block 0 RowMajor
8418 OpDecorate %var DescriptorSet 0
8419 OpDecorate %var Binding 0
8420 %void = OpTypeVoid
8421 %float = OpTypeFloat 32
8422 %float4 = OpTypeVector %float 4
8423 %matrix4x4 = OpTypeMatrix %float4 4
8424 %block = OpTypeStruct %matrix4x4
8425 %block_ptr = OpTypePointer StorageBuffer %block
8426 %var = OpVariable %block_ptr StorageBuffer
8427 %void_fn = OpTypeFunction %void
8428 %main = OpFunction %void None %void_fn
8429 %entry = OpLabel
8430 OpReturn
8431 OpFunctionEnd
8432 )";
8433
8434 options_->scalar_block_layout = true;
8435 CompileSuccessfully(spirv);
8436 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8437 EXPECT_THAT(
8438 getDiagnosticString(),
8439 HasSubstr(
8440 "Structure id 2 decorated as Block for variable in StorageBuffer "
8441 "storage class must follow scalar storage buffer layout rules: "
8442 "member 0 is a matrix with stride 3 not satisfying alignment to 4"));
8443 }
8444
TEST_F(ValidateDecorations, MissingOffsetStructNestedInArray)8445 TEST_F(ValidateDecorations, MissingOffsetStructNestedInArray) {
8446 const std::string spirv = R"(
8447 OpCapability Shader
8448 OpExtension "SPV_KHR_storage_buffer_storage_class"
8449 OpMemoryModel Logical GLSL450
8450 OpEntryPoint GLCompute %main "main"
8451 OpExecutionMode %main LocalSize 1 1 1
8452 OpDecorate %array ArrayStride 4
8453 OpDecorate %outer Block
8454 OpMemberDecorate %outer 0 Offset 0
8455 OpDecorate %var DescriptorSet 0
8456 OpDecorate %var Binding 0
8457 %void = OpTypeVoid
8458 %int = OpTypeInt 32 0
8459 %int_4 = OpConstant %int 4
8460 %inner = OpTypeStruct %int
8461 %array = OpTypeArray %inner %int_4
8462 %outer = OpTypeStruct %array
8463 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer
8464 %var = OpVariable %ptr_ssbo_outer StorageBuffer
8465 %void_fn = OpTypeFunction %void
8466 %main = OpFunction %void None %void_fn
8467 %entry = OpLabel
8468 OpReturn
8469 OpFunctionEnd
8470 )";
8471
8472 CompileSuccessfully(spirv);
8473 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8474 EXPECT_THAT(getDiagnosticString(),
8475 HasSubstr("Structure id 3 decorated as Block must be explicitly "
8476 "laid out with Offset decorations"));
8477 }
8478
TEST_F(ValidateDecorations, AllOnesOffset)8479 TEST_F(ValidateDecorations, AllOnesOffset) {
8480 const std::string spirv = R"(
8481 OpCapability Shader
8482 OpMemoryModel Logical GLSL450
8483 OpEntryPoint GLCompute %main "main"
8484 OpDecorate %var DescriptorSet 0
8485 OpDecorate %var Binding 0
8486 OpDecorate %outer Block
8487 OpMemberDecorate %outer 0 Offset 0
8488 OpMemberDecorate %struct 0 Offset 4294967295
8489 %void = OpTypeVoid
8490 %int = OpTypeInt 32 0
8491 %struct = OpTypeStruct %int
8492 %outer = OpTypeStruct %struct
8493 %ptr = OpTypePointer Uniform %outer
8494 %var = OpVariable %ptr Uniform
8495 %void_fn = OpTypeFunction %void
8496 %main = OpFunction %void None %void_fn
8497 %entry = OpLabel
8498 OpReturn
8499 OpFunctionEnd
8500 )";
8501
8502 CompileSuccessfully(spirv);
8503 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8504 EXPECT_THAT(getDiagnosticString(),
8505 HasSubstr("decorated as Block must be explicitly laid out with "
8506 "Offset decorations"));
8507 }
8508
TEST_F(ValidateDecorations, PerVertexVulkanGood)8509 TEST_F(ValidateDecorations, PerVertexVulkanGood) {
8510 const std::string spirv = R"(
8511 OpCapability Shader
8512 OpCapability FragmentBarycentricKHR
8513 OpExtension "SPV_KHR_fragment_shader_barycentric"
8514 %1 = OpExtInstImport "GLSL.std.450"
8515 OpMemoryModel Logical GLSL450
8516 OpEntryPoint Fragment %main "main" %vertexIDs
8517 OpExecutionMode %main OriginUpperLeft
8518 OpDecorate %vertexIDs Location 0
8519 OpDecorate %vertexIDs PerVertexKHR
8520 %void = OpTypeVoid
8521 %func = OpTypeFunction %void
8522 %float = OpTypeFloat 32
8523 %uint = OpTypeInt 32 0
8524 %ptrFloat = OpTypePointer Input %float
8525 %uint_3 = OpConstant %uint 3
8526 %floatArray = OpTypeArray %float %uint_3
8527 %ptrFloatArray = OpTypePointer Input %floatArray
8528 %vertexIDs = OpVariable %ptrFloatArray Input
8529 %int = OpTypeInt 32 1
8530 %int_0 = OpConstant %int 0
8531 %main = OpFunction %void None %func
8532 %label = OpLabel
8533 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8534 %load = OpLoad %float %access
8535 OpReturn
8536 OpFunctionEnd
8537 )";
8538
8539 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8540 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8541 }
8542
TEST_F(ValidateDecorations, PerVertexVulkanOutput)8543 TEST_F(ValidateDecorations, PerVertexVulkanOutput) {
8544 const std::string spirv = R"(
8545 OpCapability Shader
8546 OpCapability FragmentBarycentricKHR
8547 OpExtension "SPV_KHR_fragment_shader_barycentric"
8548 %1 = OpExtInstImport "GLSL.std.450"
8549 OpMemoryModel Logical GLSL450
8550 OpEntryPoint Fragment %main "main" %vertexIDs
8551 OpExecutionMode %main OriginUpperLeft
8552 OpDecorate %vertexIDs Location 0
8553 OpDecorate %vertexIDs PerVertexKHR
8554 %void = OpTypeVoid
8555 %func = OpTypeFunction %void
8556 %float = OpTypeFloat 32
8557 %uint = OpTypeInt 32 0
8558 %ptrFloat = OpTypePointer Output %float
8559 %uint_3 = OpConstant %uint 3
8560 %floatArray = OpTypeArray %float %uint_3
8561 %ptrFloatArray = OpTypePointer Output %floatArray
8562 %vertexIDs = OpVariable %ptrFloatArray Output
8563 %int = OpTypeInt 32 1
8564 %int_0 = OpConstant %int 0
8565 %main = OpFunction %void None %func
8566 %label = OpLabel
8567 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8568 %load = OpLoad %float %access
8569 OpReturn
8570 OpFunctionEnd
8571 )";
8572
8573 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8574 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8575 EXPECT_THAT(getDiagnosticString(),
8576 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8577 EXPECT_THAT(getDiagnosticString(), HasSubstr("storage class must be Input"));
8578 }
8579
TEST_F(ValidateDecorations, PerVertexVulkanNonFragment)8580 TEST_F(ValidateDecorations, PerVertexVulkanNonFragment) {
8581 const std::string spirv = R"(
8582 OpCapability Shader
8583 OpCapability FragmentBarycentricKHR
8584 OpExtension "SPV_KHR_fragment_shader_barycentric"
8585 %1 = OpExtInstImport "GLSL.std.450"
8586 OpMemoryModel Logical GLSL450
8587 OpEntryPoint Vertex %main "main" %vertexIDs
8588 OpDecorate %vertexIDs Location 0
8589 OpDecorate %vertexIDs PerVertexKHR
8590 %void = OpTypeVoid
8591 %func = OpTypeFunction %void
8592 %float = OpTypeFloat 32
8593 %uint = OpTypeInt 32 0
8594 %ptrFloat = OpTypePointer Input %float
8595 %uint_3 = OpConstant %uint 3
8596 %floatArray = OpTypeArray %float %uint_3
8597 %ptrFloatArray = OpTypePointer Input %floatArray
8598 %vertexIDs = OpVariable %ptrFloatArray Input
8599 %int = OpTypeInt 32 1
8600 %int_0 = OpConstant %int 0
8601 %main = OpFunction %void None %func
8602 %label = OpLabel
8603 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8604 %load = OpLoad %float %access
8605 OpReturn
8606 OpFunctionEnd
8607 )";
8608
8609 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8610 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8611 EXPECT_THAT(getDiagnosticString(),
8612 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8613 EXPECT_THAT(
8614 getDiagnosticString(),
8615 HasSubstr(
8616 "PerVertexKHR can only be applied to Fragment Execution Models"));
8617 }
8618
TEST_F(ValidateDecorations, PerVertexVulkanNonArray)8619 TEST_F(ValidateDecorations, PerVertexVulkanNonArray) {
8620 const std::string spirv = R"(
8621 OpCapability Shader
8622 OpCapability FragmentBarycentricKHR
8623 OpExtension "SPV_KHR_fragment_shader_barycentric"
8624 %1 = OpExtInstImport "GLSL.std.450"
8625 OpMemoryModel Logical GLSL450
8626 OpEntryPoint Fragment %main "main" %vertexIDs
8627 OpExecutionMode %main OriginUpperLeft
8628 OpDecorate %vertexIDs Location 0
8629 OpDecorate %vertexIDs PerVertexKHR
8630 %void = OpTypeVoid
8631 %func = OpTypeFunction %void
8632 %float = OpTypeFloat 32
8633 %ptrFloat = OpTypePointer Input %float
8634 %vertexIDs = OpVariable %ptrFloat Input
8635 %int = OpTypeInt 32 1
8636 %int_0 = OpConstant %int 0
8637 %main = OpFunction %void None %func
8638 %label = OpLabel
8639 %load = OpLoad %float %vertexIDs
8640 OpReturn
8641 OpFunctionEnd
8642 )";
8643
8644 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8645 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8646 EXPECT_THAT(getDiagnosticString(),
8647 AnyVUID("VUID-StandaloneSpirv-Input-06778"));
8648 EXPECT_THAT(getDiagnosticString(),
8649 HasSubstr("PerVertexKHR must be declared as arrays"));
8650 }
8651
TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnNumericTypeBad)8652 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnNumericTypeBad) {
8653 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8654 std::string spirv = R"(
8655 OpCapability Shader
8656 OpMemoryModel Logical GLSL450
8657 OpEntryPoint Fragment %main "main"
8658 OpExecutionMode %main OriginUpperLeft
8659 OpDecorate %float RelaxedPrecision
8660 %void = OpTypeVoid
8661 %voidfn = OpTypeFunction %void
8662 %float = OpTypeFloat 32
8663 %main = OpFunction %void None %voidfn
8664 %label = OpLabel
8665 OpReturn
8666 OpFunctionEnd
8667 )";
8668
8669 CompileSuccessfully(spirv, env);
8670 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
8671 EXPECT_THAT(
8672 getDiagnosticString(),
8673 HasSubstr("RelaxPrecision decoration cannot be applied to a type"));
8674 }
8675
TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnStructMember)8676 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnStructMember) {
8677 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8678 std::string spirv = R"(
8679 OpCapability Shader
8680 OpMemoryModel Logical GLSL450
8681 OpEntryPoint Fragment %main "main"
8682 OpExecutionMode %main OriginUpperLeft
8683 OpMemberDecorate %struct 0 RelaxedPrecision
8684 %void = OpTypeVoid
8685 %voidfn = OpTypeFunction %void
8686 %float = OpTypeFloat 32
8687 %struct = OpTypeStruct %float
8688 %main = OpFunction %void None %voidfn
8689 %label = OpLabel
8690 OpReturn
8691 OpFunctionEnd
8692 )";
8693
8694 CompileSuccessfully(spirv, env);
8695 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
8696 }
8697
TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceGood)8698 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceGood) {
8699 std::string spirv = R"(
8700 OpCapability Shader
8701 OpCapability Geometry
8702 %1 = OpExtInstImport "GLSL.std.450"
8703 OpMemoryModel Logical GLSL450
8704 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8705 OpExecutionMode %main OriginUpperLeft
8706 OpSource GLSL 450
8707 OpDecorate %layer Location 0
8708 OpDecorate %gl_Layer Flat
8709 OpDecorate %gl_Layer BuiltIn Layer
8710 %void = OpTypeVoid
8711 %3 = OpTypeFunction %void
8712 %int = OpTypeInt 32 1
8713 %_ptr_Output_int = OpTypePointer Output %int
8714 %layer = OpVariable %_ptr_Output_int Output
8715 %_ptr_Input_int = OpTypePointer Input %int
8716 %gl_Layer = OpVariable %_ptr_Input_int Input
8717 %main = OpFunction %void None %3
8718 %5 = OpLabel
8719 %11 = OpLoad %int %gl_Layer
8720 OpStore %layer %11
8721 OpReturn
8722 OpFunctionEnd
8723 )";
8724
8725 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8726 EXPECT_EQ(SPV_SUCCESS,
8727 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8728 }
8729
TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceBad)8730 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceBad) {
8731 std::string spirv = R"(
8732 OpCapability Shader
8733 OpCapability Geometry
8734 %1 = OpExtInstImport "GLSL.std.450"
8735 OpMemoryModel Logical GLSL450
8736 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8737 OpExecutionMode %main OriginUpperLeft
8738 OpSource GLSL 450
8739 OpDecorate %layer Location 0
8740 OpDecorate %gl_Layer BuiltIn Layer
8741 %void = OpTypeVoid
8742 %3 = OpTypeFunction %void
8743 %int = OpTypeInt 32 1
8744 %_ptr_Output_int = OpTypePointer Output %int
8745 %layer = OpVariable %_ptr_Output_int Output
8746 %_ptr_Input_int = OpTypePointer Input %int
8747 %gl_Layer = OpVariable %_ptr_Input_int Input
8748 %main = OpFunction %void None %3
8749 %5 = OpLabel
8750 %11 = OpLoad %int %gl_Layer
8751 OpStore %layer %11
8752 OpReturn
8753 OpFunctionEnd
8754 )";
8755
8756 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8757 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8758 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8759 EXPECT_THAT(getDiagnosticString(),
8760 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8761 EXPECT_THAT(
8762 getDiagnosticString(),
8763 HasSubstr(
8764 "Fragment OpEntryPoint operand 4 with Input interfaces with integer "
8765 "or float type must have a Flat decoration for Entry Point id 2."));
8766 }
8767
TEST_F(ValidateDecorations, VulkanNoFlatFloat32)8768 TEST_F(ValidateDecorations, VulkanNoFlatFloat32) {
8769 std::string spirv = R"(
8770 OpCapability Shader
8771 %1 = OpExtInstImport "GLSL.std.450"
8772 OpMemoryModel Logical GLSL450
8773 OpEntryPoint Fragment %main "main" %in
8774 OpExecutionMode %main OriginUpperLeft
8775 OpSource GLSL 450
8776 OpDecorate %in Location 0
8777 %void = OpTypeVoid
8778 %3 = OpTypeFunction %void
8779 %float = OpTypeFloat 32
8780 %_ptr_Function_float = OpTypePointer Function %float
8781 %_ptr_Input_float = OpTypePointer Input %float
8782 %in = OpVariable %_ptr_Input_float Input
8783 %main = OpFunction %void None %3
8784 %5 = OpLabel
8785 %b = OpVariable %_ptr_Function_float Function
8786 %11 = OpLoad %float %in
8787 OpStore %b %11
8788 OpReturn
8789 OpFunctionEnd
8790 )";
8791
8792 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8793 EXPECT_EQ(SPV_SUCCESS,
8794 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8795 }
8796
TEST_F(ValidateDecorations, VulkanNoFlatFloat64)8797 TEST_F(ValidateDecorations, VulkanNoFlatFloat64) {
8798 std::string spirv = R"(
8799 OpCapability Shader
8800 OpCapability Float64
8801 %1 = OpExtInstImport "GLSL.std.450"
8802 OpMemoryModel Logical GLSL450
8803 OpEntryPoint Fragment %main "main" %in
8804 OpExecutionMode %main OriginUpperLeft
8805 OpSource GLSL 450
8806 OpDecorate %in Location 0
8807 %void = OpTypeVoid
8808 %3 = OpTypeFunction %void
8809 %double = OpTypeFloat 64
8810 %_ptr_Function_double = OpTypePointer Function %double
8811 %_ptr_Input_double = OpTypePointer Input %double
8812 %in = OpVariable %_ptr_Input_double Input
8813 %main = OpFunction %void None %3
8814 %5 = OpLabel
8815 %b = OpVariable %_ptr_Function_double Function
8816 %11 = OpLoad %double %in
8817 OpStore %b %11
8818 OpReturn
8819 OpFunctionEnd
8820 )";
8821
8822 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8823 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8824 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8825 EXPECT_THAT(getDiagnosticString(),
8826 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8827 EXPECT_THAT(
8828 getDiagnosticString(),
8829 HasSubstr(
8830 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8831 "or float type must have a Flat decoration for Entry Point id 2."));
8832 }
8833
TEST_F(ValidateDecorations, VulkanNoFlatVectorFloat64)8834 TEST_F(ValidateDecorations, VulkanNoFlatVectorFloat64) {
8835 std::string spirv = R"(
8836 OpCapability Shader
8837 OpCapability Float64
8838 %1 = OpExtInstImport "GLSL.std.450"
8839 OpMemoryModel Logical GLSL450
8840 OpEntryPoint Fragment %main "main" %in
8841 OpExecutionMode %main OriginUpperLeft
8842 OpSource GLSL 450
8843 OpDecorate %in Location 0
8844 %void = OpTypeVoid
8845 %3 = OpTypeFunction %void
8846 %double = OpTypeFloat 64
8847 %v2double = OpTypeVector %double 2
8848 %_ptr_Function_v2double = OpTypePointer Function %v2double
8849 %_ptr_Input_v2double = OpTypePointer Input %v2double
8850 %in = OpVariable %_ptr_Input_v2double Input
8851 %main = OpFunction %void None %3
8852 %5 = OpLabel
8853 %b = OpVariable %_ptr_Function_v2double Function
8854 %11 = OpLoad %v2double %in
8855 OpStore %b %11
8856 OpReturn
8857 OpFunctionEnd
8858 )";
8859
8860 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8861 EXPECT_EQ(SPV_SUCCESS,
8862 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8863 }
8864
TEST_F(ValidateDecorations, VulkanNoFlatIntVector)8865 TEST_F(ValidateDecorations, VulkanNoFlatIntVector) {
8866 std::string spirv = R"(
8867 OpCapability Shader
8868 %1 = OpExtInstImport "GLSL.std.450"
8869 OpMemoryModel Logical GLSL450
8870 OpEntryPoint Fragment %main "main" %in
8871 OpExecutionMode %main OriginUpperLeft
8872 OpSource GLSL 450
8873 OpDecorate %in Location 0
8874 %void = OpTypeVoid
8875 %3 = OpTypeFunction %void
8876 %int = OpTypeInt 32 1
8877 %v2int = OpTypeVector %int 2
8878 %_ptr_Function_v2int = OpTypePointer Function %v2int
8879 %_ptr_Input_v2int = OpTypePointer Input %v2int
8880 %in = OpVariable %_ptr_Input_v2int Input
8881 %main = OpFunction %void None %3
8882 %5 = OpLabel
8883 %b = OpVariable %_ptr_Function_v2int Function
8884 %12 = OpLoad %v2int %in
8885 OpStore %b %12
8886 OpReturn
8887 OpFunctionEnd
8888 )";
8889
8890 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8891 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8892 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8893 EXPECT_THAT(getDiagnosticString(),
8894 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8895 EXPECT_THAT(
8896 getDiagnosticString(),
8897 HasSubstr(
8898 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8899 "or float type must have a Flat decoration for Entry Point id 2."));
8900 }
8901
TEST_P(ValidateDecorationString, VulkanOutputInvalidInterface)8902 TEST_P(ValidateDecorationString, VulkanOutputInvalidInterface) {
8903 const std::string decoration = GetParam();
8904 std::stringstream ss;
8905 ss << R"(
8906 OpCapability Shader
8907 OpCapability SampleRateShading
8908 %1 = OpExtInstImport "GLSL.std.450"
8909 OpMemoryModel Logical GLSL450
8910 OpEntryPoint Fragment %main "main" %out
8911 OpExecutionMode %main OriginUpperLeft
8912 OpSource GLSL 450
8913 OpDecorate %out )"
8914 << decoration << R"(
8915 OpDecorate %out Location 0
8916 %void = OpTypeVoid
8917 %3 = OpTypeFunction %void
8918 %int = OpTypeInt 32 1
8919 %_ptr_Output_int = OpTypePointer Output %int
8920 %out = OpVariable %_ptr_Output_int Output
8921 %int_1 = OpConstant %int 1
8922 %main = OpFunction %void None %3
8923 %5 = OpLabel
8924 OpStore %out %int_1
8925 OpReturn
8926 OpFunctionEnd
8927 )";
8928
8929 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
8930 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8931 EXPECT_THAT(getDiagnosticString(),
8932 AnyVUID("VUID-StandaloneSpirv-Flat-06201"));
8933 EXPECT_THAT(
8934 getDiagnosticString(),
8935 HasSubstr("decorated variable must not be used in fragment execution "
8936 "model as an Output storage class for Entry Point id 2."));
8937 }
8938
TEST_P(ValidateDecorationString, VulkanVertexInputInvalidInterface)8939 TEST_P(ValidateDecorationString, VulkanVertexInputInvalidInterface) {
8940 const std::string decoration = GetParam();
8941 std::stringstream ss;
8942 ss << R"(
8943 OpCapability Shader
8944 OpCapability SampleRateShading
8945 %1 = OpExtInstImport "GLSL.std.450"
8946 OpMemoryModel Logical GLSL450
8947 OpEntryPoint Vertex %main "main" %out %in
8948 OpSource GLSL 450
8949 OpDecorate %in )"
8950 << decoration << R"(
8951 OpDecorate %out Location 0
8952 OpDecorate %in Location 0
8953 %void = OpTypeVoid
8954 %3 = OpTypeFunction %void
8955 %int = OpTypeInt 32 1
8956 %_ptr_Output_int = OpTypePointer Output %int
8957 %out = OpVariable %_ptr_Output_int Output
8958 %_ptr_Input_int = OpTypePointer Input %int
8959 %in = OpVariable %_ptr_Input_int Input
8960 %main = OpFunction %void None %3
8961 %5 = OpLabel
8962 %11 = OpLoad %int %in
8963 OpStore %out %11
8964 OpReturn
8965 OpFunctionEnd
8966 )";
8967
8968 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
8969 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8970 EXPECT_THAT(getDiagnosticString(),
8971 AnyVUID("VUID-StandaloneSpirv-Flat-06202"));
8972 EXPECT_THAT(
8973 getDiagnosticString(),
8974 HasSubstr("decorated variable must not be used in vertex execution model "
8975 "as an Input storage class for Entry Point id 2."));
8976 }
8977
8978 INSTANTIATE_TEST_SUITE_P(FragmentInputInterface, ValidateDecorationString,
8979 ::testing::Values("Flat", "NoPerspective", "Sample",
8980 "Centroid"));
8981
TEST_F(ValidateDecorations, NVBindlessSamplerArrayInBlock)8982 TEST_F(ValidateDecorations, NVBindlessSamplerArrayInBlock) {
8983 const std::string spirv = R"(
8984 OpCapability Shader
8985 OpCapability BindlessTextureNV
8986 OpExtension "SPV_NV_bindless_texture"
8987 %1 = OpExtInstImport "GLSL.std.450"
8988 OpMemoryModel Logical GLSL450
8989 OpSamplerImageAddressingModeNV 64
8990 OpEntryPoint Fragment %main "main"
8991 OpExecutionMode %main OriginUpperLeft
8992 OpSource GLSL 450
8993 OpName %main "main"
8994 OpName %UBO "UBO"
8995 OpMemberName %UBO 0 "uboSampler"
8996 OpName %_ ""
8997 OpDecorate %array ArrayStride 16
8998 OpMemberDecorate %UBO 0 Offset 0
8999 OpDecorate %UBO Block
9000 OpDecorate %_ DescriptorSet 0
9001 OpDecorate %_ Binding 2
9002 %void = OpTypeVoid
9003 %3 = OpTypeFunction %void
9004 %float = OpTypeFloat 32
9005 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
9006 %8 = OpTypeSampledImage %7
9007 %uint = OpTypeInt 32 0
9008 %uint_3 = OpConstant %uint 3
9009 %array = OpTypeArray %8 %uint_3
9010 %UBO = OpTypeStruct %array
9011 %pointer = OpTypePointer Uniform %UBO
9012 %_ = OpVariable %pointer Uniform
9013 %main = OpFunction %void None %3
9014 %5 = OpLabel
9015 OpReturn
9016 OpFunctionEnd
9017 )";
9018
9019 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
9020 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
9021 }
9022
TEST_F(ValidateDecorations, Std140ColMajorMat2x2)9023 TEST_F(ValidateDecorations, Std140ColMajorMat2x2) {
9024 const std::string spirv = R"(
9025 OpCapability Shader
9026 OpMemoryModel Logical GLSL450
9027 OpEntryPoint GLCompute %main "main"
9028 OpExecutionMode %main LocalSize 1 1 1
9029 OpDecorate %block Block
9030 OpMemberDecorate %block 0 Offset 0
9031 OpMemberDecorate %block 0 ColMajor
9032 OpMemberDecorate %block 0 MatrixStride 8
9033 OpDecorate %var DescriptorSet 0
9034 OpDecorate %var Binding 0
9035 %void = OpTypeVoid
9036 %void_fn = OpTypeFunction %void
9037 %float = OpTypeFloat 32
9038 %float2 = OpTypeVector %float 2
9039 %matrix = OpTypeMatrix %float2 2
9040 %block = OpTypeStruct %matrix
9041 %ptr_block = OpTypePointer Uniform %block
9042 %var = OpVariable %ptr_block Uniform
9043 %main = OpFunction %void None %void_fn
9044 %entry = OpLabel
9045 OpReturn
9046 OpFunctionEnd
9047 )";
9048
9049 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9050 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9051 EXPECT_THAT(
9052 getDiagnosticString(),
9053 HasSubstr(
9054 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9055 }
9056
TEST_F(ValidateDecorations, Std140RowMajorMat2x2)9057 TEST_F(ValidateDecorations, Std140RowMajorMat2x2) {
9058 const std::string spirv = R"(
9059 OpCapability Shader
9060 OpMemoryModel Logical GLSL450
9061 OpEntryPoint GLCompute %main "main"
9062 OpExecutionMode %main LocalSize 1 1 1
9063 OpDecorate %block Block
9064 OpMemberDecorate %block 0 Offset 0
9065 OpMemberDecorate %block 0 RowMajor
9066 OpMemberDecorate %block 0 MatrixStride 8
9067 OpDecorate %var DescriptorSet 0
9068 OpDecorate %var Binding 0
9069 %void = OpTypeVoid
9070 %void_fn = OpTypeFunction %void
9071 %float = OpTypeFloat 32
9072 %float2 = OpTypeVector %float 2
9073 %matrix = OpTypeMatrix %float2 2
9074 %block = OpTypeStruct %matrix
9075 %ptr_block = OpTypePointer Uniform %block
9076 %var = OpVariable %ptr_block Uniform
9077 %main = OpFunction %void None %void_fn
9078 %entry = OpLabel
9079 OpReturn
9080 OpFunctionEnd
9081 )";
9082
9083 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9084 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9085 EXPECT_THAT(
9086 getDiagnosticString(),
9087 HasSubstr(
9088 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9089 }
9090
TEST_F(ValidateDecorations, Std140ColMajorMat4x2)9091 TEST_F(ValidateDecorations, Std140ColMajorMat4x2) {
9092 const std::string spirv = R"(
9093 OpCapability Shader
9094 OpMemoryModel Logical GLSL450
9095 OpEntryPoint GLCompute %main "main"
9096 OpExecutionMode %main LocalSize 1 1 1
9097 OpDecorate %block Block
9098 OpMemberDecorate %block 0 Offset 0
9099 OpMemberDecorate %block 0 ColMajor
9100 OpMemberDecorate %block 0 MatrixStride 8
9101 OpDecorate %var DescriptorSet 0
9102 OpDecorate %var Binding 0
9103 %void = OpTypeVoid
9104 %void_fn = OpTypeFunction %void
9105 %float = OpTypeFloat 32
9106 %float2 = OpTypeVector %float 2
9107 %matrix = OpTypeMatrix %float2 4
9108 %block = OpTypeStruct %matrix
9109 %ptr_block = OpTypePointer Uniform %block
9110 %var = OpVariable %ptr_block Uniform
9111 %main = OpFunction %void None %void_fn
9112 %entry = OpLabel
9113 OpReturn
9114 OpFunctionEnd
9115 )";
9116
9117 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9118 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9119 EXPECT_THAT(
9120 getDiagnosticString(),
9121 HasSubstr(
9122 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
9123 }
9124
TEST_F(ValidateDecorations, Std140ColMajorMat2x3)9125 TEST_F(ValidateDecorations, Std140ColMajorMat2x3) {
9126 const std::string spirv = R"(
9127 OpCapability Shader
9128 OpMemoryModel Logical GLSL450
9129 OpEntryPoint GLCompute %main "main"
9130 OpExecutionMode %main LocalSize 1 1 1
9131 OpDecorate %block Block
9132 OpMemberDecorate %block 0 Offset 0
9133 OpMemberDecorate %block 0 ColMajor
9134 OpMemberDecorate %block 0 MatrixStride 12
9135 OpDecorate %var DescriptorSet 0
9136 OpDecorate %var Binding 0
9137 %void = OpTypeVoid
9138 %void_fn = OpTypeFunction %void
9139 %float = OpTypeFloat 32
9140 %float3 = OpTypeVector %float 3
9141 %matrix = OpTypeMatrix %float3 2
9142 %block = OpTypeStruct %matrix
9143 %ptr_block = OpTypePointer Uniform %block
9144 %var = OpVariable %ptr_block Uniform
9145 %main = OpFunction %void None %void_fn
9146 %entry = OpLabel
9147 OpReturn
9148 OpFunctionEnd
9149 )";
9150
9151 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9152 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9153 EXPECT_THAT(getDiagnosticString(),
9154 HasSubstr("member 0 is a matrix with stride 12 not satisfying "
9155 "alignment to 16"));
9156 }
9157
TEST_F(ValidateDecorations, MatrixMissingMajornessUniform)9158 TEST_F(ValidateDecorations, MatrixMissingMajornessUniform) {
9159 const std::string spirv = R"(
9160 OpCapability Shader
9161 OpMemoryModel Logical GLSL450
9162 OpEntryPoint GLCompute %main "main"
9163 OpExecutionMode %main LocalSize 1 1 1
9164 OpDecorate %block Block
9165 OpMemberDecorate %block 0 Offset 0
9166 OpMemberDecorate %block 0 MatrixStride 16
9167 OpDecorate %var DescriptorSet 0
9168 OpDecorate %var Binding 0
9169 %void = OpTypeVoid
9170 %void_fn = OpTypeFunction %void
9171 %float = OpTypeFloat 32
9172 %float2 = OpTypeVector %float 2
9173 %matrix = OpTypeMatrix %float2 2
9174 %block = OpTypeStruct %matrix
9175 %ptr_block = OpTypePointer Uniform %block
9176 %var = OpVariable %ptr_block Uniform
9177 %main = OpFunction %void None %void_fn
9178 %entry = OpLabel
9179 OpReturn
9180 OpFunctionEnd
9181 )";
9182
9183 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9184 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9185 EXPECT_THAT(
9186 getDiagnosticString(),
9187 HasSubstr(
9188 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9189 }
9190
TEST_F(ValidateDecorations, MatrixMissingMajornessStorageBuffer)9191 TEST_F(ValidateDecorations, MatrixMissingMajornessStorageBuffer) {
9192 const std::string spirv = R"(
9193 OpCapability Shader
9194 OpExtension "SPV_KHR_storage_buffer_storage_class"
9195 OpMemoryModel Logical GLSL450
9196 OpEntryPoint GLCompute %main "main"
9197 OpExecutionMode %main LocalSize 1 1 1
9198 OpDecorate %block Block
9199 OpMemberDecorate %block 0 Offset 0
9200 OpMemberDecorate %block 0 MatrixStride 16
9201 OpDecorate %var DescriptorSet 0
9202 OpDecorate %var Binding 0
9203 %void = OpTypeVoid
9204 %void_fn = OpTypeFunction %void
9205 %float = OpTypeFloat 32
9206 %float2 = OpTypeVector %float 2
9207 %matrix = OpTypeMatrix %float2 2
9208 %block = OpTypeStruct %matrix
9209 %ptr_block = OpTypePointer StorageBuffer %block
9210 %var = OpVariable %ptr_block StorageBuffer
9211 %main = OpFunction %void None %void_fn
9212 %entry = OpLabel
9213 OpReturn
9214 OpFunctionEnd
9215 )";
9216
9217 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9218 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9219 EXPECT_THAT(
9220 getDiagnosticString(),
9221 HasSubstr(
9222 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9223 }
9224
TEST_F(ValidateDecorations, MatrixMissingMajornessPushConstant)9225 TEST_F(ValidateDecorations, MatrixMissingMajornessPushConstant) {
9226 const std::string spirv = R"(
9227 OpCapability Shader
9228 OpMemoryModel Logical GLSL450
9229 OpEntryPoint GLCompute %main "main"
9230 OpExecutionMode %main LocalSize 1 1 1
9231 OpDecorate %block Block
9232 OpMemberDecorate %block 0 Offset 0
9233 OpMemberDecorate %block 0 MatrixStride 16
9234 %void = OpTypeVoid
9235 %void_fn = OpTypeFunction %void
9236 %float = OpTypeFloat 32
9237 %float2 = OpTypeVector %float 2
9238 %matrix = OpTypeMatrix %float2 2
9239 %block = OpTypeStruct %matrix
9240 %ptr_block = OpTypePointer PushConstant %block
9241 %var = OpVariable %ptr_block PushConstant
9242 %main = OpFunction %void None %void_fn
9243 %entry = OpLabel
9244 OpReturn
9245 OpFunctionEnd
9246 )";
9247
9248 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9249 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9250 EXPECT_THAT(
9251 getDiagnosticString(),
9252 HasSubstr(
9253 "must be explicitly laid out with RowMajor or ColMajor decorations"));
9254 }
9255
TEST_F(ValidateDecorations, StructWithRowAndColMajor)9256 TEST_F(ValidateDecorations, StructWithRowAndColMajor) {
9257 const std::string spirv = R"(
9258 OpCapability Shader
9259 OpMemoryModel Logical GLSL450
9260 OpEntryPoint GLCompute %main "main"
9261 OpExecutionMode %main LocalSize 1 1 1
9262 OpDecorate %block Block
9263 OpMemberDecorate %block 0 Offset 0
9264 OpMemberDecorate %block 0 MatrixStride 16
9265 OpMemberDecorate %block 0 ColMajor
9266 OpMemberDecorate %block 1 Offset 32
9267 OpMemberDecorate %block 1 MatrixStride 16
9268 OpMemberDecorate %block 1 RowMajor
9269 %void = OpTypeVoid
9270 %void_fn = OpTypeFunction %void
9271 %float = OpTypeFloat 32
9272 %float2 = OpTypeVector %float 2
9273 %matrix = OpTypeMatrix %float2 2
9274 %block = OpTypeStruct %matrix %matrix
9275 %ptr_block = OpTypePointer PushConstant %block
9276 %var = OpVariable %ptr_block PushConstant
9277 %main = OpFunction %void None %void_fn
9278 %entry = OpLabel
9279 OpReturn
9280 OpFunctionEnd
9281 )";
9282
9283 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9284 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9285 }
9286
TEST_F(ValidateDecorations, PhysicalStorageBufferWithOffset)9287 TEST_F(ValidateDecorations, PhysicalStorageBufferWithOffset) {
9288 const std::string spirv = R"(
9289 OpCapability Shader
9290 OpCapability Int64
9291 OpCapability PhysicalStorageBufferAddresses
9292 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9293 OpEntryPoint GLCompute %main "main" %pc
9294 OpExecutionMode %main LocalSize 1 1 1
9295 OpDecorate %pc_block Block
9296 OpMemberDecorate %pc_block 0 Offset 0
9297 OpMemberDecorate %pssbo_struct 0 Offset 0
9298 %void = OpTypeVoid
9299 %long = OpTypeInt 64 0
9300 %float = OpTypeFloat 32
9301 %int = OpTypeInt 32 0
9302 %int_0 = OpConstant %int 0
9303 %pc_block = OpTypeStruct %long
9304 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9305 %pc_long_ptr = OpTypePointer PushConstant %long
9306 %pc = OpVariable %pc_block_ptr PushConstant
9307 %pssbo_struct = OpTypeStruct %float
9308 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_struct
9309 %void_fn = OpTypeFunction %void
9310 %main = OpFunction %void None %void_fn
9311 %entry = OpLabel
9312 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9313 %addr = OpLoad %long %pc_gep
9314 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9315 OpReturn
9316 OpFunctionEnd
9317 )";
9318
9319 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9320 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9321 }
9322
TEST_F(ValidateDecorations, PhysicalStorageBufferMissingOffset)9323 TEST_F(ValidateDecorations, PhysicalStorageBufferMissingOffset) {
9324 const std::string spirv = R"(
9325 OpCapability Shader
9326 OpCapability Int64
9327 OpCapability PhysicalStorageBufferAddresses
9328 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9329 OpEntryPoint GLCompute %main "main" %pc
9330 OpExecutionMode %main LocalSize 1 1 1
9331 OpDecorate %pc_block Block
9332 OpMemberDecorate %pc_block 0 Offset 0
9333 %void = OpTypeVoid
9334 %long = OpTypeInt 64 0
9335 %float = OpTypeFloat 32
9336 %int = OpTypeInt 32 0
9337 %int_0 = OpConstant %int 0
9338 %pc_block = OpTypeStruct %long
9339 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9340 %pc_long_ptr = OpTypePointer PushConstant %long
9341 %pc = OpVariable %pc_block_ptr PushConstant
9342 %pssbo_struct = OpTypeStruct %float
9343 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_struct
9344 %void_fn = OpTypeFunction %void
9345 %main = OpFunction %void None %void_fn
9346 %entry = OpLabel
9347 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9348 %addr = OpLoad %long %pc_gep
9349 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9350 OpReturn
9351 OpFunctionEnd
9352 )";
9353
9354 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9355 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9356 EXPECT_THAT(
9357 getDiagnosticString(),
9358 HasSubstr("decorated as Block for variable in PhysicalStorageBuffer "
9359 "storage class must follow relaxed storage buffer layout "
9360 "rules: member 0 is missing an Offset decoration"));
9361 }
9362
TEST_F(ValidateDecorations, PhysicalStorageBufferMissingArrayStride)9363 TEST_F(ValidateDecorations, PhysicalStorageBufferMissingArrayStride) {
9364 const std::string spirv = R"(
9365 OpCapability Shader
9366 OpCapability Int64
9367 OpCapability PhysicalStorageBufferAddresses
9368 OpMemoryModel PhysicalStorageBuffer64 GLSL450
9369 OpEntryPoint GLCompute %main "main" %pc
9370 OpExecutionMode %main LocalSize 1 1 1
9371 OpDecorate %pc_block Block
9372 OpMemberDecorate %pc_block 0 Offset 0
9373 %void = OpTypeVoid
9374 %long = OpTypeInt 64 0
9375 %float = OpTypeFloat 32
9376 %int = OpTypeInt 32 0
9377 %int_0 = OpConstant %int 0
9378 %int_4 = OpConstant %int 4
9379 %pc_block = OpTypeStruct %long
9380 %pc_block_ptr = OpTypePointer PushConstant %pc_block
9381 %pc_long_ptr = OpTypePointer PushConstant %long
9382 %pc = OpVariable %pc_block_ptr PushConstant
9383 %pssbo_array = OpTypeArray %float %int_4
9384 %pssbo_ptr = OpTypePointer PhysicalStorageBuffer %pssbo_array
9385 %void_fn = OpTypeFunction %void
9386 %main = OpFunction %void None %void_fn
9387 %entry = OpLabel
9388 %pc_gep = OpAccessChain %pc_long_ptr %pc %int_0
9389 %addr = OpLoad %long %pc_gep
9390 %ptr = OpConvertUToPtr %pssbo_ptr %addr
9391 OpReturn
9392 OpFunctionEnd
9393 )";
9394
9395 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
9396 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_3));
9397 EXPECT_THAT(
9398 getDiagnosticString(),
9399 HasSubstr(
9400 "decorated as Block for variable in PhysicalStorageBuffer storage "
9401 "class must follow relaxed storage buffer layout rules: member 0 "
9402 "contains an array with stride 0, but with an element size of 4"));
9403 }
9404
9405 } // namespace
9406 } // namespace val
9407 } // namespace spvtools
9408