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/test_fixture.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_code_generator.h"
25 #include "test/val/val_fixtures.h"
26
27 namespace spvtools {
28 namespace val {
29 namespace {
30
31 using ::testing::Combine;
32 using ::testing::Eq;
33 using ::testing::HasSubstr;
34 using ::testing::Values;
35
36 struct TestResult {
TestResultspvtools::val::__anonfeb8b59f0111::TestResult37 TestResult(spv_result_t in_validation_result = SPV_SUCCESS,
38 const std::string& in_error_str = "")
39 : validation_result(in_validation_result), error_str(in_error_str) {}
40 spv_result_t validation_result;
41 const std::string error_str;
42 };
43
44 using ValidateDecorations = spvtest::ValidateBase<bool>;
45 using ValidateDecorationString = spvtest::ValidateBase<std::string>;
46 using ValidateVulkanCombineDecorationResult =
47 spvtest::ValidateBase<std::tuple<const char*, const char*, TestResult>>;
48
TEST_F(ValidateDecorations,ValidateOpDecorateRegistration)49 TEST_F(ValidateDecorations, ValidateOpDecorateRegistration) {
50 std::string spirv = R"(
51 OpCapability Shader
52 OpCapability Linkage
53 OpMemoryModel Logical GLSL450
54 OpDecorate %1 Location 4
55 OpDecorate %1 Centroid
56 %2 = OpTypeFloat 32
57 %3 = OpTypePointer Output %2
58 %1 = OpVariable %3 Output
59 ; Since %1 is used first in Decoration, it gets id 1.
60 )";
61 const uint32_t id = 1;
62 CompileSuccessfully(spirv);
63 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
64 // Must have 2 decorations.
65 EXPECT_THAT(vstate_->id_decorations(id),
66 Eq(std::set<Decoration>{Decoration(SpvDecorationLocation, {4}),
67 Decoration(SpvDecorationCentroid)}));
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(SpvDecorationArrayStride, {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(SpvDecorationNonReadable, {}, 2),
99 Decoration(SpvDecorationOffset, {2}, 2),
100 Decoration(SpvDecorationBufferBlock)}));
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(SpvDecorationDescriptorSet, {0}),
156 Decoration(SpvDecorationRelaxedPrecision),
157 Decoration(SpvDecorationRestrict)};
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(SpvDecorationOffset, {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, ValidateAndRetrieveValidationState());
1222 EXPECT_THAT(getDiagnosticString(),
1223 HasSubstr("must not use GLSLShared decoration"));
1224 }
1225
TEST_F(ValidateDecorations,BufferBlockGLSLSharedBad)1226 TEST_F(ValidateDecorations, BufferBlockGLSLSharedBad) {
1227 std::string spirv = R"(
1228 OpCapability Shader
1229 %1 = OpExtInstImport "GLSL.std.450"
1230 OpMemoryModel Logical GLSL450
1231 OpEntryPoint GLCompute %main "main"
1232 OpExecutionMode %main LocalSize 1 1 1
1233 OpSource GLSL 430
1234 OpDecorate %Output BufferBlock
1235 OpDecorate %Output GLSLShared
1236 OpMemberDecorate %Output 0 Offset 0
1237 %void = OpTypeVoid
1238 %3 = OpTypeFunction %void
1239 %float = OpTypeFloat 32
1240 %Output = OpTypeStruct %float
1241 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1242 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1243 %main = OpFunction %void None %3
1244 %5 = OpLabel
1245 OpReturn
1246 OpFunctionEnd
1247 )";
1248
1249 CompileSuccessfully(spirv);
1250 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1251 EXPECT_THAT(getDiagnosticString(),
1252 HasSubstr("must not use GLSLShared decoration"));
1253 }
1254
TEST_F(ValidateDecorations,BlockNestedStructGLSLSharedBad)1255 TEST_F(ValidateDecorations, BlockNestedStructGLSLSharedBad) {
1256 std::string spirv = R"(
1257 OpCapability Shader
1258 %1 = OpExtInstImport "GLSL.std.450"
1259 OpMemoryModel Logical GLSL450
1260 OpEntryPoint GLCompute %main "main"
1261 OpExecutionMode %main LocalSize 1 1 1
1262 OpSource GLSL 430
1263 OpMemberDecorate %S 0 Offset 0
1264 OpDecorate %S GLSLShared
1265 OpMemberDecorate %Output 0 Offset 0
1266 OpMemberDecorate %Output 1 Offset 16
1267 OpMemberDecorate %Output 2 Offset 32
1268 OpDecorate %Output Block
1269 %void = OpTypeVoid
1270 %3 = OpTypeFunction %void
1271 %float = OpTypeFloat 32
1272 %v4float = OpTypeVector %float 4
1273 %int = OpTypeInt 32 1
1274 %S = OpTypeStruct %int
1275 %Output = OpTypeStruct %float %v4float %S
1276 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1277 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1278 %main = OpFunction %void None %3
1279 %5 = OpLabel
1280 OpReturn
1281 OpFunctionEnd
1282 )";
1283
1284 CompileSuccessfully(spirv);
1285 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1286 EXPECT_THAT(getDiagnosticString(),
1287 HasSubstr("must not use GLSLShared decoration"));
1288 }
1289
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLSharedBad)1290 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLSharedBad) {
1291 std::string spirv = R"(
1292 OpCapability Shader
1293 %1 = OpExtInstImport "GLSL.std.450"
1294 OpMemoryModel Logical GLSL450
1295 OpEntryPoint GLCompute %main "main"
1296 OpExecutionMode %main LocalSize 1 1 1
1297 OpSource GLSL 430
1298 OpMemberDecorate %S 0 Offset 0
1299 OpDecorate %S GLSLShared
1300 OpMemberDecorate %Output 0 Offset 0
1301 OpMemberDecorate %Output 1 Offset 16
1302 OpMemberDecorate %Output 2 Offset 32
1303 OpDecorate %Output BufferBlock
1304 %void = OpTypeVoid
1305 %3 = OpTypeFunction %void
1306 %float = OpTypeFloat 32
1307 %v4float = OpTypeVector %float 4
1308 %int = OpTypeInt 32 1
1309 %S = OpTypeStruct %int
1310 %Output = OpTypeStruct %float %v4float %S
1311 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1312 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1313 %main = OpFunction %void None %3
1314 %5 = OpLabel
1315 OpReturn
1316 OpFunctionEnd
1317 )";
1318
1319 CompileSuccessfully(spirv);
1320 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1321 EXPECT_THAT(getDiagnosticString(),
1322 HasSubstr("must not use GLSLShared decoration"));
1323 }
1324
TEST_F(ValidateDecorations,BlockGLSLPackedBad)1325 TEST_F(ValidateDecorations, BlockGLSLPackedBad) {
1326 std::string spirv = R"(
1327 OpCapability Shader
1328 %1 = OpExtInstImport "GLSL.std.450"
1329 OpMemoryModel Logical GLSL450
1330 OpEntryPoint GLCompute %main "main"
1331 OpExecutionMode %main LocalSize 1 1 1
1332 OpSource GLSL 430
1333 OpDecorate %Output Block
1334 OpDecorate %Output GLSLPacked
1335 OpMemberDecorate %Output 0 Offset 0
1336 %void = OpTypeVoid
1337 %3 = OpTypeFunction %void
1338 %float = OpTypeFloat 32
1339 %Output = OpTypeStruct %float
1340 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1341 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1342 %main = OpFunction %void None %3
1343 %5 = OpLabel
1344 OpReturn
1345 OpFunctionEnd
1346 )";
1347
1348 CompileSuccessfully(spirv);
1349 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1350 EXPECT_THAT(getDiagnosticString(),
1351 HasSubstr("must not use GLSLPacked decoration"));
1352 }
1353
TEST_F(ValidateDecorations,BufferBlockGLSLPackedBad)1354 TEST_F(ValidateDecorations, BufferBlockGLSLPackedBad) {
1355 std::string spirv = R"(
1356 OpCapability Shader
1357 %1 = OpExtInstImport "GLSL.std.450"
1358 OpMemoryModel Logical GLSL450
1359 OpEntryPoint GLCompute %main "main"
1360 OpExecutionMode %main LocalSize 1 1 1
1361 OpSource GLSL 430
1362 OpDecorate %Output BufferBlock
1363 OpDecorate %Output GLSLPacked
1364 OpMemberDecorate %Output 0 Offset 0
1365 %void = OpTypeVoid
1366 %3 = OpTypeFunction %void
1367 %float = OpTypeFloat 32
1368 %Output = OpTypeStruct %float
1369 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1370 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1371 %main = OpFunction %void None %3
1372 %5 = OpLabel
1373 OpReturn
1374 OpFunctionEnd
1375 )";
1376
1377 CompileSuccessfully(spirv);
1378 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1379 EXPECT_THAT(getDiagnosticString(),
1380 HasSubstr("must not use GLSLPacked decoration"));
1381 }
1382
TEST_F(ValidateDecorations,BlockNestedStructGLSLPackedBad)1383 TEST_F(ValidateDecorations, BlockNestedStructGLSLPackedBad) {
1384 std::string spirv = R"(
1385 OpCapability Shader
1386 %1 = OpExtInstImport "GLSL.std.450"
1387 OpMemoryModel Logical GLSL450
1388 OpEntryPoint GLCompute %main "main"
1389 OpExecutionMode %main LocalSize 1 1 1
1390 OpSource GLSL 430
1391 OpMemberDecorate %S 0 Offset 0
1392 OpDecorate %S GLSLPacked
1393 OpMemberDecorate %Output 0 Offset 0
1394 OpMemberDecorate %Output 1 Offset 16
1395 OpMemberDecorate %Output 2 Offset 32
1396 OpDecorate %Output Block
1397 %void = OpTypeVoid
1398 %3 = OpTypeFunction %void
1399 %float = OpTypeFloat 32
1400 %v4float = OpTypeVector %float 4
1401 %int = OpTypeInt 32 1
1402 %S = OpTypeStruct %int
1403 %Output = OpTypeStruct %float %v4float %S
1404 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1405 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1406 %main = OpFunction %void None %3
1407 %5 = OpLabel
1408 OpReturn
1409 OpFunctionEnd
1410 )";
1411
1412 CompileSuccessfully(spirv);
1413 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1414 EXPECT_THAT(getDiagnosticString(),
1415 HasSubstr("must not use GLSLPacked decoration"));
1416 }
1417
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLPackedBad)1418 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLPackedBad) {
1419 std::string spirv = R"(
1420 OpCapability Shader
1421 %1 = OpExtInstImport "GLSL.std.450"
1422 OpMemoryModel Logical GLSL450
1423 OpEntryPoint GLCompute %main "main"
1424 OpExecutionMode %main LocalSize 1 1 1
1425 OpSource GLSL 430
1426 OpMemberDecorate %S 0 Offset 0
1427 OpDecorate %S GLSLPacked
1428 OpMemberDecorate %Output 0 Offset 0
1429 OpMemberDecorate %Output 1 Offset 16
1430 OpMemberDecorate %Output 2 Offset 32
1431 OpDecorate %Output BufferBlock
1432 %void = OpTypeVoid
1433 %3 = OpTypeFunction %void
1434 %float = OpTypeFloat 32
1435 %v4float = OpTypeVector %float 4
1436 %int = OpTypeInt 32 1
1437 %S = OpTypeStruct %int
1438 %Output = OpTypeStruct %float %v4float %S
1439 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1440 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1441 %main = OpFunction %void None %3
1442 %5 = OpLabel
1443 OpReturn
1444 OpFunctionEnd
1445 )";
1446
1447 CompileSuccessfully(spirv);
1448 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1449 EXPECT_THAT(getDiagnosticString(),
1450 HasSubstr("must not use GLSLPacked decoration"));
1451 }
1452
TEST_F(ValidateDecorations,BlockMissingArrayStrideBad)1453 TEST_F(ValidateDecorations, BlockMissingArrayStrideBad) {
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 OpDecorate %Output Block
1462 OpMemberDecorate %Output 0 Offset 0
1463 %void = OpTypeVoid
1464 %3 = OpTypeFunction %void
1465 %float = OpTypeFloat 32
1466 %int = OpTypeInt 32 1
1467 %int_3 = OpConstant %int 3
1468 %array = OpTypeArray %float %int_3
1469 %Output = OpTypeStruct %array
1470 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1471 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1472 %main = OpFunction %void None %3
1473 %5 = OpLabel
1474 OpReturn
1475 OpFunctionEnd
1476 )";
1477
1478 CompileSuccessfully(spirv);
1479 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1480 EXPECT_THAT(
1481 getDiagnosticString(),
1482 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1483 }
1484
TEST_F(ValidateDecorations,BufferBlockMissingArrayStrideBad)1485 TEST_F(ValidateDecorations, BufferBlockMissingArrayStrideBad) {
1486 std::string spirv = R"(
1487 OpCapability Shader
1488 %1 = OpExtInstImport "GLSL.std.450"
1489 OpMemoryModel Logical GLSL450
1490 OpEntryPoint GLCompute %main "main"
1491 OpExecutionMode %main LocalSize 1 1 1
1492 OpSource GLSL 430
1493 OpDecorate %Output BufferBlock
1494 OpMemberDecorate %Output 0 Offset 0
1495 %void = OpTypeVoid
1496 %3 = OpTypeFunction %void
1497 %float = OpTypeFloat 32
1498 %int = OpTypeInt 32 1
1499 %int_3 = OpConstant %int 3
1500 %array = OpTypeArray %float %int_3
1501 %Output = OpTypeStruct %array
1502 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1503 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1504 %main = OpFunction %void None %3
1505 %5 = OpLabel
1506 OpReturn
1507 OpFunctionEnd
1508 )";
1509
1510 CompileSuccessfully(spirv);
1511 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1512 EXPECT_THAT(
1513 getDiagnosticString(),
1514 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1515 }
1516
TEST_F(ValidateDecorations,BlockNestedStructMissingArrayStrideBad)1517 TEST_F(ValidateDecorations, BlockNestedStructMissingArrayStrideBad) {
1518 std::string spirv = R"(
1519 OpCapability Shader
1520 %1 = OpExtInstImport "GLSL.std.450"
1521 OpMemoryModel Logical GLSL450
1522 OpEntryPoint GLCompute %main "main"
1523 OpExecutionMode %main LocalSize 1 1 1
1524 OpSource GLSL 430
1525 OpMemberDecorate %S 0 Offset 0
1526 OpMemberDecorate %Output 0 Offset 0
1527 OpMemberDecorate %Output 1 Offset 16
1528 OpMemberDecorate %Output 2 Offset 32
1529 OpDecorate %Output Block
1530 %void = OpTypeVoid
1531 %3 = OpTypeFunction %void
1532 %float = OpTypeFloat 32
1533 %v4float = OpTypeVector %float 4
1534 %int = OpTypeInt 32 1
1535 %int_3 = OpConstant %int 3
1536 %array = OpTypeArray %float %int_3
1537 %S = OpTypeStruct %array
1538 %Output = OpTypeStruct %float %v4float %S
1539 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1540 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1541 %main = OpFunction %void None %3
1542 %5 = OpLabel
1543 OpReturn
1544 OpFunctionEnd
1545 )";
1546
1547 CompileSuccessfully(spirv);
1548 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1549 EXPECT_THAT(
1550 getDiagnosticString(),
1551 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1552 }
1553
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingArrayStrideBad)1554 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingArrayStrideBad) {
1555 std::string spirv = R"(
1556 OpCapability Shader
1557 %1 = OpExtInstImport "GLSL.std.450"
1558 OpMemoryModel Logical GLSL450
1559 OpEntryPoint GLCompute %main "main"
1560 OpExecutionMode %main LocalSize 1 1 1
1561 OpSource GLSL 430
1562 OpMemberDecorate %S 0 Offset 0
1563 OpMemberDecorate %Output 0 Offset 0
1564 OpMemberDecorate %Output 1 Offset 16
1565 OpMemberDecorate %Output 2 Offset 32
1566 OpDecorate %Output BufferBlock
1567 %void = OpTypeVoid
1568 %3 = OpTypeFunction %void
1569 %float = OpTypeFloat 32
1570 %v4float = OpTypeVector %float 4
1571 %int = OpTypeInt 32 1
1572 %int_3 = OpConstant %int 3
1573 %array = OpTypeArray %float %int_3
1574 %S = OpTypeStruct %array
1575 %Output = OpTypeStruct %float %v4float %S
1576 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1577 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1578 %main = OpFunction %void None %3
1579 %5 = OpLabel
1580 OpReturn
1581 OpFunctionEnd
1582 )";
1583
1584 CompileSuccessfully(spirv);
1585 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1586 EXPECT_THAT(
1587 getDiagnosticString(),
1588 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1589 }
1590
TEST_F(ValidateDecorations,BlockMissingMatrixStrideBad)1591 TEST_F(ValidateDecorations, BlockMissingMatrixStrideBad) {
1592 std::string spirv = R"(
1593 OpCapability Shader
1594 %1 = OpExtInstImport "GLSL.std.450"
1595 OpMemoryModel Logical GLSL450
1596 OpEntryPoint GLCompute %main "main"
1597 OpExecutionMode %main LocalSize 1 1 1
1598 OpSource GLSL 430
1599 OpDecorate %Output Block
1600 OpMemberDecorate %Output 0 Offset 0
1601 %void = OpTypeVoid
1602 %3 = OpTypeFunction %void
1603 %float = OpTypeFloat 32
1604 %v3float = OpTypeVector %float 3
1605 %matrix = OpTypeMatrix %v3float 4
1606 %Output = OpTypeStruct %matrix
1607 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1608 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1609 %main = OpFunction %void None %3
1610 %5 = OpLabel
1611 OpReturn
1612 OpFunctionEnd
1613 )";
1614
1615 CompileSuccessfully(spirv);
1616 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1617 EXPECT_THAT(
1618 getDiagnosticString(),
1619 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1620 }
1621
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideBad)1622 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideBad) {
1623 std::string spirv = R"(
1624 OpCapability Shader
1625 %1 = OpExtInstImport "GLSL.std.450"
1626 OpMemoryModel Logical GLSL450
1627 OpEntryPoint GLCompute %main "main"
1628 OpExecutionMode %main LocalSize 1 1 1
1629 OpSource GLSL 430
1630 OpDecorate %Output BufferBlock
1631 OpMemberDecorate %Output 0 Offset 0
1632 %void = OpTypeVoid
1633 %3 = OpTypeFunction %void
1634 %float = OpTypeFloat 32
1635 %v3float = OpTypeVector %float 3
1636 %matrix = OpTypeMatrix %v3float 4
1637 %Output = OpTypeStruct %matrix
1638 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1639 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1640 %main = OpFunction %void None %3
1641 %5 = OpLabel
1642 OpReturn
1643 OpFunctionEnd
1644 )";
1645
1646 CompileSuccessfully(spirv);
1647 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1648 EXPECT_THAT(
1649 getDiagnosticString(),
1650 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1651 }
1652
TEST_F(ValidateDecorations,BlockMissingMatrixStrideArrayBad)1653 TEST_F(ValidateDecorations, BlockMissingMatrixStrideArrayBad) {
1654 std::string spirv = R"(
1655 OpCapability Shader
1656 %1 = OpExtInstImport "GLSL.std.450"
1657 OpMemoryModel Logical GLSL450
1658 OpEntryPoint GLCompute %main "main"
1659 OpExecutionMode %main LocalSize 1 1 1
1660 OpSource GLSL 430
1661 OpDecorate %Output Block
1662 OpMemberDecorate %Output 0 Offset 0
1663 %void = OpTypeVoid
1664 %3 = OpTypeFunction %void
1665 %float = OpTypeFloat 32
1666 %v3float = OpTypeVector %float 3
1667 %matrix = OpTypeMatrix %v3float 4
1668 %int = OpTypeInt 32 1
1669 %int_3 = OpConstant %int 3
1670 %array = OpTypeArray %matrix %int_3
1671 %Output = OpTypeStruct %matrix
1672 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1673 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1674 %main = OpFunction %void None %3
1675 %5 = OpLabel
1676 OpReturn
1677 OpFunctionEnd
1678 )";
1679
1680 CompileSuccessfully(spirv);
1681 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1682 EXPECT_THAT(
1683 getDiagnosticString(),
1684 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1685 }
1686
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideArrayBad)1687 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideArrayBad) {
1688 std::string spirv = R"(
1689 OpCapability Shader
1690 %1 = OpExtInstImport "GLSL.std.450"
1691 OpMemoryModel Logical GLSL450
1692 OpEntryPoint GLCompute %main "main"
1693 OpExecutionMode %main LocalSize 1 1 1
1694 OpSource GLSL 430
1695 OpDecorate %Output BufferBlock
1696 OpMemberDecorate %Output 0 Offset 0
1697 %void = OpTypeVoid
1698 %3 = OpTypeFunction %void
1699 %float = OpTypeFloat 32
1700 %v3float = OpTypeVector %float 3
1701 %matrix = OpTypeMatrix %v3float 4
1702 %int = OpTypeInt 32 1
1703 %int_3 = OpConstant %int 3
1704 %array = OpTypeArray %matrix %int_3
1705 %Output = OpTypeStruct %matrix
1706 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1707 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1708 %main = OpFunction %void None %3
1709 %5 = OpLabel
1710 OpReturn
1711 OpFunctionEnd
1712 )";
1713
1714 CompileSuccessfully(spirv);
1715 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1716 EXPECT_THAT(
1717 getDiagnosticString(),
1718 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1719 }
1720
TEST_F(ValidateDecorations,BlockNestedStructMissingMatrixStrideBad)1721 TEST_F(ValidateDecorations, BlockNestedStructMissingMatrixStrideBad) {
1722 std::string spirv = R"(
1723 OpCapability Shader
1724 %1 = OpExtInstImport "GLSL.std.450"
1725 OpMemoryModel Logical GLSL450
1726 OpEntryPoint GLCompute %main "main"
1727 OpExecutionMode %main LocalSize 1 1 1
1728 OpSource GLSL 430
1729 OpMemberDecorate %S 0 Offset 0
1730 OpMemberDecorate %Output 0 Offset 0
1731 OpMemberDecorate %Output 1 Offset 16
1732 OpMemberDecorate %Output 2 Offset 32
1733 OpDecorate %Output Block
1734 %void = OpTypeVoid
1735 %3 = OpTypeFunction %void
1736 %float = OpTypeFloat 32
1737 %v3float = OpTypeVector %float 3
1738 %v4float = OpTypeVector %float 4
1739 %matrix = OpTypeMatrix %v3float 4
1740 %S = OpTypeStruct %matrix
1741 %Output = OpTypeStruct %float %v4float %S
1742 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1743 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1744 %main = OpFunction %void None %3
1745 %5 = OpLabel
1746 OpReturn
1747 OpFunctionEnd
1748 )";
1749
1750 CompileSuccessfully(spirv);
1751 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1752 EXPECT_THAT(
1753 getDiagnosticString(),
1754 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1755 }
1756
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingMatrixStrideBad)1757 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingMatrixStrideBad) {
1758 std::string spirv = R"(
1759 OpCapability Shader
1760 %1 = OpExtInstImport "GLSL.std.450"
1761 OpMemoryModel Logical GLSL450
1762 OpEntryPoint GLCompute %main "main"
1763 OpExecutionMode %main LocalSize 1 1 1
1764 OpSource GLSL 430
1765 OpMemberDecorate %S 0 Offset 0
1766 OpMemberDecorate %Output 0 Offset 0
1767 OpMemberDecorate %Output 1 Offset 16
1768 OpMemberDecorate %Output 2 Offset 32
1769 OpDecorate %Output BufferBlock
1770 %void = OpTypeVoid
1771 %3 = OpTypeFunction %void
1772 %float = OpTypeFloat 32
1773 %v3float = OpTypeVector %float 3
1774 %v4float = OpTypeVector %float 4
1775 %matrix = OpTypeMatrix %v3float 4
1776 %S = OpTypeStruct %matrix
1777 %Output = OpTypeStruct %float %v4float %S
1778 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1779 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1780 %main = OpFunction %void None %3
1781 %5 = OpLabel
1782 OpReturn
1783 OpFunctionEnd
1784 )";
1785
1786 CompileSuccessfully(spirv);
1787 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1788 EXPECT_THAT(
1789 getDiagnosticString(),
1790 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1791 }
1792
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayout)1793 TEST_F(ValidateDecorations, BlockStandardUniformBufferLayout) {
1794 std::string spirv = R"(
1795 OpCapability Shader
1796 %1 = OpExtInstImport "GLSL.std.450"
1797 OpMemoryModel Logical GLSL450
1798 OpEntryPoint GLCompute %main "main"
1799 OpExecutionMode %main LocalSize 1 1 1
1800 OpSource GLSL 430
1801 OpMemberDecorate %F 0 Offset 0
1802 OpMemberDecorate %F 1 Offset 8
1803 OpDecorate %_arr_float_uint_2 ArrayStride 16
1804 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
1805 OpMemberDecorate %O 0 Offset 0
1806 OpMemberDecorate %O 1 Offset 16
1807 OpMemberDecorate %O 2 Offset 32
1808 OpMemberDecorate %O 3 Offset 64
1809 OpMemberDecorate %O 4 ColMajor
1810 OpMemberDecorate %O 4 Offset 80
1811 OpMemberDecorate %O 4 MatrixStride 16
1812 OpDecorate %_arr_O_uint_2 ArrayStride 176
1813 OpMemberDecorate %Output 0 Offset 0
1814 OpMemberDecorate %Output 1 Offset 8
1815 OpMemberDecorate %Output 2 Offset 16
1816 OpMemberDecorate %Output 3 Offset 32
1817 OpMemberDecorate %Output 4 Offset 48
1818 OpMemberDecorate %Output 5 Offset 64
1819 OpMemberDecorate %Output 6 ColMajor
1820 OpMemberDecorate %Output 6 Offset 96
1821 OpMemberDecorate %Output 6 MatrixStride 16
1822 OpMemberDecorate %Output 7 Offset 128
1823 OpDecorate %Output Block
1824 %void = OpTypeVoid
1825 %3 = OpTypeFunction %void
1826 %float = OpTypeFloat 32
1827 %v2float = OpTypeVector %float 2
1828 %v3float = OpTypeVector %float 3
1829 %int = OpTypeInt 32 1
1830 %uint = OpTypeInt 32 0
1831 %v2uint = OpTypeVector %uint 2
1832 %F = OpTypeStruct %int %v2uint
1833 %uint_2 = OpConstant %uint 2
1834 %_arr_float_uint_2 = OpTypeArray %float %uint_2
1835 %mat2v3float = OpTypeMatrix %v3float 2
1836 %v3uint = OpTypeVector %uint 3
1837 %mat3v3float = OpTypeMatrix %v3float 3
1838 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
1839 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
1840 %_arr_O_uint_2 = OpTypeArray %O %uint_2
1841 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
1842 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1843 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1844 %main = OpFunction %void None %3
1845 %5 = OpLabel
1846 OpReturn
1847 OpFunctionEnd
1848 )";
1849
1850 CompileSuccessfully(spirv);
1851 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
1852 }
1853
TEST_F(ValidateDecorations,BlockLayoutPermitsTightVec3ScalarPackingGood)1854 TEST_F(ValidateDecorations, BlockLayoutPermitsTightVec3ScalarPackingGood) {
1855 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
1856 std::string spirv = R"(
1857 OpCapability Shader
1858 OpMemoryModel Logical GLSL450
1859 OpEntryPoint Vertex %main "main"
1860 OpSource GLSL 450
1861 OpMemberDecorate %S 0 Offset 0
1862 OpMemberDecorate %S 1 Offset 12
1863 OpDecorate %S Block
1864 OpDecorate %B DescriptorSet 0
1865 OpDecorate %B Binding 0
1866 %void = OpTypeVoid
1867 %3 = OpTypeFunction %void
1868 %float = OpTypeFloat 32
1869 %v3float = OpTypeVector %float 3
1870 %S = OpTypeStruct %v3float %float
1871 %_ptr_Uniform_S = OpTypePointer Uniform %S
1872 %B = OpVariable %_ptr_Uniform_S Uniform
1873 %main = OpFunction %void None %3
1874 %5 = OpLabel
1875 OpReturn
1876 OpFunctionEnd
1877 )";
1878
1879 CompileSuccessfully(spirv);
1880 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
1881 << getDiagnosticString();
1882 }
1883
TEST_F(ValidateDecorations,BlockCantAppearWithinABlockBad)1884 TEST_F(ValidateDecorations, BlockCantAppearWithinABlockBad) {
1885 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1886 std::string spirv = R"(
1887 OpCapability Shader
1888 OpMemoryModel Logical GLSL450
1889 OpEntryPoint Vertex %main "main"
1890 OpSource GLSL 450
1891 OpMemberDecorate %S 0 Offset 0
1892 OpMemberDecorate %S 1 Offset 16
1893 OpMemberDecorate %S2 0 Offset 0
1894 OpMemberDecorate %S2 1 Offset 12
1895 OpDecorate %S Block
1896 OpDecorate %S2 Block
1897 OpDecorate %B DescriptorSet 0
1898 OpDecorate %B Binding 0
1899 %void = OpTypeVoid
1900 %3 = OpTypeFunction %void
1901 %float = OpTypeFloat 32
1902 %S2 = OpTypeStruct %float %float
1903 %S = OpTypeStruct %float %S2
1904 %_ptr_Uniform_S = OpTypePointer Uniform %S
1905 %B = OpVariable %_ptr_Uniform_S Uniform
1906 %main = OpFunction %void None %3
1907 %5 = OpLabel
1908 OpReturn
1909 OpFunctionEnd
1910 )";
1911
1912 CompileSuccessfully(spirv);
1913 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1914 EXPECT_THAT(getDiagnosticString(),
1915 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1916 "another Block or BufferBlock."));
1917 }
1918
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABufferblockBad)1919 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABufferblockBad) {
1920 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1921 std::string spirv = R"(
1922 OpCapability Shader
1923 OpMemoryModel Logical GLSL450
1924 OpEntryPoint Vertex %main "main"
1925 OpSource GLSL 450
1926 OpMemberDecorate %S 0 Offset 0
1927 OpMemberDecorate %S 1 Offset 16
1928 OpMemberDecorate %S2 0 Offset 0
1929 OpMemberDecorate %S2 1 Offset 16
1930 OpMemberDecorate %S3 0 Offset 0
1931 OpMemberDecorate %S3 1 Offset 12
1932 OpDecorate %S BufferBlock
1933 OpDecorate %S3 BufferBlock
1934 OpDecorate %B DescriptorSet 0
1935 OpDecorate %B Binding 0
1936 %void = OpTypeVoid
1937 %3 = OpTypeFunction %void
1938 %float = OpTypeFloat 32
1939 %S3 = OpTypeStruct %float %float
1940 %S2 = OpTypeStruct %float %S3
1941 %S = OpTypeStruct %float %S2
1942 %_ptr_Uniform_S = OpTypePointer Uniform %S
1943 %B = OpVariable %_ptr_Uniform_S Uniform
1944 %main = OpFunction %void None %3
1945 %5 = OpLabel
1946 OpReturn
1947 OpFunctionEnd
1948 )";
1949
1950 CompileSuccessfully(spirv);
1951 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1952 EXPECT_THAT(getDiagnosticString(),
1953 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1954 "another Block or BufferBlock."));
1955 }
1956
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABlockBad)1957 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABlockBad) {
1958 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1959 std::string spirv = R"(
1960 OpCapability Shader
1961 OpMemoryModel Logical GLSL450
1962 OpEntryPoint Vertex %main "main"
1963 OpSource GLSL 450
1964 OpMemberDecorate %S 0 Offset 0
1965 OpMemberDecorate %S 1 Offset 16
1966 OpMemberDecorate %S2 0 Offset 0
1967 OpMemberDecorate %S2 1 Offset 16
1968 OpMemberDecorate %S3 0 Offset 0
1969 OpMemberDecorate %S3 1 Offset 12
1970 OpDecorate %S Block
1971 OpDecorate %S3 BufferBlock
1972 OpDecorate %B DescriptorSet 0
1973 OpDecorate %B Binding 0
1974 %void = OpTypeVoid
1975 %3 = OpTypeFunction %void
1976 %float = OpTypeFloat 32
1977 %S3 = OpTypeStruct %float %float
1978 %S2 = OpTypeStruct %float %S3
1979 %S = OpTypeStruct %float %S2
1980 %_ptr_Uniform_S = OpTypePointer Uniform %S
1981 %B = OpVariable %_ptr_Uniform_S Uniform
1982 %main = OpFunction %void None %3
1983 %5 = OpLabel
1984 OpReturn
1985 OpFunctionEnd
1986 )";
1987
1988 CompileSuccessfully(spirv);
1989 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1990 EXPECT_THAT(getDiagnosticString(),
1991 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1992 "another Block or BufferBlock."));
1993 }
1994
TEST_F(ValidateDecorations,BlockCantAppearWithinABufferblockBad)1995 TEST_F(ValidateDecorations, BlockCantAppearWithinABufferblockBad) {
1996 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1997 std::string spirv = R"(
1998 OpCapability Shader
1999 OpMemoryModel Logical GLSL450
2000 OpEntryPoint Vertex %main "main"
2001 OpSource GLSL 450
2002 OpMemberDecorate %S 0 Offset 0
2003 OpMemberDecorate %S 1 Offset 16
2004 OpMemberDecorate %S2 0 Offset 0
2005 OpMemberDecorate %S2 1 Offset 16
2006 OpMemberDecorate %S3 0 Offset 0
2007 OpMemberDecorate %S3 1 Offset 16
2008 OpMemberDecorate %S4 0 Offset 0
2009 OpMemberDecorate %S4 1 Offset 12
2010 OpDecorate %S BufferBlock
2011 OpDecorate %S4 Block
2012 OpDecorate %B DescriptorSet 0
2013 OpDecorate %B Binding 0
2014 %void = OpTypeVoid
2015 %3 = OpTypeFunction %void
2016 %float = OpTypeFloat 32
2017 %S4 = OpTypeStruct %float %float
2018 %S3 = OpTypeStruct %float %S4
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,BlockLayoutForbidsTightScalarVec3PackingBad)2036 TEST_F(ValidateDecorations, BlockLayoutForbidsTightScalarVec3PackingBad) {
2037 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
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 4
2045 OpDecorate %S Block
2046 OpDecorate %B DescriptorSet 0
2047 OpDecorate %B Binding 0
2048 %void = OpTypeVoid
2049 %3 = OpTypeFunction %void
2050 %float = OpTypeFloat 32
2051 %v3float = OpTypeVector %float 3
2052 %S = OpTypeStruct %float %v3float
2053 %_ptr_Uniform_S = OpTypePointer Uniform %S
2054 %B = OpVariable %_ptr_Uniform_S Uniform
2055 %main = OpFunction %void None %3
2056 %5 = OpLabel
2057 OpReturn
2058 OpFunctionEnd
2059 )";
2060
2061 CompileSuccessfully(spirv);
2062 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2063 EXPECT_THAT(
2064 getDiagnosticString(),
2065 HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
2066 "storage class must follow standard uniform buffer layout "
2067 "rules: member 1 at offset 4 is not aligned to 16"));
2068 }
2069
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood)2070 TEST_F(ValidateDecorations,
2071 BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood) {
2072 // Same as previous test, but with explicit option to relax block layout.
2073 std::string spirv = R"(
2074 OpCapability Shader
2075 OpMemoryModel Logical GLSL450
2076 OpEntryPoint Vertex %main "main"
2077 OpSource GLSL 450
2078 OpMemberDecorate %S 0 Offset 0
2079 OpMemberDecorate %S 1 Offset 4
2080 OpDecorate %S Block
2081 OpDecorate %B DescriptorSet 0
2082 OpDecorate %B Binding 0
2083 %void = OpTypeVoid
2084 %3 = OpTypeFunction %void
2085 %float = OpTypeFloat 32
2086 %v3float = OpTypeVector %float 3
2087 %S = OpTypeStruct %float %v3float
2088 %_ptr_Uniform_S = OpTypePointer Uniform %S
2089 %B = OpVariable %_ptr_Uniform_S Uniform
2090 %main = OpFunction %void None %3
2091 %5 = OpLabel
2092 OpReturn
2093 OpFunctionEnd
2094 )";
2095
2096 CompileSuccessfully(spirv);
2097 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2098 EXPECT_EQ(SPV_SUCCESS,
2099 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2100 EXPECT_THAT(getDiagnosticString(), Eq(""));
2101 }
2102
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad)2103 TEST_F(ValidateDecorations,
2104 BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad) {
2105 // Same as previous test, but with the vector not aligned to its scalar
2106 // element. Use offset 5 instead of a multiple of 4.
2107 std::string spirv = R"(
2108 OpCapability Shader
2109 OpMemoryModel Logical GLSL450
2110 OpEntryPoint Vertex %main "main"
2111 OpSource GLSL 450
2112 OpMemberDecorate %S 0 Offset 0
2113 OpMemberDecorate %S 1 Offset 5
2114 OpDecorate %S Block
2115 OpDecorate %B DescriptorSet 0
2116 OpDecorate %B Binding 0
2117 %void = OpTypeVoid
2118 %3 = OpTypeFunction %void
2119 %float = OpTypeFloat 32
2120 %v3float = OpTypeVector %float 3
2121 %S = OpTypeStruct %float %v3float
2122 %_ptr_Uniform_S = OpTypePointer Uniform %S
2123 %B = OpVariable %_ptr_Uniform_S Uniform
2124 %main = OpFunction %void None %3
2125 %5 = OpLabel
2126 OpReturn
2127 OpFunctionEnd
2128 )";
2129
2130 CompileSuccessfully(spirv);
2131 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2132 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2133 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2134 EXPECT_THAT(
2135 getDiagnosticString(),
2136 HasSubstr(
2137 "Structure id 2 decorated as Block for variable in Uniform storage "
2138 "class must follow relaxed uniform buffer layout rules: member 1 at "
2139 "offset 5 is not aligned to scalar element size 4"));
2140 }
2141
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good)2142 TEST_F(ValidateDecorations,
2143 BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good) {
2144 // Same as previous test, but with Vulkan 1.1. Vulkan 1.1 included
2145 // VK_KHR_relaxed_block_layout in core.
2146 std::string spirv = R"(
2147 OpCapability Shader
2148 OpMemoryModel Logical GLSL450
2149 OpEntryPoint Vertex %main "main"
2150 OpSource GLSL 450
2151 OpMemberDecorate %S 0 Offset 0
2152 OpMemberDecorate %S 1 Offset 4
2153 OpDecorate %S Block
2154 OpDecorate %B DescriptorSet 0
2155 OpDecorate %B Binding 0
2156 %void = OpTypeVoid
2157 %3 = OpTypeFunction %void
2158 %float = OpTypeFloat 32
2159 %v3float = OpTypeVector %float 3
2160 %S = OpTypeStruct %float %v3float
2161 %_ptr_Uniform_S = OpTypePointer Uniform %S
2162 %B = OpVariable %_ptr_Uniform_S Uniform
2163 %main = OpFunction %void None %3
2164 %5 = OpLabel
2165 OpReturn
2166 OpFunctionEnd
2167 )";
2168
2169 CompileSuccessfully(spirv);
2170 EXPECT_EQ(SPV_SUCCESS,
2171 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2172 EXPECT_THAT(getDiagnosticString(), Eq(""));
2173 }
2174
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood)2175 TEST_F(ValidateDecorations,
2176 BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood) {
2177 // Same as previous test, but with scalar block layout.
2178 std::string spirv = R"(
2179 OpCapability Shader
2180 OpMemoryModel Logical GLSL450
2181 OpEntryPoint Vertex %main "main"
2182 OpSource GLSL 450
2183 OpMemberDecorate %S 0 Offset 0
2184 OpMemberDecorate %S 1 Offset 4
2185 OpDecorate %S Block
2186 OpDecorate %B DescriptorSet 0
2187 OpDecorate %B Binding 0
2188 %void = OpTypeVoid
2189 %3 = OpTypeFunction %void
2190 %float = OpTypeFloat 32
2191 %v3float = OpTypeVector %float 3
2192 %S = OpTypeStruct %float %v3float
2193 %_ptr_Uniform_S = OpTypePointer Uniform %S
2194 %B = OpVariable %_ptr_Uniform_S Uniform
2195 %main = OpFunction %void None %3
2196 %5 = OpLabel
2197 OpReturn
2198 OpFunctionEnd
2199 )";
2200
2201 CompileSuccessfully(spirv);
2202 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2203 EXPECT_EQ(SPV_SUCCESS,
2204 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2205 EXPECT_THAT(getDiagnosticString(), Eq(""));
2206 }
2207
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood)2208 TEST_F(ValidateDecorations,
2209 BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood) {
2210 // The array at offset 4 is ok with scalar block layout.
2211 std::string spirv = R"(
2212 OpCapability Shader
2213 OpMemoryModel Logical GLSL450
2214 OpEntryPoint Vertex %main "main"
2215 OpSource GLSL 450
2216 OpMemberDecorate %S 0 Offset 0
2217 OpMemberDecorate %S 1 Offset 4
2218 OpDecorate %S Block
2219 OpDecorate %B DescriptorSet 0
2220 OpDecorate %B Binding 0
2221 OpDecorate %arr_float ArrayStride 4
2222 %void = OpTypeVoid
2223 %3 = OpTypeFunction %void
2224 %uint = OpTypeInt 32 0
2225 %uint_3 = OpConstant %uint 3
2226 %float = OpTypeFloat 32
2227 %arr_float = OpTypeArray %float %uint_3
2228 %S = OpTypeStruct %float %arr_float
2229 %_ptr_Uniform_S = OpTypePointer Uniform %S
2230 %B = OpVariable %_ptr_Uniform_S Uniform
2231 %main = OpFunction %void None %3
2232 %5 = OpLabel
2233 OpReturn
2234 OpFunctionEnd
2235 )";
2236
2237 CompileSuccessfully(spirv);
2238 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2239 EXPECT_EQ(SPV_SUCCESS,
2240 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2241 EXPECT_THAT(getDiagnosticString(), Eq(""));
2242 }
2243
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood)2244 TEST_F(ValidateDecorations,
2245 BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood) {
2246 // The array at offset 4 is ok with scalar block layout, even though
2247 // its elements are vec3.
2248 // This is the same as the previous case, but the array elements are vec3
2249 // instead of float.
2250 std::string spirv = R"(
2251 OpCapability Shader
2252 OpMemoryModel Logical GLSL450
2253 OpEntryPoint Vertex %main "main"
2254 OpSource GLSL 450
2255 OpMemberDecorate %S 0 Offset 0
2256 OpMemberDecorate %S 1 Offset 4
2257 OpDecorate %S Block
2258 OpDecorate %B DescriptorSet 0
2259 OpDecorate %B Binding 0
2260 OpDecorate %arr_vec3 ArrayStride 12
2261 %void = OpTypeVoid
2262 %3 = OpTypeFunction %void
2263 %uint = OpTypeInt 32 0
2264 %uint_3 = OpConstant %uint 3
2265 %float = OpTypeFloat 32
2266 %vec3 = OpTypeVector %float 3
2267 %arr_vec3 = OpTypeArray %vec3 %uint_3
2268 %S = OpTypeStruct %float %arr_vec3
2269 %_ptr_Uniform_S = OpTypePointer Uniform %S
2270 %B = OpVariable %_ptr_Uniform_S Uniform
2271 %main = OpFunction %void None %3
2272 %5 = OpLabel
2273 OpReturn
2274 OpFunctionEnd
2275 )";
2276
2277 CompileSuccessfully(spirv);
2278 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2279 EXPECT_EQ(SPV_SUCCESS,
2280 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2281 EXPECT_THAT(getDiagnosticString(), Eq(""));
2282 }
2283
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood)2284 TEST_F(ValidateDecorations,
2285 BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood) {
2286 // Scalar block layout permits the struct at offset 4, even though
2287 // it contains a vector with base alignment 8 and scalar alignment 4.
2288 std::string spirv = R"(
2289 OpCapability Shader
2290 OpMemoryModel Logical GLSL450
2291 OpEntryPoint Vertex %main "main"
2292 OpSource GLSL 450
2293 OpMemberDecorate %S 0 Offset 0
2294 OpMemberDecorate %S 1 Offset 4
2295 OpMemberDecorate %st 0 Offset 0
2296 OpMemberDecorate %st 1 Offset 8
2297 OpDecorate %S Block
2298 OpDecorate %B DescriptorSet 0
2299 OpDecorate %B Binding 0
2300 %void = OpTypeVoid
2301 %3 = OpTypeFunction %void
2302 %float = OpTypeFloat 32
2303 %vec2 = OpTypeVector %float 2
2304 %st = OpTypeStruct %vec2 %float
2305 %S = OpTypeStruct %float %st
2306 %_ptr_Uniform_S = OpTypePointer Uniform %S
2307 %B = OpVariable %_ptr_Uniform_S Uniform
2308 %main = OpFunction %void None %3
2309 %5 = OpLabel
2310 OpReturn
2311 OpFunctionEnd
2312 )";
2313
2314 CompileSuccessfully(spirv);
2315 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2316 EXPECT_EQ(SPV_SUCCESS,
2317 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2318 EXPECT_THAT(getDiagnosticString(), Eq(""));
2319 }
2320
TEST_F(ValidateDecorations,BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood)2321 TEST_F(
2322 ValidateDecorations,
2323 BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood) {
2324 // Scalar block layout permits fields in what would normally be the padding at
2325 // the end of a struct.
2326 std::string spirv = R"(
2327 OpCapability Shader
2328 OpCapability Float64
2329 OpMemoryModel Logical GLSL450
2330 OpEntryPoint Vertex %main "main"
2331 OpSource GLSL 450
2332 OpMemberDecorate %st 0 Offset 0
2333 OpMemberDecorate %st 1 Offset 8
2334 OpMemberDecorate %S 0 Offset 0
2335 OpMemberDecorate %S 1 Offset 12
2336 OpDecorate %S Block
2337 OpDecorate %B DescriptorSet 0
2338 OpDecorate %B Binding 0
2339 %void = OpTypeVoid
2340 %3 = OpTypeFunction %void
2341 %float = OpTypeFloat 32
2342 %double = OpTypeFloat 64
2343 %st = OpTypeStruct %double %float
2344 %S = OpTypeStruct %st %float
2345 %_ptr_Uniform_S = OpTypePointer Uniform %S
2346 %B = OpVariable %_ptr_Uniform_S Uniform
2347 %main = OpFunction %void None %3
2348 %5 = OpLabel
2349 OpReturn
2350 OpFunctionEnd
2351 )";
2352
2353 CompileSuccessfully(spirv);
2354 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2355 EXPECT_EQ(SPV_SUCCESS,
2356 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2357 EXPECT_THAT(getDiagnosticString(), Eq(""));
2358 }
2359
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood)2360 TEST_F(
2361 ValidateDecorations,
2362 BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood) {
2363 // Same as previous, but set relaxed block layout first. Scalar layout always
2364 // wins.
2365 std::string spirv = R"(
2366 OpCapability Shader
2367 OpMemoryModel Logical GLSL450
2368 OpEntryPoint Vertex %main "main"
2369 OpSource GLSL 450
2370 OpMemberDecorate %S 0 Offset 0
2371 OpMemberDecorate %S 1 Offset 4
2372 OpDecorate %S Block
2373 OpDecorate %B DescriptorSet 0
2374 OpDecorate %B Binding 0
2375 %void = OpTypeVoid
2376 %3 = OpTypeFunction %void
2377 %float = OpTypeFloat 32
2378 %vec4 = OpTypeVector %float 4
2379 %S = OpTypeStruct %float %vec4
2380 %_ptr_Uniform_S = OpTypePointer Uniform %S
2381 %B = OpVariable %_ptr_Uniform_S Uniform
2382 %main = OpFunction %void None %3
2383 %5 = OpLabel
2384 OpReturn
2385 OpFunctionEnd
2386 )";
2387
2388 CompileSuccessfully(spirv);
2389 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2390 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2391 EXPECT_EQ(SPV_SUCCESS,
2392 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2393 EXPECT_THAT(getDiagnosticString(), Eq(""));
2394 }
2395
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood)2396 TEST_F(
2397 ValidateDecorations,
2398 BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood) {
2399 // Same as previous, but set scalar block layout first. Scalar layout always
2400 // wins.
2401 std::string spirv = R"(
2402 OpCapability Shader
2403 OpMemoryModel Logical GLSL450
2404 OpEntryPoint Vertex %main "main"
2405 OpSource GLSL 450
2406 OpMemberDecorate %S 0 Offset 0
2407 OpMemberDecorate %S 1 Offset 4
2408 OpDecorate %S Block
2409 OpDecorate %B DescriptorSet 0
2410 OpDecorate %B Binding 0
2411 %void = OpTypeVoid
2412 %3 = OpTypeFunction %void
2413 %float = OpTypeFloat 32
2414 %vec4 = OpTypeVector %float 4
2415 %S = OpTypeStruct %float %vec4
2416 %_ptr_Uniform_S = OpTypePointer Uniform %S
2417 %B = OpVariable %_ptr_Uniform_S Uniform
2418 %main = OpFunction %void None %3
2419 %5 = OpLabel
2420 OpReturn
2421 OpFunctionEnd
2422 )";
2423
2424 CompileSuccessfully(spirv);
2425 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2426 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2427 EXPECT_EQ(SPV_SUCCESS,
2428 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2429 EXPECT_THAT(getDiagnosticString(), Eq(""));
2430 }
2431
TEST_F(ValidateDecorations,BufferBlock16bitStandardStorageBufferLayout)2432 TEST_F(ValidateDecorations, BufferBlock16bitStandardStorageBufferLayout) {
2433 std::string spirv = R"(
2434 OpCapability Shader
2435 OpCapability StorageUniform16
2436 OpExtension "SPV_KHR_16bit_storage"
2437 OpMemoryModel Logical GLSL450
2438 OpEntryPoint GLCompute %main "main"
2439 OpExecutionMode %main LocalSize 1 1 1
2440 OpDecorate %f32arr ArrayStride 4
2441 OpDecorate %f16arr ArrayStride 2
2442 OpMemberDecorate %SSBO32 0 Offset 0
2443 OpMemberDecorate %SSBO16 0 Offset 0
2444 OpDecorate %SSBO32 BufferBlock
2445 OpDecorate %SSBO16 BufferBlock
2446 %void = OpTypeVoid
2447 %voidf = OpTypeFunction %void
2448 %u32 = OpTypeInt 32 0
2449 %i32 = OpTypeInt 32 1
2450 %f32 = OpTypeFloat 32
2451 %uvec3 = OpTypeVector %u32 3
2452 %c_i32_32 = OpConstant %i32 32
2453 %c_i32_128 = OpConstant %i32 128
2454 %f32arr = OpTypeArray %f32 %c_i32_128
2455 %f16 = OpTypeFloat 16
2456 %f16arr = OpTypeArray %f16 %c_i32_128
2457 %SSBO32 = OpTypeStruct %f32arr
2458 %SSBO16 = OpTypeStruct %f16arr
2459 %_ptr_Uniform_SSBO32 = OpTypePointer Uniform %SSBO32
2460 %varSSBO32 = OpVariable %_ptr_Uniform_SSBO32 Uniform
2461 %_ptr_Uniform_SSBO16 = OpTypePointer Uniform %SSBO16
2462 %varSSBO16 = OpVariable %_ptr_Uniform_SSBO16 Uniform
2463 %main = OpFunction %void None %voidf
2464 %label = OpLabel
2465 OpReturn
2466 OpFunctionEnd
2467 )";
2468
2469 CompileSuccessfully(spirv);
2470 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
2471 }
2472
TEST_F(ValidateDecorations,BlockArrayExtendedAlignmentGood)2473 TEST_F(ValidateDecorations, BlockArrayExtendedAlignmentGood) {
2474 // For uniform buffer, Array base alignment is 16, and ArrayStride
2475 // must be a multiple of 16.
2476 std::string spirv = R"(
2477 OpCapability Shader
2478 OpMemoryModel Logical GLSL450
2479 OpEntryPoint Vertex %main "main"
2480 OpSource GLSL 450
2481 OpDecorate %_arr_float_uint_2 ArrayStride 16
2482 OpMemberDecorate %S 0 Offset 0
2483 OpMemberDecorate %S 1 Offset 16
2484 OpDecorate %S Block
2485 %void = OpTypeVoid
2486 %3 = OpTypeFunction %void
2487 %float = OpTypeFloat 32
2488 %v2float = OpTypeVector %float 2
2489 %uint = OpTypeInt 32 0
2490 %uint_2 = OpConstant %uint 2
2491 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2492 %S = OpTypeStruct %v2float %_arr_float_uint_2
2493 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2494 %u = OpVariable %_ptr_PushConstant_S PushConstant
2495 %main = OpFunction %void None %3
2496 %5 = OpLabel
2497 OpReturn
2498 OpFunctionEnd
2499 )";
2500
2501 CompileSuccessfully(spirv);
2502 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2503 << getDiagnosticString();
2504 }
2505
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentBad)2506 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentBad) {
2507 // For uniform buffer, Array base alignment is 16.
2508 std::string spirv = R"(
2509 OpCapability Shader
2510 OpMemoryModel Logical GLSL450
2511 OpEntryPoint Vertex %main "main"
2512 OpSource GLSL 450
2513 OpDecorate %_arr_float_uint_2 ArrayStride 16
2514 OpMemberDecorate %S 0 Offset 0
2515 OpMemberDecorate %S 1 Offset 8
2516 OpDecorate %S Block
2517 %void = OpTypeVoid
2518 %3 = OpTypeFunction %void
2519 %float = OpTypeFloat 32
2520 %v2float = OpTypeVector %float 2
2521 %uint = OpTypeInt 32 0
2522 %uint_2 = OpConstant %uint 2
2523 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2524 %S = OpTypeStruct %v2float %_arr_float_uint_2
2525 %_ptr_Uniform_S = OpTypePointer Uniform %S
2526 %u = OpVariable %_ptr_Uniform_S Uniform
2527 %main = OpFunction %void None %3
2528 %5 = OpLabel
2529 OpReturn
2530 OpFunctionEnd
2531 )";
2532
2533 CompileSuccessfully(spirv);
2534 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2535 EXPECT_THAT(
2536 getDiagnosticString(),
2537 HasSubstr(
2538 "Structure id 3 decorated as Block for variable in Uniform "
2539 "storage class must follow standard uniform buffer layout rules: "
2540 "member 1 at offset 8 is not aligned to 16"));
2541 }
2542
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithRelaxedLayoutStillBad)2543 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithRelaxedLayoutStillBad) {
2544 // For uniform buffer, Array base alignment is 16, and ArrayStride
2545 // must be a multiple of 16. This case uses relaxed block layout. Relaxed
2546 // layout only relaxes rules for vector alignment, not array alignment.
2547 std::string spirv = R"(
2548 OpCapability Shader
2549 OpMemoryModel Logical GLSL450
2550 OpEntryPoint Vertex %main "main"
2551 OpSource GLSL 450
2552 OpDecorate %_arr_float_uint_2 ArrayStride 16
2553 OpDecorate %u DescriptorSet 0
2554 OpDecorate %u Binding 0
2555 OpMemberDecorate %S 0 Offset 0
2556 OpMemberDecorate %S 1 Offset 8
2557 OpDecorate %S Block
2558 %void = OpTypeVoid
2559 %3 = OpTypeFunction %void
2560 %float = OpTypeFloat 32
2561 %v2float = OpTypeVector %float 2
2562 %uint = OpTypeInt 32 0
2563 %uint_2 = OpConstant %uint 2
2564 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2565 %S = OpTypeStruct %v2float %_arr_float_uint_2
2566 %_ptr_Uniform_S = OpTypePointer Uniform %S
2567 %u = OpVariable %_ptr_Uniform_S Uniform
2568 %main = OpFunction %void None %3
2569 %5 = OpLabel
2570 OpReturn
2571 OpFunctionEnd
2572 )";
2573
2574 CompileSuccessfully(spirv);
2575 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2576 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2577 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2578 EXPECT_THAT(
2579 getDiagnosticString(),
2580 HasSubstr(
2581 "Structure id 4 decorated as Block for variable in Uniform "
2582 "storage class must follow standard uniform buffer layout rules: "
2583 "member 1 at offset 8 is not aligned to 16"));
2584 }
2585
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithVulkan1_1StillBad)2586 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithVulkan1_1StillBad) {
2587 // Same as previous test, but with Vulkan 1.1, which includes
2588 // VK_KHR_relaxed_block_layout in core.
2589 std::string spirv = R"(
2590 OpCapability Shader
2591 OpMemoryModel Logical GLSL450
2592 OpEntryPoint Vertex %main "main"
2593 OpSource GLSL 450
2594 OpDecorate %_arr_float_uint_2 ArrayStride 16
2595 OpDecorate %u DescriptorSet 0
2596 OpDecorate %u Binding 0
2597 OpMemberDecorate %S 0 Offset 0
2598 OpMemberDecorate %S 1 Offset 8
2599 OpDecorate %S Block
2600 %void = OpTypeVoid
2601 %3 = OpTypeFunction %void
2602 %float = OpTypeFloat 32
2603 %v2float = OpTypeVector %float 2
2604 %uint = OpTypeInt 32 0
2605 %uint_2 = OpConstant %uint 2
2606 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2607 %S = OpTypeStruct %v2float %_arr_float_uint_2
2608 %_ptr_Uniform_S = OpTypePointer Uniform %S
2609 %u = OpVariable %_ptr_Uniform_S Uniform
2610 %main = OpFunction %void None %3
2611 %5 = OpLabel
2612 OpReturn
2613 OpFunctionEnd
2614 )";
2615
2616 CompileSuccessfully(spirv);
2617 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2618 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2619 EXPECT_THAT(
2620 getDiagnosticString(),
2621 HasSubstr(
2622 "Structure id 4 decorated as Block for variable in Uniform "
2623 "storage class must follow relaxed uniform buffer layout rules: "
2624 "member 1 at offset 8 is not aligned to 16"));
2625 }
2626
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithBlockStandardLayoutGood)2627 TEST_F(ValidateDecorations,
2628 BlockArrayBaseAlignmentWithBlockStandardLayoutGood) {
2629 // Same as previous test, but with VK_KHR_uniform_buffer_standard_layout
2630 std::string spirv = R"(
2631 OpCapability Shader
2632 OpMemoryModel Logical GLSL450
2633 OpEntryPoint Vertex %main "main"
2634 OpSource GLSL 450
2635 OpDecorate %_arr_float_uint_2 ArrayStride 16
2636 OpDecorate %u DescriptorSet 0
2637 OpDecorate %u Binding 0
2638 OpMemberDecorate %S 0 Offset 0
2639 OpMemberDecorate %S 1 Offset 8
2640 OpDecorate %S Block
2641 %void = OpTypeVoid
2642 %3 = OpTypeFunction %void
2643 %float = OpTypeFloat 32
2644 %v2float = OpTypeVector %float 2
2645 %uint = OpTypeInt 32 0
2646 %uint_2 = OpConstant %uint 2
2647 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2648 %S = OpTypeStruct %v2float %_arr_float_uint_2
2649 %_ptr_Uniform_S = OpTypePointer Uniform %S
2650 %u = OpVariable %_ptr_Uniform_S Uniform
2651 %main = OpFunction %void None %3
2652 %5 = OpLabel
2653 OpReturn
2654 OpFunctionEnd
2655 )";
2656
2657 CompileSuccessfully(spirv);
2658 spvValidatorOptionsSetUniformBufferStandardLayout(getValidatorOptions(),
2659 true);
2660 EXPECT_EQ(SPV_SUCCESS,
2661 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2662 EXPECT_THAT(getDiagnosticString(), Eq(""));
2663 }
2664
TEST_F(ValidateDecorations,VulkanBufferBlockOnStorageBufferBad)2665 TEST_F(ValidateDecorations, VulkanBufferBlockOnStorageBufferBad) {
2666 std::string spirv = R"(
2667 OpCapability Shader
2668 OpExtension "SPV_KHR_storage_buffer_storage_class"
2669 OpMemoryModel Logical GLSL450
2670 OpEntryPoint Fragment %1 "main"
2671 OpExecutionMode %1 OriginUpperLeft
2672
2673 OpDecorate %struct BufferBlock
2674
2675 %void = OpTypeVoid
2676 %voidfn = OpTypeFunction %void
2677 %float = OpTypeFloat 32
2678 %struct = OpTypeStruct %float
2679 %ptr = OpTypePointer StorageBuffer %struct
2680 %var = OpVariable %ptr StorageBuffer
2681
2682 %1 = OpFunction %void None %voidfn
2683 %label = OpLabel
2684 OpReturn
2685 OpFunctionEnd
2686 )";
2687
2688 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2689 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2690 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2691 EXPECT_THAT(getDiagnosticString(),
2692 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
2693 EXPECT_THAT(getDiagnosticString(),
2694 HasSubstr("In Vulkan, BufferBlock is disallowed on variables in "
2695 "the StorageBuffer storage class"));
2696 }
2697
TEST_F(ValidateDecorations,PushConstantArrayBaseAlignmentGood)2698 TEST_F(ValidateDecorations, PushConstantArrayBaseAlignmentGood) {
2699 // Tests https://github.com/KhronosGroup/SPIRV-Tools/issues/1664
2700 // From GLSL vertex shader:
2701 // #version 450
2702 // layout(push_constant) uniform S { vec2 v; float arr[2]; } u;
2703 // void main() { }
2704
2705 std::string spirv = R"(
2706 OpCapability Shader
2707 OpMemoryModel Logical GLSL450
2708 OpEntryPoint Vertex %main "main"
2709 OpSource GLSL 450
2710 OpDecorate %_arr_float_uint_2 ArrayStride 4
2711 OpMemberDecorate %S 0 Offset 0
2712 OpMemberDecorate %S 1 Offset 8
2713 OpDecorate %S Block
2714 %void = OpTypeVoid
2715 %3 = OpTypeFunction %void
2716 %float = OpTypeFloat 32
2717 %v2float = OpTypeVector %float 2
2718 %uint = OpTypeInt 32 0
2719 %uint_2 = OpConstant %uint 2
2720 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2721 %S = OpTypeStruct %v2float %_arr_float_uint_2
2722 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2723 %u = OpVariable %_ptr_PushConstant_S PushConstant
2724 %main = OpFunction %void None %3
2725 %5 = OpLabel
2726 OpReturn
2727 OpFunctionEnd
2728 )";
2729
2730 CompileSuccessfully(spirv);
2731 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2732 << getDiagnosticString();
2733 }
2734
TEST_F(ValidateDecorations,PushConstantArrayBadAlignmentBad)2735 TEST_F(ValidateDecorations, PushConstantArrayBadAlignmentBad) {
2736 // Like the previous test, but with offset 7 instead of 8.
2737 std::string spirv = R"(
2738 OpCapability Shader
2739 OpMemoryModel Logical GLSL450
2740 OpEntryPoint Vertex %main "main"
2741 OpSource GLSL 450
2742 OpDecorate %_arr_float_uint_2 ArrayStride 4
2743 OpMemberDecorate %S 0 Offset 0
2744 OpMemberDecorate %S 1 Offset 7
2745 OpDecorate %S Block
2746 %void = OpTypeVoid
2747 %3 = OpTypeFunction %void
2748 %float = OpTypeFloat 32
2749 %v2float = OpTypeVector %float 2
2750 %uint = OpTypeInt 32 0
2751 %uint_2 = OpConstant %uint 2
2752 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2753 %S = OpTypeStruct %v2float %_arr_float_uint_2
2754 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2755 %u = OpVariable %_ptr_PushConstant_S PushConstant
2756 %main = OpFunction %void None %3
2757 %5 = OpLabel
2758 OpReturn
2759 OpFunctionEnd
2760 )";
2761
2762 CompileSuccessfully(spirv);
2763 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2764 EXPECT_THAT(
2765 getDiagnosticString(),
2766 HasSubstr(
2767 "Structure id 3 decorated as Block for variable in PushConstant "
2768 "storage class must follow standard storage buffer layout rules: "
2769 "member 1 at offset 7 is not aligned to 4"));
2770 }
2771
TEST_F(ValidateDecorations,PushConstantLayoutPermitsTightVec3ScalarPackingGood)2772 TEST_F(ValidateDecorations,
2773 PushConstantLayoutPermitsTightVec3ScalarPackingGood) {
2774 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2775 std::string spirv = R"(
2776 OpCapability Shader
2777 OpMemoryModel Logical GLSL450
2778 OpEntryPoint Vertex %main "main"
2779 OpSource GLSL 450
2780 OpMemberDecorate %S 0 Offset 0
2781 OpMemberDecorate %S 1 Offset 12
2782 OpDecorate %S Block
2783 %void = OpTypeVoid
2784 %3 = OpTypeFunction %void
2785 %float = OpTypeFloat 32
2786 %v3float = OpTypeVector %float 3
2787 %S = OpTypeStruct %v3float %float
2788 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2789 %B = OpVariable %_ptr_PushConstant_S PushConstant
2790 %main = OpFunction %void None %3
2791 %5 = OpLabel
2792 OpReturn
2793 OpFunctionEnd
2794 )";
2795
2796 CompileSuccessfully(spirv);
2797 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2798 << getDiagnosticString();
2799 }
2800
TEST_F(ValidateDecorations,PushConstantLayoutForbidsTightScalarVec3PackingBad)2801 TEST_F(ValidateDecorations,
2802 PushConstantLayoutForbidsTightScalarVec3PackingBad) {
2803 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2804 std::string spirv = R"(
2805 OpCapability Shader
2806 OpMemoryModel Logical GLSL450
2807 OpEntryPoint Vertex %main "main"
2808 OpSource GLSL 450
2809 OpMemberDecorate %S 0 Offset 0
2810 OpMemberDecorate %S 1 Offset 4
2811 OpDecorate %S Block
2812 %void = OpTypeVoid
2813 %3 = OpTypeFunction %void
2814 %float = OpTypeFloat 32
2815 %v3float = OpTypeVector %float 3
2816 %S = OpTypeStruct %float %v3float
2817 %_ptr_Uniform_S = OpTypePointer PushConstant %S
2818 %B = OpVariable %_ptr_Uniform_S PushConstant
2819 %main = OpFunction %void None %3
2820 %5 = OpLabel
2821 OpReturn
2822 OpFunctionEnd
2823 )";
2824
2825 CompileSuccessfully(spirv);
2826 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2827 EXPECT_THAT(
2828 getDiagnosticString(),
2829 HasSubstr(
2830 "Structure id 2 decorated as Block for variable in PushConstant "
2831 "storage class must follow standard storage buffer layout "
2832 "rules: member 1 at offset 4 is not aligned to 16"));
2833 }
2834
TEST_F(ValidateDecorations,PushConstantMissingBlockGood)2835 TEST_F(ValidateDecorations, PushConstantMissingBlockGood) {
2836 std::string spirv = R"(
2837 OpCapability Shader
2838 OpMemoryModel Logical GLSL450
2839 OpEntryPoint Fragment %1 "main"
2840 OpExecutionMode %1 OriginUpperLeft
2841
2842 OpMemberDecorate %struct 0 Offset 0
2843
2844 %void = OpTypeVoid
2845 %voidfn = OpTypeFunction %void
2846 %float = OpTypeFloat 32
2847 %struct = OpTypeStruct %float
2848 %ptr = OpTypePointer PushConstant %struct
2849 %pc = OpVariable %ptr PushConstant
2850
2851 %1 = OpFunction %void None %voidfn
2852 %label = OpLabel
2853 OpReturn
2854 OpFunctionEnd
2855 )";
2856
2857 CompileSuccessfully(spirv);
2858 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2859 << getDiagnosticString();
2860 }
2861
TEST_F(ValidateDecorations,VulkanPushConstantMissingBlockBad)2862 TEST_F(ValidateDecorations, VulkanPushConstantMissingBlockBad) {
2863 std::string spirv = R"(
2864 OpCapability Shader
2865 OpMemoryModel Logical GLSL450
2866 OpEntryPoint Fragment %1 "main"
2867 OpExecutionMode %1 OriginUpperLeft
2868
2869 OpMemberDecorate %struct 0 Offset 0
2870
2871 %void = OpTypeVoid
2872 %voidfn = OpTypeFunction %void
2873 %float = OpTypeFloat 32
2874 %struct = OpTypeStruct %float
2875 %ptr = OpTypePointer PushConstant %struct
2876 %pc = OpVariable %ptr PushConstant
2877
2878 %1 = OpFunction %void None %voidfn
2879 %label = OpLabel
2880 OpReturn
2881 OpFunctionEnd
2882 )";
2883
2884 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2885 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2886 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2887 EXPECT_THAT(getDiagnosticString(),
2888 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
2889 EXPECT_THAT(getDiagnosticString(),
2890 HasSubstr("PushConstant id '2' is missing Block decoration.\n"
2891 "From Vulkan spec:\n"
2892 "Such variables must be identified with a Block "
2893 "decoration"));
2894 }
2895
TEST_F(ValidateDecorations,MultiplePushConstantsSingleEntryPointGood)2896 TEST_F(ValidateDecorations, MultiplePushConstantsSingleEntryPointGood) {
2897 std::string spirv = R"(
2898 OpCapability Shader
2899 OpMemoryModel Logical GLSL450
2900 OpEntryPoint Fragment %1 "main"
2901 OpExecutionMode %1 OriginUpperLeft
2902
2903 OpDecorate %struct Block
2904 OpMemberDecorate %struct 0 Offset 0
2905
2906 %void = OpTypeVoid
2907 %voidfn = OpTypeFunction %void
2908 %float = OpTypeFloat 32
2909 %int = OpTypeInt 32 0
2910 %int_0 = OpConstant %int 0
2911 %struct = OpTypeStruct %float
2912 %ptr = OpTypePointer PushConstant %struct
2913 %ptr_float = OpTypePointer PushConstant %float
2914 %pc1 = OpVariable %ptr PushConstant
2915 %pc2 = OpVariable %ptr PushConstant
2916
2917 %1 = OpFunction %void None %voidfn
2918 %label = OpLabel
2919 %2 = OpAccessChain %ptr_float %pc1 %int_0
2920 %3 = OpLoad %float %2
2921 %4 = OpAccessChain %ptr_float %pc2 %int_0
2922 %5 = OpLoad %float %4
2923 OpReturn
2924 OpFunctionEnd
2925 )";
2926
2927 CompileSuccessfully(spirv);
2928 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2929 << getDiagnosticString();
2930 }
2931
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointGood)2932 TEST_F(ValidateDecorations,
2933 VulkanMultiplePushConstantsDifferentEntryPointGood) {
2934 std::string spirv = R"(
2935 OpCapability Shader
2936 OpMemoryModel Logical GLSL450
2937 OpEntryPoint Vertex %1 "func1"
2938 OpEntryPoint Fragment %2 "func2"
2939 OpExecutionMode %2 OriginUpperLeft
2940
2941 OpDecorate %struct Block
2942 OpMemberDecorate %struct 0 Offset 0
2943
2944 %void = OpTypeVoid
2945 %voidfn = OpTypeFunction %void
2946 %float = OpTypeFloat 32
2947 %int = OpTypeInt 32 0
2948 %int_0 = OpConstant %int 0
2949 %struct = OpTypeStruct %float
2950 %ptr = OpTypePointer PushConstant %struct
2951 %ptr_float = OpTypePointer PushConstant %float
2952 %pc1 = OpVariable %ptr PushConstant
2953 %pc2 = OpVariable %ptr PushConstant
2954
2955 %1 = OpFunction %void None %voidfn
2956 %label1 = OpLabel
2957 %3 = OpAccessChain %ptr_float %pc1 %int_0
2958 %4 = OpLoad %float %3
2959 OpReturn
2960 OpFunctionEnd
2961
2962 %2 = OpFunction %void None %voidfn
2963 %label2 = OpLabel
2964 %5 = OpAccessChain %ptr_float %pc2 %int_0
2965 %6 = OpLoad %float %5
2966 OpReturn
2967 OpFunctionEnd
2968 )";
2969
2970 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2971 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
2972 << getDiagnosticString();
2973 }
2974
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsUnusedSingleEntryPointGood)2975 TEST_F(ValidateDecorations,
2976 VulkanMultiplePushConstantsUnusedSingleEntryPointGood) {
2977 std::string spirv = R"(
2978 OpCapability Shader
2979 OpMemoryModel Logical GLSL450
2980 OpEntryPoint Fragment %1 "main"
2981 OpExecutionMode %1 OriginUpperLeft
2982
2983 OpDecorate %struct Block
2984 OpMemberDecorate %struct 0 Offset 0
2985
2986 %void = OpTypeVoid
2987 %voidfn = OpTypeFunction %void
2988 %float = OpTypeFloat 32
2989 %int = OpTypeInt 32 0
2990 %int_0 = OpConstant %int 0
2991 %struct = OpTypeStruct %float
2992 %ptr = OpTypePointer PushConstant %struct
2993 %ptr_float = OpTypePointer PushConstant %float
2994 %pc1 = OpVariable %ptr PushConstant
2995 %pc2 = OpVariable %ptr PushConstant
2996
2997 %1 = OpFunction %void None %voidfn
2998 %label = OpLabel
2999 OpReturn
3000 OpFunctionEnd
3001 )";
3002
3003 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3004 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3005 << getDiagnosticString();
3006 }
3007
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointBad)3008 TEST_F(ValidateDecorations, VulkanMultiplePushConstantsSingleEntryPointBad) {
3009 std::string spirv = R"(
3010 OpCapability Shader
3011 OpMemoryModel Logical GLSL450
3012 OpEntryPoint Fragment %1 "main"
3013 OpExecutionMode %1 OriginUpperLeft
3014
3015 OpDecorate %struct Block
3016 OpMemberDecorate %struct 0 Offset 0
3017
3018 %void = OpTypeVoid
3019 %voidfn = OpTypeFunction %void
3020 %float = OpTypeFloat 32
3021 %int = OpTypeInt 32 0
3022 %int_0 = OpConstant %int 0
3023 %struct = OpTypeStruct %float
3024 %ptr = OpTypePointer PushConstant %struct
3025 %ptr_float = OpTypePointer PushConstant %float
3026 %pc1 = OpVariable %ptr PushConstant
3027 %pc2 = OpVariable %ptr PushConstant
3028
3029 %1 = OpFunction %void None %voidfn
3030 %label = OpLabel
3031 %2 = OpAccessChain %ptr_float %pc1 %int_0
3032 %3 = OpLoad %float %2
3033 %4 = OpAccessChain %ptr_float %pc2 %int_0
3034 %5 = OpLoad %float %4
3035 OpReturn
3036 OpFunctionEnd
3037 )";
3038
3039 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3040 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3041 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3042 EXPECT_THAT(getDiagnosticString(),
3043 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-06674"));
3044 EXPECT_THAT(
3045 getDiagnosticString(),
3046 HasSubstr(
3047 "Entry point id '1' uses more than one PushConstant interface.\n"
3048 "From Vulkan spec:\n"
3049 "There must be no more than one push constant block "
3050 "statically used per shader entry point."));
3051 }
3052
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood)3053 TEST_F(ValidateDecorations,
3054 VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood) {
3055 std::string spirv = R"(
3056 OpCapability Shader
3057 OpMemoryModel Logical GLSL450
3058 OpEntryPoint Vertex %1 "func1"
3059 OpEntryPoint Fragment %2 "func2"
3060 OpExecutionMode %2 OriginUpperLeft
3061
3062 OpDecorate %struct Block
3063 OpMemberDecorate %struct 0 Offset 0
3064
3065 %void = OpTypeVoid
3066 %voidfn = OpTypeFunction %void
3067 %float = OpTypeFloat 32
3068 %int = OpTypeInt 32 0
3069 %int_0 = OpConstant %int 0
3070 %struct = OpTypeStruct %float
3071 %ptr = OpTypePointer PushConstant %struct
3072 %ptr_float = OpTypePointer PushConstant %float
3073 %pc1 = OpVariable %ptr PushConstant
3074 %pc2 = OpVariable %ptr PushConstant
3075
3076 %sub1 = OpFunction %void None %voidfn
3077 %label_sub1 = OpLabel
3078 %3 = OpAccessChain %ptr_float %pc1 %int_0
3079 %4 = OpLoad %float %3
3080 OpReturn
3081 OpFunctionEnd
3082
3083 %sub2 = OpFunction %void None %voidfn
3084 %label_sub2 = OpLabel
3085 %5 = OpAccessChain %ptr_float %pc2 %int_0
3086 %6 = OpLoad %float %5
3087 OpReturn
3088 OpFunctionEnd
3089
3090 %1 = OpFunction %void None %voidfn
3091 %label1 = OpLabel
3092 %call1 = OpFunctionCall %void %sub1
3093 OpReturn
3094 OpFunctionEnd
3095
3096 %2 = OpFunction %void None %voidfn
3097 %label2 = OpLabel
3098 %call2 = OpFunctionCall %void %sub2
3099 OpReturn
3100 OpFunctionEnd
3101 )";
3102
3103 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3104 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3105 << getDiagnosticString();
3106 }
3107
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad)3108 TEST_F(ValidateDecorations,
3109 VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad) {
3110 std::string spirv = R"(
3111 OpCapability Shader
3112 OpMemoryModel Logical GLSL450
3113 OpEntryPoint Fragment %1 "main"
3114 OpExecutionMode %1 OriginUpperLeft
3115
3116 OpDecorate %struct Block
3117 OpMemberDecorate %struct 0 Offset 0
3118
3119 %void = OpTypeVoid
3120 %voidfn = OpTypeFunction %void
3121 %float = OpTypeFloat 32
3122 %int = OpTypeInt 32 0
3123 %int_0 = OpConstant %int 0
3124 %struct = OpTypeStruct %float
3125 %ptr = OpTypePointer PushConstant %struct
3126 %ptr_float = OpTypePointer PushConstant %float
3127 %pc1 = OpVariable %ptr PushConstant
3128 %pc2 = OpVariable %ptr PushConstant
3129
3130 %sub1 = OpFunction %void None %voidfn
3131 %label_sub1 = OpLabel
3132 %3 = OpAccessChain %ptr_float %pc1 %int_0
3133 %4 = OpLoad %float %3
3134 OpReturn
3135 OpFunctionEnd
3136
3137 %sub2 = OpFunction %void None %voidfn
3138 %label_sub2 = OpLabel
3139 %5 = OpAccessChain %ptr_float %pc2 %int_0
3140 %6 = OpLoad %float %5
3141 OpReturn
3142 OpFunctionEnd
3143
3144 %1 = OpFunction %void None %voidfn
3145 %label1 = OpLabel
3146 %call1 = OpFunctionCall %void %sub1
3147 %call2 = OpFunctionCall %void %sub2
3148 OpReturn
3149 OpFunctionEnd
3150 )";
3151
3152 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3153 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3154 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3155 EXPECT_THAT(getDiagnosticString(),
3156 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-06674"));
3157 EXPECT_THAT(
3158 getDiagnosticString(),
3159 HasSubstr(
3160 "Entry point id '1' uses more than one PushConstant interface.\n"
3161 "From Vulkan spec:\n"
3162 "There must be no more than one push constant block "
3163 "statically used per shader entry point."));
3164 }
3165
TEST_F(ValidateDecorations,VulkanUniformMissingDescriptorSetBad)3166 TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
3167 std::string spirv = R"(
3168 OpCapability Shader
3169 OpMemoryModel Logical GLSL450
3170 OpEntryPoint Fragment %1 "main"
3171 OpExecutionMode %1 OriginUpperLeft
3172
3173 OpDecorate %struct Block
3174 OpMemberDecorate %struct 0 Offset 0
3175 OpDecorate %var Binding 0
3176
3177 %void = OpTypeVoid
3178 %voidfn = OpTypeFunction %void
3179 %float = OpTypeFloat 32
3180 %struct = OpTypeStruct %float
3181 %ptr = OpTypePointer Uniform %struct
3182 %ptr_float = OpTypePointer Uniform %float
3183 %var = OpVariable %ptr Uniform
3184 %int = OpTypeInt 32 0
3185 %int_0 = OpConstant %int 0
3186
3187 %1 = OpFunction %void None %voidfn
3188 %label = OpLabel
3189 %2 = OpAccessChain %ptr_float %var %int_0
3190 %3 = OpLoad %float %2
3191 OpReturn
3192 OpFunctionEnd
3193 )";
3194
3195 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3196 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3197 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3198 EXPECT_THAT(getDiagnosticString(),
3199 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3200 EXPECT_THAT(getDiagnosticString(),
3201 HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n"
3202 "From Vulkan spec:\n"
3203 "These variables must have DescriptorSet and Binding "
3204 "decorations specified"));
3205 }
3206
TEST_F(ValidateDecorations,VulkanUniformMissingBindingBad)3207 TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) {
3208 std::string spirv = R"(
3209 OpCapability Shader
3210 OpMemoryModel Logical GLSL450
3211 OpEntryPoint Fragment %1 "main"
3212 OpExecutionMode %1 OriginUpperLeft
3213
3214 OpDecorate %struct Block
3215 OpMemberDecorate %struct 0 Offset 0
3216 OpDecorate %var DescriptorSet 0
3217
3218 %void = OpTypeVoid
3219 %voidfn = OpTypeFunction %void
3220 %float = OpTypeFloat 32
3221 %struct = OpTypeStruct %float
3222 %ptr = OpTypePointer Uniform %struct
3223 %ptr_float = OpTypePointer Uniform %float
3224 %var = OpVariable %ptr Uniform
3225 %int = OpTypeInt 32 0
3226 %int_0 = OpConstant %int 0
3227
3228 %1 = OpFunction %void None %voidfn
3229 %label = OpLabel
3230 %2 = OpAccessChain %ptr_float %var %int_0
3231 %3 = OpLoad %float %2
3232 OpReturn
3233 OpFunctionEnd
3234 )";
3235
3236 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3237 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3238 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3239 EXPECT_THAT(getDiagnosticString(),
3240 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3241 EXPECT_THAT(getDiagnosticString(),
3242 HasSubstr("Uniform id '3' is missing Binding decoration.\n"
3243 "From Vulkan spec:\n"
3244 "These variables must have DescriptorSet and Binding "
3245 "decorations specified"));
3246 }
3247
TEST_F(ValidateDecorations,VulkanUniformConstantMissingDescriptorSetBad)3248 TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) {
3249 std::string spirv = R"(
3250 OpCapability Shader
3251 OpMemoryModel Logical GLSL450
3252 OpEntryPoint Fragment %1 "main"
3253 OpExecutionMode %1 OriginUpperLeft
3254
3255 OpDecorate %var Binding 0
3256
3257 %void = OpTypeVoid
3258 %voidfn = OpTypeFunction %void
3259 %sampler = OpTypeSampler
3260 %ptr = OpTypePointer UniformConstant %sampler
3261 %var = OpVariable %ptr UniformConstant
3262
3263 %1 = OpFunction %void None %voidfn
3264 %label = OpLabel
3265 %2 = OpLoad %sampler %var
3266 OpReturn
3267 OpFunctionEnd
3268 )";
3269
3270 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3271 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3272 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3273 EXPECT_THAT(getDiagnosticString(),
3274 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3275 EXPECT_THAT(
3276 getDiagnosticString(),
3277 HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n"
3278 "From Vulkan spec:\n"
3279 "These variables must have DescriptorSet and Binding "
3280 "decorations specified"));
3281 }
3282
TEST_F(ValidateDecorations,VulkanUniformConstantMissingBindingBad)3283 TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) {
3284 std::string spirv = R"(
3285 OpCapability Shader
3286 OpMemoryModel Logical GLSL450
3287 OpEntryPoint Fragment %1 "main"
3288 OpExecutionMode %1 OriginUpperLeft
3289
3290 OpDecorate %var DescriptorSet 0
3291
3292 %void = OpTypeVoid
3293 %voidfn = OpTypeFunction %void
3294 %sampler = OpTypeSampler
3295 %ptr = OpTypePointer UniformConstant %sampler
3296 %var = OpVariable %ptr UniformConstant
3297
3298 %1 = OpFunction %void None %voidfn
3299 %label = OpLabel
3300 %2 = OpLoad %sampler %var
3301 OpReturn
3302 OpFunctionEnd
3303 )";
3304
3305 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3306 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3307 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3308 EXPECT_THAT(getDiagnosticString(),
3309 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3310 EXPECT_THAT(
3311 getDiagnosticString(),
3312 HasSubstr("UniformConstant id '2' is missing Binding decoration.\n"
3313 "From Vulkan spec:\n"
3314 "These variables must have DescriptorSet and Binding "
3315 "decorations specified"));
3316 }
3317
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetBad)3318 TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) {
3319 std::string spirv = R"(
3320 OpCapability Shader
3321 OpExtension "SPV_KHR_storage_buffer_storage_class"
3322 OpMemoryModel Logical GLSL450
3323 OpEntryPoint Fragment %1 "main"
3324 OpExecutionMode %1 OriginUpperLeft
3325
3326 OpDecorate %struct Block
3327 OpDecorate %var Binding 0
3328
3329 %void = OpTypeVoid
3330 %voidfn = OpTypeFunction %void
3331 %float = OpTypeFloat 32
3332 %struct = OpTypeStruct %float
3333 %ptr = OpTypePointer StorageBuffer %struct
3334 %var = OpVariable %ptr StorageBuffer
3335 %ptr_float = OpTypePointer StorageBuffer %float
3336 %int = OpTypeInt 32 0
3337 %int_0 = OpConstant %int 0
3338
3339 %1 = OpFunction %void None %voidfn
3340 %label = OpLabel
3341 %2 = OpAccessChain %ptr_float %var %int_0
3342 %3 = OpLoad %float %2
3343 OpReturn
3344 OpFunctionEnd
3345 )";
3346
3347 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3348 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3349 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3350 EXPECT_THAT(getDiagnosticString(),
3351 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3352 EXPECT_THAT(
3353 getDiagnosticString(),
3354 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3355 "From Vulkan spec:\n"
3356 "These variables must have DescriptorSet and Binding "
3357 "decorations specified"));
3358 }
3359
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBindingBad)3360 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) {
3361 std::string spirv = R"(
3362 OpCapability Shader
3363 OpExtension "SPV_KHR_storage_buffer_storage_class"
3364 OpMemoryModel Logical GLSL450
3365 OpEntryPoint Fragment %1 "main"
3366 OpExecutionMode %1 OriginUpperLeft
3367
3368 OpDecorate %struct Block
3369 OpDecorate %var DescriptorSet 0
3370
3371 %void = OpTypeVoid
3372 %voidfn = OpTypeFunction %void
3373 %float = OpTypeFloat 32
3374 %struct = OpTypeStruct %float
3375 %ptr = OpTypePointer StorageBuffer %struct
3376 %var = OpVariable %ptr StorageBuffer
3377 %ptr_float = OpTypePointer StorageBuffer %float
3378 %int = OpTypeInt 32 0
3379 %int_0 = OpConstant %int 0
3380
3381 %1 = OpFunction %void None %voidfn
3382 %label = OpLabel
3383 %2 = OpAccessChain %ptr_float %var %int_0
3384 %3 = OpLoad %float %2
3385 OpReturn
3386 OpFunctionEnd
3387 )";
3388
3389 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3390 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3391 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3392 EXPECT_THAT(getDiagnosticString(),
3393 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3394 EXPECT_THAT(getDiagnosticString(),
3395 HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n"
3396 "From Vulkan spec:\n"
3397 "These variables must have DescriptorSet and Binding "
3398 "decorations specified"));
3399 }
3400
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetSubFunctionBad)3401 TEST_F(ValidateDecorations,
3402 VulkanStorageBufferMissingDescriptorSetSubFunctionBad) {
3403 std::string spirv = R"(
3404 OpCapability Shader
3405 OpExtension "SPV_KHR_storage_buffer_storage_class"
3406 OpMemoryModel Logical GLSL450
3407 OpEntryPoint Fragment %1 "main"
3408 OpExecutionMode %1 OriginUpperLeft
3409
3410 OpDecorate %struct Block
3411 OpDecorate %var Binding 0
3412
3413 %void = OpTypeVoid
3414 %voidfn = OpTypeFunction %void
3415 %float = OpTypeFloat 32
3416 %struct = OpTypeStruct %float
3417 %ptr = OpTypePointer StorageBuffer %struct
3418 %var = OpVariable %ptr StorageBuffer
3419 %ptr_float = OpTypePointer StorageBuffer %float
3420 %int = OpTypeInt 32 0
3421 %int_0 = OpConstant %int 0
3422
3423 %1 = OpFunction %void None %voidfn
3424 %label = OpLabel
3425 %call = OpFunctionCall %void %2
3426 OpReturn
3427 OpFunctionEnd
3428 %2 = OpFunction %void None %voidfn
3429 %label2 = OpLabel
3430 %3 = OpAccessChain %ptr_float %var %int_0
3431 %4 = OpLoad %float %3
3432 OpReturn
3433 OpFunctionEnd
3434 )";
3435
3436 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3437 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3438 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3439 EXPECT_THAT(getDiagnosticString(),
3440 AnyVUID("VUID-StandaloneSpirv-UniformConstant-06677"));
3441 EXPECT_THAT(
3442 getDiagnosticString(),
3443 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3444 "From Vulkan spec:\n"
3445 "These variables must have DescriptorSet and Binding "
3446 "decorations specified"));
3447 }
3448
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorAndBindingUnusedGood)3449 TEST_F(ValidateDecorations,
3450 VulkanStorageBufferMissingDescriptorAndBindingUnusedGood) {
3451 std::string spirv = R"(
3452 OpCapability Shader
3453 OpExtension "SPV_KHR_storage_buffer_storage_class"
3454 OpMemoryModel Logical GLSL450
3455 OpEntryPoint Fragment %1 "main"
3456 OpExecutionMode %1 OriginUpperLeft
3457 OpDecorate %struct Block
3458 OpMemberDecorate %struct 0 Offset 0
3459
3460 %void = OpTypeVoid
3461 %voidfn = OpTypeFunction %void
3462 %float = OpTypeFloat 32
3463 %struct = OpTypeStruct %float
3464 %ptr = OpTypePointer StorageBuffer %struct
3465 %var = OpVariable %ptr StorageBuffer
3466
3467 %1 = OpFunction %void None %voidfn
3468 %label = OpLabel
3469 OpReturn
3470 OpFunctionEnd
3471 )";
3472
3473 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3474 EXPECT_EQ(SPV_SUCCESS,
3475 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3476 }
3477
TEST_F(ValidateDecorations,UniformMissingDescriptorSetGood)3478 TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) {
3479 std::string spirv = R"(
3480 OpCapability Shader
3481 OpMemoryModel Logical GLSL450
3482 OpEntryPoint Fragment %1 "main"
3483 OpExecutionMode %1 OriginUpperLeft
3484
3485 OpDecorate %struct Block
3486 OpMemberDecorate %struct 0 Offset 0
3487 OpDecorate %var Binding 0
3488
3489 %void = OpTypeVoid
3490 %voidfn = OpTypeFunction %void
3491 %float = OpTypeFloat 32
3492 %struct = OpTypeStruct %float
3493 %ptr = OpTypePointer Uniform %struct
3494 %var = OpVariable %ptr Uniform
3495
3496 %1 = OpFunction %void None %voidfn
3497 %label = OpLabel
3498 OpReturn
3499 OpFunctionEnd
3500 )";
3501
3502 CompileSuccessfully(spirv);
3503 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3504 << getDiagnosticString();
3505 }
3506
TEST_F(ValidateDecorations,UniformMissingBindingGood)3507 TEST_F(ValidateDecorations, UniformMissingBindingGood) {
3508 std::string spirv = R"(
3509 OpCapability Shader
3510 OpMemoryModel Logical GLSL450
3511 OpEntryPoint Fragment %1 "main"
3512 OpExecutionMode %1 OriginUpperLeft
3513
3514 OpDecorate %struct Block
3515 OpMemberDecorate %struct 0 Offset 0
3516 OpDecorate %var DescriptorSet 0
3517
3518 %void = OpTypeVoid
3519 %voidfn = OpTypeFunction %void
3520 %float = OpTypeFloat 32
3521 %struct = OpTypeStruct %float
3522 %ptr = OpTypePointer Uniform %struct
3523 %var = OpVariable %ptr Uniform
3524
3525 %1 = OpFunction %void None %voidfn
3526 %label = OpLabel
3527 OpReturn
3528 OpFunctionEnd
3529 )";
3530
3531 CompileSuccessfully(spirv);
3532 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3533 << getDiagnosticString();
3534 }
3535
TEST_F(ValidateDecorations,UniformConstantMissingDescriptorSetGood)3536 TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) {
3537 std::string spirv = R"(
3538 OpCapability Shader
3539 OpMemoryModel Logical GLSL450
3540 OpEntryPoint Fragment %1 "main"
3541 OpExecutionMode %1 OriginUpperLeft
3542
3543 OpDecorate %var Binding 0
3544
3545 %void = OpTypeVoid
3546 %voidfn = OpTypeFunction %void
3547 %sampler = OpTypeSampler
3548 %ptr = OpTypePointer UniformConstant %sampler
3549 %var = OpVariable %ptr UniformConstant
3550
3551 %1 = OpFunction %void None %voidfn
3552 %label = OpLabel
3553 OpReturn
3554 OpFunctionEnd
3555 )";
3556
3557 CompileSuccessfully(spirv);
3558 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3559 << getDiagnosticString();
3560 }
3561
TEST_F(ValidateDecorations,UniformConstantMissingBindingGood)3562 TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) {
3563 std::string spirv = R"(
3564 OpCapability Shader
3565 OpMemoryModel Logical GLSL450
3566 OpEntryPoint Fragment %1 "main"
3567 OpExecutionMode %1 OriginUpperLeft
3568
3569 OpDecorate %var DescriptorSet 0
3570
3571 %void = OpTypeVoid
3572 %voidfn = OpTypeFunction %void
3573 %sampler = OpTypeSampler
3574 %ptr = OpTypePointer UniformConstant %sampler
3575 %var = OpVariable %ptr UniformConstant
3576
3577 %1 = OpFunction %void None %voidfn
3578 %label = OpLabel
3579 OpReturn
3580 OpFunctionEnd
3581 )";
3582
3583 CompileSuccessfully(spirv);
3584 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3585 << getDiagnosticString();
3586 }
3587
TEST_F(ValidateDecorations,StorageBufferMissingDescriptorSetGood)3588 TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) {
3589 std::string spirv = R"(
3590 OpCapability Shader
3591 OpExtension "SPV_KHR_storage_buffer_storage_class"
3592 OpMemoryModel Logical GLSL450
3593 OpEntryPoint Fragment %1 "main"
3594 OpExecutionMode %1 OriginUpperLeft
3595
3596 OpDecorate %struct BufferBlock
3597 OpDecorate %var Binding 0
3598
3599 %void = OpTypeVoid
3600 %voidfn = OpTypeFunction %void
3601 %float = OpTypeFloat 32
3602 %struct = OpTypeStruct %float
3603 %ptr = OpTypePointer StorageBuffer %struct
3604 %var = OpVariable %ptr StorageBuffer
3605
3606 %1 = OpFunction %void None %voidfn
3607 %label = OpLabel
3608 OpReturn
3609 OpFunctionEnd
3610 )";
3611
3612 CompileSuccessfully(spirv);
3613 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3614 << getDiagnosticString();
3615 }
3616
TEST_F(ValidateDecorations,StorageBufferMissingBindingGood)3617 TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) {
3618 std::string spirv = R"(
3619 OpCapability Shader
3620 OpExtension "SPV_KHR_storage_buffer_storage_class"
3621 OpMemoryModel Logical GLSL450
3622 OpEntryPoint Fragment %1 "main"
3623 OpExecutionMode %1 OriginUpperLeft
3624
3625 OpDecorate %struct BufferBlock
3626 OpDecorate %var DescriptorSet 0
3627
3628 %void = OpTypeVoid
3629 %voidfn = OpTypeFunction %void
3630 %float = OpTypeFloat 32
3631 %struct = OpTypeStruct %float
3632 %ptr = OpTypePointer StorageBuffer %struct
3633 %var = OpVariable %ptr StorageBuffer
3634
3635 %1 = OpFunction %void None %voidfn
3636 %label = OpLabel
3637 OpReturn
3638 OpFunctionEnd
3639 )";
3640
3641 CompileSuccessfully(spirv);
3642 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3643 << getDiagnosticString();
3644 }
3645
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBaseAlignmentGood)3646 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) {
3647 // Spot check buffer rules when using StorageBuffer storage class with Block
3648 // decoration.
3649 std::string spirv = R"(
3650 OpCapability Shader
3651 OpExtension "SPV_KHR_storage_buffer_storage_class"
3652 OpMemoryModel Logical GLSL450
3653 OpEntryPoint Vertex %main "main"
3654 OpSource GLSL 450
3655 OpDecorate %_arr_float_uint_2 ArrayStride 4
3656 OpMemberDecorate %S 0 Offset 0
3657 OpMemberDecorate %S 1 Offset 8
3658 OpDecorate %S Block
3659 OpDecorate %u DescriptorSet 0
3660 OpDecorate %u Binding 0
3661 %void = OpTypeVoid
3662 %3 = OpTypeFunction %void
3663 %float = OpTypeFloat 32
3664 %v2float = OpTypeVector %float 2
3665 %uint = OpTypeInt 32 0
3666 %uint_2 = OpConstant %uint 2
3667 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3668 %S = OpTypeStruct %v2float %_arr_float_uint_2
3669 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3670 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3671 %main = OpFunction %void None %3
3672 %5 = OpLabel
3673 OpReturn
3674 OpFunctionEnd
3675 )";
3676
3677 CompileSuccessfully(spirv);
3678 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3679 << getDiagnosticString();
3680 }
3681
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBadAlignmentBad)3682 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad) {
3683 // Like the previous test, but with offset 7.
3684 std::string spirv = R"(
3685 OpCapability Shader
3686 OpExtension "SPV_KHR_storage_buffer_storage_class"
3687 OpMemoryModel Logical GLSL450
3688 OpEntryPoint Vertex %main "main"
3689 OpSource GLSL 450
3690 OpDecorate %_arr_float_uint_2 ArrayStride 4
3691 OpMemberDecorate %S 0 Offset 0
3692 OpMemberDecorate %S 1 Offset 7
3693 OpDecorate %S Block
3694 OpDecorate %u DescriptorSet 0
3695 OpDecorate %u Binding 0
3696 %void = OpTypeVoid
3697 %3 = OpTypeFunction %void
3698 %float = OpTypeFloat 32
3699 %v2float = OpTypeVector %float 2
3700 %uint = OpTypeInt 32 0
3701 %uint_2 = OpConstant %uint 2
3702 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3703 %S = OpTypeStruct %v2float %_arr_float_uint_2
3704 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3705 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3706 %main = OpFunction %void None %3
3707 %5 = OpLabel
3708 OpReturn
3709 OpFunctionEnd
3710 )";
3711
3712 CompileSuccessfully(spirv);
3713 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3714 EXPECT_THAT(
3715 getDiagnosticString(),
3716 HasSubstr(
3717 "Structure id 3 decorated as Block for variable in StorageBuffer "
3718 "storage class must follow standard storage buffer layout rules: "
3719 "member 1 at offset 7 is not aligned to 4"));
3720 }
3721
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayout)3722 TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout) {
3723 std::string spirv = R"(
3724 OpCapability Shader
3725 %1 = OpExtInstImport "GLSL.std.450"
3726 OpMemoryModel Logical GLSL450
3727 OpEntryPoint GLCompute %main "main"
3728 OpExecutionMode %main LocalSize 1 1 1
3729 OpSource GLSL 430
3730 OpMemberDecorate %F 0 Offset 0
3731 OpMemberDecorate %F 1 Offset 8
3732 OpDecorate %_arr_float_uint_2 ArrayStride 4
3733 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3734 OpMemberDecorate %O 0 Offset 0
3735 OpMemberDecorate %O 1 Offset 16
3736 OpMemberDecorate %O 2 Offset 24
3737 OpMemberDecorate %O 3 Offset 32
3738 OpMemberDecorate %O 4 ColMajor
3739 OpMemberDecorate %O 4 Offset 48
3740 OpMemberDecorate %O 4 MatrixStride 16
3741 OpDecorate %_arr_O_uint_2 ArrayStride 144
3742 OpMemberDecorate %Output 0 Offset 0
3743 OpMemberDecorate %Output 1 Offset 8
3744 OpMemberDecorate %Output 2 Offset 16
3745 OpMemberDecorate %Output 3 Offset 32
3746 OpMemberDecorate %Output 4 Offset 48
3747 OpMemberDecorate %Output 5 Offset 52
3748 OpMemberDecorate %Output 6 ColMajor
3749 OpMemberDecorate %Output 6 Offset 64
3750 OpMemberDecorate %Output 6 MatrixStride 16
3751 OpMemberDecorate %Output 7 Offset 96
3752 OpDecorate %Output BufferBlock
3753 %void = OpTypeVoid
3754 %3 = OpTypeFunction %void
3755 %float = OpTypeFloat 32
3756 %v2float = OpTypeVector %float 2
3757 %v3float = OpTypeVector %float 3
3758 %int = OpTypeInt 32 1
3759 %uint = OpTypeInt 32 0
3760 %v2uint = OpTypeVector %uint 2
3761 %F = OpTypeStruct %int %v2uint
3762 %uint_2 = OpConstant %uint 2
3763 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3764 %mat2v3float = OpTypeMatrix %v3float 2
3765 %v3uint = OpTypeVector %uint 3
3766 %mat3v3float = OpTypeMatrix %v3float 3
3767 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3768 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3769 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3770 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3771 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3772 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3773 %main = OpFunction %void None %3
3774 %5 = OpLabel
3775 OpReturn
3776 OpFunctionEnd
3777 )";
3778
3779 CompileSuccessfully(spirv);
3780 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
3781 }
3782
TEST_F(ValidateDecorations,StorageBufferLayoutPermitsTightVec3ScalarPackingGood)3783 TEST_F(ValidateDecorations,
3784 StorageBufferLayoutPermitsTightVec3ScalarPackingGood) {
3785 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3786 std::string spirv = R"(
3787 OpCapability Shader
3788 OpExtension "SPV_KHR_storage_buffer_storage_class"
3789 OpMemoryModel Logical GLSL450
3790 OpEntryPoint Vertex %main "main"
3791 OpSource GLSL 450
3792 OpMemberDecorate %S 0 Offset 0
3793 OpMemberDecorate %S 1 Offset 12
3794 OpDecorate %S Block
3795 OpDecorate %B DescriptorSet 0
3796 OpDecorate %B Binding 0
3797 %void = OpTypeVoid
3798 %3 = OpTypeFunction %void
3799 %float = OpTypeFloat 32
3800 %v3float = OpTypeVector %float 3
3801 %S = OpTypeStruct %v3float %float
3802 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3803 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3804 %main = OpFunction %void None %3
3805 %5 = OpLabel
3806 OpReturn
3807 OpFunctionEnd
3808 )";
3809
3810 CompileSuccessfully(spirv);
3811 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3812 << getDiagnosticString();
3813 }
3814
TEST_F(ValidateDecorations,StorageBufferLayoutForbidsTightScalarVec3PackingBad)3815 TEST_F(ValidateDecorations,
3816 StorageBufferLayoutForbidsTightScalarVec3PackingBad) {
3817 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3818 std::string spirv = R"(
3819 OpCapability Shader
3820 OpExtension "SPV_KHR_storage_buffer_storage_class"
3821 OpMemoryModel Logical GLSL450
3822 OpEntryPoint Vertex %main "main"
3823 OpSource GLSL 450
3824 OpMemberDecorate %S 0 Offset 0
3825 OpMemberDecorate %S 1 Offset 4
3826 OpDecorate %S Block
3827 OpDecorate %B DescriptorSet 0
3828 OpDecorate %B Binding 0
3829 %void = OpTypeVoid
3830 %3 = OpTypeFunction %void
3831 %float = OpTypeFloat 32
3832 %v3float = OpTypeVector %float 3
3833 %S = OpTypeStruct %float %v3float
3834 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3835 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3836 %main = OpFunction %void None %3
3837 %5 = OpLabel
3838 OpReturn
3839 OpFunctionEnd
3840 )";
3841
3842 CompileSuccessfully(spirv);
3843 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3844 EXPECT_THAT(
3845 getDiagnosticString(),
3846 HasSubstr(
3847 "Structure id 2 decorated as Block for variable in StorageBuffer "
3848 "storage class must follow standard storage buffer layout "
3849 "rules: member 1 at offset 4 is not aligned to 16"));
3850 }
3851
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset0Bad)3852 TEST_F(ValidateDecorations,
3853 BlockStandardUniformBufferLayoutIncorrectOffset0Bad) {
3854 std::string spirv = R"(
3855 OpCapability Shader
3856 %1 = OpExtInstImport "GLSL.std.450"
3857 OpMemoryModel Logical GLSL450
3858 OpEntryPoint GLCompute %main "main"
3859 OpExecutionMode %main LocalSize 1 1 1
3860 OpSource GLSL 430
3861 OpMemberDecorate %F 0 Offset 0
3862 OpMemberDecorate %F 1 Offset 8
3863 OpDecorate %_arr_float_uint_2 ArrayStride 16
3864 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3865 OpMemberDecorate %O 0 Offset 0
3866 OpMemberDecorate %O 1 Offset 16
3867 OpMemberDecorate %O 2 Offset 24
3868 OpMemberDecorate %O 3 Offset 33
3869 OpMemberDecorate %O 4 ColMajor
3870 OpMemberDecorate %O 4 Offset 80
3871 OpMemberDecorate %O 4 MatrixStride 16
3872 OpDecorate %_arr_O_uint_2 ArrayStride 176
3873 OpMemberDecorate %Output 0 Offset 0
3874 OpMemberDecorate %Output 1 Offset 8
3875 OpMemberDecorate %Output 2 Offset 16
3876 OpMemberDecorate %Output 3 Offset 32
3877 OpMemberDecorate %Output 4 Offset 48
3878 OpMemberDecorate %Output 5 Offset 64
3879 OpMemberDecorate %Output 6 ColMajor
3880 OpMemberDecorate %Output 6 Offset 96
3881 OpMemberDecorate %Output 6 MatrixStride 16
3882 OpMemberDecorate %Output 7 Offset 128
3883 OpDecorate %Output Block
3884 %void = OpTypeVoid
3885 %3 = OpTypeFunction %void
3886 %float = OpTypeFloat 32
3887 %v2float = OpTypeVector %float 2
3888 %v3float = OpTypeVector %float 3
3889 %int = OpTypeInt 32 1
3890 %uint = OpTypeInt 32 0
3891 %v2uint = OpTypeVector %uint 2
3892 %F = OpTypeStruct %int %v2uint
3893 %uint_2 = OpConstant %uint 2
3894 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3895 %mat2v3float = OpTypeMatrix %v3float 2
3896 %v3uint = OpTypeVector %uint 3
3897 %mat3v3float = OpTypeMatrix %v3float 3
3898 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3899 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3900 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3901 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3902 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3903 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3904 %main = OpFunction %void None %3
3905 %5 = OpLabel
3906 OpReturn
3907 OpFunctionEnd
3908 )";
3909
3910 CompileSuccessfully(spirv);
3911 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3912 EXPECT_THAT(
3913 getDiagnosticString(),
3914 HasSubstr("Structure id 6 decorated as Block for variable in Uniform "
3915 "storage class must follow standard uniform buffer layout "
3916 "rules: member 2 at offset 152 is not aligned to 16"));
3917 }
3918
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset1Bad)3919 TEST_F(ValidateDecorations,
3920 BlockStandardUniformBufferLayoutIncorrectOffset1Bad) {
3921 std::string spirv = R"(
3922 OpCapability Shader
3923 %1 = OpExtInstImport "GLSL.std.450"
3924 OpMemoryModel Logical GLSL450
3925 OpEntryPoint GLCompute %main "main"
3926 OpExecutionMode %main LocalSize 1 1 1
3927 OpSource GLSL 430
3928 OpMemberDecorate %F 0 Offset 0
3929 OpMemberDecorate %F 1 Offset 8
3930 OpDecorate %_arr_float_uint_2 ArrayStride 16
3931 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3932 OpMemberDecorate %O 0 Offset 0
3933 OpMemberDecorate %O 1 Offset 16
3934 OpMemberDecorate %O 2 Offset 32
3935 OpMemberDecorate %O 3 Offset 64
3936 OpMemberDecorate %O 4 ColMajor
3937 OpMemberDecorate %O 4 Offset 80
3938 OpMemberDecorate %O 4 MatrixStride 16
3939 OpDecorate %_arr_O_uint_2 ArrayStride 176
3940 OpMemberDecorate %Output 0 Offset 0
3941 OpMemberDecorate %Output 1 Offset 8
3942 OpMemberDecorate %Output 2 Offset 16
3943 OpMemberDecorate %Output 3 Offset 32
3944 OpMemberDecorate %Output 4 Offset 48
3945 OpMemberDecorate %Output 5 Offset 71
3946 OpMemberDecorate %Output 6 ColMajor
3947 OpMemberDecorate %Output 6 Offset 96
3948 OpMemberDecorate %Output 6 MatrixStride 16
3949 OpMemberDecorate %Output 7 Offset 128
3950 OpDecorate %Output Block
3951 %void = OpTypeVoid
3952 %3 = OpTypeFunction %void
3953 %float = OpTypeFloat 32
3954 %v2float = OpTypeVector %float 2
3955 %v3float = OpTypeVector %float 3
3956 %int = OpTypeInt 32 1
3957 %uint = OpTypeInt 32 0
3958 %v2uint = OpTypeVector %uint 2
3959 %F = OpTypeStruct %int %v2uint
3960 %uint_2 = OpConstant %uint 2
3961 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3962 %mat2v3float = OpTypeMatrix %v3float 2
3963 %v3uint = OpTypeVector %uint 3
3964 %mat3v3float = OpTypeMatrix %v3float 3
3965 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3966 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3967 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3968 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3969 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3970 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3971 %main = OpFunction %void None %3
3972 %5 = OpLabel
3973 OpReturn
3974 OpFunctionEnd
3975 )";
3976
3977 CompileSuccessfully(spirv);
3978 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3979 EXPECT_THAT(
3980 getDiagnosticString(),
3981 HasSubstr("Structure id 8 decorated as Block for variable in Uniform "
3982 "storage class must follow standard uniform buffer layout "
3983 "rules: member 5 at offset 71 is not aligned to 16"));
3984 }
3985
TEST_F(ValidateDecorations,BlockUniformBufferLayoutIncorrectArrayStrideBad)3986 TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad) {
3987 std::string spirv = R"(
3988 OpCapability Shader
3989 %1 = OpExtInstImport "GLSL.std.450"
3990 OpMemoryModel Logical GLSL450
3991 OpEntryPoint GLCompute %main "main"
3992 OpExecutionMode %main LocalSize 1 1 1
3993 OpSource GLSL 430
3994 OpMemberDecorate %F 0 Offset 0
3995 OpMemberDecorate %F 1 Offset 8
3996 OpDecorate %_arr_float_uint_2 ArrayStride 16
3997 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 49
3998 OpMemberDecorate %O 0 Offset 0
3999 OpMemberDecorate %O 1 Offset 16
4000 OpMemberDecorate %O 2 Offset 32
4001 OpMemberDecorate %O 3 Offset 64
4002 OpMemberDecorate %O 4 ColMajor
4003 OpMemberDecorate %O 4 Offset 80
4004 OpMemberDecorate %O 4 MatrixStride 16
4005 OpDecorate %_arr_O_uint_2 ArrayStride 176
4006 OpMemberDecorate %Output 0 Offset 0
4007 OpMemberDecorate %Output 1 Offset 8
4008 OpMemberDecorate %Output 2 Offset 16
4009 OpMemberDecorate %Output 3 Offset 32
4010 OpMemberDecorate %Output 4 Offset 48
4011 OpMemberDecorate %Output 5 Offset 64
4012 OpMemberDecorate %Output 6 ColMajor
4013 OpMemberDecorate %Output 6 Offset 96
4014 OpMemberDecorate %Output 6 MatrixStride 16
4015 OpMemberDecorate %Output 7 Offset 128
4016 OpDecorate %Output Block
4017 %void = OpTypeVoid
4018 %3 = OpTypeFunction %void
4019 %float = OpTypeFloat 32
4020 %v2float = OpTypeVector %float 2
4021 %v3float = OpTypeVector %float 3
4022 %int = OpTypeInt 32 1
4023 %uint = OpTypeInt 32 0
4024 %v2uint = OpTypeVector %uint 2
4025 %F = OpTypeStruct %int %v2uint
4026 %uint_2 = OpConstant %uint 2
4027 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4028 %mat2v3float = OpTypeMatrix %v3float 2
4029 %v3uint = OpTypeVector %uint 3
4030 %mat3v3float = OpTypeMatrix %v3float 3
4031 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
4032 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
4033 %_arr_O_uint_2 = OpTypeArray %O %uint_2
4034 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
4035 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4036 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4037 %main = OpFunction %void None %3
4038 %5 = OpLabel
4039 OpReturn
4040 OpFunctionEnd
4041 )";
4042
4043 CompileSuccessfully(spirv);
4044 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4045 EXPECT_THAT(
4046 getDiagnosticString(),
4047 HasSubstr(
4048 "Structure id 6 decorated as Block for variable in Uniform storage "
4049 "class must follow standard uniform buffer layout rules: member 4 "
4050 "contains "
4051 "an array with stride 49 not satisfying alignment to 16"));
4052 }
4053
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayoutImproperStraddleBad)4054 TEST_F(ValidateDecorations,
4055 BufferBlockStandardStorageBufferLayoutImproperStraddleBad) {
4056 std::string spirv = R"(
4057 OpCapability Shader
4058 %1 = OpExtInstImport "GLSL.std.450"
4059 OpMemoryModel Logical GLSL450
4060 OpEntryPoint GLCompute %main "main"
4061 OpExecutionMode %main LocalSize 1 1 1
4062 OpSource GLSL 430
4063 OpMemberDecorate %Output 0 Offset 0
4064 OpMemberDecorate %Output 1 Offset 8
4065 OpDecorate %Output BufferBlock
4066 %void = OpTypeVoid
4067 %3 = OpTypeFunction %void
4068 %float = OpTypeFloat 32
4069 %v3float = OpTypeVector %float 3
4070 %Output = OpTypeStruct %float %v3float
4071 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4072 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4073 %main = OpFunction %void None %3
4074 %5 = OpLabel
4075 OpReturn
4076 OpFunctionEnd
4077 )";
4078
4079 CompileSuccessfully(spirv);
4080 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4081 EXPECT_THAT(
4082 getDiagnosticString(),
4083 HasSubstr("Structure id 3 decorated as BufferBlock for variable in "
4084 "Uniform storage class must follow standard storage buffer "
4085 "layout rules: member 1 at offset 8 is not aligned to 16"));
4086 }
4087
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideArrayPaddingBad)4088 TEST_F(ValidateDecorations,
4089 BlockUniformBufferLayoutOffsetInsideArrayPaddingBad) {
4090 // In this case the 2nd member fits entirely within the padding.
4091 std::string spirv = R"(
4092 OpCapability Shader
4093 %1 = OpExtInstImport "GLSL.std.450"
4094 OpMemoryModel Logical GLSL450
4095 OpEntryPoint GLCompute %main "main"
4096 OpExecutionMode %main LocalSize 1 1 1
4097 OpSource GLSL 430
4098 OpDecorate %_arr_float_uint_2 ArrayStride 16
4099 OpMemberDecorate %Output 0 Offset 0
4100 OpMemberDecorate %Output 1 Offset 20
4101 OpDecorate %Output Block
4102 %void = OpTypeVoid
4103 %3 = OpTypeFunction %void
4104 %float = OpTypeFloat 32
4105 %uint = OpTypeInt 32 0
4106 %v2uint = OpTypeVector %uint 2
4107 %uint_2 = OpConstant %uint 2
4108 %_arr_float_uint_2 = OpTypeArray %float %uint_2
4109 %Output = OpTypeStruct %_arr_float_uint_2 %float
4110 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4111 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4112 %main = OpFunction %void None %3
4113 %5 = OpLabel
4114 OpReturn
4115 OpFunctionEnd
4116 )";
4117
4118 CompileSuccessfully(spirv);
4119 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4120 EXPECT_THAT(
4121 getDiagnosticString(),
4122 HasSubstr(
4123 "Structure id 4 decorated as Block for variable in Uniform storage "
4124 "class must follow standard uniform buffer layout rules: member 1 at "
4125 "offset 20 overlaps previous member ending at offset 31"));
4126 }
4127
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideStructPaddingBad)4128 TEST_F(ValidateDecorations,
4129 BlockUniformBufferLayoutOffsetInsideStructPaddingBad) {
4130 // In this case the 2nd member fits entirely within the padding.
4131 std::string spirv = R"(
4132 OpCapability Shader
4133 OpMemoryModel Logical GLSL450
4134 OpEntryPoint GLCompute %1 "main"
4135 OpMemberDecorate %_struct_6 0 Offset 0
4136 OpMemberDecorate %_struct_2 0 Offset 0
4137 OpMemberDecorate %_struct_2 1 Offset 4
4138 OpDecorate %_struct_2 Block
4139 %void = OpTypeVoid
4140 %4 = OpTypeFunction %void
4141 %float = OpTypeFloat 32
4142 %_struct_6 = OpTypeStruct %float
4143 %_struct_2 = OpTypeStruct %_struct_6 %float
4144 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4145 %8 = OpVariable %_ptr_Uniform__struct_2 Uniform
4146 %1 = OpFunction %void None %4
4147 %9 = OpLabel
4148 OpReturn
4149 OpFunctionEnd
4150 )";
4151
4152 CompileSuccessfully(spirv);
4153 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4154 EXPECT_THAT(
4155 getDiagnosticString(),
4156 HasSubstr(
4157 "Structure id 3 decorated as Block for variable in Uniform storage "
4158 "class must follow standard uniform buffer layout rules: member 1 at "
4159 "offset 4 overlaps previous member ending at offset 15"));
4160 }
4161
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodUniversal1_0)4162 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0) {
4163 std::string spirv = R"(
4164 OpCapability Shader
4165 %1 = OpExtInstImport "GLSL.std.450"
4166 OpMemoryModel Logical GLSL450
4167 OpEntryPoint GLCompute %main "main"
4168 OpExecutionMode %main LocalSize 1 1 1
4169 OpMemberDecorate %Outer 0 Offset 4
4170 OpMemberDecorate %Outer 1 Offset 0
4171 OpDecorate %Outer Block
4172 OpDecorate %O DescriptorSet 0
4173 OpDecorate %O Binding 0
4174 %void = OpTypeVoid
4175 %3 = OpTypeFunction %void
4176 %uint = OpTypeInt 32 0
4177 %Outer = OpTypeStruct %uint %uint
4178 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4179 %O = OpVariable %_ptr_Uniform_Outer Uniform
4180 %main = OpFunction %void None %3
4181 %5 = OpLabel
4182 OpReturn
4183 OpFunctionEnd
4184 )";
4185
4186 CompileSuccessfully(spirv);
4187 EXPECT_EQ(SPV_SUCCESS,
4188 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
4189 }
4190
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodOpenGL4_5)4191 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5) {
4192 std::string spirv = R"(
4193 OpCapability Shader
4194 %1 = OpExtInstImport "GLSL.std.450"
4195 OpMemoryModel Logical GLSL450
4196 OpEntryPoint GLCompute %main "main"
4197 OpExecutionMode %main LocalSize 1 1 1
4198 OpMemberDecorate %Outer 0 Offset 4
4199 OpMemberDecorate %Outer 1 Offset 0
4200 OpDecorate %Outer Block
4201 OpDecorate %O DescriptorSet 0
4202 OpDecorate %O Binding 0
4203 %void = OpTypeVoid
4204 %3 = OpTypeFunction %void
4205 %uint = OpTypeInt 32 0
4206 %Outer = OpTypeStruct %uint %uint
4207 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4208 %O = OpVariable %_ptr_Uniform_Outer Uniform
4209 %main = OpFunction %void None %3
4210 %5 = OpLabel
4211 OpReturn
4212 OpFunctionEnd
4213 )";
4214
4215 CompileSuccessfully(spirv);
4216 EXPECT_EQ(SPV_SUCCESS,
4217 ValidateAndRetrieveValidationState(SPV_ENV_OPENGL_4_5));
4218 }
4219
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodVulkan1_1)4220 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1) {
4221 std::string spirv = R"(
4222 OpCapability Shader
4223 %1 = OpExtInstImport "GLSL.std.450"
4224 OpMemoryModel Logical GLSL450
4225 OpEntryPoint GLCompute %main "main"
4226 OpExecutionMode %main LocalSize 1 1 1
4227 OpMemberDecorate %Outer 0 Offset 4
4228 OpMemberDecorate %Outer 1 Offset 0
4229 OpDecorate %Outer Block
4230 OpDecorate %O DescriptorSet 0
4231 OpDecorate %O Binding 0
4232 %void = OpTypeVoid
4233 %3 = OpTypeFunction %void
4234 %uint = OpTypeInt 32 0
4235 %Outer = OpTypeStruct %uint %uint
4236 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4237 %O = OpVariable %_ptr_Uniform_Outer Uniform
4238 %main = OpFunction %void None %3
4239 %5 = OpLabel
4240 OpReturn
4241 OpFunctionEnd
4242 )";
4243
4244 CompileSuccessfully(spirv);
4245 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
4246 << getDiagnosticString();
4247 EXPECT_THAT(getDiagnosticString(), Eq(""));
4248 }
4249
TEST_F(ValidateDecorations,BlockLayoutOffsetOverlapBad)4250 TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad) {
4251 std::string spirv = R"(
4252 OpCapability Shader
4253 %1 = OpExtInstImport "GLSL.std.450"
4254 OpMemoryModel Logical GLSL450
4255 OpEntryPoint GLCompute %main "main"
4256 OpExecutionMode %main LocalSize 1 1 1
4257 OpMemberDecorate %Outer 0 Offset 0
4258 OpMemberDecorate %Outer 1 Offset 16
4259 OpMemberDecorate %Inner 0 Offset 0
4260 OpMemberDecorate %Inner 1 Offset 16
4261 OpDecorate %Outer Block
4262 OpDecorate %O DescriptorSet 0
4263 OpDecorate %O Binding 0
4264 %void = OpTypeVoid
4265 %3 = OpTypeFunction %void
4266 %uint = OpTypeInt 32 0
4267 %Inner = OpTypeStruct %uint %uint
4268 %Outer = OpTypeStruct %Inner %uint
4269 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
4270 %O = OpVariable %_ptr_Uniform_Outer Uniform
4271 %main = OpFunction %void None %3
4272 %5 = OpLabel
4273 OpReturn
4274 OpFunctionEnd
4275 )";
4276
4277 CompileSuccessfully(spirv);
4278 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4279 EXPECT_THAT(
4280 getDiagnosticString(),
4281 HasSubstr(
4282 "Structure id 3 decorated as Block for variable in Uniform storage "
4283 "class must follow standard uniform buffer layout rules: member 1 at "
4284 "offset 16 overlaps previous member ending at offset 31"));
4285 }
4286
TEST_F(ValidateDecorations,BufferBlockEmptyStruct)4287 TEST_F(ValidateDecorations, BufferBlockEmptyStruct) {
4288 std::string spirv = R"(
4289 OpCapability Shader
4290 %1 = OpExtInstImport "GLSL.std.450"
4291 OpMemoryModel Logical GLSL450
4292 OpEntryPoint GLCompute %main "main"
4293 OpExecutionMode %main LocalSize 1 1 1
4294 OpSource GLSL 430
4295 OpMemberDecorate %Output 0 Offset 0
4296 OpDecorate %Output BufferBlock
4297 %void = OpTypeVoid
4298 %3 = OpTypeFunction %void
4299 %S = OpTypeStruct
4300 %Output = OpTypeStruct %S
4301 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
4302 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
4303 %main = OpFunction %void None %3
4304 %5 = OpLabel
4305 OpReturn
4306 OpFunctionEnd
4307 )";
4308
4309 CompileSuccessfully(spirv);
4310 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4311 }
4312
TEST_F(ValidateDecorations,RowMajorMatrixTightPackingGood)4313 TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood) {
4314 // Row major matrix rule:
4315 // A row-major matrix of C columns has a base alignment equal to
4316 // the base alignment of a vector of C matrix components.
4317 // Note: The "matrix component" is the scalar element type.
4318
4319 // The matrix has 3 columns and 2 rows (C=3, R=2).
4320 // So the base alignment of b is the same as a vector of 3 floats, which is 16
4321 // bytes. The matrix consists of two of these, and therefore occupies 2 x 16
4322 // bytes, or 32 bytes.
4323 //
4324 // So the offsets can be:
4325 // a -> 0
4326 // b -> 16
4327 // c -> 48
4328 // d -> 60 ; d fits at bytes 12-15 after offset of c. Tight (vec3;float)
4329 // packing
4330
4331 std::string spirv = R"(
4332 OpCapability Shader
4333 OpMemoryModel Logical GLSL450
4334 OpEntryPoint Vertex %1 "main"
4335 OpSource GLSL 450
4336 OpMemberDecorate %_struct_2 0 Offset 0
4337 OpMemberDecorate %_struct_2 1 RowMajor
4338 OpMemberDecorate %_struct_2 1 Offset 16
4339 OpMemberDecorate %_struct_2 1 MatrixStride 16
4340 OpMemberDecorate %_struct_2 2 Offset 48
4341 OpMemberDecorate %_struct_2 3 Offset 60
4342 OpDecorate %_struct_2 Block
4343 OpDecorate %3 DescriptorSet 0
4344 OpDecorate %3 Binding 0
4345 %void = OpTypeVoid
4346 %5 = OpTypeFunction %void
4347 %float = OpTypeFloat 32
4348 %v4float = OpTypeVector %float 4
4349 %v2float = OpTypeVector %float 2
4350 %mat3v2float = OpTypeMatrix %v2float 3
4351 %v3float = OpTypeVector %float 3
4352 %_struct_2 = OpTypeStruct %v4float %mat3v2float %v3float %float
4353 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4354 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4355 %1 = OpFunction %void None %5
4356 %12 = OpLabel
4357 OpReturn
4358 OpFunctionEnd
4359 )";
4360
4361 CompileSuccessfully(spirv);
4362 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
4363 << getDiagnosticString();
4364 }
4365
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixTightPackingGood)4366 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood) {
4367 // Like the previous case, but we have an array of arrays of matrices.
4368 // The RowMajor decoration goes on the struct member (surprisingly).
4369
4370 std::string spirv = R"(
4371 OpCapability Shader
4372 OpMemoryModel Logical GLSL450
4373 OpEntryPoint Vertex %1 "main"
4374 OpSource GLSL 450
4375 OpMemberDecorate %_struct_2 0 Offset 0
4376 OpMemberDecorate %_struct_2 1 RowMajor
4377 OpMemberDecorate %_struct_2 1 Offset 16
4378 OpMemberDecorate %_struct_2 1 MatrixStride 16
4379 OpMemberDecorate %_struct_2 2 Offset 80
4380 OpMemberDecorate %_struct_2 3 Offset 92
4381 OpDecorate %arr_mat ArrayStride 32
4382 OpDecorate %arr_arr_mat ArrayStride 32
4383 OpDecorate %_struct_2 Block
4384 OpDecorate %3 DescriptorSet 0
4385 OpDecorate %3 Binding 0
4386 %void = OpTypeVoid
4387 %5 = OpTypeFunction %void
4388 %float = OpTypeFloat 32
4389 %v4float = OpTypeVector %float 4
4390 %v2float = OpTypeVector %float 2
4391 %mat3v2float = OpTypeMatrix %v2float 3
4392 %uint = OpTypeInt 32 0
4393 %uint_1 = OpConstant %uint 1
4394 %uint_2 = OpConstant %uint 2
4395 %arr_mat = OpTypeArray %mat3v2float %uint_1
4396 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4397 %v3float = OpTypeVector %float 3
4398 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4399 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4400 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4401 %1 = OpFunction %void None %5
4402 %12 = OpLabel
4403 OpReturn
4404 OpFunctionEnd
4405 )";
4406
4407 CompileSuccessfully(spirv);
4408 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
4409 << getDiagnosticString();
4410 }
4411
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixNextMemberOverlapsBad)4412 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad) {
4413 // Like the previous case, but the offset of member 2 overlaps the matrix.
4414 std::string spirv = R"(
4415 OpCapability Shader
4416 OpMemoryModel Logical GLSL450
4417 OpEntryPoint Vertex %1 "main"
4418 OpSource GLSL 450
4419 OpMemberDecorate %_struct_2 0 Offset 0
4420 OpMemberDecorate %_struct_2 1 RowMajor
4421 OpMemberDecorate %_struct_2 1 Offset 16
4422 OpMemberDecorate %_struct_2 1 MatrixStride 16
4423 OpMemberDecorate %_struct_2 2 Offset 64
4424 OpMemberDecorate %_struct_2 3 Offset 92
4425 OpDecorate %arr_mat ArrayStride 32
4426 OpDecorate %arr_arr_mat ArrayStride 32
4427 OpDecorate %_struct_2 Block
4428 OpDecorate %3 DescriptorSet 0
4429 OpDecorate %3 Binding 0
4430 %void = OpTypeVoid
4431 %5 = OpTypeFunction %void
4432 %float = OpTypeFloat 32
4433 %v4float = OpTypeVector %float 4
4434 %v2float = OpTypeVector %float 2
4435 %mat3v2float = OpTypeMatrix %v2float 3
4436 %uint = OpTypeInt 32 0
4437 %uint_1 = OpConstant %uint 1
4438 %uint_2 = OpConstant %uint 2
4439 %arr_mat = OpTypeArray %mat3v2float %uint_1
4440 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4441 %v3float = OpTypeVector %float 3
4442 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4443 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4444 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4445 %1 = OpFunction %void None %5
4446 %12 = OpLabel
4447 OpReturn
4448 OpFunctionEnd
4449 )";
4450
4451 CompileSuccessfully(spirv);
4452 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4453 EXPECT_THAT(
4454 getDiagnosticString(),
4455 HasSubstr(
4456 "Structure id 2 decorated as Block for variable in Uniform storage "
4457 "class must follow standard uniform buffer layout rules: member 2 at "
4458 "offset 64 overlaps previous member ending at offset 79"));
4459 }
4460
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackGood)4461 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood) {
4462 // Original GLSL
4463
4464 // #version 450
4465 // layout (set=0,binding=0) buffer S {
4466 // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
4467 // uint i; // Can have offset 60 = 3x16 + 12
4468 // } B;
4469 // void main() {}
4470
4471 std::string spirv = R"(
4472 OpCapability Shader
4473 OpMemoryModel Logical GLSL450
4474 OpEntryPoint Vertex %1 "main"
4475 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4476 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4477 OpMemberDecorate %_struct_4 0 Offset 0
4478 OpMemberDecorate %_struct_4 1 Offset 60
4479 OpDecorate %_struct_4 BufferBlock
4480 OpDecorate %5 DescriptorSet 0
4481 OpDecorate %5 Binding 0
4482 %void = OpTypeVoid
4483 %7 = OpTypeFunction %void
4484 %uint = OpTypeInt 32 0
4485 %v3uint = OpTypeVector %uint 3
4486 %uint_2 = OpConstant %uint 2
4487 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4488 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4489 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4490 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4491 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4492 %1 = OpFunction %void None %7
4493 %12 = OpLabel
4494 OpReturn
4495 OpFunctionEnd
4496 )";
4497
4498 CompileSuccessfully(spirv);
4499 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4500 }
4501
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackBad)4502 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) {
4503 // Like previous but, the offset of the second member is too small.
4504
4505 std::string spirv = R"(
4506 OpCapability Shader
4507 OpMemoryModel Logical GLSL450
4508 OpEntryPoint Vertex %1 "main"
4509 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4510 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4511 OpMemberDecorate %_struct_4 0 Offset 0
4512 OpMemberDecorate %_struct_4 1 Offset 56
4513 OpDecorate %_struct_4 BufferBlock
4514 OpDecorate %5 DescriptorSet 0
4515 OpDecorate %5 Binding 0
4516 %void = OpTypeVoid
4517 %7 = OpTypeFunction %void
4518 %uint = OpTypeInt 32 0
4519 %v3uint = OpTypeVector %uint 3
4520 %uint_2 = OpConstant %uint 2
4521 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4522 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4523 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4524 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4525 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4526 %1 = OpFunction %void None %7
4527 %12 = OpLabel
4528 OpReturn
4529 OpFunctionEnd
4530 )";
4531
4532 CompileSuccessfully(spirv);
4533 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4534 EXPECT_THAT(getDiagnosticString(),
4535 HasSubstr("Structure id 4 decorated as BufferBlock for variable "
4536 "in Uniform storage class must follow standard storage "
4537 "buffer layout rules: member 1 at offset 56 overlaps "
4538 "previous member ending at offset 59"));
4539 }
4540
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackGood)4541 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) {
4542 // Like the corresponding buffer block case, but the array padding must
4543 // count for the last element as well, and so the offset of the second
4544 // member must be at least 64.
4545 std::string spirv = R"(
4546 OpCapability Shader
4547 OpMemoryModel Logical GLSL450
4548 OpEntryPoint Vertex %1 "main"
4549 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4550 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4551 OpMemberDecorate %_struct_4 0 Offset 0
4552 OpMemberDecorate %_struct_4 1 Offset 64
4553 OpDecorate %_struct_4 Block
4554 OpDecorate %5 DescriptorSet 0
4555 OpDecorate %5 Binding 0
4556 %void = OpTypeVoid
4557 %7 = OpTypeFunction %void
4558 %uint = OpTypeInt 32 0
4559 %v3uint = OpTypeVector %uint 3
4560 %uint_2 = OpConstant %uint 2
4561 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4562 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4563 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4564 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4565 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4566 %1 = OpFunction %void None %7
4567 %12 = OpLabel
4568 OpReturn
4569 OpFunctionEnd
4570 )";
4571
4572 CompileSuccessfully(spirv);
4573 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4574 }
4575
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackBad)4576 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) {
4577 // Like previous but, the offset of the second member is too small.
4578
4579 std::string spirv = R"(
4580 OpCapability Shader
4581 OpMemoryModel Logical GLSL450
4582 OpEntryPoint Vertex %1 "main"
4583 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4584 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4585 OpMemberDecorate %_struct_4 0 Offset 0
4586 OpMemberDecorate %_struct_4 1 Offset 60
4587 OpDecorate %_struct_4 Block
4588 OpDecorate %5 DescriptorSet 0
4589 OpDecorate %5 Binding 0
4590 %void = OpTypeVoid
4591 %7 = OpTypeFunction %void
4592 %uint = OpTypeInt 32 0
4593 %v3uint = OpTypeVector %uint 3
4594 %uint_2 = OpConstant %uint 2
4595 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4596 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4597 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4598 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4599 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4600 %1 = OpFunction %void None %7
4601 %12 = OpLabel
4602 OpReturn
4603 OpFunctionEnd
4604 )";
4605
4606 CompileSuccessfully(spirv);
4607 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4608 EXPECT_THAT(
4609 getDiagnosticString(),
4610 HasSubstr(
4611 "Structure id 4 decorated as Block for variable in Uniform storage "
4612 "class must follow standard uniform buffer layout rules: member 1 at "
4613 "offset 60 overlaps previous member ending at offset 63"));
4614 }
4615
TEST_F(ValidateDecorations,LayoutNotCheckedWhenSkipBlockLayout)4616 TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) {
4617 // Checks that block layout is not verified in skipping block layout mode.
4618 // Even for obviously wrong layout.
4619 std::string spirv = R"(
4620 OpCapability Shader
4621 OpMemoryModel Logical GLSL450
4622 OpEntryPoint Vertex %main "main"
4623 OpSource GLSL 450
4624 OpMemberDecorate %S 0 Offset 3 ; wrong alignment
4625 OpMemberDecorate %S 1 Offset 3 ; same offset as before!
4626 OpDecorate %S Block
4627 OpDecorate %B DescriptorSet 0
4628 OpDecorate %B Binding 0
4629 %void = OpTypeVoid
4630 %3 = OpTypeFunction %void
4631 %float = OpTypeFloat 32
4632 %v3float = OpTypeVector %float 3
4633 %S = OpTypeStruct %float %v3float
4634 %_ptr_Uniform_S = OpTypePointer Uniform %S
4635 %B = OpVariable %_ptr_Uniform_S Uniform
4636 %main = OpFunction %void None %3
4637 %5 = OpLabel
4638 OpReturn
4639 OpFunctionEnd
4640 )";
4641
4642 CompileSuccessfully(spirv);
4643 spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true);
4644 EXPECT_EQ(SPV_SUCCESS,
4645 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4646 EXPECT_THAT(getDiagnosticString(), Eq(""));
4647 }
4648
TEST_F(ValidateDecorations,EntryPointVariableWrongStorageClass)4649 TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) {
4650 const std::string spirv = R"(
4651 OpCapability Shader
4652 OpMemoryModel Logical GLSL450
4653 OpEntryPoint Fragment %1 "func" %var
4654 OpExecutionMode %1 OriginUpperLeft
4655 %void = OpTypeVoid
4656 %int = OpTypeInt 32 0
4657 %ptr_int_Workgroup = OpTypePointer Workgroup %int
4658 %var = OpVariable %ptr_int_Workgroup Workgroup
4659 %func_ty = OpTypeFunction %void
4660 %1 = OpFunction %void None %func_ty
4661 %2 = OpLabel
4662 OpReturn
4663 OpFunctionEnd
4664 )";
4665
4666 CompileSuccessfully(spirv);
4667 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4668 EXPECT_THAT(getDiagnosticString(),
4669 HasSubstr("OpEntryPoint interfaces must be OpVariables with "
4670 "Storage Class of Input(1) or Output(3). Found Storage "
4671 "Class 4 for Entry Point id 1."));
4672 }
4673
TEST_F(ValidateDecorations,VulkanMemoryModelNonCoherent)4674 TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent) {
4675 const std::string spirv = R"(
4676 OpCapability Shader
4677 OpCapability VulkanMemoryModelKHR
4678 OpCapability Linkage
4679 OpExtension "SPV_KHR_vulkan_memory_model"
4680 OpExtension "SPV_KHR_storage_buffer_storage_class"
4681 OpMemoryModel Logical VulkanKHR
4682 OpDecorate %1 Coherent
4683 %2 = OpTypeInt 32 0
4684 %3 = OpTypePointer StorageBuffer %2
4685 %1 = OpVariable %3 StorageBuffer
4686 )";
4687
4688 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4689 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4690 EXPECT_THAT(getDiagnosticString(),
4691 HasSubstr("Coherent decoration targeting '1[%1]' is "
4692 "banned when using the Vulkan memory model."));
4693 }
4694
TEST_F(ValidateDecorations,VulkanMemoryModelNoCoherentMember)4695 TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember) {
4696 const std::string spirv = R"(
4697 OpCapability Shader
4698 OpCapability VulkanMemoryModelKHR
4699 OpCapability Linkage
4700 OpExtension "SPV_KHR_vulkan_memory_model"
4701 OpMemoryModel Logical VulkanKHR
4702 OpMemberDecorate %1 0 Coherent
4703 %2 = OpTypeInt 32 0
4704 %1 = OpTypeStruct %2 %2
4705 )";
4706
4707 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4708 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4709 EXPECT_THAT(
4710 getDiagnosticString(),
4711 HasSubstr(
4712 "Coherent decoration targeting '1[%_struct_1]' (member index 0) "
4713 "is banned when using the Vulkan memory model."));
4714 }
4715
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatile)4716 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) {
4717 const std::string spirv = R"(
4718 OpCapability Shader
4719 OpCapability VulkanMemoryModelKHR
4720 OpCapability Linkage
4721 OpExtension "SPV_KHR_vulkan_memory_model"
4722 OpExtension "SPV_KHR_storage_buffer_storage_class"
4723 OpMemoryModel Logical VulkanKHR
4724 OpDecorate %1 Volatile
4725 %2 = OpTypeInt 32 0
4726 %3 = OpTypePointer StorageBuffer %2
4727 %1 = OpVariable %3 StorageBuffer
4728 )";
4729
4730 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4731 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4732 EXPECT_THAT(getDiagnosticString(),
4733 HasSubstr("Volatile decoration targeting '1[%1]' is banned when "
4734 "using the Vulkan memory model."));
4735 }
4736
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatileMember)4737 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember) {
4738 const std::string spirv = R"(
4739 OpCapability Shader
4740 OpCapability VulkanMemoryModelKHR
4741 OpCapability Linkage
4742 OpExtension "SPV_KHR_vulkan_memory_model"
4743 OpMemoryModel Logical VulkanKHR
4744 OpMemberDecorate %1 1 Volatile
4745 %2 = OpTypeInt 32 0
4746 %1 = OpTypeStruct %2 %2
4747 )";
4748
4749 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4750 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4751 EXPECT_THAT(getDiagnosticString(),
4752 HasSubstr("Volatile decoration targeting '1[%_struct_1]' (member "
4753 "index 1) is banned when using the Vulkan memory "
4754 "model."));
4755 }
4756
TEST_F(ValidateDecorations,FPRoundingModeGood)4757 TEST_F(ValidateDecorations, FPRoundingModeGood) {
4758 std::string spirv = R"(
4759 OpCapability Shader
4760 OpCapability Linkage
4761 OpCapability StorageBuffer16BitAccess
4762 OpExtension "SPV_KHR_storage_buffer_storage_class"
4763 OpExtension "SPV_KHR_variable_pointers"
4764 OpExtension "SPV_KHR_16bit_storage"
4765 OpMemoryModel Logical GLSL450
4766 OpEntryPoint GLCompute %main "main"
4767 OpDecorate %_ FPRoundingMode RTE
4768 %half = OpTypeFloat 16
4769 %float = OpTypeFloat 32
4770 %float_1_25 = OpConstant %float 1.25
4771 %half_ptr = OpTypePointer StorageBuffer %half
4772 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4773 %void = OpTypeVoid
4774 %func = OpTypeFunction %void
4775 %main = OpFunction %void None %func
4776 %main_entry = OpLabel
4777 %_ = OpFConvert %half %float_1_25
4778 OpStore %half_ptr_var %_
4779 OpReturn
4780 OpFunctionEnd
4781 )";
4782
4783 CompileSuccessfully(spirv);
4784 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4785 }
4786
TEST_F(ValidateDecorations,FPRoundingModeVectorGood)4787 TEST_F(ValidateDecorations, FPRoundingModeVectorGood) {
4788 std::string spirv = R"(
4789 OpCapability Shader
4790 OpCapability Linkage
4791 OpCapability StorageBuffer16BitAccess
4792 OpExtension "SPV_KHR_storage_buffer_storage_class"
4793 OpExtension "SPV_KHR_variable_pointers"
4794 OpExtension "SPV_KHR_16bit_storage"
4795 OpMemoryModel Logical GLSL450
4796 OpEntryPoint GLCompute %main "main"
4797 OpDecorate %_ FPRoundingMode RTE
4798 %half = OpTypeFloat 16
4799 %float = OpTypeFloat 32
4800 %v2half = OpTypeVector %half 2
4801 %v2float = OpTypeVector %float 2
4802 %float_1_25 = OpConstant %float 1.25
4803 %floats = OpConstantComposite %v2float %float_1_25 %float_1_25
4804 %halfs_ptr = OpTypePointer StorageBuffer %v2half
4805 %halfs_ptr_var = OpVariable %halfs_ptr StorageBuffer
4806 %void = OpTypeVoid
4807 %func = OpTypeFunction %void
4808 %main = OpFunction %void None %func
4809 %main_entry = OpLabel
4810 %_ = OpFConvert %v2half %floats
4811 OpStore %halfs_ptr_var %_
4812 OpReturn
4813 OpFunctionEnd
4814 )";
4815
4816 CompileSuccessfully(spirv);
4817 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4818 }
4819
TEST_F(ValidateDecorations,FPRoundingModeNotOpFConvert)4820 TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert) {
4821 std::string spirv = R"(
4822 OpCapability Shader
4823 OpCapability Linkage
4824 OpCapability StorageBuffer16BitAccess
4825 OpExtension "SPV_KHR_storage_buffer_storage_class"
4826 OpExtension "SPV_KHR_variable_pointers"
4827 OpExtension "SPV_KHR_16bit_storage"
4828 OpMemoryModel Logical GLSL450
4829 OpEntryPoint GLCompute %main "main"
4830 OpDecorate %_ FPRoundingMode RTE
4831 %short = OpTypeInt 16 1
4832 %int = OpTypeInt 32 1
4833 %int_17 = OpConstant %int 17
4834 %short_ptr = OpTypePointer StorageBuffer %short
4835 %short_ptr_var = OpVariable %short_ptr StorageBuffer
4836 %void = OpTypeVoid
4837 %func = OpTypeFunction %void
4838 %main = OpFunction %void None %func
4839 %main_entry = OpLabel
4840 %_ = OpSConvert %short %int_17
4841 OpStore %short_ptr_var %_
4842 OpReturn
4843 OpFunctionEnd
4844 )";
4845
4846 CompileSuccessfully(spirv);
4847 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4848 EXPECT_THAT(getDiagnosticString(),
4849 HasSubstr("FPRoundingMode decoration can be applied only to a "
4850 "width-only conversion instruction for floating-point "
4851 "object."));
4852 }
4853
TEST_F(ValidateDecorations,FPRoundingModeNoOpStoreGood)4854 TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood) {
4855 std::string spirv = R"(
4856 OpCapability Shader
4857 OpCapability Linkage
4858 OpCapability StorageBuffer16BitAccess
4859 OpExtension "SPV_KHR_storage_buffer_storage_class"
4860 OpExtension "SPV_KHR_variable_pointers"
4861 OpExtension "SPV_KHR_16bit_storage"
4862 OpMemoryModel Logical GLSL450
4863 OpEntryPoint GLCompute %main "main"
4864 OpDecorate %_ FPRoundingMode RTE
4865 %half = OpTypeFloat 16
4866 %float = OpTypeFloat 32
4867 %float_1_25 = OpConstant %float 1.25
4868 %half_ptr = OpTypePointer StorageBuffer %half
4869 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4870 %void = OpTypeVoid
4871 %func = OpTypeFunction %void
4872 %main = OpFunction %void None %func
4873 %main_entry = OpLabel
4874 %_ = OpFConvert %half %float_1_25
4875 OpReturn
4876 OpFunctionEnd
4877 )";
4878
4879 CompileSuccessfully(spirv);
4880 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4881 }
4882
TEST_F(ValidateDecorations,FPRoundingModeFConvert64to16Good)4883 TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good) {
4884 std::string spirv = R"(
4885 OpCapability Shader
4886 OpCapability Linkage
4887 OpCapability StorageBuffer16BitAccess
4888 OpCapability Float64
4889 OpExtension "SPV_KHR_storage_buffer_storage_class"
4890 OpExtension "SPV_KHR_variable_pointers"
4891 OpExtension "SPV_KHR_16bit_storage"
4892 OpMemoryModel Logical GLSL450
4893 OpEntryPoint GLCompute %main "main"
4894 OpDecorate %_ FPRoundingMode RTE
4895 %half = OpTypeFloat 16
4896 %double = OpTypeFloat 64
4897 %double_1_25 = OpConstant %double 1.25
4898 %half_ptr = OpTypePointer StorageBuffer %half
4899 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4900 %void = OpTypeVoid
4901 %func = OpTypeFunction %void
4902 %main = OpFunction %void None %func
4903 %main_entry = OpLabel
4904 %_ = OpFConvert %half %double_1_25
4905 OpStore %half_ptr_var %_
4906 OpReturn
4907 OpFunctionEnd
4908 )";
4909
4910 CompileSuccessfully(spirv);
4911 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4912 }
4913
TEST_F(ValidateDecorations,FPRoundingModeNotStoreInFloat16)4914 TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16) {
4915 std::string spirv = R"(
4916 OpCapability Shader
4917 OpCapability Linkage
4918 OpCapability StorageBuffer16BitAccess
4919 OpCapability Float64
4920 OpExtension "SPV_KHR_storage_buffer_storage_class"
4921 OpExtension "SPV_KHR_variable_pointers"
4922 OpExtension "SPV_KHR_16bit_storage"
4923 OpMemoryModel Logical GLSL450
4924 OpEntryPoint GLCompute %main "main"
4925 OpDecorate %_ FPRoundingMode RTE
4926 %float = OpTypeFloat 32
4927 %double = OpTypeFloat 64
4928 %double_1_25 = OpConstant %double 1.25
4929 %float_ptr = OpTypePointer StorageBuffer %float
4930 %float_ptr_var = OpVariable %float_ptr StorageBuffer
4931 %void = OpTypeVoid
4932 %func = OpTypeFunction %void
4933 %main = OpFunction %void None %func
4934 %main_entry = OpLabel
4935 %_ = OpFConvert %float %double_1_25
4936 OpStore %float_ptr_var %_
4937 OpReturn
4938 OpFunctionEnd
4939 )";
4940
4941 CompileSuccessfully(spirv);
4942 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4943 EXPECT_THAT(
4944 getDiagnosticString(),
4945 HasSubstr("FPRoundingMode decoration can be applied only to the "
4946 "Object operand of an OpStore storing through a "
4947 "pointer to a 16-bit floating-point scalar or vector object."));
4948 }
4949
TEST_F(ValidateDecorations,FPRoundingModeMultipleOpStoreGood)4950 TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood) {
4951 std::string spirv = R"(
4952 OpCapability Shader
4953 OpCapability Linkage
4954 OpCapability StorageBuffer16BitAccess
4955 OpExtension "SPV_KHR_storage_buffer_storage_class"
4956 OpExtension "SPV_KHR_variable_pointers"
4957 OpExtension "SPV_KHR_16bit_storage"
4958 OpMemoryModel Logical GLSL450
4959 OpEntryPoint GLCompute %main "main"
4960 OpDecorate %_ FPRoundingMode RTE
4961 %half = OpTypeFloat 16
4962 %float = OpTypeFloat 32
4963 %float_1_25 = OpConstant %float 1.25
4964 %half_ptr = OpTypePointer StorageBuffer %half
4965 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
4966 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
4967 %half_ptr_var_2 = OpVariable %half_ptr StorageBuffer
4968 %void = OpTypeVoid
4969 %func = OpTypeFunction %void
4970 %main = OpFunction %void None %func
4971 %main_entry = OpLabel
4972 %_ = OpFConvert %half %float_1_25
4973 OpStore %half_ptr_var_0 %_
4974 OpStore %half_ptr_var_1 %_
4975 OpStore %half_ptr_var_2 %_
4976 OpReturn
4977 OpFunctionEnd
4978 )";
4979
4980 CompileSuccessfully(spirv);
4981 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4982 }
4983
TEST_F(ValidateDecorations,FPRoundingModeMultipleUsesBad)4984 TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad) {
4985 std::string spirv = R"(
4986 OpCapability Shader
4987 OpCapability Linkage
4988 OpCapability StorageBuffer16BitAccess
4989 OpExtension "SPV_KHR_storage_buffer_storage_class"
4990 OpExtension "SPV_KHR_variable_pointers"
4991 OpExtension "SPV_KHR_16bit_storage"
4992 OpMemoryModel Logical GLSL450
4993 OpEntryPoint GLCompute %main "main"
4994 OpDecorate %_ FPRoundingMode RTE
4995 %half = OpTypeFloat 16
4996 %float = OpTypeFloat 32
4997 %float_1_25 = OpConstant %float 1.25
4998 %half_ptr = OpTypePointer StorageBuffer %half
4999 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
5000 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
5001 %void = OpTypeVoid
5002 %func = OpTypeFunction %void
5003 %main = OpFunction %void None %func
5004 %main_entry = OpLabel
5005 %_ = OpFConvert %half %float_1_25
5006 OpStore %half_ptr_var_0 %_
5007 %result = OpFAdd %half %_ %_
5008 OpStore %half_ptr_var_1 %_
5009 OpReturn
5010 OpFunctionEnd
5011 )";
5012
5013 CompileSuccessfully(spirv);
5014 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5015 EXPECT_THAT(getDiagnosticString(),
5016 HasSubstr("FPRoundingMode decoration can be applied only to the "
5017 "Object operand of an OpStore."));
5018 }
5019
TEST_F(ValidateDecorations,VulkanFPRoundingModeGood)5020 TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
5021 std::string spirv = R"(
5022 OpCapability Shader
5023 OpCapability StorageBuffer16BitAccess
5024 %1 = OpExtInstImport "GLSL.std.450"
5025 OpMemoryModel Logical GLSL450
5026 OpEntryPoint GLCompute %main "main" %_
5027 OpExecutionMode %main LocalSize 1 1 1
5028 OpMemberDecorate %ssbo 0 Offset 0
5029 OpDecorate %ssbo Block
5030 OpDecorate %_ DescriptorSet 0
5031 OpDecorate %_ Binding 0
5032 OpDecorate %17 FPRoundingMode RTE
5033 %void = OpTypeVoid
5034 %3 = OpTypeFunction %void
5035 %float = OpTypeFloat 32
5036 %_ptr_Function_float = OpTypePointer Function %float
5037 %float_1 = OpConstant %float 1
5038 %half = OpTypeFloat 16
5039 %ssbo = OpTypeStruct %half
5040 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
5041 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
5042 %int = OpTypeInt 32 1
5043 %int_0 = OpConstant %int 0
5044 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
5045 %main = OpFunction %void None %3
5046 %5 = OpLabel
5047 %b = OpVariable %_ptr_Function_float Function
5048 OpStore %b %float_1
5049 %16 = OpLoad %float %b
5050 %17 = OpFConvert %half %16
5051 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
5052 OpStore %19 %17
5053 OpReturn
5054 OpFunctionEnd
5055 )";
5056
5057 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5058 EXPECT_EQ(SPV_SUCCESS,
5059 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5060 }
5061
TEST_F(ValidateDecorations,VulkanFPRoundingModeBadMode)5062 TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
5063 std::string spirv = R"(
5064 OpCapability Shader
5065 OpCapability StorageBuffer16BitAccess
5066 %1 = OpExtInstImport "GLSL.std.450"
5067 OpMemoryModel Logical GLSL450
5068 OpEntryPoint GLCompute %main "main" %_
5069 OpExecutionMode %main LocalSize 1 1 1
5070 OpMemberDecorate %ssbo 0 Offset 0
5071 OpDecorate %ssbo Block
5072 OpDecorate %_ DescriptorSet 0
5073 OpDecorate %_ Binding 0
5074 OpDecorate %17 FPRoundingMode RTP
5075 %void = OpTypeVoid
5076 %3 = OpTypeFunction %void
5077 %float = OpTypeFloat 32
5078 %_ptr_Function_float = OpTypePointer Function %float
5079 %float_1 = OpConstant %float 1
5080 %half = OpTypeFloat 16
5081 %ssbo = OpTypeStruct %half
5082 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
5083 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
5084 %int = OpTypeInt 32 1
5085 %int_0 = OpConstant %int 0
5086 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
5087 %main = OpFunction %void None %3
5088 %5 = OpLabel
5089 %b = OpVariable %_ptr_Function_float Function
5090 OpStore %b %float_1
5091 %16 = OpLoad %float %b
5092 %17 = OpFConvert %half %16
5093 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
5094 OpStore %19 %17
5095 OpReturn
5096 OpFunctionEnd
5097 )";
5098
5099 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5100 EXPECT_EQ(SPV_ERROR_INVALID_ID,
5101 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
5102 EXPECT_THAT(getDiagnosticString(),
5103 AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
5104 EXPECT_THAT(
5105 getDiagnosticString(),
5106 HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
5107 }
5108
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup)5109 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
5110 std::string spirv = R"(
5111 OpCapability Shader
5112 OpCapability Linkage
5113 OpMemoryModel Logical GLSL450
5114 %1 = OpDecorationGroup
5115 OpGroupDecorate %1 %1
5116 )";
5117
5118 CompileSuccessfully(spirv);
5119 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5120 EXPECT_THAT(getDiagnosticString(),
5121 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5122 "'1[%1]'"));
5123 }
5124
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup2)5125 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2) {
5126 std::string spirv = R"(
5127 OpCapability Shader
5128 OpCapability Linkage
5129 OpMemoryModel Logical GLSL450
5130 %1 = OpDecorationGroup
5131 OpGroupDecorate %1 %2 %1
5132 %2 = OpTypeVoid
5133 )";
5134
5135 CompileSuccessfully(spirv);
5136 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5137 EXPECT_THAT(getDiagnosticString(),
5138 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
5139 "'1[%1]'"));
5140 }
5141
TEST_F(ValidateDecorations,RecurseThroughRuntimeArray)5142 TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) {
5143 const std::string spirv = R"(
5144 OpCapability Shader
5145 OpCapability Linkage
5146 OpMemoryModel Logical GLSL450
5147 OpDecorate %outer Block
5148 OpMemberDecorate %inner 0 Offset 0
5149 OpMemberDecorate %inner 1 Offset 1
5150 OpDecorate %runtime ArrayStride 16
5151 OpMemberDecorate %outer 0 Offset 0
5152 %int = OpTypeInt 32 0
5153 %inner = OpTypeStruct %int %int
5154 %runtime = OpTypeRuntimeArray %inner
5155 %outer = OpTypeStruct %runtime
5156 %outer_ptr = OpTypePointer Uniform %outer
5157 %var = OpVariable %outer_ptr Uniform
5158 )";
5159
5160 CompileSuccessfully(spirv);
5161 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5162 EXPECT_THAT(
5163 getDiagnosticString(),
5164 HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
5165 "storage class must follow standard uniform buffer layout "
5166 "rules: member 1 at offset 1 is not aligned to 4"));
5167 }
5168
TEST_F(ValidateDecorations,EmptyStructAtNonZeroOffsetGood)5169 TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) {
5170 const std::string spirv = R"(
5171 OpCapability Shader
5172 OpMemoryModel Logical GLSL450
5173 OpEntryPoint GLCompute %main "main"
5174 OpExecutionMode %main LocalSize 1 1 1
5175 OpDecorate %struct Block
5176 OpMemberDecorate %struct 0 Offset 0
5177 OpMemberDecorate %struct 1 Offset 16
5178 OpDecorate %var DescriptorSet 0
5179 OpDecorate %var Binding 0
5180 %void = OpTypeVoid
5181 %float = OpTypeFloat 32
5182 %empty = OpTypeStruct
5183 %struct = OpTypeStruct %float %empty
5184 %ptr_struct_ubo = OpTypePointer Uniform %struct
5185 %var = OpVariable %ptr_struct_ubo Uniform
5186 %voidfn = OpTypeFunction %void
5187 %main = OpFunction %void None %voidfn
5188 %entry = OpLabel
5189 OpReturn
5190 OpFunctionEnd
5191 )";
5192
5193 CompileSuccessfully(spirv);
5194 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5195 }
5196
5197 // Uniform and UniformId decorations
5198
TEST_F(ValidateDecorations,UniformDecorationGood)5199 TEST_F(ValidateDecorations, UniformDecorationGood) {
5200 const std::string spirv = R"(
5201 OpCapability Shader
5202 OpMemoryModel Logical Simple
5203 OpEntryPoint GLCompute %main "main"
5204 OpExecutionMode %main LocalSize 1 1 1
5205 OpDecorate %int0 Uniform
5206 OpDecorate %var Uniform
5207 OpDecorate %val Uniform
5208 %void = OpTypeVoid
5209 %int = OpTypeInt 32 1
5210 %int0 = OpConstantNull %int
5211 %intptr = OpTypePointer Private %int
5212 %var = OpVariable %intptr Private
5213 %fn = OpTypeFunction %void
5214 %main = OpFunction %void None %fn
5215 %entry = OpLabel
5216 %val = OpLoad %int %var
5217 OpReturn
5218 OpFunctionEnd
5219 )";
5220
5221 CompileSuccessfully(spirv);
5222 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5223 EXPECT_THAT(getDiagnosticString(), Eq(""));
5224 }
5225
5226 // Returns SPIR-V assembly for a shader that uses a given decoration
5227 // instruction.
ShaderWithUniformLikeDecoration(const std::string & inst)5228 std::string ShaderWithUniformLikeDecoration(const std::string& inst) {
5229 return std::string(R"(
5230 OpCapability Shader
5231 OpMemoryModel Logical Simple
5232 OpEntryPoint GLCompute %main "main"
5233 OpExecutionMode %main LocalSize 1 1 1
5234 OpName %subgroupscope "subgroupscope"
5235 OpName %call "call"
5236 OpName %myfunc "myfunc"
5237 OpName %int0 "int0"
5238 OpName %float0 "float0"
5239 OpName %fn "fn"
5240 )") + inst +
5241 R"(
5242 %void = OpTypeVoid
5243 %float = OpTypeFloat 32
5244 %int = OpTypeInt 32 1
5245 %int0 = OpConstantNull %int
5246 %int_99 = OpConstant %int 99
5247 %subgroupscope = OpConstant %int 3
5248 %float0 = OpConstantNull %float
5249 %fn = OpTypeFunction %void
5250 %myfunc = OpFunction %void None %fn
5251 %myfuncentry = OpLabel
5252 OpReturn
5253 OpFunctionEnd
5254 %main = OpFunction %void None %fn
5255 %entry = OpLabel
5256 %call = OpFunctionCall %void %myfunc
5257 OpReturn
5258 OpFunctionEnd
5259 )";
5260 }
5261
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13Bad)5262 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad) {
5263 const std::string spirv = ShaderWithUniformLikeDecoration(
5264 "OpDecorateId %int0 UniformId %subgroupscope");
5265 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5266 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5267 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5268 EXPECT_THAT(getDiagnosticString(),
5269 HasSubstr("requires SPIR-V version 1.4 or later\n"
5270 " OpDecorateId %int0 UniformId %subgroupscope"))
5271 << spirv;
5272 }
5273
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13BadTargetV14)5274 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14) {
5275 const std::string spirv = ShaderWithUniformLikeDecoration(
5276 "OpDecorateId %int0 UniformId %subgroupscope");
5277 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5278 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
5279 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5280 EXPECT_THAT(getDiagnosticString(),
5281 HasSubstr("requires SPIR-V version 1.4 or later"));
5282 }
5283
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV14Good)5284 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good) {
5285 const std::string spirv = ShaderWithUniformLikeDecoration(
5286 "OpDecorateId %int0 UniformId %subgroupscope");
5287 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5288 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5289 EXPECT_THAT(getDiagnosticString(), Eq(""));
5290 }
5291
TEST_F(ValidateDecorations,UniformDecorationTargetsTypeBad)5292 TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad) {
5293 const std::string spirv =
5294 ShaderWithUniformLikeDecoration("OpDecorate %fn Uniform");
5295
5296 CompileSuccessfully(spirv);
5297 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5298 EXPECT_THAT(getDiagnosticString(),
5299 HasSubstr("Uniform decoration applied to a non-object"));
5300 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5301 }
5302
TEST_F(ValidateDecorations,UniformIdDecorationTargetsTypeBad)5303 TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad) {
5304 const std::string spirv = ShaderWithUniformLikeDecoration(
5305 "OpDecorateId %fn UniformId %subgroupscope");
5306
5307 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5308 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5309 EXPECT_THAT(getDiagnosticString(),
5310 HasSubstr("UniformId decoration applied to a non-object"));
5311 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
5312 }
5313
TEST_F(ValidateDecorations,UniformDecorationTargetsVoidValueBad)5314 TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad) {
5315 const std::string spirv =
5316 ShaderWithUniformLikeDecoration("OpDecorate %call Uniform");
5317
5318 CompileSuccessfully(spirv);
5319 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5320 EXPECT_THAT(getDiagnosticString(),
5321 HasSubstr("Uniform decoration applied to a value with void type\n"
5322 " %call = OpFunctionCall %void %myfunc"));
5323 }
5324
TEST_F(ValidateDecorations,UniformIdDecorationTargetsVoidValueBad)5325 TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad) {
5326 const std::string spirv = ShaderWithUniformLikeDecoration(
5327 "OpDecorateId %call UniformId %subgroupscope");
5328
5329 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5330 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4))
5331 << spirv;
5332 EXPECT_THAT(
5333 getDiagnosticString(),
5334 HasSubstr("UniformId decoration applied to a value with void type\n"
5335 " %call = OpFunctionCall %void %myfunc"));
5336 }
5337
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsFloatValueIsBad)5338 TEST_F(ValidateDecorations,
5339 UniformDecorationWithScopeIdV14IdIsFloatValueIsBad) {
5340 const std::string spirv =
5341 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %float0");
5342
5343 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5344 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5345 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5346 EXPECT_THAT(getDiagnosticString(),
5347 HasSubstr("ConstantNull: expected scope to be a 32-bit int"));
5348 }
5349
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad)5350 TEST_F(ValidateDecorations,
5351 UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad) {
5352 const std::string spirv =
5353 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int_99");
5354
5355 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5356 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5357 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5358 EXPECT_THAT(
5359 getDiagnosticString(),
5360 HasSubstr("Invalid scope value:\n %int_99 = OpConstant %int 99\n"));
5361 }
5362
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14VulkanEnv)5363 TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
5364 const std::string spirv =
5365 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int0");
5366
5367 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
5368 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
5369 ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
5370 EXPECT_THAT(getDiagnosticString(),
5371 AnyVUID("VUID-StandaloneSpirv-None-04636"));
5372 EXPECT_THAT(getDiagnosticString(),
5373 HasSubstr(": in Vulkan environment Execution Scope is limited to "
5374 "Workgroup and Subgroup"));
5375 }
5376
TEST_F(ValidateDecorations,UniformDecorationWithWrongInstructionBad)5377 TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) {
5378 const std::string spirv =
5379 ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform");
5380
5381 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
5382 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
5383 EXPECT_THAT(getDiagnosticString(),
5384 HasSubstr("Decorations that don't take ID parameters may not be "
5385 "used with OpDecorateId\n"
5386 " OpDecorateId %int0 Uniform"));
5387 }
5388
TEST_F(ValidateDecorations,UniformIdDecorationWithWrongInstructionBad)5389 TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) {
5390 const std::string spirv = ShaderWithUniformLikeDecoration(
5391 "OpDecorate %int0 UniformId %subgroupscope");
5392
5393 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5394 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5395 EXPECT_THAT(
5396 getDiagnosticString(),
5397 HasSubstr(
5398 "Decorations taking ID parameters may not be used with OpDecorateId\n"
5399 " OpDecorate %int0 UniformId %subgroupscope"));
5400 }
5401
TEST_F(ValidateDecorations,MultipleOffsetDecorationsOnSameID)5402 TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) {
5403 std::string spirv = R"(
5404 OpCapability Shader
5405 OpMemoryModel Logical GLSL450
5406 OpEntryPoint Fragment %1 "main"
5407 OpExecutionMode %1 OriginUpperLeft
5408
5409 OpMemberDecorate %struct 0 Offset 0
5410 OpMemberDecorate %struct 0 Offset 0
5411
5412 %void = OpTypeVoid
5413 %voidfn = OpTypeFunction %void
5414 %float = OpTypeFloat 32
5415 %struct = OpTypeStruct %float
5416
5417 %1 = OpFunction %void None %voidfn
5418 %label = OpLabel
5419 OpReturn
5420 OpFunctionEnd
5421 )";
5422
5423 CompileSuccessfully(spirv);
5424 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5425 EXPECT_THAT(getDiagnosticString(),
5426 HasSubstr("ID '2', member '0' decorated with Offset multiple "
5427 "times is not allowed."));
5428 }
5429
TEST_F(ValidateDecorations,MultipleArrayStrideDecorationsOnSameID)5430 TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) {
5431 std::string spirv = R"(
5432 OpCapability Shader
5433 OpMemoryModel Logical GLSL450
5434 OpEntryPoint Fragment %1 "main"
5435 OpExecutionMode %1 OriginUpperLeft
5436
5437 OpDecorate %array ArrayStride 4
5438 OpDecorate %array ArrayStride 4
5439
5440 %void = OpTypeVoid
5441 %voidfn = OpTypeFunction %void
5442 %float = OpTypeFloat 32
5443 %uint = OpTypeInt 32 0
5444 %uint_4 = OpConstant %uint 4
5445 %array = OpTypeArray %float %uint_4
5446
5447 %1 = OpFunction %void None %voidfn
5448 %label = OpLabel
5449 OpReturn
5450 OpFunctionEnd
5451 )";
5452
5453 CompileSuccessfully(spirv);
5454 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5455 EXPECT_THAT(getDiagnosticString(),
5456 HasSubstr("ID '2' decorated with ArrayStride multiple "
5457 "times is not allowed."));
5458 }
5459
TEST_F(ValidateDecorations,MultipleMatrixStrideDecorationsOnSameID)5460 TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) {
5461 std::string spirv = R"(
5462 OpCapability Shader
5463 OpMemoryModel Logical GLSL450
5464 OpEntryPoint Fragment %1 "main"
5465 OpExecutionMode %1 OriginUpperLeft
5466
5467 OpMemberDecorate %struct 0 Offset 0
5468 OpMemberDecorate %struct 0 ColMajor
5469 OpMemberDecorate %struct 0 MatrixStride 16
5470 OpMemberDecorate %struct 0 MatrixStride 16
5471
5472 %void = OpTypeVoid
5473 %voidfn = OpTypeFunction %void
5474 %float = OpTypeFloat 32
5475 %fvec4 = OpTypeVector %float 4
5476 %fmat4 = OpTypeMatrix %fvec4 4
5477 %struct = OpTypeStruct %fmat4
5478
5479 %1 = OpFunction %void None %voidfn
5480 %label = OpLabel
5481 OpReturn
5482 OpFunctionEnd
5483 )";
5484
5485 CompileSuccessfully(spirv);
5486 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5487 EXPECT_THAT(getDiagnosticString(),
5488 HasSubstr("ID '2', member '0' decorated with MatrixStride "
5489 "multiple times is not allowed."));
5490 }
5491
TEST_F(ValidateDecorations,MultipleRowMajorDecorationsOnSameID)5492 TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) {
5493 std::string spirv = R"(
5494 OpCapability Shader
5495 OpMemoryModel Logical GLSL450
5496 OpEntryPoint Fragment %1 "main"
5497 OpExecutionMode %1 OriginUpperLeft
5498
5499 OpMemberDecorate %struct 0 Offset 0
5500 OpMemberDecorate %struct 0 MatrixStride 16
5501 OpMemberDecorate %struct 0 RowMajor
5502 OpMemberDecorate %struct 0 RowMajor
5503
5504 %void = OpTypeVoid
5505 %voidfn = OpTypeFunction %void
5506 %float = OpTypeFloat 32
5507 %fvec4 = OpTypeVector %float 4
5508 %fmat4 = OpTypeMatrix %fvec4 4
5509 %struct = OpTypeStruct %fmat4
5510
5511 %1 = OpFunction %void None %voidfn
5512 %label = OpLabel
5513 OpReturn
5514 OpFunctionEnd
5515 )";
5516
5517 CompileSuccessfully(spirv);
5518 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5519 EXPECT_THAT(getDiagnosticString(),
5520 HasSubstr("ID '2', member '0' decorated with RowMajor multiple "
5521 "times is not allowed."));
5522 }
5523
TEST_F(ValidateDecorations,MultipleColMajorDecorationsOnSameID)5524 TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) {
5525 std::string spirv = R"(
5526 OpCapability Shader
5527 OpMemoryModel Logical GLSL450
5528 OpEntryPoint Fragment %1 "main"
5529 OpExecutionMode %1 OriginUpperLeft
5530
5531 OpMemberDecorate %struct 0 Offset 0
5532 OpMemberDecorate %struct 0 MatrixStride 16
5533 OpMemberDecorate %struct 0 ColMajor
5534 OpMemberDecorate %struct 0 ColMajor
5535
5536 %void = OpTypeVoid
5537 %voidfn = OpTypeFunction %void
5538 %float = OpTypeFloat 32
5539 %fvec4 = OpTypeVector %float 4
5540 %fmat4 = OpTypeMatrix %fvec4 4
5541 %struct = OpTypeStruct %fmat4
5542
5543 %1 = OpFunction %void None %voidfn
5544 %label = OpLabel
5545 OpReturn
5546 OpFunctionEnd
5547 )";
5548
5549 CompileSuccessfully(spirv);
5550 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5551 EXPECT_THAT(getDiagnosticString(),
5552 HasSubstr("ID '2', member '0' decorated with ColMajor multiple "
5553 "times is not allowed."));
5554 }
5555
TEST_F(ValidateDecorations,RowMajorAndColMajorDecorationsOnSameID)5556 TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) {
5557 std::string spirv = R"(
5558 OpCapability Shader
5559 OpMemoryModel Logical GLSL450
5560 OpEntryPoint Fragment %1 "main"
5561 OpExecutionMode %1 OriginUpperLeft
5562
5563 OpMemberDecorate %struct 0 Offset 0
5564 OpMemberDecorate %struct 0 MatrixStride 16
5565 OpMemberDecorate %struct 0 ColMajor
5566 OpMemberDecorate %struct 0 RowMajor
5567
5568 %void = OpTypeVoid
5569 %voidfn = OpTypeFunction %void
5570 %float = OpTypeFloat 32
5571 %fvec4 = OpTypeVector %float 4
5572 %fmat4 = OpTypeMatrix %fvec4 4
5573 %struct = OpTypeStruct %fmat4
5574
5575 %1 = OpFunction %void None %voidfn
5576 %label = OpLabel
5577 OpReturn
5578 OpFunctionEnd
5579 )";
5580
5581 CompileSuccessfully(spirv);
5582 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5583 EXPECT_THAT(getDiagnosticString(),
5584 HasSubstr("ID '2', member '0' decorated with both RowMajor and "
5585 "ColMajor is not allowed."));
5586 }
5587
TEST_F(ValidateDecorations,BlockAndBufferBlockDecorationsOnSameID)5588 TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
5589 std::string spirv = R"(
5590 OpCapability Shader
5591 OpMemoryModel Logical GLSL450
5592 OpEntryPoint Fragment %1 "main"
5593 OpExecutionMode %1 OriginUpperLeft
5594
5595 OpDecorate %struct Block
5596 OpDecorate %struct BufferBlock
5597 OpMemberDecorate %struct 0 Offset 0
5598 OpMemberDecorate %struct 0 MatrixStride 16
5599 OpMemberDecorate %struct 0 RowMajor
5600
5601 %void = OpTypeVoid
5602 %voidfn = OpTypeFunction %void
5603 %float = OpTypeFloat 32
5604 %fvec4 = OpTypeVector %float 4
5605 %fmat4 = OpTypeMatrix %fvec4 4
5606 %struct = OpTypeStruct %fmat4
5607
5608 %1 = OpFunction %void None %voidfn
5609 %label = OpLabel
5610 OpReturn
5611 OpFunctionEnd
5612 )";
5613
5614 CompileSuccessfully(spirv);
5615 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5616 EXPECT_THAT(
5617 getDiagnosticString(),
5618 HasSubstr(
5619 "ID '2' decorated with both BufferBlock and Block is not allowed."));
5620 }
5621
MakeIntegerShader(const std::string & decoration,const std::string & inst,const std::string & extension="OpExtension \\"SPV_KHR_no_integer_wrap_decoration\\"")5622 std::string MakeIntegerShader(
5623 const std::string& decoration, const std::string& inst,
5624 const std::string& extension =
5625 "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
5626 return R"(
5627 OpCapability Shader
5628 OpCapability Linkage
5629 )" + extension +
5630 R"(
5631 %glsl = OpExtInstImport "GLSL.std.450"
5632 %opencl = OpExtInstImport "OpenCL.std"
5633 OpMemoryModel Logical GLSL450
5634 OpEntryPoint GLCompute %main "main"
5635 OpName %entry "entry"
5636 )" + decoration +
5637 R"(
5638 %void = OpTypeVoid
5639 %voidfn = OpTypeFunction %void
5640 %int = OpTypeInt 32 1
5641 %zero = OpConstantNull %int
5642 %float = OpTypeFloat 32
5643 %float0 = OpConstantNull %float
5644 %main = OpFunction %void None %voidfn
5645 %entry = OpLabel
5646 )" + inst +
5647 R"(
5648 OpReturn
5649 OpFunctionEnd)";
5650 }
5651
5652 // NoSignedWrap
5653
TEST_F(ValidateDecorations,NoSignedWrapOnTypeBad)5654 TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
5655 std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
5656
5657 CompileSuccessfully(spirv);
5658 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5659 EXPECT_THAT(
5660 getDiagnosticString(),
5661 HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
5662 }
5663
TEST_F(ValidateDecorations,NoSignedWrapOnLabelBad)5664 TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
5665 std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
5666
5667 CompileSuccessfully(spirv);
5668 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5669 EXPECT_THAT(getDiagnosticString(),
5670 HasSubstr("NoSignedWrap decoration may not be applied to Label"));
5671 }
5672
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionBad)5673 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
5674 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5675 "%val = OpIAdd %int %zero %zero", "");
5676
5677 CompileSuccessfully(spirv);
5678 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5679 EXPECT_THAT(getDiagnosticString(),
5680 HasSubstr("requires one of these extensions: "
5681 "SPV_KHR_no_integer_wrap_decoration"));
5682 }
5683
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionV13Bad)5684 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) {
5685 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5686 "%val = OpIAdd %int %zero %zero", "");
5687
5688 CompileSuccessfully(spirv);
5689 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5690 EXPECT_THAT(getDiagnosticString(),
5691 HasSubstr("requires one of these extensions: "
5692 "SPV_KHR_no_integer_wrap_decoration"));
5693 }
5694
TEST_F(ValidateDecorations,NoSignedWrapOkInSPV14Good)5695 TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) {
5696 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5697 "%val = OpIAdd %int %zero %zero", "");
5698
5699 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5700 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5701 EXPECT_THAT(getDiagnosticString(), Eq(""));
5702 }
5703
TEST_F(ValidateDecorations,NoSignedWrapIAddGood)5704 TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
5705 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5706 "%val = OpIAdd %int %zero %zero");
5707
5708 CompileSuccessfully(spirv);
5709 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5710 EXPECT_THAT(getDiagnosticString(), Eq(""));
5711 }
5712
TEST_F(ValidateDecorations,NoSignedWrapISubGood)5713 TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
5714 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5715 "%val = OpISub %int %zero %zero");
5716
5717 CompileSuccessfully(spirv);
5718 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5719 EXPECT_THAT(getDiagnosticString(), Eq(""));
5720 }
5721
TEST_F(ValidateDecorations,NoSignedWrapIMulGood)5722 TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
5723 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5724 "%val = OpIMul %int %zero %zero");
5725
5726 CompileSuccessfully(spirv);
5727 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5728 EXPECT_THAT(getDiagnosticString(), Eq(""));
5729 }
5730
TEST_F(ValidateDecorations,NoSignedWrapShiftLeftLogicalGood)5731 TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
5732 std::string spirv =
5733 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5734 "%val = OpShiftLeftLogical %int %zero %zero");
5735
5736 CompileSuccessfully(spirv);
5737 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5738 EXPECT_THAT(getDiagnosticString(), Eq(""));
5739 }
5740
TEST_F(ValidateDecorations,NoSignedWrapSNegateGood)5741 TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
5742 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5743 "%val = OpSNegate %int %zero");
5744
5745 CompileSuccessfully(spirv);
5746 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5747 EXPECT_THAT(getDiagnosticString(), Eq(""));
5748 }
5749
TEST_F(ValidateDecorations,NoSignedWrapSRemBad)5750 TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
5751 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5752 "%val = OpSRem %int %zero %zero");
5753
5754 CompileSuccessfully(spirv);
5755 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5756 EXPECT_THAT(getDiagnosticString(),
5757 HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
5758 }
5759
TEST_F(ValidateDecorations,NoSignedWrapFAddBad)5760 TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
5761 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5762 "%val = OpFAdd %float %float0 %float0");
5763
5764 CompileSuccessfully(spirv);
5765 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5766 EXPECT_THAT(getDiagnosticString(),
5767 HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
5768 }
5769
TEST_F(ValidateDecorations,NoSignedWrapExtInstOpenCLGood)5770 TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
5771 std::string spirv =
5772 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5773 "%val = OpExtInst %int %opencl s_abs %zero");
5774
5775 CompileSuccessfully(spirv);
5776 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5777 EXPECT_THAT(getDiagnosticString(), Eq(""));
5778 }
5779
TEST_F(ValidateDecorations,NoSignedWrapExtInstGLSLGood)5780 TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
5781 std::string spirv = MakeIntegerShader(
5782 "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
5783
5784 CompileSuccessfully(spirv);
5785 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5786 EXPECT_THAT(getDiagnosticString(), Eq(""));
5787 }
5788
5789 // TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
5790 // "OpExtInst for instruction numbers specified in the extended
5791 // instruction-set specifications as accepting this decoration."
5792
5793 // NoUnignedWrap
5794
TEST_F(ValidateDecorations,NoUnsignedWrapOnTypeBad)5795 TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
5796 std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
5797
5798 CompileSuccessfully(spirv);
5799 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5800 EXPECT_THAT(
5801 getDiagnosticString(),
5802 HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
5803 }
5804
TEST_F(ValidateDecorations,NoUnsignedWrapOnLabelBad)5805 TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
5806 std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
5807
5808 CompileSuccessfully(spirv);
5809 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5810 EXPECT_THAT(
5811 getDiagnosticString(),
5812 HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
5813 }
5814
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionBad)5815 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
5816 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5817 "%val = OpIAdd %int %zero %zero", "");
5818
5819 CompileSuccessfully(spirv);
5820 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5821 EXPECT_THAT(getDiagnosticString(),
5822 HasSubstr("requires one of these extensions: "
5823 "SPV_KHR_no_integer_wrap_decoration"));
5824 }
5825
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionV13Bad)5826 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) {
5827 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5828 "%val = OpIAdd %int %zero %zero", "");
5829
5830 CompileSuccessfully(spirv);
5831 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5832 EXPECT_THAT(getDiagnosticString(),
5833 HasSubstr("requires one of these extensions: "
5834 "SPV_KHR_no_integer_wrap_decoration"));
5835 }
5836
TEST_F(ValidateDecorations,NoUnsignedWrapOkInSPV14Good)5837 TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) {
5838 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5839 "%val = OpIAdd %int %zero %zero", "");
5840
5841 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5842 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5843 EXPECT_THAT(getDiagnosticString(), Eq(""));
5844 }
5845
TEST_F(ValidateDecorations,NoUnsignedWrapIAddGood)5846 TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
5847 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5848 "%val = OpIAdd %int %zero %zero");
5849
5850 CompileSuccessfully(spirv);
5851 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5852 EXPECT_THAT(getDiagnosticString(), Eq(""));
5853 }
5854
TEST_F(ValidateDecorations,NoUnsignedWrapISubGood)5855 TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
5856 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5857 "%val = OpISub %int %zero %zero");
5858
5859 CompileSuccessfully(spirv);
5860 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5861 EXPECT_THAT(getDiagnosticString(), Eq(""));
5862 }
5863
TEST_F(ValidateDecorations,NoUnsignedWrapIMulGood)5864 TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
5865 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5866 "%val = OpIMul %int %zero %zero");
5867
5868 CompileSuccessfully(spirv);
5869 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5870 EXPECT_THAT(getDiagnosticString(), Eq(""));
5871 }
5872
TEST_F(ValidateDecorations,NoUnsignedWrapShiftLeftLogicalGood)5873 TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
5874 std::string spirv =
5875 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5876 "%val = OpShiftLeftLogical %int %zero %zero");
5877
5878 CompileSuccessfully(spirv);
5879 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5880 EXPECT_THAT(getDiagnosticString(), Eq(""));
5881 }
5882
TEST_F(ValidateDecorations,NoUnsignedWrapSNegateGood)5883 TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
5884 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5885 "%val = OpSNegate %int %zero");
5886
5887 CompileSuccessfully(spirv);
5888 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5889 EXPECT_THAT(getDiagnosticString(), Eq(""));
5890 }
5891
TEST_F(ValidateDecorations,NoUnsignedWrapSRemBad)5892 TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
5893 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5894 "%val = OpSRem %int %zero %zero");
5895
5896 CompileSuccessfully(spirv);
5897 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5898 EXPECT_THAT(
5899 getDiagnosticString(),
5900 HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
5901 }
5902
TEST_F(ValidateDecorations,NoUnsignedWrapFAddBad)5903 TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
5904 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5905 "%val = OpFAdd %float %float0 %float0");
5906
5907 CompileSuccessfully(spirv);
5908 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5909 EXPECT_THAT(
5910 getDiagnosticString(),
5911 HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
5912 }
5913
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstOpenCLGood)5914 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
5915 std::string spirv =
5916 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5917 "%val = OpExtInst %int %opencl s_abs %zero");
5918
5919 CompileSuccessfully(spirv);
5920 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5921 EXPECT_THAT(getDiagnosticString(), Eq(""));
5922 }
5923
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstGLSLGood)5924 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
5925 std::string spirv =
5926 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5927 "%val = OpExtInst %int %glsl SAbs %zero");
5928
5929 CompileSuccessfully(spirv);
5930 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5931 EXPECT_THAT(getDiagnosticString(), Eq(""));
5932 }
5933
TEST_F(ValidateDecorations,AliasedandRestrictBad)5934 TEST_F(ValidateDecorations, AliasedandRestrictBad) {
5935 const std::string body = R"(
5936 OpCapability Shader
5937 %1 = OpExtInstImport "GLSL.std.450"
5938 OpMemoryModel Logical GLSL450
5939 OpEntryPoint GLCompute %main "main"
5940 OpExecutionMode %main LocalSize 1 1 1
5941 OpSource GLSL 430
5942 OpMemberDecorate %Output 0 Offset 0
5943 OpDecorate %Output BufferBlock
5944 OpDecorate %dataOutput Restrict
5945 OpDecorate %dataOutput Aliased
5946 %void = OpTypeVoid
5947 %3 = OpTypeFunction %void
5948 %float = OpTypeFloat 32
5949 %Output = OpTypeStruct %float
5950 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
5951 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
5952 %main = OpFunction %void None %3
5953 %5 = OpLabel
5954 OpReturn
5955 OpFunctionEnd
5956 )";
5957
5958 CompileSuccessfully(body.c_str());
5959 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5960 EXPECT_THAT(
5961 getDiagnosticString(),
5962 HasSubstr("decorated with both Aliased and Restrict is not allowed"));
5963 }
5964
5965 // TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
5966 // "OpExtInst for instruction numbers specified in the extended
5967 // instruction-set specifications as accepting this decoration."
5968
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerSuccess)5969 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
5970 const std::string body = R"(
5971 OpCapability PhysicalStorageBufferAddresses
5972 OpCapability Int64
5973 OpCapability Shader
5974 OpExtension "SPV_EXT_physical_storage_buffer"
5975 OpMemoryModel PhysicalStorageBuffer64 GLSL450
5976 OpEntryPoint Fragment %main "main"
5977 OpExecutionMode %main OriginUpperLeft
5978 OpDecorate %val1 RestrictPointer
5979 %uint64 = OpTypeInt 64 0
5980 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
5981 %pptr_f = OpTypePointer Function %ptr
5982 %void = OpTypeVoid
5983 %voidfn = OpTypeFunction %void
5984 %main = OpFunction %void None %voidfn
5985 %entry = OpLabel
5986 %val1 = OpVariable %pptr_f Function
5987 OpReturn
5988 OpFunctionEnd
5989 )";
5990
5991 CompileSuccessfully(body.c_str());
5992 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5993 }
5994
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerMissing)5995 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) {
5996 const std::string body = R"(
5997 OpCapability PhysicalStorageBufferAddresses
5998 OpCapability Int64
5999 OpCapability Shader
6000 OpExtension "SPV_EXT_physical_storage_buffer"
6001 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6002 OpEntryPoint Fragment %main "main"
6003 OpExecutionMode %main OriginUpperLeft
6004 %uint64 = OpTypeInt 64 0
6005 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6006 %pptr_f = OpTypePointer Function %ptr
6007 %void = OpTypeVoid
6008 %voidfn = OpTypeFunction %void
6009 %main = OpFunction %void None %voidfn
6010 %entry = OpLabel
6011 %val1 = OpVariable %pptr_f Function
6012 OpReturn
6013 OpFunctionEnd
6014 )";
6015
6016 CompileSuccessfully(body.c_str());
6017 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6018 EXPECT_THAT(getDiagnosticString(),
6019 HasSubstr("expected AliasedPointer or RestrictPointer for "
6020 "PhysicalStorageBuffer pointer"));
6021 }
6022
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerBoth)6023 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) {
6024 const std::string body = R"(
6025 OpCapability PhysicalStorageBufferAddresses
6026 OpCapability Int64
6027 OpCapability Shader
6028 OpExtension "SPV_EXT_physical_storage_buffer"
6029 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6030 OpEntryPoint Fragment %main "main"
6031 OpExecutionMode %main OriginUpperLeft
6032 OpDecorate %val1 RestrictPointer
6033 OpDecorate %val1 AliasedPointer
6034 %uint64 = OpTypeInt 64 0
6035 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6036 %pptr_f = OpTypePointer Function %ptr
6037 %void = OpTypeVoid
6038 %voidfn = OpTypeFunction %void
6039 %main = OpFunction %void None %voidfn
6040 %entry = OpLabel
6041 %val1 = OpVariable %pptr_f Function
6042 OpReturn
6043 OpFunctionEnd
6044 )";
6045
6046 CompileSuccessfully(body.c_str());
6047 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6048 EXPECT_THAT(getDiagnosticString(),
6049 HasSubstr("can't specify both AliasedPointer and RestrictPointer "
6050 "for PhysicalStorageBuffer pointer"));
6051 }
6052
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamSuccess)6053 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) {
6054 const std::string body = R"(
6055 OpCapability PhysicalStorageBufferAddresses
6056 OpCapability Int64
6057 OpCapability Shader
6058 OpExtension "SPV_EXT_physical_storage_buffer"
6059 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6060 OpEntryPoint Fragment %main "main"
6061 OpExecutionMode %main OriginUpperLeft
6062 OpDecorate %fparam Restrict
6063 %uint64 = OpTypeInt 64 0
6064 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6065 %void = OpTypeVoid
6066 %voidfn = OpTypeFunction %void
6067 %fnptr = OpTypeFunction %void %ptr
6068 %main = OpFunction %void None %voidfn
6069 %entry = OpLabel
6070 OpReturn
6071 OpFunctionEnd
6072 %fn = OpFunction %void None %fnptr
6073 %fparam = OpFunctionParameter %ptr
6074 %lab = OpLabel
6075 OpReturn
6076 OpFunctionEnd
6077 )";
6078
6079 CompileSuccessfully(body.c_str());
6080 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
6081 }
6082
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamMissing)6083 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) {
6084 const std::string body = R"(
6085 OpCapability PhysicalStorageBufferAddresses
6086 OpCapability Int64
6087 OpCapability Shader
6088 OpExtension "SPV_EXT_physical_storage_buffer"
6089 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6090 OpEntryPoint Fragment %main "main"
6091 OpExecutionMode %main OriginUpperLeft
6092 %uint64 = OpTypeInt 64 0
6093 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6094 %void = OpTypeVoid
6095 %voidfn = OpTypeFunction %void
6096 %fnptr = OpTypeFunction %void %ptr
6097 %main = OpFunction %void None %voidfn
6098 %entry = OpLabel
6099 OpReturn
6100 OpFunctionEnd
6101 %fn = OpFunction %void None %fnptr
6102 %fparam = OpFunctionParameter %ptr
6103 %lab = OpLabel
6104 OpReturn
6105 OpFunctionEnd
6106 )";
6107
6108 CompileSuccessfully(body.c_str());
6109 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6110 EXPECT_THAT(getDiagnosticString(),
6111 HasSubstr("expected Aliased or Restrict for "
6112 "PhysicalStorageBuffer pointer"));
6113 }
6114
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamBoth)6115 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
6116 const std::string body = R"(
6117 OpCapability PhysicalStorageBufferAddresses
6118 OpCapability Int64
6119 OpCapability Shader
6120 OpExtension "SPV_EXT_physical_storage_buffer"
6121 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6122 OpEntryPoint Fragment %main "main"
6123 OpExecutionMode %main OriginUpperLeft
6124 OpDecorate %fparam Restrict
6125 OpDecorate %fparam Aliased
6126 %uint64 = OpTypeInt 64 0
6127 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
6128 %void = OpTypeVoid
6129 %voidfn = OpTypeFunction %void
6130 %fnptr = OpTypeFunction %void %ptr
6131 %main = OpFunction %void None %voidfn
6132 %entry = OpLabel
6133 OpReturn
6134 OpFunctionEnd
6135 %fn = OpFunction %void None %fnptr
6136 %fparam = OpFunctionParameter %ptr
6137 %lab = OpLabel
6138 OpReturn
6139 OpFunctionEnd
6140 )";
6141
6142 CompileSuccessfully(body.c_str());
6143 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6144 EXPECT_THAT(getDiagnosticString(),
6145 HasSubstr("can't specify both Aliased and Restrict for "
6146 "PhysicalStorageBuffer pointer"));
6147 }
6148
TEST_F(ValidateDecorations,PSBFPRoundingModeSuccess)6149 TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) {
6150 std::string spirv = R"(
6151 OpCapability PhysicalStorageBufferAddresses
6152 OpCapability Shader
6153 OpCapability Linkage
6154 OpCapability StorageBuffer16BitAccess
6155 OpExtension "SPV_EXT_physical_storage_buffer"
6156 OpExtension "SPV_KHR_storage_buffer_storage_class"
6157 OpExtension "SPV_KHR_variable_pointers"
6158 OpExtension "SPV_KHR_16bit_storage"
6159 OpMemoryModel PhysicalStorageBuffer64 GLSL450
6160 OpEntryPoint GLCompute %main "main"
6161 OpDecorate %_ FPRoundingMode RTE
6162 OpDecorate %half_ptr_var AliasedPointer
6163 %half = OpTypeFloat 16
6164 %float = OpTypeFloat 32
6165 %float_1_25 = OpConstant %float 1.25
6166 %half_ptr = OpTypePointer PhysicalStorageBuffer %half
6167 %half_pptr_f = OpTypePointer Function %half_ptr
6168 %void = OpTypeVoid
6169 %func = OpTypeFunction %void
6170 %main = OpFunction %void None %func
6171 %main_entry = OpLabel
6172 %half_ptr_var = OpVariable %half_pptr_f Function
6173 %val1 = OpLoad %half_ptr %half_ptr_var
6174 %_ = OpFConvert %half %float_1_25
6175 OpStore %val1 %_ Aligned 2
6176 OpReturn
6177 OpFunctionEnd
6178 )";
6179
6180 CompileSuccessfully(spirv);
6181 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6182 }
6183
TEST_F(ValidateDecorations,InvalidStraddle)6184 TEST_F(ValidateDecorations, InvalidStraddle) {
6185 const std::string spirv = R"(
6186 OpCapability Shader
6187 OpMemoryModel Logical GLSL450
6188 OpEntryPoint GLCompute %main "main"
6189 OpExecutionMode %main LocalSize 1 1 1
6190 OpMemberDecorate %inner_struct 0 Offset 0
6191 OpMemberDecorate %inner_struct 1 Offset 4
6192 OpDecorate %outer_struct Block
6193 OpMemberDecorate %outer_struct 0 Offset 0
6194 OpMemberDecorate %outer_struct 1 Offset 8
6195 OpDecorate %var DescriptorSet 0
6196 OpDecorate %var Binding 0
6197 %void = OpTypeVoid
6198 %float = OpTypeFloat 32
6199 %float2 = OpTypeVector %float 2
6200 %inner_struct = OpTypeStruct %float %float2
6201 %outer_struct = OpTypeStruct %float2 %inner_struct
6202 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct
6203 %var = OpVariable %ptr_ssbo_outer StorageBuffer
6204 %void_fn = OpTypeFunction %void
6205 %main = OpFunction %void None %void_fn
6206 %entry = OpLabel
6207 OpReturn
6208 OpFunctionEnd
6209 )";
6210
6211 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6212 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6213 EXPECT_THAT(getDiagnosticString(),
6214 HasSubstr("Structure id 2 decorated as Block for variable in "
6215 "StorageBuffer storage class must follow relaxed "
6216 "storage buffer layout rules: member 1 is an "
6217 "improperly straddling vector at offset 12"));
6218 }
6219
TEST_F(ValidateDecorations,DescriptorArray)6220 TEST_F(ValidateDecorations, DescriptorArray) {
6221 const std::string spirv = R"(
6222 OpCapability Shader
6223 OpExtension "SPV_KHR_storage_buffer_storage_class"
6224 OpMemoryModel Logical GLSL450
6225 OpEntryPoint GLCompute %main "main"
6226 OpExecutionMode %main LocalSize 1 1 1
6227 OpDecorate %struct Block
6228 OpMemberDecorate %struct 0 Offset 0
6229 OpMemberDecorate %struct 1 Offset 1
6230 OpDecorate %var DescriptorSet 0
6231 OpDecorate %var Binding 0
6232 %void = OpTypeVoid
6233 %float = OpTypeFloat 32
6234 %int = OpTypeInt 32 0
6235 %int_2 = OpConstant %int 2
6236 %float2 = OpTypeVector %float 2
6237 %struct = OpTypeStruct %float %float2
6238 %struct_array = OpTypeArray %struct %int_2
6239 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6240 %var = OpVariable %ptr_ssbo_array StorageBuffer
6241 %void_fn = OpTypeFunction %void
6242 %main = OpFunction %void None %void_fn
6243 %entry = OpLabel
6244 OpReturn
6245 OpFunctionEnd
6246 )";
6247
6248 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6249 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6250 EXPECT_THAT(getDiagnosticString(),
6251 HasSubstr("Structure id 2 decorated as Block for variable in "
6252 "StorageBuffer storage class must follow standard "
6253 "storage buffer layout rules: member 1 at offset 1 is "
6254 "not aligned to 8"));
6255 }
6256
TEST_F(ValidateDecorations,DescriptorRuntimeArray)6257 TEST_F(ValidateDecorations, DescriptorRuntimeArray) {
6258 const std::string spirv = R"(
6259 OpCapability Shader
6260 OpCapability RuntimeDescriptorArrayEXT
6261 OpExtension "SPV_KHR_storage_buffer_storage_class"
6262 OpExtension "SPV_EXT_descriptor_indexing"
6263 OpMemoryModel Logical GLSL450
6264 OpEntryPoint GLCompute %main "main"
6265 OpExecutionMode %main LocalSize 1 1 1
6266 OpDecorate %struct Block
6267 OpMemberDecorate %struct 0 Offset 0
6268 OpMemberDecorate %struct 1 Offset 1
6269 OpDecorate %var DescriptorSet 0
6270 OpDecorate %var Binding 0
6271 %void = OpTypeVoid
6272 %float = OpTypeFloat 32
6273 %int = OpTypeInt 32 0
6274 %float2 = OpTypeVector %float 2
6275 %struct = OpTypeStruct %float %float2
6276 %struct_array = OpTypeRuntimeArray %struct
6277 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
6278 %var = OpVariable %ptr_ssbo_array StorageBuffer
6279 %void_fn = OpTypeFunction %void
6280 %main = OpFunction %void None %void_fn
6281 %entry = OpLabel
6282 OpReturn
6283 OpFunctionEnd
6284 )";
6285
6286 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6287 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6288 EXPECT_THAT(getDiagnosticString(),
6289 HasSubstr("Structure id 2 decorated as Block for variable in "
6290 "StorageBuffer storage class must follow standard "
6291 "storage buffer layout rules: member 1 at offset 1 is "
6292 "not aligned to 8"));
6293 }
6294
TEST_F(ValidateDecorations,MultiDimensionalArray)6295 TEST_F(ValidateDecorations, MultiDimensionalArray) {
6296 const std::string spirv = R"(
6297 OpCapability Shader
6298 OpMemoryModel Logical GLSL450
6299 OpEntryPoint GLCompute %main "main"
6300 OpExecutionMode %main LocalSize 1 1 1
6301 OpDecorate %struct Block
6302 OpMemberDecorate %struct 0 Offset 0
6303 OpDecorate %array_4 ArrayStride 4
6304 OpDecorate %array_3 ArrayStride 48
6305 OpDecorate %var DescriptorSet 0
6306 OpDecorate %var Binding 0
6307 %void = OpTypeVoid
6308 %int = OpTypeInt 32 0
6309 %int_3 = OpConstant %int 3
6310 %int_4 = OpConstant %int 4
6311 %array_4 = OpTypeArray %int %int_4
6312 %array_3 = OpTypeArray %array_4 %int_3
6313 %struct = OpTypeStruct %array_3
6314 %ptr_struct = OpTypePointer Uniform %struct
6315 %var = OpVariable %ptr_struct Uniform
6316 %void_fn = OpTypeFunction %void
6317 %main = OpFunction %void None %void_fn
6318 %entry = OpLabel
6319 OpReturn
6320 OpFunctionEnd
6321 )";
6322
6323 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6324 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6325 EXPECT_THAT(getDiagnosticString(),
6326 HasSubstr("Structure id 2 decorated as Block for variable in "
6327 "Uniform storage class must follow standard uniform "
6328 "buffer layout rules: member 0 contains an array with "
6329 "stride 4 not satisfying alignment to 16"));
6330 }
6331
TEST_F(ValidateDecorations,ImproperStraddleInArray)6332 TEST_F(ValidateDecorations, ImproperStraddleInArray) {
6333 const std::string spirv = R"(
6334 OpCapability Shader
6335 OpMemoryModel Logical GLSL450
6336 OpEntryPoint GLCompute %main "main"
6337 OpExecutionMode %main LocalSize 1 1 1
6338 OpDecorate %struct Block
6339 OpMemberDecorate %struct 0 Offset 0
6340 OpDecorate %array ArrayStride 24
6341 OpMemberDecorate %inner 0 Offset 0
6342 OpMemberDecorate %inner 1 Offset 4
6343 OpMemberDecorate %inner 2 Offset 12
6344 OpMemberDecorate %inner 3 Offset 16
6345 OpDecorate %var DescriptorSet 0
6346 OpDecorate %var Binding 0
6347 %void = OpTypeVoid
6348 %int = OpTypeInt 32 0
6349 %int_2 = OpConstant %int 2
6350 %int2 = OpTypeVector %int 2
6351 %inner = OpTypeStruct %int %int2 %int %int
6352 %array = OpTypeArray %inner %int_2
6353 %struct = OpTypeStruct %array
6354 %ptr_struct = OpTypePointer StorageBuffer %struct
6355 %var = OpVariable %ptr_struct StorageBuffer
6356 %void_fn = OpTypeFunction %void
6357 %main = OpFunction %void None %void_fn
6358 %entry = OpLabel
6359 OpReturn
6360 OpFunctionEnd
6361 )";
6362
6363 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6364 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6365 EXPECT_THAT(getDiagnosticString(),
6366 HasSubstr("Structure id 4 decorated as Block for variable in "
6367 "StorageBuffer storage class must follow relaxed "
6368 "storage buffer layout rules: member 1 is an "
6369 "improperly straddling vector at offset 28"));
6370 }
6371
TEST_F(ValidateDecorations,LargeArray)6372 TEST_F(ValidateDecorations, LargeArray) {
6373 const std::string spirv = R"(
6374 OpCapability Shader
6375 OpMemoryModel Logical GLSL450
6376 OpEntryPoint GLCompute %main "main"
6377 OpExecutionMode %main LocalSize 1 1 1
6378 OpDecorate %struct Block
6379 OpMemberDecorate %struct 0 Offset 0
6380 OpDecorate %array ArrayStride 24
6381 OpMemberDecorate %inner 0 Offset 0
6382 OpMemberDecorate %inner 1 Offset 8
6383 OpMemberDecorate %inner 2 Offset 16
6384 OpMemberDecorate %inner 3 Offset 20
6385 OpDecorate %var DescriptorSet 0
6386 OpDecorate %var Binding 0
6387 %void = OpTypeVoid
6388 %int = OpTypeInt 32 0
6389 %int_2000000 = OpConstant %int 2000000
6390 %int2 = OpTypeVector %int 2
6391 %inner = OpTypeStruct %int %int2 %int %int
6392 %array = OpTypeArray %inner %int_2000000
6393 %struct = OpTypeStruct %array
6394 %ptr_struct = OpTypePointer StorageBuffer %struct
6395 %var = OpVariable %ptr_struct StorageBuffer
6396 %void_fn = OpTypeFunction %void
6397 %main = OpFunction %void None %void_fn
6398 %entry = OpLabel
6399 OpReturn
6400 OpFunctionEnd
6401 )";
6402
6403 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6404 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6405 }
6406
6407 // NonWritable
6408
6409 // Returns a SPIR-V shader module with variables in various storage classes,
6410 // parameterizable by which ID should be decorated as NonWritable.
ShaderWithNonWritableTarget(const std::string & target,bool member_decorate=false)6411 std::string ShaderWithNonWritableTarget(const std::string& target,
6412 bool member_decorate = false) {
6413 const std::string decoration_inst =
6414 std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") +
6415 target + (member_decorate ? " 0" : "");
6416
6417 return std::string(R"(
6418 OpCapability Shader
6419 OpCapability RuntimeDescriptorArrayEXT
6420 OpExtension "SPV_EXT_descriptor_indexing"
6421 OpExtension "SPV_KHR_storage_buffer_storage_class"
6422 OpMemoryModel Logical GLSL450
6423 OpEntryPoint Vertex %main "main"
6424 OpName %label "label"
6425 OpName %param_f "param_f"
6426 OpName %param_p "param_p"
6427 OpName %_ptr_imstor "_ptr_imstor"
6428 OpName %_ptr_imsam "_ptr_imsam"
6429 OpName %var_wg "var_wg"
6430 OpName %var_imsam "var_imsam"
6431 OpName %var_priv "var_priv"
6432 OpName %var_func "var_func"
6433 OpName %simple_struct "simple_struct"
6434
6435 OpDecorate %struct_b Block
6436 OpDecorate %struct_b_rtarr Block
6437 OpMemberDecorate %struct_b 0 Offset 0
6438 OpMemberDecorate %struct_b_rtarr 0 Offset 0
6439 OpDecorate %rtarr ArrayStride 4
6440 )") + decoration_inst +
6441
6442 R"( NonWritable
6443
6444 %void = OpTypeVoid
6445 %void_fn = OpTypeFunction %void
6446 %float = OpTypeFloat 32
6447 %float_0 = OpConstant %float 0
6448 %int = OpTypeInt 32 0
6449 %int_2 = OpConstant %int 2
6450 %struct_b = OpTypeStruct %float
6451 %rtarr = OpTypeRuntimeArray %float
6452 %struct_b_rtarr = OpTypeStruct %rtarr
6453 %simple_struct = OpTypeStruct %float
6454 ; storage image
6455 %imstor = OpTypeImage %float 2D 0 0 0 2 R32f
6456 ; sampled image
6457 %imsam = OpTypeImage %float 2D 0 0 0 1 R32f
6458 %array_imstor = OpTypeArray %imstor %int_2
6459 %rta_imstor = OpTypeRuntimeArray %imstor
6460
6461 %_ptr_Uniform_stb = OpTypePointer Uniform %struct_b
6462 %_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b
6463 %_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr
6464 %_ptr_Workgroup = OpTypePointer Workgroup %float
6465 %_ptr_Private = OpTypePointer Private %float
6466 %_ptr_Function = OpTypePointer Function %float
6467 %_ptr_imstor = OpTypePointer UniformConstant %imstor
6468 %_ptr_imsam = OpTypePointer UniformConstant %imsam
6469 %_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor
6470 %_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor
6471
6472 %extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor
6473
6474 %var_ubo = OpVariable %_ptr_Uniform_stb Uniform
6475 %var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer
6476 %var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer
6477 %var_wg = OpVariable %_ptr_Workgroup Workgroup
6478 %var_priv = OpVariable %_ptr_Private Private
6479 %var_imstor = OpVariable %_ptr_imstor UniformConstant
6480 %var_imsam = OpVariable %_ptr_imsam UniformConstant
6481 %var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant
6482 %var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant
6483
6484 %helper = OpFunction %void None %extra_fn
6485 %param_f = OpFunctionParameter %float
6486 %param_p = OpFunctionParameter %_ptr_Private
6487 %param_pimstor = OpFunctionParameter %_ptr_imstor
6488 %helper_label = OpLabel
6489 %helper_func_var = OpVariable %_ptr_Function Function
6490 OpReturn
6491 OpFunctionEnd
6492
6493 %main = OpFunction %void None %void_fn
6494 %label = OpLabel
6495 %var_func = OpVariable %_ptr_Function Function
6496 OpReturn
6497 OpFunctionEnd
6498 )";
6499 }
6500
TEST_F(ValidateDecorations,NonWritableLabelTargetBad)6501 TEST_F(ValidateDecorations, NonWritableLabelTargetBad) {
6502 std::string spirv = ShaderWithNonWritableTarget("%label");
6503
6504 CompileSuccessfully(spirv);
6505 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6506 EXPECT_THAT(getDiagnosticString(),
6507 HasSubstr("must be a memory object declaration"));
6508 }
6509
TEST_F(ValidateDecorations,NonWritableTypeTargetBad)6510 TEST_F(ValidateDecorations, NonWritableTypeTargetBad) {
6511 std::string spirv = ShaderWithNonWritableTarget("%void");
6512
6513 CompileSuccessfully(spirv);
6514 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6515 EXPECT_THAT(getDiagnosticString(),
6516 HasSubstr("must be a memory object declaration"));
6517 }
6518
TEST_F(ValidateDecorations,NonWritableValueTargetBad)6519 TEST_F(ValidateDecorations, NonWritableValueTargetBad) {
6520 std::string spirv = ShaderWithNonWritableTarget("%float_0");
6521
6522 CompileSuccessfully(spirv);
6523 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6524 EXPECT_THAT(getDiagnosticString(),
6525 HasSubstr("must be a memory object declaration"));
6526 }
6527
TEST_F(ValidateDecorations,NonWritableValueParamBad)6528 TEST_F(ValidateDecorations, NonWritableValueParamBad) {
6529 std::string spirv = ShaderWithNonWritableTarget("%param_f");
6530
6531 CompileSuccessfully(spirv);
6532 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6533 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
6534 }
6535
TEST_F(ValidateDecorations,NonWritablePointerParamButWrongTypeBad)6536 TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) {
6537 std::string spirv = ShaderWithNonWritableTarget("%param_p");
6538
6539 CompileSuccessfully(spirv);
6540 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6541 EXPECT_THAT(
6542 getDiagnosticString(),
6543 HasSubstr(
6544 "Target of NonWritable decoration is invalid: must "
6545 "point to a storage image, uniform block, or storage "
6546 "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float"));
6547 }
6548
TEST_F(ValidateDecorations,NonWritablePointerParamStorageImageGood)6549 TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) {
6550 std::string spirv = ShaderWithNonWritableTarget("%param_pimstor");
6551
6552 CompileSuccessfully(spirv);
6553 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6554 EXPECT_THAT(getDiagnosticString(), Eq(""));
6555 }
6556
TEST_F(ValidateDecorations,NonWritableVarStorageImageGood)6557 TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) {
6558 std::string spirv = ShaderWithNonWritableTarget("%var_imstor");
6559
6560 CompileSuccessfully(spirv);
6561 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6562 EXPECT_THAT(getDiagnosticString(), Eq(""));
6563 }
6564
TEST_F(ValidateDecorations,NonWritableVarSampledImageBad)6565 TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) {
6566 std::string spirv = ShaderWithNonWritableTarget("%var_imsam");
6567
6568 CompileSuccessfully(spirv);
6569 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6570 EXPECT_THAT(getDiagnosticString(),
6571 HasSubstr("Target of NonWritable decoration is invalid: must "
6572 "point to a storage image, uniform block, or storage "
6573 "buffer\n %var_imsam"));
6574 }
6575
TEST_F(ValidateDecorations,NonWritableVarUboGood)6576 TEST_F(ValidateDecorations, NonWritableVarUboGood) {
6577 std::string spirv = ShaderWithNonWritableTarget("%var_ubo");
6578
6579 CompileSuccessfully(spirv);
6580 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6581 EXPECT_THAT(getDiagnosticString(), Eq(""));
6582 }
6583
TEST_F(ValidateDecorations,NonWritableVarSsboInUniformGood)6584 TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) {
6585 const std::string spirv = R"(
6586 OpCapability Shader
6587 OpMemoryModel Logical GLSL450
6588 OpEntryPoint Vertex %main "main"
6589 OpDecorate %struct_bb BufferBlock
6590 OpMemberDecorate %struct_bb 0 Offset 0
6591 OpDecorate %var_ssbo_u NonWritable
6592 %void = OpTypeVoid
6593 %void_fn = OpTypeFunction %void
6594 %float = OpTypeFloat 32
6595 %struct_bb = OpTypeStruct %float
6596 %_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb
6597 %var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform
6598 %main = OpFunction %void None %void_fn
6599 %label = OpLabel
6600 OpReturn
6601 OpFunctionEnd
6602 )";
6603
6604 CompileSuccessfully(spirv);
6605 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6606 EXPECT_THAT(getDiagnosticString(), Eq(""));
6607 }
6608
TEST_F(ValidateDecorations,NonWritableVarSsboInStorageBufferGood)6609 TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) {
6610 std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb");
6611
6612 CompileSuccessfully(spirv);
6613 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6614 EXPECT_THAT(getDiagnosticString(), Eq(""));
6615 }
6616
TEST_F(ValidateDecorations,NonWritableMemberOfSsboInStorageBufferGood)6617 TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) {
6618 std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true);
6619
6620 CompileSuccessfully(spirv);
6621 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6622 EXPECT_THAT(getDiagnosticString(), Eq(""));
6623 }
6624
TEST_F(ValidateDecorations,NonWritableMemberOfStructGood)6625 TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) {
6626 std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true);
6627
6628 CompileSuccessfully(spirv);
6629 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6630 }
6631
TEST_F(ValidateDecorations,NonWritableVarWorkgroupBad)6632 TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) {
6633 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6634
6635 CompileSuccessfully(spirv);
6636 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6637 EXPECT_THAT(getDiagnosticString(),
6638 HasSubstr("Target of NonWritable decoration is invalid: must "
6639 "point to a storage image, uniform block, or storage "
6640 "buffer\n %var_wg"));
6641 }
6642
TEST_F(ValidateDecorations,NonWritableVarWorkgroupV14Bad)6643 TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) {
6644 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6645
6646 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6647 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6648 EXPECT_THAT(getDiagnosticString(),
6649 HasSubstr("Target of NonWritable decoration is invalid: must "
6650 "point to a storage image, uniform block, storage "
6651 "buffer, or variable in Private or Function storage "
6652 "class\n %var_wg"));
6653 }
6654
TEST_F(ValidateDecorations,NonWritableVarPrivateBad)6655 TEST_F(ValidateDecorations, NonWritableVarPrivateBad) {
6656 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6657
6658 CompileSuccessfully(spirv);
6659 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6660 EXPECT_THAT(getDiagnosticString(),
6661 HasSubstr("Target of NonWritable decoration is invalid: must "
6662 "point to a storage image, uniform block, or storage "
6663 "buffer\n %var_priv"));
6664 }
6665
TEST_F(ValidateDecorations,NonWritableVarPrivateV13Bad)6666 TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) {
6667 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6668
6669 CompileSuccessfully(spirv);
6670 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6671 EXPECT_THAT(getDiagnosticString(),
6672 HasSubstr("Target of NonWritable decoration is invalid: must "
6673 "point to a storage image, uniform block, or storage "
6674 "buffer\n %var_priv"));
6675 }
6676
TEST_F(ValidateDecorations,NonWritableVarPrivateV14Good)6677 TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) {
6678 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6679
6680 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6681 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6682 EXPECT_THAT(getDiagnosticString(), Eq(""));
6683 }
6684
TEST_F(ValidateDecorations,NonWritableVarPrivateV13TargetV14Bad)6685 TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) {
6686 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6687
6688 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6689 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6690 EXPECT_THAT(getDiagnosticString(),
6691 HasSubstr("Target of NonWritable decoration is invalid: must "
6692 "point to a storage image, uniform block, or storage "
6693 "buffer\n %var_priv"));
6694 }
6695
TEST_F(ValidateDecorations,NonWritableVarFunctionBad)6696 TEST_F(ValidateDecorations, NonWritableVarFunctionBad) {
6697 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6698
6699 CompileSuccessfully(spirv);
6700 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6701 EXPECT_THAT(getDiagnosticString(),
6702 HasSubstr("Target of NonWritable decoration is invalid: must "
6703 "point to a storage image, uniform block, or storage "
6704 "buffer\n %var_func"));
6705 }
6706
TEST_F(ValidateDecorations,NonWritableArrayGood)6707 TEST_F(ValidateDecorations, NonWritableArrayGood) {
6708 std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor");
6709
6710 CompileSuccessfully(spirv);
6711 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6712 }
6713
TEST_F(ValidateDecorations,NonWritableRuntimeArrayGood)6714 TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) {
6715 std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor");
6716
6717 CompileSuccessfully(spirv);
6718 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6719 }
6720
TEST_P(ValidateVulkanCombineDecorationResult,Decorate)6721 TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
6722 const char* const decoration = std::get<0>(GetParam());
6723 const char* const vuid = std::get<1>(GetParam());
6724 const TestResult& test_result = std::get<2>(GetParam());
6725
6726 CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
6727 generator.before_types_ = "OpDecorate %u32 ";
6728 generator.before_types_ += decoration;
6729 generator.before_types_ += "\n";
6730
6731 EntryPoint entry_point;
6732 entry_point.name = "main";
6733 entry_point.execution_model = "Vertex";
6734 generator.entry_points_.push_back(std::move(entry_point));
6735
6736 CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
6737 ASSERT_EQ(test_result.validation_result,
6738 ValidateInstructions(SPV_ENV_VULKAN_1_0));
6739 if (!test_result.error_str.empty()) {
6740 EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
6741 }
6742 if (vuid) {
6743 EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
6744 }
6745 }
6746
6747 INSTANTIATE_TEST_SUITE_P(
6748 DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
6749 Combine(Values("GLSLShared", "GLSLPacked"),
6750 Values("VUID-StandaloneSpirv-GLSLShared-04669"),
6751 Values(TestResult(
6752 SPV_ERROR_INVALID_ID,
6753 "is not valid for the Vulkan execution environment."))));
6754
TEST_F(ValidateDecorations,NonWritableVarFunctionV13Bad)6755 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
6756 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6757
6758 CompileSuccessfully(spirv);
6759 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6760 EXPECT_THAT(getDiagnosticString(),
6761 HasSubstr("Target of NonWritable decoration is invalid: must "
6762 "point to a storage image, uniform block, or storage "
6763 "buffer\n %var_func"));
6764 }
6765
TEST_F(ValidateDecorations,NonWritableVarFunctionV14Good)6766 TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) {
6767 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6768
6769 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6770 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6771 EXPECT_THAT(getDiagnosticString(), Eq(""));
6772 }
6773
TEST_F(ValidateDecorations,NonWritableVarFunctionV13TargetV14Bad)6774 TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) {
6775 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6776
6777 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6778 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6779 EXPECT_THAT(getDiagnosticString(),
6780 HasSubstr("Target of NonWritable decoration is invalid: must "
6781 "point to a storage image, uniform block, or storage "
6782 "buffer\n %var_func"));
6783 }
6784
TEST_F(ValidateDecorations,BufferBlockV13ValV14Good)6785 TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) {
6786 std::string spirv = R"(
6787 OpCapability Shader
6788 OpCapability Linkage
6789 OpMemoryModel Logical GLSL450
6790 OpDecorate %1 BufferBlock
6791 %1 = OpTypeStruct
6792 )";
6793
6794 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6795 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6796 }
6797
TEST_F(ValidateDecorations,BufferBlockV14Bad)6798 TEST_F(ValidateDecorations, BufferBlockV14Bad) {
6799 std::string spirv = R"(
6800 OpCapability Shader
6801 OpCapability Linkage
6802 OpMemoryModel Logical GLSL450
6803 OpDecorate %1 BufferBlock
6804 %1 = OpTypeStruct
6805 )";
6806
6807 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6808 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
6809 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6810 EXPECT_THAT(getDiagnosticString(),
6811 HasSubstr("2nd operand of Decorate: operand BufferBlock(3) "
6812 "requires SPIR-V version 1.3 or earlier"));
6813 }
6814
6815 // Component
6816
TEST_F(ValidateDecorations,ComponentDecorationBadTarget)6817 TEST_F(ValidateDecorations, ComponentDecorationBadTarget) {
6818 std::string spirv = R"(
6819 OpCapability Shader
6820 OpMemoryModel Logical GLSL450
6821 OpEntryPoint Vertex %main "main"
6822 OpDecorate %t Component 0
6823 %void = OpTypeVoid
6824 %3 = OpTypeFunction %void
6825 %float = OpTypeFloat 32
6826 %t = OpTypeVector %float 2
6827 %main = OpFunction %void None %3
6828 %5 = OpLabel
6829 OpReturn
6830 OpFunctionEnd
6831 )";
6832
6833 CompileSuccessfully(spirv);
6834 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6835 EXPECT_THAT(getDiagnosticString(),
6836 HasSubstr("must be a memory object declaration"));
6837 }
6838
TEST_F(ValidateDecorations,ComponentDecorationBadStorageClass)6839 TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) {
6840 std::string spirv = R"(
6841 OpCapability Shader
6842 OpMemoryModel Logical GLSL450
6843 OpEntryPoint Vertex %main "main"
6844 OpDecorate %v Component 0
6845 %void = OpTypeVoid
6846 %3 = OpTypeFunction %void
6847 %float = OpTypeFloat 32
6848 %t = OpTypeVector %float 2
6849 %ptr_private = OpTypePointer Private %t
6850 %v = OpVariable %ptr_private Private
6851 %main = OpFunction %void None %3
6852 %5 = OpLabel
6853 OpReturn
6854 OpFunctionEnd
6855 )";
6856
6857 CompileSuccessfully(spirv);
6858 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6859 EXPECT_THAT(getDiagnosticString(),
6860 HasSubstr("Target of Component decoration is invalid: must "
6861 "point to a Storage Class of Input(1) or Output(3)"));
6862 }
6863
TEST_F(ValidateDecorations,ComponentDecorationBadTypeVulkan)6864 TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) {
6865 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6866 std::string spirv = R"(
6867 OpCapability Shader
6868 OpCapability Matrix
6869 OpMemoryModel Logical GLSL450
6870 OpEntryPoint Vertex %main "main"
6871 OpDecorate %v Component 0
6872 %void = OpTypeVoid
6873 %3 = OpTypeFunction %void
6874 %float = OpTypeFloat 32
6875 %vtype = OpTypeVector %float 4
6876 %t = OpTypeMatrix %vtype 4
6877 %ptr_input = OpTypePointer Input %t
6878 %v = OpVariable %ptr_input Input
6879 %main = OpFunction %void None %3
6880 %5 = OpLabel
6881 OpReturn
6882 OpFunctionEnd
6883 )";
6884
6885 CompileSuccessfully(spirv, env);
6886 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6887 EXPECT_THAT(getDiagnosticString(),
6888 HasSubstr("Component decoration specified for type"));
6889 EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
6890 }
6891
ShaderWithComponentDecoration(const std::string & type,const std::string & decoration)6892 std::string ShaderWithComponentDecoration(const std::string& type,
6893 const std::string& decoration) {
6894 return R"(
6895 OpCapability Shader
6896 OpMemoryModel Logical GLSL450
6897 OpEntryPoint Fragment %main "main" %entryPointOutput
6898 OpExecutionMode %main OriginUpperLeft
6899 OpDecorate %entryPointOutput Location 0
6900 OpDecorate %entryPointOutput )" +
6901 decoration + R"(
6902 %void = OpTypeVoid
6903 %3 = OpTypeFunction %void
6904 %float = OpTypeFloat 32
6905 %v3float = OpTypeVector %float 3
6906 %v4float = OpTypeVector %float 4
6907 %uint = OpTypeInt 32 0
6908 %uint_2 = OpConstant %uint 2
6909 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
6910 %float_0 = OpConstant %float 0
6911 %_ptr_Output_type = OpTypePointer Output %)" + type + R"(
6912 %entryPointOutput = OpVariable %_ptr_Output_type Output
6913 %main = OpFunction %void None %3
6914 %5 = OpLabel
6915 OpReturn
6916 OpFunctionEnd
6917 )";
6918 }
6919
TEST_F(ValidateDecorations,ComponentDecorationIntGood0Vulkan)6920 TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
6921 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6922 std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
6923
6924 CompileSuccessfully(spirv, env);
6925 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6926 EXPECT_THAT(getDiagnosticString(), Eq(""));
6927 }
6928
TEST_F(ValidateDecorations,ComponentDecorationIntGood1Vulkan)6929 TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
6930 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6931 std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
6932
6933 CompileSuccessfully(spirv, env);
6934 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6935 EXPECT_THAT(getDiagnosticString(), Eq(""));
6936 }
6937
TEST_F(ValidateDecorations,ComponentDecorationIntGood2Vulkan)6938 TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
6939 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6940 std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
6941
6942 CompileSuccessfully(spirv, env);
6943 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6944 EXPECT_THAT(getDiagnosticString(), Eq(""));
6945 }
6946
TEST_F(ValidateDecorations,ComponentDecorationIntGood3Vulkan)6947 TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
6948 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6949 std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
6950
6951 CompileSuccessfully(spirv, env);
6952 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6953 EXPECT_THAT(getDiagnosticString(), Eq(""));
6954 }
6955
TEST_F(ValidateDecorations,ComponentDecorationIntBad4Vulkan)6956 TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
6957 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6958 std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
6959
6960 CompileSuccessfully(spirv, env);
6961 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6962 EXPECT_THAT(getDiagnosticString(),
6963 HasSubstr("Sequence of components starting with 4 "
6964 "and ending with 4 gets larger than 3"));
6965 }
6966
TEST_F(ValidateDecorations,ComponentDecorationVector3GoodVulkan)6967 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
6968 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6969 std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
6970
6971 CompileSuccessfully(spirv, env);
6972 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6973 EXPECT_THAT(getDiagnosticString(), Eq(""));
6974 }
6975
TEST_F(ValidateDecorations,ComponentDecorationVector4GoodVulkan)6976 TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
6977 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6978 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
6979
6980 CompileSuccessfully(spirv, env);
6981 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6982 EXPECT_THAT(getDiagnosticString(), Eq(""));
6983 }
6984
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad1Vulkan)6985 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
6986 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6987 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
6988
6989 CompileSuccessfully(spirv, env);
6990 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6991 EXPECT_THAT(getDiagnosticString(),
6992 HasSubstr("Sequence of components starting with 1 "
6993 "and ending with 4 gets larger than 3"));
6994 }
6995
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad3Vulkan)6996 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
6997 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6998 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
6999
7000 CompileSuccessfully(spirv, env);
7001 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7002 EXPECT_THAT(getDiagnosticString(),
7003 HasSubstr("Sequence of components starting with 3 "
7004 "and ending with 6 gets larger than 3"));
7005 }
7006
TEST_F(ValidateDecorations,ComponentDecorationArrayGoodVulkan)7007 TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
7008 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7009 std::string spirv =
7010 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
7011
7012 CompileSuccessfully(spirv, env);
7013 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
7014 EXPECT_THAT(getDiagnosticString(), Eq(""));
7015 }
7016
TEST_F(ValidateDecorations,ComponentDecorationArrayBadVulkan)7017 TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
7018 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7019 std::string spirv =
7020 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
7021
7022 CompileSuccessfully(spirv, env);
7023 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7024 EXPECT_THAT(getDiagnosticString(),
7025 HasSubstr("Sequence of components starting with 2 "
7026 "and ending with 4 gets larger than 3"));
7027 }
7028
TEST_F(ValidateDecorations,ComponentDecorationBlockGood)7029 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
7030 std::string spirv = R"(
7031 OpCapability Shader
7032 OpMemoryModel Logical GLSL450
7033 OpEntryPoint Fragment %4 "main" %9 %12
7034 OpExecutionMode %4 OriginUpperLeft
7035 OpDecorate %9 Location 0
7036 OpMemberDecorate %block 0 Location 2
7037 OpMemberDecorate %block 0 Component 1
7038 OpDecorate %block Block
7039 %2 = OpTypeVoid
7040 %3 = OpTypeFunction %2
7041 %float = OpTypeFloat 32
7042 %vec3 = OpTypeVector %float 3
7043 %8 = OpTypePointer Output %vec3
7044 %9 = OpVariable %8 Output
7045 %block = OpTypeStruct %vec3
7046 %11 = OpTypePointer Input %block
7047 %12 = OpVariable %11 Input
7048 %int = OpTypeInt 32 1
7049 %14 = OpConstant %int 0
7050 %15 = OpTypePointer Input %vec3
7051 %4 = OpFunction %2 None %3
7052 %5 = OpLabel
7053 %16 = OpAccessChain %15 %12 %14
7054 %17 = OpLoad %vec3 %16
7055 OpStore %9 %17
7056 OpReturn
7057 OpFunctionEnd
7058 )";
7059
7060 CompileSuccessfully(spirv);
7061 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7062 EXPECT_THAT(getDiagnosticString(), Eq(""));
7063 }
7064
TEST_F(ValidateDecorations,ComponentDecorationBlockBadVulkan)7065 TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) {
7066 const spv_target_env env = SPV_ENV_VULKAN_1_0;
7067 std::string spirv = R"(
7068 OpCapability Shader
7069 OpMemoryModel Logical GLSL450
7070 OpEntryPoint Fragment %4 "main" %9 %12
7071 OpExecutionMode %4 OriginUpperLeft
7072 OpDecorate %9 Location 0
7073 OpMemberDecorate %block 0 Location 2
7074 OpMemberDecorate %block 0 Component 2
7075 OpDecorate %block Block
7076 %2 = OpTypeVoid
7077 %3 = OpTypeFunction %2
7078 %float = OpTypeFloat 32
7079 %vec3 = OpTypeVector %float 3
7080 %8 = OpTypePointer Output %vec3
7081 %9 = OpVariable %8 Output
7082 %block = OpTypeStruct %vec3
7083 %11 = OpTypePointer Input %block
7084 %12 = OpVariable %11 Input
7085 %int = OpTypeInt 32 1
7086 %14 = OpConstant %int 0
7087 %15 = OpTypePointer Input %vec3
7088 %4 = OpFunction %2 None %3
7089 %5 = OpLabel
7090 %16 = OpAccessChain %15 %12 %14
7091 %17 = OpLoad %vec3 %16
7092 OpStore %9 %17
7093 OpReturn
7094 OpFunctionEnd
7095 )";
7096
7097 CompileSuccessfully(spirv, env);
7098 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
7099 EXPECT_THAT(getDiagnosticString(),
7100 HasSubstr("Sequence of components starting with 2 "
7101 "and ending with 4 gets larger than 3"));
7102 }
7103
TEST_F(ValidateDecorations,ComponentDecorationFunctionParameter)7104 TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
7105 std::string spirv = R"(
7106 OpCapability Shader
7107 OpMemoryModel Logical GLSL450
7108 OpEntryPoint Vertex %main "main"
7109
7110 OpDecorate %param_f Component 0
7111
7112 %void = OpTypeVoid
7113 %void_fn = OpTypeFunction %void
7114 %float = OpTypeFloat 32
7115 %float_0 = OpConstant %float 0
7116 %int = OpTypeInt 32 0
7117 %int_2 = OpConstant %int 2
7118 %struct_b = OpTypeStruct %float
7119
7120 %extra_fn = OpTypeFunction %void %float
7121
7122 %helper = OpFunction %void None %extra_fn
7123 %param_f = OpFunctionParameter %float
7124 %helper_label = OpLabel
7125 OpReturn
7126 OpFunctionEnd
7127
7128 %main = OpFunction %void None %void_fn
7129 %label = OpLabel
7130 OpReturn
7131 OpFunctionEnd
7132 )";
7133
7134 CompileSuccessfully(spirv);
7135 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
7136 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a pointer type"));
7137 }
7138
TEST_F(ValidateDecorations,VulkanStorageBufferBlock)7139 TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
7140 const std::string spirv = R"(
7141 OpCapability Shader
7142 OpExtension "SPV_KHR_storage_buffer_storage_class"
7143 OpMemoryModel Logical GLSL450
7144 OpEntryPoint GLCompute %main "main"
7145 OpExecutionMode %main LocalSize 1 1 1
7146 OpDecorate %struct Block
7147 OpMemberDecorate %struct 0 Offset 0
7148 %void = OpTypeVoid
7149 %uint = OpTypeInt 32 0
7150 %struct = OpTypeStruct %uint
7151 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7152 %var = OpVariable %ptr_ssbo StorageBuffer
7153 %void_fn = OpTypeFunction %void
7154 %main = OpFunction %void None %void_fn
7155 %entry = OpLabel
7156 OpReturn
7157 OpFunctionEnd
7158 )";
7159
7160 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7161 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7162 }
7163
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBlock)7164 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
7165 const std::string spirv = R"(
7166 OpCapability Shader
7167 OpExtension "SPV_KHR_storage_buffer_storage_class"
7168 OpMemoryModel Logical GLSL450
7169 OpEntryPoint GLCompute %main "main"
7170 OpExecutionMode %main LocalSize 1 1 1
7171 %void = OpTypeVoid
7172 %uint = OpTypeInt 32 0
7173 %struct = OpTypeStruct %uint
7174 %ptr_ssbo = OpTypePointer StorageBuffer %struct
7175 %var = OpVariable %ptr_ssbo StorageBuffer
7176 %void_fn = OpTypeFunction %void
7177 %main = OpFunction %void None %void_fn
7178 %entry = OpLabel
7179 OpReturn
7180 OpFunctionEnd
7181 )";
7182
7183 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7184 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7185 EXPECT_THAT(getDiagnosticString(),
7186 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7187 EXPECT_THAT(getDiagnosticString(),
7188 HasSubstr("From Vulkan spec:\nSuch variables "
7189 "must be identified with a Block decoration"));
7190 }
7191
TEST_F(ValidateDecorations,VulkanStorageBufferArrayMissingBlock)7192 TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
7193 const std::string spirv = R"(
7194 OpCapability Shader
7195 OpExtension "SPV_KHR_storage_buffer_storage_class"
7196 OpMemoryModel Logical GLSL450
7197 OpEntryPoint GLCompute %main "main"
7198 OpExecutionMode %main LocalSize 1 1 1
7199 %void = OpTypeVoid
7200 %uint = OpTypeInt 32 0
7201 %uint_4 = OpConstant %uint 4
7202 %struct = OpTypeStruct %uint
7203 %array = OpTypeArray %struct %uint_4
7204 %ptr_ssbo = OpTypePointer StorageBuffer %array
7205 %var = OpVariable %ptr_ssbo StorageBuffer
7206 %void_fn = OpTypeFunction %void
7207 %main = OpFunction %void None %void_fn
7208 %entry = OpLabel
7209 OpReturn
7210 OpFunctionEnd
7211 )";
7212
7213 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7214 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7215 EXPECT_THAT(getDiagnosticString(),
7216 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7217 EXPECT_THAT(getDiagnosticString(),
7218 HasSubstr("From Vulkan spec:\nSuch variables "
7219 "must be identified with a Block decoration"));
7220 }
7221
TEST_F(ValidateDecorations,VulkanStorageBufferRuntimeArrayMissingBlock)7222 TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
7223 const std::string spirv = R"(
7224 OpCapability Shader
7225 OpCapability RuntimeDescriptorArrayEXT
7226 OpExtension "SPV_EXT_descriptor_indexing"
7227 OpExtension "SPV_KHR_storage_buffer_storage_class"
7228 OpMemoryModel Logical GLSL450
7229 OpEntryPoint GLCompute %main "main"
7230 OpExecutionMode %main LocalSize 1 1 1
7231 %void = OpTypeVoid
7232 %uint = OpTypeInt 32 0
7233 %struct = OpTypeStruct %uint
7234 %array = OpTypeRuntimeArray %struct
7235 %ptr_ssbo = OpTypePointer StorageBuffer %array
7236 %var = OpVariable %ptr_ssbo StorageBuffer
7237 %void_fn = OpTypeFunction %void
7238 %main = OpFunction %void None %void_fn
7239 %entry = OpLabel
7240 OpReturn
7241 OpFunctionEnd
7242 )";
7243
7244 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7245 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7246 EXPECT_THAT(getDiagnosticString(),
7247 AnyVUID("VUID-StandaloneSpirv-PushConstant-06675"));
7248 EXPECT_THAT(getDiagnosticString(),
7249 HasSubstr("From Vulkan spec:\nSuch variables "
7250 "must be identified with a Block decoration"));
7251 }
7252
TEST_F(ValidateDecorations,VulkanUniformBlock)7253 TEST_F(ValidateDecorations, VulkanUniformBlock) {
7254 const std::string spirv = R"(
7255 OpCapability Shader
7256 OpMemoryModel Logical GLSL450
7257 OpEntryPoint GLCompute %main "main"
7258 OpExecutionMode %main LocalSize 1 1 1
7259 OpDecorate %struct Block
7260 OpMemberDecorate %struct 0 Offset 0
7261 %void = OpTypeVoid
7262 %uint = OpTypeInt 32 0
7263 %struct = OpTypeStruct %uint
7264 %ptr_ubo = OpTypePointer Uniform %struct
7265 %var = OpVariable %ptr_ubo Uniform
7266 %void_fn = OpTypeFunction %void
7267 %main = OpFunction %void None %void_fn
7268 %entry = OpLabel
7269 OpReturn
7270 OpFunctionEnd
7271 )";
7272
7273 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7274 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7275 }
7276
TEST_F(ValidateDecorations,VulkanUniformBufferBlock)7277 TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
7278 const std::string spirv = R"(
7279 OpCapability Shader
7280 OpMemoryModel Logical GLSL450
7281 OpEntryPoint GLCompute %main "main"
7282 OpExecutionMode %main LocalSize 1 1 1
7283 OpDecorate %struct BufferBlock
7284 OpMemberDecorate %struct 0 Offset 0
7285 %void = OpTypeVoid
7286 %uint = OpTypeInt 32 0
7287 %struct = OpTypeStruct %uint
7288 %ptr_ubo = OpTypePointer Uniform %struct
7289 %var = OpVariable %ptr_ubo Uniform
7290 %void_fn = OpTypeFunction %void
7291 %main = OpFunction %void None %void_fn
7292 %entry = OpLabel
7293 OpReturn
7294 OpFunctionEnd
7295 )";
7296
7297 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7298 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7299 }
7300
TEST_F(ValidateDecorations,VulkanUniformMissingBlock)7301 TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
7302 const std::string spirv = R"(
7303 OpCapability Shader
7304 OpMemoryModel Logical GLSL450
7305 OpEntryPoint GLCompute %main "main"
7306 OpExecutionMode %main LocalSize 1 1 1
7307 %void = OpTypeVoid
7308 %uint = OpTypeInt 32 0
7309 %struct = OpTypeStruct %uint
7310 %ptr_ubo = OpTypePointer Uniform %struct
7311 %var = OpVariable %ptr_ubo Uniform
7312 %void_fn = OpTypeFunction %void
7313 %main = OpFunction %void None %void_fn
7314 %entry = OpLabel
7315 OpReturn
7316 OpFunctionEnd
7317 )";
7318
7319 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7320 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7321 EXPECT_THAT(getDiagnosticString(),
7322 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7323 EXPECT_THAT(getDiagnosticString(),
7324 HasSubstr("From Vulkan spec:\nSuch variables must be "
7325 "identified with a Block or BufferBlock decoration"));
7326 }
7327
TEST_F(ValidateDecorations,VulkanUniformArrayMissingBlock)7328 TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
7329 const std::string spirv = R"(
7330 OpCapability Shader
7331 OpMemoryModel Logical GLSL450
7332 OpEntryPoint GLCompute %main "main"
7333 OpExecutionMode %main LocalSize 1 1 1
7334 %void = OpTypeVoid
7335 %uint = OpTypeInt 32 0
7336 %uint_4 = OpConstant %uint 4
7337 %struct = OpTypeStruct %uint
7338 %array = OpTypeArray %struct %uint_4
7339 %ptr_ubo = OpTypePointer Uniform %array
7340 %var = OpVariable %ptr_ubo Uniform
7341 %void_fn = OpTypeFunction %void
7342 %main = OpFunction %void None %void_fn
7343 %entry = OpLabel
7344 OpReturn
7345 OpFunctionEnd
7346 )";
7347
7348 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7349 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7350 EXPECT_THAT(getDiagnosticString(),
7351 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7352 EXPECT_THAT(getDiagnosticString(),
7353 HasSubstr("From Vulkan spec:\nSuch variables must be "
7354 "identified with a Block or BufferBlock decoration"));
7355 }
7356
TEST_F(ValidateDecorations,VulkanUniformRuntimeArrayMissingBlock)7357 TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
7358 const std::string spirv = R"(
7359 OpCapability Shader
7360 OpCapability RuntimeDescriptorArrayEXT
7361 OpExtension "SPV_EXT_descriptor_indexing"
7362 OpMemoryModel Logical GLSL450
7363 OpEntryPoint GLCompute %main "main"
7364 OpExecutionMode %main LocalSize 1 1 1
7365 %void = OpTypeVoid
7366 %uint = OpTypeInt 32 0
7367 %struct = OpTypeStruct %uint
7368 %array = OpTypeRuntimeArray %struct
7369 %ptr_ubo = OpTypePointer Uniform %array
7370 %var = OpVariable %ptr_ubo Uniform
7371 %void_fn = OpTypeFunction %void
7372 %main = OpFunction %void None %void_fn
7373 %entry = OpLabel
7374 OpReturn
7375 OpFunctionEnd
7376 )";
7377
7378 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7379 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7380 EXPECT_THAT(getDiagnosticString(),
7381 AnyVUID("VUID-StandaloneSpirv-Uniform-06676"));
7382 EXPECT_THAT(getDiagnosticString(),
7383 HasSubstr("From Vulkan spec:\nSuch variables must be "
7384 "identified with a Block or BufferBlock decoration"));
7385 }
7386
TEST_F(ValidateDecorations,VulkanArrayStrideZero)7387 TEST_F(ValidateDecorations, VulkanArrayStrideZero) {
7388 const std::string spirv = R"(
7389 OpCapability Shader
7390 OpMemoryModel Logical GLSL450
7391 OpEntryPoint GLCompute %main "main"
7392 OpExecutionMode %main LocalSize 1 1 1
7393 OpDecorate %var DescriptorSet 0
7394 OpDecorate %var Binding 0
7395 OpDecorate %struct Block
7396 OpMemberDecorate %struct 0 Offset 0
7397 OpDecorate %array ArrayStride 0
7398 %void = OpTypeVoid
7399 %int = OpTypeInt 32 0
7400 %int_4 = OpConstant %int 4
7401 %array = OpTypeArray %int %int_4
7402 %struct = OpTypeStruct %array
7403 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7404 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7405 %void_fn = OpTypeFunction %void
7406 %main = OpFunction %void None %void_fn
7407 %entry = OpLabel
7408 OpReturn
7409 OpFunctionEnd
7410 )";
7411
7412 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7413 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7414 EXPECT_THAT(getDiagnosticString(),
7415 HasSubstr("contains an array with stride 0"));
7416 }
7417
TEST_F(ValidateDecorations,VulkanArrayStrideTooSmall)7418 TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) {
7419 const std::string spirv = R"(
7420 OpCapability Shader
7421 OpMemoryModel Logical GLSL450
7422 OpEntryPoint GLCompute %main "main"
7423 OpExecutionMode %main LocalSize 1 1 1
7424 OpDecorate %var DescriptorSet 0
7425 OpDecorate %var Binding 0
7426 OpDecorate %struct Block
7427 OpMemberDecorate %struct 0 Offset 0
7428 OpDecorate %inner ArrayStride 4
7429 OpDecorate %outer ArrayStride 4
7430 %void = OpTypeVoid
7431 %int = OpTypeInt 32 0
7432 %int_4 = OpConstant %int 4
7433 %inner = OpTypeArray %int %int_4
7434 %outer = OpTypeArray %inner %int_4
7435 %struct = OpTypeStruct %outer
7436 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7437 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7438 %void_fn = OpTypeFunction %void
7439 %main = OpFunction %void None %void_fn
7440 %entry = OpLabel
7441 OpReturn
7442 OpFunctionEnd
7443 )";
7444
7445 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7446 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7447 EXPECT_THAT(
7448 getDiagnosticString(),
7449 HasSubstr(
7450 "contains an array with stride 4, but with an element size of 16"));
7451 }
7452
TEST_F(ValidateDecorations,FunctionsWithOpGroupDecorate)7453 TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate) {
7454 std::string spirv = R"(
7455 OpCapability Addresses
7456 OpCapability Linkage
7457 OpCapability Kernel
7458 OpCapability Int8
7459 %1 = OpExtInstImport "OpenCL.std"
7460 OpMemoryModel Physical32 OpenCL
7461 OpName %foo "foo"
7462 OpName %entry "entry"
7463 OpName %bar "bar"
7464 OpName %entry_0 "entry"
7465 OpName %k "k"
7466 OpName %entry_1 "entry"
7467 OpName %b "b"
7468 OpDecorate %28 FuncParamAttr Zext
7469 %28 = OpDecorationGroup
7470 OpDecorate %k LinkageAttributes "k" Export
7471 OpDecorate %foo LinkageAttributes "foo" Export
7472 OpDecorate %bar LinkageAttributes "bar" Export
7473 OpDecorate %b Alignment 1
7474 OpGroupDecorate %28 %foo %bar
7475 %uchar = OpTypeInt 8 0
7476 %bool = OpTypeBool
7477 %3 = OpTypeFunction %bool
7478 %void = OpTypeVoid
7479 %10 = OpTypeFunction %void
7480 %_ptr_Function_uchar = OpTypePointer Function %uchar
7481 %true = OpConstantTrue %bool
7482 %foo = OpFunction %bool DontInline %3
7483 %entry = OpLabel
7484 OpReturnValue %true
7485 OpFunctionEnd
7486 %bar = OpFunction %bool DontInline %3
7487 %entry_0 = OpLabel
7488 OpReturnValue %true
7489 OpFunctionEnd
7490 %k = OpFunction %void DontInline %10
7491 %entry_1 = OpLabel
7492 %b = OpVariable %_ptr_Function_uchar Function
7493 OpReturn
7494 OpFunctionEnd
7495 )";
7496 CompileSuccessfully(spirv);
7497 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7498 }
7499
TEST_F(ValidateDecorations,LocationVariableGood)7500 TEST_F(ValidateDecorations, LocationVariableGood) {
7501 const std::string spirv = R"(
7502 OpCapability Shader
7503 OpCapability Linkage
7504 OpMemoryModel Logical GLSL450
7505 OpDecorate %in_var Location 0
7506 %float = OpTypeFloat 32
7507 %ptr_input_float = OpTypePointer Input %float
7508 %in_var = OpVariable %ptr_input_float Input
7509 )";
7510
7511 CompileSuccessfully(spirv);
7512 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7513 }
7514
TEST_F(ValidateDecorations,LocationStructMemberGood)7515 TEST_F(ValidateDecorations, LocationStructMemberGood) {
7516 const std::string spirv = R"(
7517 OpCapability Shader
7518 OpCapability Linkage
7519 OpMemoryModel Logical GLSL450
7520 OpMemberDecorate %struct 0 Location 0
7521 %float = OpTypeFloat 32
7522 %struct = OpTypeStruct %float
7523 )";
7524
7525 CompileSuccessfully(spirv);
7526 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7527 }
7528
TEST_F(ValidateDecorations,LocationStructBad)7529 TEST_F(ValidateDecorations, LocationStructBad) {
7530 const std::string spirv = R"(
7531 OpCapability Shader
7532 OpCapability Linkage
7533 OpMemoryModel Logical GLSL450
7534 OpDecorate %struct Location 0
7535 %float = OpTypeFloat 32
7536 %struct = OpTypeStruct %float
7537 )";
7538
7539 CompileSuccessfully(spirv);
7540 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7541 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7542 }
7543
TEST_F(ValidateDecorations,LocationFloatBad)7544 TEST_F(ValidateDecorations, LocationFloatBad) {
7545 const std::string spirv = R"(
7546 OpCapability Shader
7547 OpCapability Linkage
7548 OpMemoryModel Logical GLSL450
7549 OpDecorate %float Location 0
7550 %float = OpTypeFloat 32
7551 )";
7552
7553 CompileSuccessfully(spirv);
7554 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7555 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a variable"));
7556 }
7557
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariable)7558 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable) {
7559 std::string spirv = R"(
7560 OpCapability Shader
7561 OpCapability WorkgroupMemoryExplicitLayoutKHR
7562 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7563 OpMemoryModel Logical GLSL450
7564 OpEntryPoint GLCompute %main "main" %_
7565 OpExecutionMode %main LocalSize 8 1 1
7566 OpMemberDecorate %first 0 Offset 0
7567 OpDecorate %first Block
7568 %void = OpTypeVoid
7569 %3 = OpTypeFunction %void
7570 %int = OpTypeInt 32 1
7571 %first = OpTypeStruct %int
7572 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7573 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7574 %int_0 = OpConstant %int 0
7575 %int_2 = OpConstant %int 2
7576 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7577 %main = OpFunction %void None %3
7578 %5 = OpLabel
7579 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7580 OpStore %13 %int_2
7581 OpReturn
7582 OpFunctionEnd
7583 )";
7584
7585 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7586 EXPECT_EQ(SPV_SUCCESS,
7587 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7588 }
7589
TEST_F(ValidateDecorations,WorkgroupBlockVariableRequiresV14)7590 TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14) {
7591 std::string spirv = R"(
7592 OpCapability Shader
7593 OpCapability WorkgroupMemoryExplicitLayoutKHR
7594 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7595 OpMemoryModel Logical GLSL450
7596 OpEntryPoint GLCompute %main "main" %_
7597 OpExecutionMode %main LocalSize 8 1 1
7598 OpMemberDecorate %first 0 Offset 0
7599 OpDecorate %first Block
7600 %void = OpTypeVoid
7601 %3 = OpTypeFunction %void
7602 %int = OpTypeInt 32 1
7603 %first = OpTypeStruct %int
7604 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7605 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7606 %int_0 = OpConstant %int 0
7607 %int_2 = OpConstant %int 2
7608 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7609 %main = OpFunction %void None %3
7610 %5 = OpLabel
7611 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7612 OpStore %13 %int_2
7613 OpReturn
7614 OpFunctionEnd
7615 )";
7616
7617 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7618 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
7619 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7620 EXPECT_THAT(getDiagnosticString(),
7621 HasSubstr("requires SPIR-V version 1.4 or later"));
7622 }
7623
TEST_F(ValidateDecorations,WorkgroupSingleNonBlockVariable)7624 TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable) {
7625 std::string spirv = R"(
7626 OpCapability Shader
7627 OpMemoryModel Logical GLSL450
7628 OpEntryPoint GLCompute %main "main" %a
7629 OpExecutionMode %main LocalSize 8 1 1
7630 %void = OpTypeVoid
7631 %3 = OpTypeFunction %void
7632 %int = OpTypeInt 32 1
7633 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7634 %a = OpVariable %_ptr_Workgroup_int Workgroup
7635 %int_2 = OpConstant %int 2
7636 %main = OpFunction %void None %3
7637 %5 = OpLabel
7638 OpStore %a %int_2
7639 OpReturn
7640 OpFunctionEnd
7641 )";
7642
7643 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7644 EXPECT_EQ(SPV_SUCCESS,
7645 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7646 }
7647
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariable)7648 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable) {
7649 std::string spirv = R"(
7650 OpCapability Shader
7651 OpCapability WorkgroupMemoryExplicitLayoutKHR
7652 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7653 OpMemoryModel Logical GLSL450
7654 OpEntryPoint GLCompute %main "main" %_ %__0
7655 OpExecutionMode %main LocalSize 8 1 1
7656 OpMemberDecorate %first 0 Offset 0
7657 OpDecorate %first Block
7658 OpMemberDecorate %second 0 Offset 0
7659 OpDecorate %second Block
7660 OpDecorate %_ Aliased
7661 OpDecorate %__0 Aliased
7662 %void = OpTypeVoid
7663 %3 = OpTypeFunction %void
7664 %int = OpTypeInt 32 1
7665 %first = OpTypeStruct %int
7666 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7667 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7668 %int_0 = OpConstant %int 0
7669 %int_2 = OpConstant %int 2
7670 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7671 %second = OpTypeStruct %int
7672 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7673 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7674 %int_3 = OpConstant %int 3
7675 %main = OpFunction %void None %3
7676 %5 = OpLabel
7677 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7678 OpStore %13 %int_2
7679 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7680 OpStore %18 %int_3
7681 OpReturn
7682 OpFunctionEnd
7683 )";
7684
7685 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7686 EXPECT_EQ(SPV_SUCCESS,
7687 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7688 }
7689
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith8BitType)7690 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith8BitType) {
7691 std::string spirv = R"(
7692 OpCapability Shader
7693 OpCapability Int8
7694 OpCapability WorkgroupMemoryExplicitLayout8BitAccessKHR
7695 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7696 OpMemoryModel Logical GLSL450
7697 OpEntryPoint GLCompute %main "main" %_
7698 OpExecutionMode %main LocalSize 2 1 1
7699 OpMemberDecorate %first 0 Offset 0
7700 OpDecorate %first Block
7701 %void = OpTypeVoid
7702 %3 = OpTypeFunction %void
7703 %char = OpTypeInt 8 1
7704 %first = OpTypeStruct %char
7705 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7706 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7707 %int = OpTypeInt 32 1
7708 %int_0 = OpConstant %int 0
7709 %char_2 = OpConstant %char 2
7710 %_ptr_Workgroup_char = OpTypePointer Workgroup %char
7711 %main = OpFunction %void None %3
7712 %5 = OpLabel
7713 %14 = OpAccessChain %_ptr_Workgroup_char %_ %int_0
7714 OpStore %14 %char_2
7715 OpReturn
7716 OpFunctionEnd
7717 )";
7718
7719 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7720 EXPECT_EQ(SPV_SUCCESS,
7721 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7722 }
7723
TEST_F(ValidateDecorations,WorkgroupMultiNonBlockVariable)7724 TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable) {
7725 std::string spirv = R"(
7726 OpCapability Shader
7727 OpMemoryModel Logical GLSL450
7728 OpEntryPoint GLCompute %main "main" %a %b
7729 OpExecutionMode %main LocalSize 8 1 1
7730 %void = OpTypeVoid
7731 %3 = OpTypeFunction %void
7732 %int = OpTypeInt 32 1
7733 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7734 %a = OpVariable %_ptr_Workgroup_int Workgroup
7735 %int_2 = OpConstant %int 2
7736 %b = OpVariable %_ptr_Workgroup_int Workgroup
7737 %int_3 = OpConstant %int 3
7738 %main = OpFunction %void None %3
7739 %5 = OpLabel
7740 OpStore %a %int_2
7741 OpStore %b %int_3
7742 OpReturn
7743 OpFunctionEnd
7744 )";
7745
7746 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7747 EXPECT_EQ(SPV_SUCCESS,
7748 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7749 }
7750
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith16BitType)7751 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType) {
7752 std::string spirv = R"(
7753 OpCapability Shader
7754 OpCapability Float16
7755 OpCapability Int16
7756 OpCapability WorkgroupMemoryExplicitLayout16BitAccessKHR
7757 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7758 OpMemoryModel Logical GLSL450
7759 OpEntryPoint GLCompute %main "main" %_
7760 OpExecutionMode %main LocalSize 2 1 1
7761 OpMemberDecorate %first 0 Offset 0
7762 OpMemberDecorate %first 1 Offset 2
7763 OpDecorate %first Block
7764 %void = OpTypeVoid
7765 %3 = OpTypeFunction %void
7766 %short = OpTypeInt 16 1
7767 %half = OpTypeFloat 16
7768 %first = OpTypeStruct %short %half
7769 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7770 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7771 %int = OpTypeInt 32 1
7772 %int_0 = OpConstant %int 0
7773 %short_3 = OpConstant %short 3
7774 %_ptr_Workgroup_short = OpTypePointer Workgroup %short
7775 %int_1 = OpConstant %int 1
7776 %half_0x1_898p_3 = OpConstant %half 0x1.898p+3
7777 %_ptr_Workgroup_half = OpTypePointer Workgroup %half
7778 %main = OpFunction %void None %3
7779 %5 = OpLabel
7780 %15 = OpAccessChain %_ptr_Workgroup_short %_ %int_0
7781 OpStore %15 %short_3
7782 %19 = OpAccessChain %_ptr_Workgroup_half %_ %int_1
7783 OpStore %19 %half_0x1_898p_3
7784 OpReturn
7785 OpFunctionEnd
7786 )";
7787
7788 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7789 EXPECT_EQ(SPV_SUCCESS,
7790 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7791 }
7792
TEST_F(ValidateDecorations,WorkgroupBlockVariableScalarLayout)7793 TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout) {
7794 std::string spirv = R"(
7795 OpCapability Shader
7796 OpCapability WorkgroupMemoryExplicitLayoutKHR
7797 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7798 OpMemoryModel Logical GLSL450
7799 OpEntryPoint Vertex %main "main" %B
7800 OpSource GLSL 450
7801 OpMemberDecorate %S 0 Offset 0
7802 OpMemberDecorate %S 1 Offset 4
7803 OpMemberDecorate %S 2 Offset 16
7804 OpMemberDecorate %S 3 Offset 28
7805 OpDecorate %S Block
7806 OpDecorate %B Aliased
7807 %void = OpTypeVoid
7808 %3 = OpTypeFunction %void
7809 %float = OpTypeFloat 32
7810 %v3float = OpTypeVector %float 3
7811 %S = OpTypeStruct %float %v3float %v3float %v3float
7812 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
7813 %B = OpVariable %_ptr_Workgroup_S Workgroup
7814 %main = OpFunction %void None %3
7815 %5 = OpLabel
7816 OpReturn
7817 OpFunctionEnd
7818 )";
7819
7820 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7821 spvValidatorOptionsSetWorkgroupScalarBlockLayout(getValidatorOptions(), true);
7822 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4))
7823 << getDiagnosticString();
7824 }
7825
TEST_F(ValidateDecorations,WorkgroupMixBlockAndNonBlockBad)7826 TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad) {
7827 std::string spirv = R"(
7828 OpCapability Shader
7829 OpCapability WorkgroupMemoryExplicitLayoutKHR
7830 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7831 OpMemoryModel Logical GLSL450
7832 OpEntryPoint GLCompute %main "main" %_ %b
7833 OpExecutionMode %main LocalSize 8 1 1
7834 OpMemberDecorate %first 0 Offset 0
7835 OpDecorate %first Block
7836 OpDecorate %_ Aliased
7837 OpDecorate %b Aliased
7838 %void = OpTypeVoid
7839 %3 = OpTypeFunction %void
7840 %int = OpTypeInt 32 1
7841 %first = OpTypeStruct %int
7842 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7843 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7844 %int_0 = OpConstant %int 0
7845 %int_2 = OpConstant %int 2
7846 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7847 %b = OpVariable %_ptr_Workgroup_int Workgroup
7848 %int_3 = OpConstant %int 3
7849 %main = OpFunction %void None %3
7850 %5 = OpLabel
7851 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7852 OpStore %13 %int_2
7853 OpStore %b %int_3
7854 OpReturn
7855 OpFunctionEnd
7856 )";
7857
7858 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7859 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7860 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7861 EXPECT_THAT(
7862 getDiagnosticString(),
7863 HasSubstr("either all or none of the Workgroup Storage Class variables "
7864 "in the entry point interface must point to struct types "
7865 "decorated with Block"));
7866 }
7867
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariableMissingAliased)7868 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased) {
7869 std::string spirv = R"(
7870 OpCapability Shader
7871 OpCapability WorkgroupMemoryExplicitLayoutKHR
7872 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7873 OpMemoryModel Logical GLSL450
7874 OpEntryPoint GLCompute %main "main" %_ %__0
7875 OpExecutionMode %main LocalSize 8 1 1
7876 OpMemberDecorate %first 0 Offset 0
7877 OpDecorate %first Block
7878 OpMemberDecorate %second 0 Offset 0
7879 OpDecorate %second Block
7880 OpDecorate %_ Aliased
7881 %void = OpTypeVoid
7882 %3 = OpTypeFunction %void
7883 %int = OpTypeInt 32 1
7884 %first = OpTypeStruct %int
7885 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7886 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7887 %int_0 = OpConstant %int 0
7888 %int_2 = OpConstant %int 2
7889 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7890 %second = OpTypeStruct %int
7891 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7892 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7893 %int_3 = OpConstant %int 3
7894 %main = OpFunction %void None %3
7895 %5 = OpLabel
7896 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7897 OpStore %13 %int_2
7898 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7899 OpStore %18 %int_3
7900 OpReturn
7901 OpFunctionEnd
7902 )";
7903
7904 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7905 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7906 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7907 EXPECT_THAT(
7908 getDiagnosticString(),
7909 HasSubstr("more than one Workgroup Storage Class variable in the "
7910 "entry point interface point to a type decorated with Block, "
7911 "all of them must be decorated with Aliased"));
7912 }
7913
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableNotAStruct)7914 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct) {
7915 std::string spirv = R"(
7916 OpCapability Shader
7917 OpCapability WorkgroupMemoryExplicitLayoutKHR
7918 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7919 OpMemoryModel Logical GLSL450
7920 OpEntryPoint GLCompute %main "main" %_
7921 OpExecutionMode %main LocalSize 8 1 1
7922 OpDecorate %first Block
7923 %void = OpTypeVoid
7924 %3 = OpTypeFunction %void
7925 %int = OpTypeInt 32 1
7926 %int_3 = OpConstant %int 3
7927 %first = OpTypeArray %int %int_3
7928 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7929 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7930 %int_0 = OpConstant %int 0
7931 %int_2 = OpConstant %int 2
7932 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7933 %main = OpFunction %void None %3
7934 %5 = OpLabel
7935 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7936 OpStore %13 %int_2
7937 OpReturn
7938 OpFunctionEnd
7939 )";
7940
7941 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7942 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7943 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7944 EXPECT_THAT(getDiagnosticString(), HasSubstr("must be a structure type"));
7945 }
7946
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableMissingLayout)7947 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout) {
7948 std::string spirv = R"(
7949 OpCapability Shader
7950 OpCapability WorkgroupMemoryExplicitLayoutKHR
7951 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7952 OpMemoryModel Logical GLSL450
7953 OpEntryPoint GLCompute %main "main" %_
7954 OpExecutionMode %main LocalSize 8 1 1
7955 OpDecorate %first Block
7956 %void = OpTypeVoid
7957 %3 = OpTypeFunction %void
7958 %int = OpTypeInt 32 1
7959 %first = OpTypeStruct %int
7960 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7961 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7962 %int_0 = OpConstant %int 0
7963 %int_2 = OpConstant %int 2
7964 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7965 %main = OpFunction %void None %3
7966 %5 = OpLabel
7967 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7968 OpStore %13 %int_2
7969 OpReturn
7970 OpFunctionEnd
7971 )";
7972
7973 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7974 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7975 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7976 EXPECT_THAT(
7977 getDiagnosticString(),
7978 HasSubstr("Block must be explicitly laid out with Offset decorations"));
7979 }
7980
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableBadLayout)7981 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout) {
7982 std::string spirv = R"(
7983 OpCapability Shader
7984 OpCapability WorkgroupMemoryExplicitLayoutKHR
7985 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7986 OpMemoryModel Logical GLSL450
7987 OpEntryPoint GLCompute %main "main" %_
7988 OpExecutionMode %main LocalSize 8 1 1
7989 OpMemberDecorate %first 0 Offset 1
7990 OpDecorate %first Block
7991 %void = OpTypeVoid
7992 %3 = OpTypeFunction %void
7993 %int = OpTypeInt 32 1
7994 %first = OpTypeStruct %int
7995 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7996 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7997 %int_0 = OpConstant %int 0
7998 %int_2 = OpConstant %int 2
7999 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
8000 %main = OpFunction %void None %3
8001 %5 = OpLabel
8002 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
8003 OpStore %13 %int_2
8004 OpReturn
8005 OpFunctionEnd
8006 )";
8007
8008 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
8009 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8010 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
8011 EXPECT_THAT(
8012 getDiagnosticString(),
8013 HasSubstr(
8014 "Block for variable in Workgroup storage class must follow "
8015 "standard storage buffer layout rules: "
8016 "member 0 at offset 1 is not aligned to 4"));
8017 }
8018
TEST_F(ValidateDecorations,BadMatrixStrideUniform)8019 TEST_F(ValidateDecorations, BadMatrixStrideUniform) {
8020 const std::string spirv = R"(
8021 OpCapability Shader
8022 OpMemoryModel Logical GLSL450
8023 OpEntryPoint GLCompute %main "main"
8024 OpExecutionMode %main LocalSize 1 1 1
8025 OpDecorate %block Block
8026 OpMemberDecorate %block 0 Offset 0
8027 OpMemberDecorate %block 0 MatrixStride 3
8028 OpMemberDecorate %block 0 ColMajor
8029 OpDecorate %var DescriptorSet 0
8030 OpDecorate %var Binding 0
8031 %void = OpTypeVoid
8032 %float = OpTypeFloat 32
8033 %float4 = OpTypeVector %float 4
8034 %matrix4x4 = OpTypeMatrix %float4 4
8035 %block = OpTypeStruct %matrix4x4
8036 %block_ptr = OpTypePointer Uniform %block
8037 %var = OpVariable %block_ptr Uniform
8038 %void_fn = OpTypeFunction %void
8039 %main = OpFunction %void None %void_fn
8040 %entry = OpLabel
8041 OpReturn
8042 OpFunctionEnd
8043 )";
8044
8045 CompileSuccessfully(spirv);
8046 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8047 EXPECT_THAT(
8048 getDiagnosticString(),
8049 HasSubstr(
8050 "Structure id 2 decorated as Block for variable in Uniform storage "
8051 "class must follow standard uniform buffer layout rules: member 0 is "
8052 "a matrix with stride 3 not satisfying alignment to 16"));
8053 }
8054
TEST_F(ValidateDecorations,BadMatrixStrideStorageBuffer)8055 TEST_F(ValidateDecorations, BadMatrixStrideStorageBuffer) {
8056 const std::string spirv = R"(
8057 OpCapability Shader
8058 OpExtension "SPV_KHR_storage_buffer_storage_class"
8059 OpMemoryModel Logical GLSL450
8060 OpEntryPoint GLCompute %main "main"
8061 OpExecutionMode %main LocalSize 1 1 1
8062 OpDecorate %block Block
8063 OpMemberDecorate %block 0 Offset 0
8064 OpMemberDecorate %block 0 MatrixStride 3
8065 OpMemberDecorate %block 0 ColMajor
8066 OpDecorate %var DescriptorSet 0
8067 OpDecorate %var Binding 0
8068 %void = OpTypeVoid
8069 %float = OpTypeFloat 32
8070 %float4 = OpTypeVector %float 4
8071 %matrix4x4 = OpTypeMatrix %float4 4
8072 %block = OpTypeStruct %matrix4x4
8073 %block_ptr = OpTypePointer StorageBuffer %block
8074 %var = OpVariable %block_ptr StorageBuffer
8075 %void_fn = OpTypeFunction %void
8076 %main = OpFunction %void None %void_fn
8077 %entry = OpLabel
8078 OpReturn
8079 OpFunctionEnd
8080 )";
8081
8082 CompileSuccessfully(spirv);
8083 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8084 EXPECT_THAT(
8085 getDiagnosticString(),
8086 HasSubstr(
8087 "Structure id 2 decorated as Block for variable in StorageBuffer "
8088 "storage class must follow standard storage buffer layout rules: "
8089 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8090 }
8091
TEST_F(ValidateDecorations,BadMatrixStridePushConstant)8092 TEST_F(ValidateDecorations, BadMatrixStridePushConstant) {
8093 const std::string spirv = R"(
8094 OpCapability Shader
8095 OpMemoryModel Logical GLSL450
8096 OpEntryPoint GLCompute %main "main"
8097 OpExecutionMode %main LocalSize 1 1 1
8098 OpDecorate %block Block
8099 OpMemberDecorate %block 0 Offset 0
8100 OpMemberDecorate %block 0 MatrixStride 3
8101 OpMemberDecorate %block 0 ColMajor
8102 OpDecorate %var DescriptorSet 0
8103 OpDecorate %var Binding 0
8104 %void = OpTypeVoid
8105 %float = OpTypeFloat 32
8106 %float4 = OpTypeVector %float 4
8107 %matrix4x4 = OpTypeMatrix %float4 4
8108 %block = OpTypeStruct %matrix4x4
8109 %block_ptr = OpTypePointer PushConstant %block
8110 %var = OpVariable %block_ptr PushConstant
8111 %void_fn = OpTypeFunction %void
8112 %main = OpFunction %void None %void_fn
8113 %entry = OpLabel
8114 OpReturn
8115 OpFunctionEnd
8116 )";
8117
8118 CompileSuccessfully(spirv);
8119 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8120 EXPECT_THAT(
8121 getDiagnosticString(),
8122 HasSubstr(
8123 "Structure id 2 decorated as Block for variable in PushConstant "
8124 "storage class must follow standard storage buffer layout rules: "
8125 "member 0 is a matrix with stride 3 not satisfying alignment to 16"));
8126 }
8127
TEST_F(ValidateDecorations,BadMatrixStrideStorageBufferScalarLayout)8128 TEST_F(ValidateDecorations, BadMatrixStrideStorageBufferScalarLayout) {
8129 const std::string spirv = R"(
8130 OpCapability Shader
8131 OpExtension "SPV_KHR_storage_buffer_storage_class"
8132 OpMemoryModel Logical GLSL450
8133 OpEntryPoint GLCompute %main "main"
8134 OpExecutionMode %main LocalSize 1 1 1
8135 OpDecorate %block Block
8136 OpMemberDecorate %block 0 Offset 0
8137 OpMemberDecorate %block 0 MatrixStride 3
8138 OpMemberDecorate %block 0 RowMajor
8139 OpDecorate %var DescriptorSet 0
8140 OpDecorate %var Binding 0
8141 %void = OpTypeVoid
8142 %float = OpTypeFloat 32
8143 %float4 = OpTypeVector %float 4
8144 %matrix4x4 = OpTypeMatrix %float4 4
8145 %block = OpTypeStruct %matrix4x4
8146 %block_ptr = OpTypePointer StorageBuffer %block
8147 %var = OpVariable %block_ptr StorageBuffer
8148 %void_fn = OpTypeFunction %void
8149 %main = OpFunction %void None %void_fn
8150 %entry = OpLabel
8151 OpReturn
8152 OpFunctionEnd
8153 )";
8154
8155 options_->scalar_block_layout = true;
8156 CompileSuccessfully(spirv);
8157 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8158 EXPECT_THAT(
8159 getDiagnosticString(),
8160 HasSubstr(
8161 "Structure id 2 decorated as Block for variable in StorageBuffer "
8162 "storage class must follow scalar storage buffer layout rules: "
8163 "member 0 is a matrix with stride 3 not satisfying alignment to 4"));
8164 }
8165
TEST_F(ValidateDecorations,MissingOffsetStructNestedInArray)8166 TEST_F(ValidateDecorations, MissingOffsetStructNestedInArray) {
8167 const std::string spirv = R"(
8168 OpCapability Shader
8169 OpExtension "SPV_KHR_storage_buffer_storage_class"
8170 OpMemoryModel Logical GLSL450
8171 OpEntryPoint GLCompute %main "main"
8172 OpExecutionMode %main LocalSize 1 1 1
8173 OpDecorate %array ArrayStride 4
8174 OpDecorate %outer Block
8175 OpMemberDecorate %outer 0 Offset 0
8176 OpDecorate %var DescriptorSet 0
8177 OpDecorate %var Binding 0
8178 %void = OpTypeVoid
8179 %int = OpTypeInt 32 0
8180 %int_4 = OpConstant %int 4
8181 %inner = OpTypeStruct %int
8182 %array = OpTypeArray %inner %int_4
8183 %outer = OpTypeStruct %array
8184 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer
8185 %var = OpVariable %ptr_ssbo_outer StorageBuffer
8186 %void_fn = OpTypeFunction %void
8187 %main = OpFunction %void None %void_fn
8188 %entry = OpLabel
8189 OpReturn
8190 OpFunctionEnd
8191 )";
8192
8193 CompileSuccessfully(spirv);
8194 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8195 EXPECT_THAT(getDiagnosticString(),
8196 HasSubstr("Structure id 3 decorated as Block must be explicitly "
8197 "laid out with Offset decorations"));
8198 }
8199
TEST_F(ValidateDecorations,AllOnesOffset)8200 TEST_F(ValidateDecorations, AllOnesOffset) {
8201 const std::string spirv = R"(
8202 OpCapability Shader
8203 OpMemoryModel Logical GLSL450
8204 OpEntryPoint GLCompute %main "main"
8205 OpDecorate %var DescriptorSet 0
8206 OpDecorate %var Binding 0
8207 OpDecorate %outer Block
8208 OpMemberDecorate %outer 0 Offset 0
8209 OpMemberDecorate %struct 0 Offset 4294967295
8210 %void = OpTypeVoid
8211 %int = OpTypeInt 32 0
8212 %struct = OpTypeStruct %int
8213 %outer = OpTypeStruct %struct
8214 %ptr = OpTypePointer Uniform %outer
8215 %var = OpVariable %ptr Uniform
8216 %void_fn = OpTypeFunction %void
8217 %main = OpFunction %void None %void_fn
8218 %entry = OpLabel
8219 OpReturn
8220 OpFunctionEnd
8221 )";
8222
8223 CompileSuccessfully(spirv);
8224 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
8225 EXPECT_THAT(getDiagnosticString(),
8226 HasSubstr("decorated as Block must be explicitly laid out with "
8227 "Offset decorations"));
8228 }
8229
TEST_F(ValidateDecorations,PerVertexVulkanGood)8230 TEST_F(ValidateDecorations, PerVertexVulkanGood) {
8231 const std::string spirv = R"(
8232 OpCapability Shader
8233 OpCapability FragmentBarycentricKHR
8234 OpExtension "SPV_KHR_fragment_shader_barycentric"
8235 %1 = OpExtInstImport "GLSL.std.450"
8236 OpMemoryModel Logical GLSL450
8237 OpEntryPoint Fragment %main "main" %vertexIDs
8238 OpExecutionMode %main OriginUpperLeft
8239 OpDecorate %vertexIDs Location 0
8240 OpDecorate %vertexIDs PerVertexKHR
8241 %void = OpTypeVoid
8242 %func = OpTypeFunction %void
8243 %float = OpTypeFloat 32
8244 %uint = OpTypeInt 32 0
8245 %ptrFloat = OpTypePointer Input %float
8246 %uint_3 = OpConstant %uint 3
8247 %floatArray = OpTypeArray %float %uint_3
8248 %ptrFloatArray = OpTypePointer Input %floatArray
8249 %vertexIDs = OpVariable %ptrFloatArray Input
8250 %int = OpTypeInt 32 1
8251 %int_0 = OpConstant %int 0
8252 %main = OpFunction %void None %func
8253 %label = OpLabel
8254 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8255 %load = OpLoad %float %access
8256 OpReturn
8257 OpFunctionEnd
8258 )";
8259
8260 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8261 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8262 }
8263
TEST_F(ValidateDecorations,PerVertexVulkanOutput)8264 TEST_F(ValidateDecorations, PerVertexVulkanOutput) {
8265 const std::string spirv = R"(
8266 OpCapability Shader
8267 OpCapability FragmentBarycentricKHR
8268 OpExtension "SPV_KHR_fragment_shader_barycentric"
8269 %1 = OpExtInstImport "GLSL.std.450"
8270 OpMemoryModel Logical GLSL450
8271 OpEntryPoint Fragment %main "main" %vertexIDs
8272 OpExecutionMode %main OriginUpperLeft
8273 OpDecorate %vertexIDs Location 0
8274 OpDecorate %vertexIDs PerVertexKHR
8275 %void = OpTypeVoid
8276 %func = OpTypeFunction %void
8277 %float = OpTypeFloat 32
8278 %uint = OpTypeInt 32 0
8279 %ptrFloat = OpTypePointer Output %float
8280 %uint_3 = OpConstant %uint 3
8281 %floatArray = OpTypeArray %float %uint_3
8282 %ptrFloatArray = OpTypePointer Output %floatArray
8283 %vertexIDs = OpVariable %ptrFloatArray Output
8284 %int = OpTypeInt 32 1
8285 %int_0 = OpConstant %int 0
8286 %main = OpFunction %void None %func
8287 %label = OpLabel
8288 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8289 %load = OpLoad %float %access
8290 OpReturn
8291 OpFunctionEnd
8292 )";
8293
8294 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8295 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8296 EXPECT_THAT(getDiagnosticString(),
8297 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8298 EXPECT_THAT(getDiagnosticString(), HasSubstr("storage class must be Input"));
8299 }
8300
TEST_F(ValidateDecorations,PerVertexVulkanNonFragment)8301 TEST_F(ValidateDecorations, PerVertexVulkanNonFragment) {
8302 const std::string spirv = R"(
8303 OpCapability Shader
8304 OpCapability FragmentBarycentricKHR
8305 OpExtension "SPV_KHR_fragment_shader_barycentric"
8306 %1 = OpExtInstImport "GLSL.std.450"
8307 OpMemoryModel Logical GLSL450
8308 OpEntryPoint Vertex %main "main" %vertexIDs
8309 OpDecorate %vertexIDs Location 0
8310 OpDecorate %vertexIDs PerVertexKHR
8311 %void = OpTypeVoid
8312 %func = OpTypeFunction %void
8313 %float = OpTypeFloat 32
8314 %uint = OpTypeInt 32 0
8315 %ptrFloat = OpTypePointer Input %float
8316 %uint_3 = OpConstant %uint 3
8317 %floatArray = OpTypeArray %float %uint_3
8318 %ptrFloatArray = OpTypePointer Input %floatArray
8319 %vertexIDs = OpVariable %ptrFloatArray Input
8320 %int = OpTypeInt 32 1
8321 %int_0 = OpConstant %int 0
8322 %main = OpFunction %void None %func
8323 %label = OpLabel
8324 %access = OpAccessChain %ptrFloat %vertexIDs %int_0
8325 %load = OpLoad %float %access
8326 OpReturn
8327 OpFunctionEnd
8328 )";
8329
8330 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8331 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8332 EXPECT_THAT(getDiagnosticString(),
8333 AnyVUID("VUID-StandaloneSpirv-PerVertexKHR-06777"));
8334 EXPECT_THAT(
8335 getDiagnosticString(),
8336 HasSubstr(
8337 "PerVertexKHR can only be applied to Fragment Execution Models"));
8338 }
8339
TEST_F(ValidateDecorations,PerVertexVulkanNonArray)8340 TEST_F(ValidateDecorations, PerVertexVulkanNonArray) {
8341 const std::string spirv = R"(
8342 OpCapability Shader
8343 OpCapability FragmentBarycentricKHR
8344 OpExtension "SPV_KHR_fragment_shader_barycentric"
8345 %1 = OpExtInstImport "GLSL.std.450"
8346 OpMemoryModel Logical GLSL450
8347 OpEntryPoint Fragment %main "main" %vertexIDs
8348 OpExecutionMode %main OriginUpperLeft
8349 OpDecorate %vertexIDs Location 0
8350 OpDecorate %vertexIDs PerVertexKHR
8351 %void = OpTypeVoid
8352 %func = OpTypeFunction %void
8353 %float = OpTypeFloat 32
8354 %ptrFloat = OpTypePointer Input %float
8355 %vertexIDs = OpVariable %ptrFloat Input
8356 %int = OpTypeInt 32 1
8357 %int_0 = OpConstant %int 0
8358 %main = OpFunction %void None %func
8359 %label = OpLabel
8360 %load = OpLoad %float %vertexIDs
8361 OpReturn
8362 OpFunctionEnd
8363 )";
8364
8365 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8366 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8367 EXPECT_THAT(getDiagnosticString(),
8368 AnyVUID("VUID-StandaloneSpirv-Input-06778"));
8369 EXPECT_THAT(getDiagnosticString(),
8370 HasSubstr("PerVertexKHR must be declared as arrays"));
8371 }
8372
TEST_F(ValidateDecorations,RelaxedPrecisionDecorationOnNumericTypeBad)8373 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnNumericTypeBad) {
8374 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8375 std::string spirv = R"(
8376 OpCapability Shader
8377 OpMemoryModel Logical GLSL450
8378 OpEntryPoint Fragment %main "main"
8379 OpExecutionMode %main OriginUpperLeft
8380 OpDecorate %float RelaxedPrecision
8381 %void = OpTypeVoid
8382 %voidfn = OpTypeFunction %void
8383 %float = OpTypeFloat 32
8384 %main = OpFunction %void None %voidfn
8385 %label = OpLabel
8386 OpReturn
8387 OpFunctionEnd
8388 )";
8389
8390 CompileSuccessfully(spirv, env);
8391 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
8392 EXPECT_THAT(
8393 getDiagnosticString(),
8394 HasSubstr("RelaxPrecision decoration cannot be applied to a type"));
8395 }
8396
TEST_F(ValidateDecorations,RelaxedPrecisionDecorationOnStructMember)8397 TEST_F(ValidateDecorations, RelaxedPrecisionDecorationOnStructMember) {
8398 const spv_target_env env = SPV_ENV_VULKAN_1_0;
8399 std::string spirv = R"(
8400 OpCapability Shader
8401 OpMemoryModel Logical GLSL450
8402 OpEntryPoint Fragment %main "main"
8403 OpExecutionMode %main OriginUpperLeft
8404 OpMemberDecorate %struct 0 RelaxedPrecision
8405 %void = OpTypeVoid
8406 %voidfn = OpTypeFunction %void
8407 %float = OpTypeFloat 32
8408 %struct = OpTypeStruct %float
8409 %main = OpFunction %void None %voidfn
8410 %label = OpLabel
8411 OpReturn
8412 OpFunctionEnd
8413 )";
8414
8415 CompileSuccessfully(spirv, env);
8416 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
8417 }
8418
TEST_F(ValidateDecorations,VulkanFlatMultipleInterfaceGood)8419 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceGood) {
8420 std::string spirv = R"(
8421 OpCapability Shader
8422 OpCapability Geometry
8423 %1 = OpExtInstImport "GLSL.std.450"
8424 OpMemoryModel Logical GLSL450
8425 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8426 OpExecutionMode %main OriginUpperLeft
8427 OpSource GLSL 450
8428 OpDecorate %layer Location 0
8429 OpDecorate %gl_Layer Flat
8430 OpDecorate %gl_Layer BuiltIn Layer
8431 %void = OpTypeVoid
8432 %3 = OpTypeFunction %void
8433 %int = OpTypeInt 32 1
8434 %_ptr_Output_int = OpTypePointer Output %int
8435 %layer = OpVariable %_ptr_Output_int Output
8436 %_ptr_Input_int = OpTypePointer Input %int
8437 %gl_Layer = OpVariable %_ptr_Input_int Input
8438 %main = OpFunction %void None %3
8439 %5 = OpLabel
8440 %11 = OpLoad %int %gl_Layer
8441 OpStore %layer %11
8442 OpReturn
8443 OpFunctionEnd
8444 )";
8445
8446 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8447 EXPECT_EQ(SPV_SUCCESS,
8448 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8449 }
8450
TEST_F(ValidateDecorations,VulkanFlatMultipleInterfaceBad)8451 TEST_F(ValidateDecorations, VulkanFlatMultipleInterfaceBad) {
8452 std::string spirv = R"(
8453 OpCapability Shader
8454 OpCapability Geometry
8455 %1 = OpExtInstImport "GLSL.std.450"
8456 OpMemoryModel Logical GLSL450
8457 OpEntryPoint Fragment %main "main" %layer %gl_Layer
8458 OpExecutionMode %main OriginUpperLeft
8459 OpSource GLSL 450
8460 OpDecorate %layer Location 0
8461 OpDecorate %gl_Layer BuiltIn Layer
8462 %void = OpTypeVoid
8463 %3 = OpTypeFunction %void
8464 %int = OpTypeInt 32 1
8465 %_ptr_Output_int = OpTypePointer Output %int
8466 %layer = OpVariable %_ptr_Output_int Output
8467 %_ptr_Input_int = OpTypePointer Input %int
8468 %gl_Layer = OpVariable %_ptr_Input_int Input
8469 %main = OpFunction %void None %3
8470 %5 = OpLabel
8471 %11 = OpLoad %int %gl_Layer
8472 OpStore %layer %11
8473 OpReturn
8474 OpFunctionEnd
8475 )";
8476
8477 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8478 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8479 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8480 EXPECT_THAT(getDiagnosticString(),
8481 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8482 EXPECT_THAT(
8483 getDiagnosticString(),
8484 HasSubstr(
8485 "Fragment OpEntryPoint operand 4 with Input interfaces with integer "
8486 "or float type must have a Flat decoration for Entry Point id 2."));
8487 }
8488
TEST_F(ValidateDecorations,VulkanNoFlatFloat32)8489 TEST_F(ValidateDecorations, VulkanNoFlatFloat32) {
8490 std::string spirv = R"(
8491 OpCapability Shader
8492 %1 = OpExtInstImport "GLSL.std.450"
8493 OpMemoryModel Logical GLSL450
8494 OpEntryPoint Fragment %main "main" %in
8495 OpExecutionMode %main OriginUpperLeft
8496 OpSource GLSL 450
8497 OpDecorate %in Location 0
8498 %void = OpTypeVoid
8499 %3 = OpTypeFunction %void
8500 %float = OpTypeFloat 32
8501 %_ptr_Function_float = OpTypePointer Function %float
8502 %_ptr_Input_float = OpTypePointer Input %float
8503 %in = OpVariable %_ptr_Input_float Input
8504 %main = OpFunction %void None %3
8505 %5 = OpLabel
8506 %b = OpVariable %_ptr_Function_float Function
8507 %11 = OpLoad %float %in
8508 OpStore %b %11
8509 OpReturn
8510 OpFunctionEnd
8511 )";
8512
8513 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8514 EXPECT_EQ(SPV_SUCCESS,
8515 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8516 }
8517
TEST_F(ValidateDecorations,VulkanNoFlatFloat64)8518 TEST_F(ValidateDecorations, VulkanNoFlatFloat64) {
8519 std::string spirv = R"(
8520 OpCapability Shader
8521 OpCapability Float64
8522 %1 = OpExtInstImport "GLSL.std.450"
8523 OpMemoryModel Logical GLSL450
8524 OpEntryPoint Fragment %main "main" %in
8525 OpExecutionMode %main OriginUpperLeft
8526 OpSource GLSL 450
8527 OpDecorate %in Location 0
8528 %void = OpTypeVoid
8529 %3 = OpTypeFunction %void
8530 %double = OpTypeFloat 64
8531 %_ptr_Function_double = OpTypePointer Function %double
8532 %_ptr_Input_double = OpTypePointer Input %double
8533 %in = OpVariable %_ptr_Input_double Input
8534 %main = OpFunction %void None %3
8535 %5 = OpLabel
8536 %b = OpVariable %_ptr_Function_double Function
8537 %11 = OpLoad %double %in
8538 OpStore %b %11
8539 OpReturn
8540 OpFunctionEnd
8541 )";
8542
8543 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8544 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8545 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8546 EXPECT_THAT(getDiagnosticString(),
8547 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8548 EXPECT_THAT(
8549 getDiagnosticString(),
8550 HasSubstr(
8551 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8552 "or float type must have a Flat decoration for Entry Point id 2."));
8553 }
8554
TEST_F(ValidateDecorations,VulkanNoFlatVectorFloat64)8555 TEST_F(ValidateDecorations, VulkanNoFlatVectorFloat64) {
8556 std::string spirv = R"(
8557 OpCapability Shader
8558 OpCapability Float64
8559 %1 = OpExtInstImport "GLSL.std.450"
8560 OpMemoryModel Logical GLSL450
8561 OpEntryPoint Fragment %main "main" %in
8562 OpExecutionMode %main OriginUpperLeft
8563 OpSource GLSL 450
8564 OpDecorate %in Location 0
8565 %void = OpTypeVoid
8566 %3 = OpTypeFunction %void
8567 %double = OpTypeFloat 64
8568 %v2double = OpTypeVector %double 2
8569 %_ptr_Function_v2double = OpTypePointer Function %v2double
8570 %_ptr_Input_v2double = OpTypePointer Input %v2double
8571 %in = OpVariable %_ptr_Input_v2double Input
8572 %main = OpFunction %void None %3
8573 %5 = OpLabel
8574 %b = OpVariable %_ptr_Function_v2double Function
8575 %11 = OpLoad %v2double %in
8576 OpStore %b %11
8577 OpReturn
8578 OpFunctionEnd
8579 )";
8580
8581 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8582 EXPECT_EQ(SPV_SUCCESS,
8583 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8584 }
8585
TEST_F(ValidateDecorations,VulkanNoFlatIntVector)8586 TEST_F(ValidateDecorations, VulkanNoFlatIntVector) {
8587 std::string spirv = R"(
8588 OpCapability Shader
8589 %1 = OpExtInstImport "GLSL.std.450"
8590 OpMemoryModel Logical GLSL450
8591 OpEntryPoint Fragment %main "main" %in
8592 OpExecutionMode %main OriginUpperLeft
8593 OpSource GLSL 450
8594 OpDecorate %in Location 0
8595 %void = OpTypeVoid
8596 %3 = OpTypeFunction %void
8597 %int = OpTypeInt 32 1
8598 %v2int = OpTypeVector %int 2
8599 %_ptr_Function_v2int = OpTypePointer Function %v2int
8600 %_ptr_Input_v2int = OpTypePointer Input %v2int
8601 %in = OpVariable %_ptr_Input_v2int Input
8602 %main = OpFunction %void None %3
8603 %5 = OpLabel
8604 %b = OpVariable %_ptr_Function_v2int Function
8605 %12 = OpLoad %v2int %in
8606 OpStore %b %12
8607 OpReturn
8608 OpFunctionEnd
8609 )";
8610
8611 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8612 EXPECT_EQ(SPV_ERROR_INVALID_ID,
8613 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
8614 EXPECT_THAT(getDiagnosticString(),
8615 AnyVUID("VUID-StandaloneSpirv-Flat-04744"));
8616 EXPECT_THAT(
8617 getDiagnosticString(),
8618 HasSubstr(
8619 "Fragment OpEntryPoint operand 3 with Input interfaces with integer "
8620 "or float type must have a Flat decoration for Entry Point id 2."));
8621 }
8622
TEST_P(ValidateDecorationString,VulkanOutputInvalidInterface)8623 TEST_P(ValidateDecorationString, VulkanOutputInvalidInterface) {
8624 const std::string decoration = GetParam();
8625 std::stringstream ss;
8626 ss << R"(
8627 OpCapability Shader
8628 OpCapability SampleRateShading
8629 %1 = OpExtInstImport "GLSL.std.450"
8630 OpMemoryModel Logical GLSL450
8631 OpEntryPoint Fragment %main "main" %out
8632 OpExecutionMode %main OriginUpperLeft
8633 OpSource GLSL 450
8634 OpDecorate %out )"
8635 << decoration << R"(
8636 OpDecorate %out Location 0
8637 %void = OpTypeVoid
8638 %3 = OpTypeFunction %void
8639 %int = OpTypeInt 32 1
8640 %_ptr_Output_int = OpTypePointer Output %int
8641 %out = OpVariable %_ptr_Output_int Output
8642 %int_1 = OpConstant %int 1
8643 %main = OpFunction %void None %3
8644 %5 = OpLabel
8645 OpStore %out %int_1
8646 OpReturn
8647 OpFunctionEnd
8648 )";
8649
8650 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
8651 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8652 EXPECT_THAT(getDiagnosticString(),
8653 AnyVUID("VUID-StandaloneSpirv-Flat-06201"));
8654 EXPECT_THAT(
8655 getDiagnosticString(),
8656 HasSubstr(
8657 "OpEntryPoint interfaces variable must not be fragment execution "
8658 "model with an output storage class for Entry Point id 2."));
8659 }
8660
TEST_P(ValidateDecorationString,VulkanVertexInputInvalidInterface)8661 TEST_P(ValidateDecorationString, VulkanVertexInputInvalidInterface) {
8662 const std::string decoration = GetParam();
8663 std::stringstream ss;
8664 ss << R"(
8665 OpCapability Shader
8666 OpCapability SampleRateShading
8667 %1 = OpExtInstImport "GLSL.std.450"
8668 OpMemoryModel Logical GLSL450
8669 OpEntryPoint Vertex %main "main" %out %in
8670 OpSource GLSL 450
8671 OpDecorate %in )"
8672 << decoration << R"(
8673 OpDecorate %out Location 0
8674 OpDecorate %in Location 0
8675 %void = OpTypeVoid
8676 %3 = OpTypeFunction %void
8677 %int = OpTypeInt 32 1
8678 %_ptr_Output_int = OpTypePointer Output %int
8679 %out = OpVariable %_ptr_Output_int Output
8680 %_ptr_Input_int = OpTypePointer Input %int
8681 %in = OpVariable %_ptr_Input_int Input
8682 %main = OpFunction %void None %3
8683 %5 = OpLabel
8684 %11 = OpLoad %int %in
8685 OpStore %out %11
8686 OpReturn
8687 OpFunctionEnd
8688 )";
8689
8690 CompileSuccessfully(ss.str(), SPV_ENV_VULKAN_1_0);
8691 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8692 EXPECT_THAT(getDiagnosticString(),
8693 AnyVUID("VUID-StandaloneSpirv-Flat-06202"));
8694 EXPECT_THAT(
8695 getDiagnosticString(),
8696 HasSubstr("OpEntryPoint interfaces variable must not be vertex execution "
8697 "model with an input storage class for Entry Point id 2."));
8698 }
8699
8700 INSTANTIATE_TEST_SUITE_P(FragmentInputInterface, ValidateDecorationString,
8701 ::testing::Values("Flat", "NoPerspective", "Sample",
8702 "Centroid"));
8703
TEST_F(ValidateDecorations,NVBindlessSamplerArrayInBlock)8704 TEST_F(ValidateDecorations, NVBindlessSamplerArrayInBlock) {
8705 const std::string spirv = R"(
8706 OpCapability Shader
8707 OpCapability BindlessTextureNV
8708 OpExtension "SPV_NV_bindless_texture"
8709 %1 = OpExtInstImport "GLSL.std.450"
8710 OpMemoryModel Logical GLSL450
8711 OpSamplerImageAddressingModeNV 64
8712 OpEntryPoint Fragment %main "main"
8713 OpExecutionMode %main OriginUpperLeft
8714 OpSource GLSL 450
8715 OpName %main "main"
8716 OpName %UBO "UBO"
8717 OpMemberName %UBO 0 "uboSampler"
8718 OpName %_ ""
8719 OpDecorate %array ArrayStride 16
8720 OpMemberDecorate %UBO 0 Offset 0
8721 OpDecorate %UBO Block
8722 OpDecorate %_ DescriptorSet 0
8723 OpDecorate %_ Binding 2
8724 %void = OpTypeVoid
8725 %3 = OpTypeFunction %void
8726 %float = OpTypeFloat 32
8727 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
8728 %8 = OpTypeSampledImage %7
8729 %uint = OpTypeInt 32 0
8730 %uint_3 = OpConstant %uint 3
8731 %array = OpTypeArray %8 %uint_3
8732 %UBO = OpTypeStruct %array
8733 %pointer = OpTypePointer Uniform %UBO
8734 %_ = OpVariable %pointer Uniform
8735 %main = OpFunction %void None %3
8736 %5 = OpLabel
8737 OpReturn
8738 OpFunctionEnd
8739 )";
8740
8741 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
8742 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
8743 }
8744
TEST_F(ValidateDecorations,Std140ColMajorMat2x2)8745 TEST_F(ValidateDecorations, Std140ColMajorMat2x2) {
8746 const std::string spirv = R"(
8747 OpCapability Shader
8748 OpMemoryModel Logical GLSL450
8749 OpEntryPoint GLCompute %main "main"
8750 OpExecutionMode %main LocalSize 1 1 1
8751 OpDecorate %block Block
8752 OpMemberDecorate %block 0 Offset 0
8753 OpMemberDecorate %block 0 ColMajor
8754 OpMemberDecorate %block 0 MatrixStride 8
8755 OpDecorate %var DescriptorSet 0
8756 OpDecorate %var Binding 0
8757 %void = OpTypeVoid
8758 %void_fn = OpTypeFunction %void
8759 %float = OpTypeFloat 32
8760 %float2 = OpTypeVector %float 2
8761 %matrix = OpTypeMatrix %float2 2
8762 %block = OpTypeStruct %matrix
8763 %ptr_block = OpTypePointer Uniform %block
8764 %var = OpVariable %ptr_block Uniform
8765 %main = OpFunction %void None %void_fn
8766 %entry = OpLabel
8767 OpReturn
8768 OpFunctionEnd
8769 )";
8770
8771 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8772 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8773 EXPECT_THAT(
8774 getDiagnosticString(),
8775 HasSubstr(
8776 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
8777 }
8778
TEST_F(ValidateDecorations,Std140RowMajorMat2x2)8779 TEST_F(ValidateDecorations, Std140RowMajorMat2x2) {
8780 const std::string spirv = R"(
8781 OpCapability Shader
8782 OpMemoryModel Logical GLSL450
8783 OpEntryPoint GLCompute %main "main"
8784 OpExecutionMode %main LocalSize 1 1 1
8785 OpDecorate %block Block
8786 OpMemberDecorate %block 0 Offset 0
8787 OpMemberDecorate %block 0 RowMajor
8788 OpMemberDecorate %block 0 MatrixStride 8
8789 OpDecorate %var DescriptorSet 0
8790 OpDecorate %var Binding 0
8791 %void = OpTypeVoid
8792 %void_fn = OpTypeFunction %void
8793 %float = OpTypeFloat 32
8794 %float2 = OpTypeVector %float 2
8795 %matrix = OpTypeMatrix %float2 2
8796 %block = OpTypeStruct %matrix
8797 %ptr_block = OpTypePointer Uniform %block
8798 %var = OpVariable %ptr_block Uniform
8799 %main = OpFunction %void None %void_fn
8800 %entry = OpLabel
8801 OpReturn
8802 OpFunctionEnd
8803 )";
8804
8805 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8806 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8807 EXPECT_THAT(
8808 getDiagnosticString(),
8809 HasSubstr(
8810 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
8811 }
8812
TEST_F(ValidateDecorations,Std140ColMajorMat4x2)8813 TEST_F(ValidateDecorations, Std140ColMajorMat4x2) {
8814 const std::string spirv = R"(
8815 OpCapability Shader
8816 OpMemoryModel Logical GLSL450
8817 OpEntryPoint GLCompute %main "main"
8818 OpExecutionMode %main LocalSize 1 1 1
8819 OpDecorate %block Block
8820 OpMemberDecorate %block 0 Offset 0
8821 OpMemberDecorate %block 0 ColMajor
8822 OpMemberDecorate %block 0 MatrixStride 8
8823 OpDecorate %var DescriptorSet 0
8824 OpDecorate %var Binding 0
8825 %void = OpTypeVoid
8826 %void_fn = OpTypeFunction %void
8827 %float = OpTypeFloat 32
8828 %float2 = OpTypeVector %float 2
8829 %matrix = OpTypeMatrix %float2 4
8830 %block = OpTypeStruct %matrix
8831 %ptr_block = OpTypePointer Uniform %block
8832 %var = OpVariable %ptr_block Uniform
8833 %main = OpFunction %void None %void_fn
8834 %entry = OpLabel
8835 OpReturn
8836 OpFunctionEnd
8837 )";
8838
8839 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8840 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8841 EXPECT_THAT(
8842 getDiagnosticString(),
8843 HasSubstr(
8844 "member 0 is a matrix with stride 8 not satisfying alignment to 16"));
8845 }
8846
TEST_F(ValidateDecorations,Std140ColMajorMat2x3)8847 TEST_F(ValidateDecorations, Std140ColMajorMat2x3) {
8848 const std::string spirv = R"(
8849 OpCapability Shader
8850 OpMemoryModel Logical GLSL450
8851 OpEntryPoint GLCompute %main "main"
8852 OpExecutionMode %main LocalSize 1 1 1
8853 OpDecorate %block Block
8854 OpMemberDecorate %block 0 Offset 0
8855 OpMemberDecorate %block 0 ColMajor
8856 OpMemberDecorate %block 0 MatrixStride 12
8857 OpDecorate %var DescriptorSet 0
8858 OpDecorate %var Binding 0
8859 %void = OpTypeVoid
8860 %void_fn = OpTypeFunction %void
8861 %float = OpTypeFloat 32
8862 %float3 = OpTypeVector %float 3
8863 %matrix = OpTypeMatrix %float3 2
8864 %block = OpTypeStruct %matrix
8865 %ptr_block = OpTypePointer Uniform %block
8866 %var = OpVariable %ptr_block Uniform
8867 %main = OpFunction %void None %void_fn
8868 %entry = OpLabel
8869 OpReturn
8870 OpFunctionEnd
8871 )";
8872
8873 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8874 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8875 EXPECT_THAT(getDiagnosticString(),
8876 HasSubstr("member 0 is a matrix with stride 12 not satisfying "
8877 "alignment to 16"));
8878 }
8879
TEST_F(ValidateDecorations,MatrixMissingMajornessUniform)8880 TEST_F(ValidateDecorations, MatrixMissingMajornessUniform) {
8881 const std::string spirv = R"(
8882 OpCapability Shader
8883 OpMemoryModel Logical GLSL450
8884 OpEntryPoint GLCompute %main "main"
8885 OpExecutionMode %main LocalSize 1 1 1
8886 OpDecorate %block Block
8887 OpMemberDecorate %block 0 Offset 0
8888 OpMemberDecorate %block 0 MatrixStride 16
8889 OpDecorate %var DescriptorSet 0
8890 OpDecorate %var Binding 0
8891 %void = OpTypeVoid
8892 %void_fn = OpTypeFunction %void
8893 %float = OpTypeFloat 32
8894 %float2 = OpTypeVector %float 2
8895 %matrix = OpTypeMatrix %float2 2
8896 %block = OpTypeStruct %matrix
8897 %ptr_block = OpTypePointer Uniform %block
8898 %var = OpVariable %ptr_block Uniform
8899 %main = OpFunction %void None %void_fn
8900 %entry = OpLabel
8901 OpReturn
8902 OpFunctionEnd
8903 )";
8904
8905 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8906 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8907 EXPECT_THAT(
8908 getDiagnosticString(),
8909 HasSubstr(
8910 "must be explicitly laid out with RowMajor or ColMajor decorations"));
8911 }
8912
TEST_F(ValidateDecorations,MatrixMissingMajornessStorageBuffer)8913 TEST_F(ValidateDecorations, MatrixMissingMajornessStorageBuffer) {
8914 const std::string spirv = R"(
8915 OpCapability Shader
8916 OpExtension "SPV_KHR_storage_buffer_storage_class"
8917 OpMemoryModel Logical GLSL450
8918 OpEntryPoint GLCompute %main "main"
8919 OpExecutionMode %main LocalSize 1 1 1
8920 OpDecorate %block Block
8921 OpMemberDecorate %block 0 Offset 0
8922 OpMemberDecorate %block 0 MatrixStride 16
8923 OpDecorate %var DescriptorSet 0
8924 OpDecorate %var Binding 0
8925 %void = OpTypeVoid
8926 %void_fn = OpTypeFunction %void
8927 %float = OpTypeFloat 32
8928 %float2 = OpTypeVector %float 2
8929 %matrix = OpTypeMatrix %float2 2
8930 %block = OpTypeStruct %matrix
8931 %ptr_block = OpTypePointer StorageBuffer %block
8932 %var = OpVariable %ptr_block StorageBuffer
8933 %main = OpFunction %void None %void_fn
8934 %entry = OpLabel
8935 OpReturn
8936 OpFunctionEnd
8937 )";
8938
8939 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8940 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8941 EXPECT_THAT(
8942 getDiagnosticString(),
8943 HasSubstr(
8944 "must be explicitly laid out with RowMajor or ColMajor decorations"));
8945 }
8946
TEST_F(ValidateDecorations,MatrixMissingMajornessPushConstant)8947 TEST_F(ValidateDecorations, MatrixMissingMajornessPushConstant) {
8948 const std::string spirv = R"(
8949 OpCapability Shader
8950 OpMemoryModel Logical GLSL450
8951 OpEntryPoint GLCompute %main "main"
8952 OpExecutionMode %main LocalSize 1 1 1
8953 OpDecorate %block Block
8954 OpMemberDecorate %block 0 Offset 0
8955 OpMemberDecorate %block 0 MatrixStride 16
8956 %void = OpTypeVoid
8957 %void_fn = OpTypeFunction %void
8958 %float = OpTypeFloat 32
8959 %float2 = OpTypeVector %float 2
8960 %matrix = OpTypeMatrix %float2 2
8961 %block = OpTypeStruct %matrix
8962 %ptr_block = OpTypePointer PushConstant %block
8963 %var = OpVariable %ptr_block PushConstant
8964 %main = OpFunction %void None %void_fn
8965 %entry = OpLabel
8966 OpReturn
8967 OpFunctionEnd
8968 )";
8969
8970 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
8971 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
8972 EXPECT_THAT(
8973 getDiagnosticString(),
8974 HasSubstr(
8975 "must be explicitly laid out with RowMajor or ColMajor decorations"));
8976 }
8977
TEST_F(ValidateDecorations,StructWithRowAndColMajor)8978 TEST_F(ValidateDecorations, StructWithRowAndColMajor) {
8979 const std::string spirv = R"(
8980 OpCapability Shader
8981 OpMemoryModel Logical GLSL450
8982 OpEntryPoint GLCompute %main "main"
8983 OpExecutionMode %main LocalSize 1 1 1
8984 OpDecorate %block Block
8985 OpMemberDecorate %block 0 Offset 0
8986 OpMemberDecorate %block 0 MatrixStride 16
8987 OpMemberDecorate %block 0 ColMajor
8988 OpMemberDecorate %block 1 Offset 32
8989 OpMemberDecorate %block 1 MatrixStride 16
8990 OpMemberDecorate %block 1 RowMajor
8991 %void = OpTypeVoid
8992 %void_fn = OpTypeFunction %void
8993 %float = OpTypeFloat 32
8994 %float2 = OpTypeVector %float 2
8995 %matrix = OpTypeMatrix %float2 2
8996 %block = OpTypeStruct %matrix %matrix
8997 %ptr_block = OpTypePointer PushConstant %block
8998 %var = OpVariable %ptr_block PushConstant
8999 %main = OpFunction %void None %void_fn
9000 %entry = OpLabel
9001 OpReturn
9002 OpFunctionEnd
9003 )";
9004
9005 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
9006 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
9007 }
9008
9009 } // namespace
9010 } // namespace val
9011 } // namespace spvtools
9012