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::__anon74f872e00111::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 ValidateVulkanCombineDecorationResult =
46 spvtest::ValidateBase<std::tuple<const char*, const char*, TestResult>>;
47
TEST_F(ValidateDecorations,ValidateOpDecorateRegistration)48 TEST_F(ValidateDecorations, ValidateOpDecorateRegistration) {
49 std::string spirv = R"(
50 OpCapability Shader
51 OpCapability Linkage
52 OpMemoryModel Logical GLSL450
53 OpDecorate %1 ArrayStride 4
54 OpDecorate %1 RelaxedPrecision
55 %2 = OpTypeFloat 32
56 %1 = OpTypeRuntimeArray %2
57 ; Since %1 is used first in Decoration, it gets id 1.
58 )";
59 const uint32_t id = 1;
60 CompileSuccessfully(spirv);
61 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
62 // Must have 2 decorations.
63 EXPECT_THAT(
64 vstate_->id_decorations(id),
65 Eq(std::vector<Decoration>{Decoration(SpvDecorationArrayStride, {4}),
66 Decoration(SpvDecorationRelaxedPrecision)}));
67 }
68
TEST_F(ValidateDecorations,ValidateOpMemberDecorateRegistration)69 TEST_F(ValidateDecorations, ValidateOpMemberDecorateRegistration) {
70 std::string spirv = R"(
71 OpCapability Shader
72 OpCapability Linkage
73 OpMemoryModel Logical GLSL450
74 OpDecorate %_arr_double_uint_6 ArrayStride 4
75 OpMemberDecorate %_struct_115 2 NonReadable
76 OpMemberDecorate %_struct_115 2 Offset 2
77 OpDecorate %_struct_115 BufferBlock
78 %float = OpTypeFloat 32
79 %uint = OpTypeInt 32 0
80 %uint_6 = OpConstant %uint 6
81 %_arr_double_uint_6 = OpTypeArray %float %uint_6
82 %_struct_115 = OpTypeStruct %float %float %_arr_double_uint_6
83 )";
84 CompileSuccessfully(spirv);
85 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
86
87 // The array must have 1 decoration.
88 const uint32_t arr_id = 1;
89 EXPECT_THAT(
90 vstate_->id_decorations(arr_id),
91 Eq(std::vector<Decoration>{Decoration(SpvDecorationArrayStride, {4})}));
92
93 // The struct must have 3 decorations.
94 const uint32_t struct_id = 2;
95 EXPECT_THAT(
96 vstate_->id_decorations(struct_id),
97 Eq(std::vector<Decoration>{Decoration(SpvDecorationNonReadable, {}, 2),
98 Decoration(SpvDecorationOffset, {2}, 2),
99 Decoration(SpvDecorationBufferBlock)}));
100 }
101
TEST_F(ValidateDecorations,ValidateOpMemberDecorateOutOfBound)102 TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) {
103 std::string spirv = R"(
104 OpCapability Shader
105 OpMemoryModel Logical GLSL450
106 OpEntryPoint Fragment %1 "Main"
107 OpExecutionMode %1 OriginUpperLeft
108 OpMemberDecorate %_struct_2 1 RelaxedPrecision
109 %void = OpTypeVoid
110 %4 = OpTypeFunction %void
111 %float = OpTypeFloat 32
112 %_struct_2 = OpTypeStruct %float
113 %1 = OpFunction %void None %4
114 %6 = OpLabel
115 OpReturn
116 OpFunctionEnd
117 )";
118 CompileSuccessfully(spirv);
119 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
120 EXPECT_THAT(getDiagnosticString(),
121 HasSubstr("Index 1 provided in OpMemberDecorate for struct <id> "
122 "2[%_struct_2] is out of bounds. The structure has 1 "
123 "members. Largest valid index is 0."));
124 }
125
TEST_F(ValidateDecorations,ValidateGroupDecorateRegistration)126 TEST_F(ValidateDecorations, ValidateGroupDecorateRegistration) {
127 std::string spirv = R"(
128 OpCapability Shader
129 OpCapability Linkage
130 OpMemoryModel Logical GLSL450
131 OpDecorate %1 DescriptorSet 0
132 OpDecorate %1 RelaxedPrecision
133 OpDecorate %1 Restrict
134 %1 = OpDecorationGroup
135 OpGroupDecorate %1 %2 %3
136 OpGroupDecorate %1 %4
137 %float = OpTypeFloat 32
138 %_runtimearr_float = OpTypeRuntimeArray %float
139 %_struct_9 = OpTypeStruct %_runtimearr_float
140 %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
141 %2 = OpVariable %_ptr_Uniform__struct_9 Uniform
142 %_struct_10 = OpTypeStruct %_runtimearr_float
143 %_ptr_Uniform__struct_10 = OpTypePointer Uniform %_struct_10
144 %3 = OpVariable %_ptr_Uniform__struct_10 Uniform
145 %_struct_11 = OpTypeStruct %_runtimearr_float
146 %_ptr_Uniform__struct_11 = OpTypePointer Uniform %_struct_11
147 %4 = OpVariable %_ptr_Uniform__struct_11 Uniform
148 )";
149 CompileSuccessfully(spirv);
150 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
151
152 // Decoration group has 3 decorations.
153 auto expected_decorations =
154 std::vector<Decoration>{Decoration(SpvDecorationDescriptorSet, {0}),
155 Decoration(SpvDecorationRelaxedPrecision),
156 Decoration(SpvDecorationRestrict)};
157
158 // Decoration group is applied to id 1, 2, 3, and 4. Note that id 1 (which is
159 // the decoration group id) also has all the decorations.
160 EXPECT_THAT(vstate_->id_decorations(1), Eq(expected_decorations));
161 EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
162 EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations));
163 EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations));
164 }
165
TEST_F(ValidateDecorations,ValidateGroupMemberDecorateRegistration)166 TEST_F(ValidateDecorations, ValidateGroupMemberDecorateRegistration) {
167 std::string spirv = R"(
168 OpCapability Shader
169 OpCapability Linkage
170 OpMemoryModel Logical GLSL450
171 OpDecorate %1 Offset 3
172 %1 = OpDecorationGroup
173 OpGroupMemberDecorate %1 %_struct_1 3 %_struct_2 3 %_struct_3 3
174 %float = OpTypeFloat 32
175 %_runtimearr = OpTypeRuntimeArray %float
176 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
177 %_struct_2 = OpTypeStruct %float %float %float %_runtimearr
178 %_struct_3 = OpTypeStruct %float %float %float %_runtimearr
179 )";
180 CompileSuccessfully(spirv);
181 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
182 // Decoration group has 1 decoration.
183 auto expected_decorations =
184 std::vector<Decoration>{Decoration(SpvDecorationOffset, {3}, 3)};
185
186 // Decoration group is applied to id 2, 3, and 4.
187 EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
188 EXPECT_THAT(vstate_->id_decorations(3), Eq(expected_decorations));
189 EXPECT_THAT(vstate_->id_decorations(4), Eq(expected_decorations));
190 }
191
TEST_F(ValidateDecorations,LinkageImportUsedForInitializedVariableBad)192 TEST_F(ValidateDecorations, LinkageImportUsedForInitializedVariableBad) {
193 std::string spirv = R"(
194 OpCapability Shader
195 OpCapability Linkage
196 OpMemoryModel Logical GLSL450
197 OpDecorate %target LinkageAttributes "link_ptr" Import
198 %float = OpTypeFloat 32
199 %_ptr_float = OpTypePointer Uniform %float
200 %zero = OpConstantNull %float
201 %target = OpVariable %_ptr_float Uniform %zero
202 )";
203 CompileSuccessfully(spirv);
204 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
205 EXPECT_THAT(getDiagnosticString(),
206 HasSubstr("A module-scope OpVariable with initialization value "
207 "cannot be marked with the Import Linkage Type."));
208 }
TEST_F(ValidateDecorations,LinkageExportUsedForInitializedVariableGood)209 TEST_F(ValidateDecorations, LinkageExportUsedForInitializedVariableGood) {
210 std::string spirv = R"(
211 OpCapability Shader
212 OpCapability Linkage
213 OpMemoryModel Logical GLSL450
214 OpDecorate %target LinkageAttributes "link_ptr" Export
215 %float = OpTypeFloat 32
216 %_ptr_float = OpTypePointer Uniform %float
217 %zero = OpConstantNull %float
218 %target = OpVariable %_ptr_float Uniform %zero
219 )";
220 CompileSuccessfully(spirv);
221 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
222 }
223
TEST_F(ValidateDecorations,StructAllMembersHaveBuiltInDecorationsGood)224 TEST_F(ValidateDecorations, StructAllMembersHaveBuiltInDecorationsGood) {
225 std::string spirv = R"(
226 OpCapability Shader
227 OpCapability Linkage
228 OpMemoryModel Logical GLSL450
229 OpMemberDecorate %_struct_1 0 BuiltIn Position
230 OpMemberDecorate %_struct_1 1 BuiltIn Position
231 OpMemberDecorate %_struct_1 2 BuiltIn Position
232 OpMemberDecorate %_struct_1 3 BuiltIn Position
233 %float = OpTypeFloat 32
234 %_runtimearr = OpTypeRuntimeArray %float
235 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
236 )";
237 CompileSuccessfully(spirv);
238 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
239 }
240
TEST_F(ValidateDecorations,MixedBuiltInDecorationsBad)241 TEST_F(ValidateDecorations, MixedBuiltInDecorationsBad) {
242 std::string spirv = R"(
243 OpCapability Shader
244 OpCapability Linkage
245 OpMemoryModel Logical GLSL450
246 OpMemberDecorate %_struct_1 0 BuiltIn Position
247 OpMemberDecorate %_struct_1 1 BuiltIn Position
248 %float = OpTypeFloat 32
249 %_runtimearr = OpTypeRuntimeArray %float
250 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
251 )";
252 CompileSuccessfully(spirv);
253 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
254 EXPECT_THAT(
255 getDiagnosticString(),
256 HasSubstr("When BuiltIn decoration is applied to a structure-type "
257 "member, all members of that structure type must also be "
258 "decorated with BuiltIn (No allowed mixing of built-in "
259 "variables and non-built-in variables within a single "
260 "structure). Structure id 1 does not meet this requirement."));
261 }
262
TEST_F(ValidateDecorations,StructContainsBuiltInStructBad)263 TEST_F(ValidateDecorations, StructContainsBuiltInStructBad) {
264 std::string spirv = R"(
265 OpCapability Shader
266 OpCapability Linkage
267 OpMemoryModel Logical GLSL450
268 OpMemberDecorate %_struct_1 0 BuiltIn Position
269 OpMemberDecorate %_struct_1 1 BuiltIn Position
270 OpMemberDecorate %_struct_1 2 BuiltIn Position
271 OpMemberDecorate %_struct_1 3 BuiltIn Position
272 %float = OpTypeFloat 32
273 %_runtimearr = OpTypeRuntimeArray %float
274 %_struct_1 = OpTypeStruct %float %float %float %_runtimearr
275 %_struct_2 = OpTypeStruct %_struct_1
276 )";
277 CompileSuccessfully(spirv);
278 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
279 EXPECT_THAT(getDiagnosticString(),
280 HasSubstr("Structure <id> 1[%_struct_1] contains members with "
281 "BuiltIn decoration. Therefore this structure may not "
282 "be contained as a member of another structure type. "
283 "Structure <id> 4[%_struct_4] contains structure <id> "
284 "1[%_struct_1]."));
285 }
286
TEST_F(ValidateDecorations,StructContainsNonBuiltInStructGood)287 TEST_F(ValidateDecorations, StructContainsNonBuiltInStructGood) {
288 std::string spirv = R"(
289 OpCapability Shader
290 OpCapability Linkage
291 OpMemoryModel Logical GLSL450
292 %float = OpTypeFloat 32
293 %_struct_1 = OpTypeStruct %float
294 %_struct_2 = OpTypeStruct %_struct_1
295 )";
296 CompileSuccessfully(spirv);
297 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
298 }
299
TEST_F(ValidateDecorations,MultipleBuiltInObjectsConsumedByOpEntryPointBad)300 TEST_F(ValidateDecorations, MultipleBuiltInObjectsConsumedByOpEntryPointBad) {
301 std::string spirv = R"(
302 OpCapability Shader
303 OpCapability Geometry
304 OpMemoryModel Logical GLSL450
305 OpEntryPoint Geometry %main "main" %in_1 %in_2
306 OpExecutionMode %main InputPoints
307 OpExecutionMode %main OutputPoints
308 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
309 OpMemberDecorate %struct_2 0 BuiltIn Position
310 %int = OpTypeInt 32 1
311 %void = OpTypeVoid
312 %func = OpTypeFunction %void
313 %float = OpTypeFloat 32
314 %struct_1 = OpTypeStruct %int
315 %struct_2 = OpTypeStruct %float
316 %ptr_builtin_1 = OpTypePointer Input %struct_1
317 %ptr_builtin_2 = OpTypePointer Input %struct_2
318 %in_1 = OpVariable %ptr_builtin_1 Input
319 %in_2 = OpVariable %ptr_builtin_2 Input
320 %main = OpFunction %void None %func
321 %5 = OpLabel
322 OpReturn
323 OpFunctionEnd
324 )";
325 CompileSuccessfully(spirv);
326 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
327 EXPECT_THAT(getDiagnosticString(),
328 HasSubstr("There must be at most one object per Storage Class "
329 "that can contain a structure type containing members "
330 "decorated with BuiltIn, consumed per entry-point."));
331 }
332
TEST_F(ValidateDecorations,OneBuiltInObjectPerStorageClassConsumedByOpEntryPointGood)333 TEST_F(ValidateDecorations,
334 OneBuiltInObjectPerStorageClassConsumedByOpEntryPointGood) {
335 std::string spirv = R"(
336 OpCapability Shader
337 OpCapability Geometry
338 OpMemoryModel Logical GLSL450
339 OpEntryPoint Geometry %main "main" %in_1 %out_1
340 OpExecutionMode %main InputPoints
341 OpExecutionMode %main OutputPoints
342 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
343 OpMemberDecorate %struct_2 0 BuiltIn Position
344 %int = OpTypeInt 32 1
345 %void = OpTypeVoid
346 %func = OpTypeFunction %void
347 %float = OpTypeFloat 32
348 %struct_1 = OpTypeStruct %int
349 %struct_2 = OpTypeStruct %float
350 %ptr_builtin_1 = OpTypePointer Input %struct_1
351 %ptr_builtin_2 = OpTypePointer Output %struct_2
352 %in_1 = OpVariable %ptr_builtin_1 Input
353 %out_1 = OpVariable %ptr_builtin_2 Output
354 %main = OpFunction %void None %func
355 %5 = OpLabel
356 OpReturn
357 OpFunctionEnd
358 )";
359 CompileSuccessfully(spirv);
360 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
361 }
362
TEST_F(ValidateDecorations,NoBuiltInObjectsConsumedByOpEntryPointGood)363 TEST_F(ValidateDecorations, NoBuiltInObjectsConsumedByOpEntryPointGood) {
364 std::string spirv = R"(
365 OpCapability Shader
366 OpCapability Geometry
367 OpMemoryModel Logical GLSL450
368 OpEntryPoint Geometry %main "main" %in_1 %out_1
369 OpExecutionMode %main InputPoints
370 OpExecutionMode %main OutputPoints
371 %int = OpTypeInt 32 1
372 %void = OpTypeVoid
373 %func = OpTypeFunction %void
374 %float = OpTypeFloat 32
375 %struct_1 = OpTypeStruct %int
376 %struct_2 = OpTypeStruct %float
377 %ptr_builtin_1 = OpTypePointer Input %struct_1
378 %ptr_builtin_2 = OpTypePointer Output %struct_2
379 %in_1 = OpVariable %ptr_builtin_1 Input
380 %out_1 = OpVariable %ptr_builtin_2 Output
381 %main = OpFunction %void None %func
382 %5 = OpLabel
383 OpReturn
384 OpFunctionEnd
385 )";
386 CompileSuccessfully(spirv);
387 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
388 }
389
TEST_F(ValidateDecorations,EntryPointFunctionHasLinkageAttributeBad)390 TEST_F(ValidateDecorations, EntryPointFunctionHasLinkageAttributeBad) {
391 std::string spirv = R"(
392 OpCapability Shader
393 OpCapability Linkage
394 OpMemoryModel Logical GLSL450
395 OpEntryPoint GLCompute %main "main"
396 OpDecorate %main LinkageAttributes "import_main" Import
397 %1 = OpTypeVoid
398 %2 = OpTypeFunction %1
399 %main = OpFunction %1 None %2
400 %4 = OpLabel
401 OpReturn
402 OpFunctionEnd
403 )";
404 CompileSuccessfully(spirv.c_str());
405 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
406 EXPECT_THAT(
407 getDiagnosticString(),
408 HasSubstr("The LinkageAttributes Decoration (Linkage name: import_main) "
409 "cannot be applied to function id 1 because it is targeted by "
410 "an OpEntryPoint instruction."));
411 }
412
TEST_F(ValidateDecorations,FunctionDeclarationWithoutImportLinkageBad)413 TEST_F(ValidateDecorations, FunctionDeclarationWithoutImportLinkageBad) {
414 std::string spirv = R"(
415 OpCapability Shader
416 OpCapability Linkage
417 OpMemoryModel Logical GLSL450
418 %void = OpTypeVoid
419 %func = OpTypeFunction %void
420 %main = OpFunction %void None %func
421 OpFunctionEnd
422 )";
423 CompileSuccessfully(spirv);
424 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
425 EXPECT_THAT(
426 getDiagnosticString(),
427 HasSubstr("Function declaration (id 3) must have a LinkageAttributes "
428 "decoration with the Import Linkage type."));
429 }
430
TEST_F(ValidateDecorations,FunctionDeclarationWithImportLinkageGood)431 TEST_F(ValidateDecorations, FunctionDeclarationWithImportLinkageGood) {
432 std::string spirv = R"(
433 OpCapability Shader
434 OpCapability Linkage
435 OpMemoryModel Logical GLSL450
436 OpDecorate %main LinkageAttributes "link_fn" Import
437 %void = OpTypeVoid
438 %func = OpTypeFunction %void
439 %main = OpFunction %void None %func
440 OpFunctionEnd
441 )";
442 CompileSuccessfully(spirv);
443 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
444 }
445
TEST_F(ValidateDecorations,FunctionDeclarationWithExportLinkageBad)446 TEST_F(ValidateDecorations, FunctionDeclarationWithExportLinkageBad) {
447 std::string spirv = R"(
448 OpCapability Shader
449 OpCapability Linkage
450 OpMemoryModel Logical GLSL450
451 OpDecorate %main LinkageAttributes "link_fn" Export
452 %void = OpTypeVoid
453 %func = OpTypeFunction %void
454 %main = OpFunction %void None %func
455 OpFunctionEnd
456 )";
457 CompileSuccessfully(spirv);
458 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
459 EXPECT_THAT(
460 getDiagnosticString(),
461 HasSubstr("Function declaration (id 1) must have a LinkageAttributes "
462 "decoration with the Import Linkage type."));
463 }
464
TEST_F(ValidateDecorations,FunctionDefinitionWithImportLinkageBad)465 TEST_F(ValidateDecorations, FunctionDefinitionWithImportLinkageBad) {
466 std::string spirv = R"(
467 OpCapability Shader
468 OpCapability Linkage
469 OpMemoryModel Logical GLSL450
470 OpDecorate %main LinkageAttributes "link_fn" Import
471 %void = OpTypeVoid
472 %func = OpTypeFunction %void
473 %main = OpFunction %void None %func
474 %label = OpLabel
475 OpReturn
476 OpFunctionEnd
477 )";
478 CompileSuccessfully(spirv);
479 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateAndRetrieveValidationState());
480 EXPECT_THAT(getDiagnosticString(),
481 HasSubstr("Function definition (id 1) may not be decorated with "
482 "Import Linkage type."));
483 }
484
TEST_F(ValidateDecorations,FunctionDefinitionWithoutImportLinkageGood)485 TEST_F(ValidateDecorations, FunctionDefinitionWithoutImportLinkageGood) {
486 std::string spirv = R"(
487 OpCapability Shader
488 OpCapability Linkage
489 OpMemoryModel Logical GLSL450
490 %void = OpTypeVoid
491 %func = OpTypeFunction %void
492 %main = OpFunction %void None %func
493 %label = OpLabel
494 OpReturn
495 OpFunctionEnd
496 )";
497 CompileSuccessfully(spirv);
498 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
499 }
500
TEST_F(ValidateDecorations,BuiltinVariablesGoodVulkan)501 TEST_F(ValidateDecorations, BuiltinVariablesGoodVulkan) {
502 const spv_target_env env = SPV_ENV_VULKAN_1_0;
503 std::string spirv = R"(
504 OpCapability Shader
505 OpMemoryModel Logical GLSL450
506 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
507 OpExecutionMode %main OriginUpperLeft
508 OpSource HLSL 500
509 OpDecorate %gl_FragCoord BuiltIn FragCoord
510 OpDecorate %_entryPointOutput Location 0
511 %void = OpTypeVoid
512 %3 = OpTypeFunction %void
513 %float = OpTypeFloat 32
514 %v4float = OpTypeVector %float 4
515 %float_0 = OpConstant %float 0
516 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
517 %_ptr_Input_v4float = OpTypePointer Input %v4float
518 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
519 %_ptr_Output_v4float = OpTypePointer Output %v4float
520 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
521 %main = OpFunction %void None %3
522 %5 = OpLabel
523 OpStore %_entryPointOutput %14
524 OpReturn
525 OpFunctionEnd
526 )";
527
528 CompileSuccessfully(spirv, env);
529 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
530 }
531
TEST_F(ValidateDecorations,BuiltinVariablesWithLocationDecorationVulkan)532 TEST_F(ValidateDecorations, BuiltinVariablesWithLocationDecorationVulkan) {
533 const spv_target_env env = SPV_ENV_VULKAN_1_0;
534 std::string spirv = R"(
535 OpCapability Shader
536 OpMemoryModel Logical GLSL450
537 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
538 OpExecutionMode %main OriginUpperLeft
539 OpSource HLSL 500
540 OpDecorate %gl_FragCoord BuiltIn FragCoord
541 OpDecorate %gl_FragCoord Location 0
542 OpDecorate %_entryPointOutput Location 0
543 %void = OpTypeVoid
544 %3 = OpTypeFunction %void
545 %float = OpTypeFloat 32
546 %v4float = OpTypeVector %float 4
547 %float_0 = OpConstant %float 0
548 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
549 %_ptr_Input_v4float = OpTypePointer Input %v4float
550 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
551 %_ptr_Output_v4float = OpTypePointer Output %v4float
552 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
553 %main = OpFunction %void None %3
554 %5 = OpLabel
555 OpStore %_entryPointOutput %14
556 OpReturn
557 OpFunctionEnd
558 )";
559
560 CompileSuccessfully(spirv, env);
561 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
562 EXPECT_THAT(getDiagnosticString(),
563 HasSubstr("A BuiltIn variable (id 2) cannot have any Location or "
564 "Component decorations"));
565 }
TEST_F(ValidateDecorations,BuiltinVariablesWithComponentDecorationVulkan)566 TEST_F(ValidateDecorations, BuiltinVariablesWithComponentDecorationVulkan) {
567 const spv_target_env env = SPV_ENV_VULKAN_1_0;
568 std::string spirv = R"(
569 OpCapability Shader
570 OpMemoryModel Logical GLSL450
571 OpEntryPoint Fragment %main "main" %gl_FragCoord %_entryPointOutput
572 OpExecutionMode %main OriginUpperLeft
573 OpSource HLSL 500
574 OpDecorate %gl_FragCoord BuiltIn FragCoord
575 OpDecorate %gl_FragCoord Component 0
576 OpDecorate %_entryPointOutput Location 0
577 %void = OpTypeVoid
578 %3 = OpTypeFunction %void
579 %float = OpTypeFloat 32
580 %v4float = OpTypeVector %float 4
581 %float_0 = OpConstant %float 0
582 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
583 %_ptr_Input_v4float = OpTypePointer Input %v4float
584 %gl_FragCoord = OpVariable %_ptr_Input_v4float Input
585 %_ptr_Output_v4float = OpTypePointer Output %v4float
586 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
587 %main = OpFunction %void None %3
588 %5 = OpLabel
589 OpStore %_entryPointOutput %14
590 OpReturn
591 OpFunctionEnd
592 )";
593
594 CompileSuccessfully(spirv, env);
595 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
596 EXPECT_THAT(getDiagnosticString(),
597 HasSubstr("A BuiltIn variable (id 2) cannot have any Location or "
598 "Component decorations"));
599 }
600
601 // #version 440
602 // #extension GL_EXT_nonuniform_qualifier : enable
603 // layout(binding = 1) uniform sampler2D s2d[];
604 // layout(location = 0) in nonuniformEXT int i;
605 // void main()
606 // {
607 // vec4 v = texture(s2d[i], vec2(0.3));
608 // }
TEST_F(ValidateDecorations,RuntimeArrayOfDescriptorSetsIsAllowed)609 TEST_F(ValidateDecorations, RuntimeArrayOfDescriptorSetsIsAllowed) {
610 const spv_target_env env = SPV_ENV_VULKAN_1_0;
611 std::string spirv = R"(
612 OpCapability Shader
613 OpCapability ShaderNonUniformEXT
614 OpCapability RuntimeDescriptorArrayEXT
615 OpCapability SampledImageArrayNonUniformIndexingEXT
616 OpExtension "SPV_EXT_descriptor_indexing"
617 %1 = OpExtInstImport "GLSL.std.450"
618 OpMemoryModel Logical GLSL450
619 OpEntryPoint Vertex %main "main" %i
620 OpSource GLSL 440
621 OpSourceExtension "GL_EXT_nonuniform_qualifier"
622 OpName %main "main"
623 OpName %v "v"
624 OpName %s2d "s2d"
625 OpName %i "i"
626 OpDecorate %s2d DescriptorSet 0
627 OpDecorate %s2d Binding 1
628 OpDecorate %i Location 0
629 OpDecorate %i NonUniformEXT
630 OpDecorate %18 NonUniformEXT
631 OpDecorate %21 NonUniformEXT
632 %void = OpTypeVoid
633 %3 = OpTypeFunction %void
634 %float = OpTypeFloat 32
635 %v4float = OpTypeVector %float 4
636 %_ptr_Function_v4float = OpTypePointer Function %v4float
637 %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
638 %11 = OpTypeSampledImage %10
639 %_runtimearr_11 = OpTypeRuntimeArray %11
640 %_ptr_Uniform__runtimearr_11 = OpTypePointer Uniform %_runtimearr_11
641 %s2d = OpVariable %_ptr_Uniform__runtimearr_11 Uniform
642 %int = OpTypeInt 32 1
643 %_ptr_Input_int = OpTypePointer Input %int
644 %i = OpVariable %_ptr_Input_int Input
645 %_ptr_Uniform_11 = OpTypePointer Uniform %11
646 %v2float = OpTypeVector %float 2
647 %float_0_300000012 = OpConstant %float 0.300000012
648 %24 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
649 %float_0 = OpConstant %float 0
650 %main = OpFunction %void None %3
651 %5 = OpLabel
652 %v = OpVariable %_ptr_Function_v4float Function
653 %18 = OpLoad %int %i
654 %20 = OpAccessChain %_ptr_Uniform_11 %s2d %18
655 %21 = OpLoad %11 %20
656 %26 = OpImageSampleExplicitLod %v4float %21 %24 Lod %float_0
657 OpStore %v %26
658 OpReturn
659 OpFunctionEnd
660 )";
661 CompileSuccessfully(spirv, env);
662 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
663 }
664
TEST_F(ValidateDecorations,BlockDecoratingArrayBad)665 TEST_F(ValidateDecorations, BlockDecoratingArrayBad) {
666 std::string spirv = R"(
667 OpCapability Shader
668 %1 = OpExtInstImport "GLSL.std.450"
669 OpMemoryModel Logical GLSL450
670 OpEntryPoint GLCompute %main "main"
671 OpExecutionMode %main LocalSize 1 1 1
672 OpSource GLSL 430
673 OpDecorate %Output Block
674 %void = OpTypeVoid
675 %3 = OpTypeFunction %void
676 %float = OpTypeFloat 32
677 %int = OpTypeInt 32 1
678 %int_3 = OpConstant %int 3
679 %Output = OpTypeArray %float %int_3
680 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
681 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
682 %main = OpFunction %void None %3
683 %5 = OpLabel
684 OpReturn
685 OpFunctionEnd
686 )";
687
688 CompileSuccessfully(spirv);
689 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
690 EXPECT_THAT(getDiagnosticString(),
691 HasSubstr("Block decoration on a non-struct type"));
692 }
693
TEST_F(ValidateDecorations,BlockDecoratingIntBad)694 TEST_F(ValidateDecorations, BlockDecoratingIntBad) {
695 std::string spirv = R"(
696 OpCapability Shader
697 %1 = OpExtInstImport "GLSL.std.450"
698 OpMemoryModel Logical GLSL450
699 OpEntryPoint GLCompute %main "main"
700 OpExecutionMode %main LocalSize 1 1 1
701 OpSource GLSL 430
702 OpDecorate %Output Block
703 %void = OpTypeVoid
704 %3 = OpTypeFunction %void
705 %Output = OpTypeInt 32 1
706 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
707 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
708 %main = OpFunction %void None %3
709 %5 = OpLabel
710 OpReturn
711 OpFunctionEnd
712 )";
713
714 CompileSuccessfully(spirv);
715 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
716 EXPECT_THAT(getDiagnosticString(),
717 HasSubstr("Block decoration on a non-struct type"));
718 }
719
TEST_F(ValidateDecorations,BlockMissingOffsetBad)720 TEST_F(ValidateDecorations, BlockMissingOffsetBad) {
721 std::string spirv = R"(
722 OpCapability Shader
723 %1 = OpExtInstImport "GLSL.std.450"
724 OpMemoryModel Logical GLSL450
725 OpEntryPoint GLCompute %main "main"
726 OpExecutionMode %main LocalSize 1 1 1
727 OpSource GLSL 430
728 OpDecorate %Output Block
729 %void = OpTypeVoid
730 %3 = OpTypeFunction %void
731 %float = OpTypeFloat 32
732 %Output = OpTypeStruct %float
733 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
734 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
735 %main = OpFunction %void None %3
736 %5 = OpLabel
737 OpReturn
738 OpFunctionEnd
739 )";
740
741 CompileSuccessfully(spirv);
742 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
743 EXPECT_THAT(getDiagnosticString(),
744 HasSubstr("must be explicitly laid out with Offset decorations"));
745 }
746
TEST_F(ValidateDecorations,BufferBlockMissingOffsetBad)747 TEST_F(ValidateDecorations, BufferBlockMissingOffsetBad) {
748 std::string spirv = R"(
749 OpCapability Shader
750 %1 = OpExtInstImport "GLSL.std.450"
751 OpMemoryModel Logical GLSL450
752 OpEntryPoint GLCompute %main "main"
753 OpExecutionMode %main LocalSize 1 1 1
754 OpSource GLSL 430
755 OpDecorate %Output BufferBlock
756 %void = OpTypeVoid
757 %3 = OpTypeFunction %void
758 %float = OpTypeFloat 32
759 %Output = OpTypeStruct %float
760 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
761 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
762 %main = OpFunction %void None %3
763 %5 = OpLabel
764 OpReturn
765 OpFunctionEnd
766 )";
767
768 CompileSuccessfully(spirv);
769 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
770 EXPECT_THAT(getDiagnosticString(),
771 HasSubstr("must be explicitly laid out with Offset decorations"));
772 }
773
TEST_F(ValidateDecorations,BlockNestedStructMissingOffsetBad)774 TEST_F(ValidateDecorations, BlockNestedStructMissingOffsetBad) {
775 std::string spirv = R"(
776 OpCapability Shader
777 %1 = OpExtInstImport "GLSL.std.450"
778 OpMemoryModel Logical GLSL450
779 OpEntryPoint GLCompute %main "main"
780 OpExecutionMode %main LocalSize 1 1 1
781 OpSource GLSL 430
782 OpMemberDecorate %S 0 Offset 0
783 OpMemberDecorate %Output 0 Offset 0
784 OpMemberDecorate %Output 1 Offset 16
785 OpMemberDecorate %Output 2 Offset 32
786 OpDecorate %Output Block
787 %void = OpTypeVoid
788 %3 = OpTypeFunction %void
789 %float = OpTypeFloat 32
790 %v4float = OpTypeVector %float 4
791 %v3float = OpTypeVector %float 3
792 %int = OpTypeInt 32 1
793 %S = OpTypeStruct %v3float %int
794 %Output = OpTypeStruct %float %v4float %S
795 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
796 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
797 %main = OpFunction %void None %3
798 %5 = OpLabel
799 OpReturn
800 OpFunctionEnd
801 )";
802
803 CompileSuccessfully(spirv);
804 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
805 EXPECT_THAT(getDiagnosticString(),
806 HasSubstr("must be explicitly laid out with Offset decorations"));
807 }
808
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingOffsetBad)809 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingOffsetBad) {
810 std::string spirv = R"(
811 OpCapability Shader
812 %1 = OpExtInstImport "GLSL.std.450"
813 OpMemoryModel Logical GLSL450
814 OpEntryPoint GLCompute %main "main"
815 OpExecutionMode %main LocalSize 1 1 1
816 OpSource GLSL 430
817 OpMemberDecorate %S 0 Offset 0
818 OpMemberDecorate %Output 0 Offset 0
819 OpMemberDecorate %Output 1 Offset 16
820 OpMemberDecorate %Output 2 Offset 32
821 OpDecorate %Output BufferBlock
822 %void = OpTypeVoid
823 %3 = OpTypeFunction %void
824 %float = OpTypeFloat 32
825 %v4float = OpTypeVector %float 4
826 %v3float = OpTypeVector %float 3
827 %int = OpTypeInt 32 1
828 %S = OpTypeStruct %v3float %int
829 %Output = OpTypeStruct %float %v4float %S
830 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
831 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
832 %main = OpFunction %void None %3
833 %5 = OpLabel
834 OpReturn
835 OpFunctionEnd
836 )";
837
838 CompileSuccessfully(spirv);
839 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
840 EXPECT_THAT(getDiagnosticString(),
841 HasSubstr("must be explicitly laid out with Offset decorations"));
842 }
843
TEST_F(ValidateDecorations,BlockGLSLSharedBad)844 TEST_F(ValidateDecorations, BlockGLSLSharedBad) {
845 std::string spirv = R"(
846 OpCapability Shader
847 %1 = OpExtInstImport "GLSL.std.450"
848 OpMemoryModel Logical GLSL450
849 OpEntryPoint GLCompute %main "main"
850 OpExecutionMode %main LocalSize 1 1 1
851 OpSource GLSL 430
852 OpDecorate %Output Block
853 OpDecorate %Output GLSLShared
854 OpMemberDecorate %Output 0 Offset 0
855 %void = OpTypeVoid
856 %3 = OpTypeFunction %void
857 %float = OpTypeFloat 32
858 %Output = OpTypeStruct %float
859 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
860 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
861 %main = OpFunction %void None %3
862 %5 = OpLabel
863 OpReturn
864 OpFunctionEnd
865 )";
866
867 CompileSuccessfully(spirv);
868 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
869 EXPECT_THAT(getDiagnosticString(),
870 HasSubstr("must not use GLSLShared decoration"));
871 }
872
TEST_F(ValidateDecorations,BufferBlockGLSLSharedBad)873 TEST_F(ValidateDecorations, BufferBlockGLSLSharedBad) {
874 std::string spirv = R"(
875 OpCapability Shader
876 %1 = OpExtInstImport "GLSL.std.450"
877 OpMemoryModel Logical GLSL450
878 OpEntryPoint GLCompute %main "main"
879 OpExecutionMode %main LocalSize 1 1 1
880 OpSource GLSL 430
881 OpDecorate %Output BufferBlock
882 OpDecorate %Output GLSLShared
883 OpMemberDecorate %Output 0 Offset 0
884 %void = OpTypeVoid
885 %3 = OpTypeFunction %void
886 %float = OpTypeFloat 32
887 %Output = OpTypeStruct %float
888 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
889 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
890 %main = OpFunction %void None %3
891 %5 = OpLabel
892 OpReturn
893 OpFunctionEnd
894 )";
895
896 CompileSuccessfully(spirv);
897 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
898 EXPECT_THAT(getDiagnosticString(),
899 HasSubstr("must not use GLSLShared decoration"));
900 }
901
TEST_F(ValidateDecorations,BlockNestedStructGLSLSharedBad)902 TEST_F(ValidateDecorations, BlockNestedStructGLSLSharedBad) {
903 std::string spirv = R"(
904 OpCapability Shader
905 %1 = OpExtInstImport "GLSL.std.450"
906 OpMemoryModel Logical GLSL450
907 OpEntryPoint GLCompute %main "main"
908 OpExecutionMode %main LocalSize 1 1 1
909 OpSource GLSL 430
910 OpMemberDecorate %S 0 Offset 0
911 OpDecorate %S GLSLShared
912 OpMemberDecorate %Output 0 Offset 0
913 OpMemberDecorate %Output 1 Offset 16
914 OpMemberDecorate %Output 2 Offset 32
915 OpDecorate %Output Block
916 %void = OpTypeVoid
917 %3 = OpTypeFunction %void
918 %float = OpTypeFloat 32
919 %v4float = OpTypeVector %float 4
920 %int = OpTypeInt 32 1
921 %S = OpTypeStruct %int
922 %Output = OpTypeStruct %float %v4float %S
923 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
924 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
925 %main = OpFunction %void None %3
926 %5 = OpLabel
927 OpReturn
928 OpFunctionEnd
929 )";
930
931 CompileSuccessfully(spirv);
932 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
933 EXPECT_THAT(getDiagnosticString(),
934 HasSubstr("must not use GLSLShared decoration"));
935 }
936
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLSharedBad)937 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLSharedBad) {
938 std::string spirv = R"(
939 OpCapability Shader
940 %1 = OpExtInstImport "GLSL.std.450"
941 OpMemoryModel Logical GLSL450
942 OpEntryPoint GLCompute %main "main"
943 OpExecutionMode %main LocalSize 1 1 1
944 OpSource GLSL 430
945 OpMemberDecorate %S 0 Offset 0
946 OpDecorate %S GLSLShared
947 OpMemberDecorate %Output 0 Offset 0
948 OpMemberDecorate %Output 1 Offset 16
949 OpMemberDecorate %Output 2 Offset 32
950 OpDecorate %Output BufferBlock
951 %void = OpTypeVoid
952 %3 = OpTypeFunction %void
953 %float = OpTypeFloat 32
954 %v4float = OpTypeVector %float 4
955 %int = OpTypeInt 32 1
956 %S = OpTypeStruct %int
957 %Output = OpTypeStruct %float %v4float %S
958 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
959 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
960 %main = OpFunction %void None %3
961 %5 = OpLabel
962 OpReturn
963 OpFunctionEnd
964 )";
965
966 CompileSuccessfully(spirv);
967 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
968 EXPECT_THAT(getDiagnosticString(),
969 HasSubstr("must not use GLSLShared decoration"));
970 }
971
TEST_F(ValidateDecorations,BlockGLSLPackedBad)972 TEST_F(ValidateDecorations, BlockGLSLPackedBad) {
973 std::string spirv = R"(
974 OpCapability Shader
975 %1 = OpExtInstImport "GLSL.std.450"
976 OpMemoryModel Logical GLSL450
977 OpEntryPoint GLCompute %main "main"
978 OpExecutionMode %main LocalSize 1 1 1
979 OpSource GLSL 430
980 OpDecorate %Output Block
981 OpDecorate %Output GLSLPacked
982 OpMemberDecorate %Output 0 Offset 0
983 %void = OpTypeVoid
984 %3 = OpTypeFunction %void
985 %float = OpTypeFloat 32
986 %Output = OpTypeStruct %float
987 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
988 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
989 %main = OpFunction %void None %3
990 %5 = OpLabel
991 OpReturn
992 OpFunctionEnd
993 )";
994
995 CompileSuccessfully(spirv);
996 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
997 EXPECT_THAT(getDiagnosticString(),
998 HasSubstr("must not use GLSLPacked decoration"));
999 }
1000
TEST_F(ValidateDecorations,BufferBlockGLSLPackedBad)1001 TEST_F(ValidateDecorations, BufferBlockGLSLPackedBad) {
1002 std::string spirv = R"(
1003 OpCapability Shader
1004 %1 = OpExtInstImport "GLSL.std.450"
1005 OpMemoryModel Logical GLSL450
1006 OpEntryPoint GLCompute %main "main"
1007 OpExecutionMode %main LocalSize 1 1 1
1008 OpSource GLSL 430
1009 OpDecorate %Output BufferBlock
1010 OpDecorate %Output GLSLPacked
1011 OpMemberDecorate %Output 0 Offset 0
1012 %void = OpTypeVoid
1013 %3 = OpTypeFunction %void
1014 %float = OpTypeFloat 32
1015 %Output = OpTypeStruct %float
1016 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1017 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1018 %main = OpFunction %void None %3
1019 %5 = OpLabel
1020 OpReturn
1021 OpFunctionEnd
1022 )";
1023
1024 CompileSuccessfully(spirv);
1025 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1026 EXPECT_THAT(getDiagnosticString(),
1027 HasSubstr("must not use GLSLPacked decoration"));
1028 }
1029
TEST_F(ValidateDecorations,BlockNestedStructGLSLPackedBad)1030 TEST_F(ValidateDecorations, BlockNestedStructGLSLPackedBad) {
1031 std::string spirv = R"(
1032 OpCapability Shader
1033 %1 = OpExtInstImport "GLSL.std.450"
1034 OpMemoryModel Logical GLSL450
1035 OpEntryPoint GLCompute %main "main"
1036 OpExecutionMode %main LocalSize 1 1 1
1037 OpSource GLSL 430
1038 OpMemberDecorate %S 0 Offset 0
1039 OpDecorate %S GLSLPacked
1040 OpMemberDecorate %Output 0 Offset 0
1041 OpMemberDecorate %Output 1 Offset 16
1042 OpMemberDecorate %Output 2 Offset 32
1043 OpDecorate %Output Block
1044 %void = OpTypeVoid
1045 %3 = OpTypeFunction %void
1046 %float = OpTypeFloat 32
1047 %v4float = OpTypeVector %float 4
1048 %int = OpTypeInt 32 1
1049 %S = OpTypeStruct %int
1050 %Output = OpTypeStruct %float %v4float %S
1051 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1052 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1053 %main = OpFunction %void None %3
1054 %5 = OpLabel
1055 OpReturn
1056 OpFunctionEnd
1057 )";
1058
1059 CompileSuccessfully(spirv);
1060 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1061 EXPECT_THAT(getDiagnosticString(),
1062 HasSubstr("must not use GLSLPacked decoration"));
1063 }
1064
TEST_F(ValidateDecorations,BufferBlockNestedStructGLSLPackedBad)1065 TEST_F(ValidateDecorations, BufferBlockNestedStructGLSLPackedBad) {
1066 std::string spirv = R"(
1067 OpCapability Shader
1068 %1 = OpExtInstImport "GLSL.std.450"
1069 OpMemoryModel Logical GLSL450
1070 OpEntryPoint GLCompute %main "main"
1071 OpExecutionMode %main LocalSize 1 1 1
1072 OpSource GLSL 430
1073 OpMemberDecorate %S 0 Offset 0
1074 OpDecorate %S GLSLPacked
1075 OpMemberDecorate %Output 0 Offset 0
1076 OpMemberDecorate %Output 1 Offset 16
1077 OpMemberDecorate %Output 2 Offset 32
1078 OpDecorate %Output BufferBlock
1079 %void = OpTypeVoid
1080 %3 = OpTypeFunction %void
1081 %float = OpTypeFloat 32
1082 %v4float = OpTypeVector %float 4
1083 %int = OpTypeInt 32 1
1084 %S = OpTypeStruct %int
1085 %Output = OpTypeStruct %float %v4float %S
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 not use GLSLPacked decoration"));
1098 }
1099
TEST_F(ValidateDecorations,BlockMissingArrayStrideBad)1100 TEST_F(ValidateDecorations, BlockMissingArrayStrideBad) {
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 Block
1109 OpMemberDecorate %Output 0 Offset 0
1110 %void = OpTypeVoid
1111 %3 = OpTypeFunction %void
1112 %float = OpTypeFloat 32
1113 %int = OpTypeInt 32 1
1114 %int_3 = OpConstant %int 3
1115 %array = OpTypeArray %float %int_3
1116 %Output = OpTypeStruct %array
1117 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1118 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1119 %main = OpFunction %void None %3
1120 %5 = OpLabel
1121 OpReturn
1122 OpFunctionEnd
1123 )";
1124
1125 CompileSuccessfully(spirv);
1126 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1127 EXPECT_THAT(
1128 getDiagnosticString(),
1129 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1130 }
1131
TEST_F(ValidateDecorations,BufferBlockMissingArrayStrideBad)1132 TEST_F(ValidateDecorations, BufferBlockMissingArrayStrideBad) {
1133 std::string spirv = R"(
1134 OpCapability Shader
1135 %1 = OpExtInstImport "GLSL.std.450"
1136 OpMemoryModel Logical GLSL450
1137 OpEntryPoint GLCompute %main "main"
1138 OpExecutionMode %main LocalSize 1 1 1
1139 OpSource GLSL 430
1140 OpDecorate %Output BufferBlock
1141 OpMemberDecorate %Output 0 Offset 0
1142 %void = OpTypeVoid
1143 %3 = OpTypeFunction %void
1144 %float = OpTypeFloat 32
1145 %int = OpTypeInt 32 1
1146 %int_3 = OpConstant %int 3
1147 %array = OpTypeArray %float %int_3
1148 %Output = OpTypeStruct %array
1149 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1150 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1151 %main = OpFunction %void None %3
1152 %5 = OpLabel
1153 OpReturn
1154 OpFunctionEnd
1155 )";
1156
1157 CompileSuccessfully(spirv);
1158 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1159 EXPECT_THAT(
1160 getDiagnosticString(),
1161 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1162 }
1163
TEST_F(ValidateDecorations,BlockNestedStructMissingArrayStrideBad)1164 TEST_F(ValidateDecorations, BlockNestedStructMissingArrayStrideBad) {
1165 std::string spirv = R"(
1166 OpCapability Shader
1167 %1 = OpExtInstImport "GLSL.std.450"
1168 OpMemoryModel Logical GLSL450
1169 OpEntryPoint GLCompute %main "main"
1170 OpExecutionMode %main LocalSize 1 1 1
1171 OpSource GLSL 430
1172 OpMemberDecorate %S 0 Offset 0
1173 OpMemberDecorate %Output 0 Offset 0
1174 OpMemberDecorate %Output 1 Offset 16
1175 OpMemberDecorate %Output 2 Offset 32
1176 OpDecorate %Output Block
1177 %void = OpTypeVoid
1178 %3 = OpTypeFunction %void
1179 %float = OpTypeFloat 32
1180 %v4float = OpTypeVector %float 4
1181 %int = OpTypeInt 32 1
1182 %int_3 = OpConstant %int 3
1183 %array = OpTypeArray %float %int_3
1184 %S = OpTypeStruct %array
1185 %Output = OpTypeStruct %float %v4float %S
1186 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1187 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1188 %main = OpFunction %void None %3
1189 %5 = OpLabel
1190 OpReturn
1191 OpFunctionEnd
1192 )";
1193
1194 CompileSuccessfully(spirv);
1195 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1196 EXPECT_THAT(
1197 getDiagnosticString(),
1198 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1199 }
1200
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingArrayStrideBad)1201 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingArrayStrideBad) {
1202 std::string spirv = R"(
1203 OpCapability Shader
1204 %1 = OpExtInstImport "GLSL.std.450"
1205 OpMemoryModel Logical GLSL450
1206 OpEntryPoint GLCompute %main "main"
1207 OpExecutionMode %main LocalSize 1 1 1
1208 OpSource GLSL 430
1209 OpMemberDecorate %S 0 Offset 0
1210 OpMemberDecorate %Output 0 Offset 0
1211 OpMemberDecorate %Output 1 Offset 16
1212 OpMemberDecorate %Output 2 Offset 32
1213 OpDecorate %Output BufferBlock
1214 %void = OpTypeVoid
1215 %3 = OpTypeFunction %void
1216 %float = OpTypeFloat 32
1217 %v4float = OpTypeVector %float 4
1218 %int = OpTypeInt 32 1
1219 %int_3 = OpConstant %int 3
1220 %array = OpTypeArray %float %int_3
1221 %S = OpTypeStruct %array
1222 %Output = OpTypeStruct %float %v4float %S
1223 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1224 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1225 %main = OpFunction %void None %3
1226 %5 = OpLabel
1227 OpReturn
1228 OpFunctionEnd
1229 )";
1230
1231 CompileSuccessfully(spirv);
1232 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1233 EXPECT_THAT(
1234 getDiagnosticString(),
1235 HasSubstr("must be explicitly laid out with ArrayStride decorations"));
1236 }
1237
TEST_F(ValidateDecorations,BlockMissingMatrixStrideBad)1238 TEST_F(ValidateDecorations, BlockMissingMatrixStrideBad) {
1239 std::string spirv = R"(
1240 OpCapability Shader
1241 %1 = OpExtInstImport "GLSL.std.450"
1242 OpMemoryModel Logical GLSL450
1243 OpEntryPoint GLCompute %main "main"
1244 OpExecutionMode %main LocalSize 1 1 1
1245 OpSource GLSL 430
1246 OpDecorate %Output Block
1247 OpMemberDecorate %Output 0 Offset 0
1248 %void = OpTypeVoid
1249 %3 = OpTypeFunction %void
1250 %float = OpTypeFloat 32
1251 %v3float = OpTypeVector %float 3
1252 %matrix = OpTypeMatrix %v3float 4
1253 %Output = OpTypeStruct %matrix
1254 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1255 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1256 %main = OpFunction %void None %3
1257 %5 = OpLabel
1258 OpReturn
1259 OpFunctionEnd
1260 )";
1261
1262 CompileSuccessfully(spirv);
1263 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1264 EXPECT_THAT(
1265 getDiagnosticString(),
1266 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1267 }
1268
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideBad)1269 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideBad) {
1270 std::string spirv = R"(
1271 OpCapability Shader
1272 %1 = OpExtInstImport "GLSL.std.450"
1273 OpMemoryModel Logical GLSL450
1274 OpEntryPoint GLCompute %main "main"
1275 OpExecutionMode %main LocalSize 1 1 1
1276 OpSource GLSL 430
1277 OpDecorate %Output BufferBlock
1278 OpMemberDecorate %Output 0 Offset 0
1279 %void = OpTypeVoid
1280 %3 = OpTypeFunction %void
1281 %float = OpTypeFloat 32
1282 %v3float = OpTypeVector %float 3
1283 %matrix = OpTypeMatrix %v3float 4
1284 %Output = OpTypeStruct %matrix
1285 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1286 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1287 %main = OpFunction %void None %3
1288 %5 = OpLabel
1289 OpReturn
1290 OpFunctionEnd
1291 )";
1292
1293 CompileSuccessfully(spirv);
1294 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1295 EXPECT_THAT(
1296 getDiagnosticString(),
1297 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1298 }
1299
TEST_F(ValidateDecorations,BlockMissingMatrixStrideArrayBad)1300 TEST_F(ValidateDecorations, BlockMissingMatrixStrideArrayBad) {
1301 std::string spirv = R"(
1302 OpCapability Shader
1303 %1 = OpExtInstImport "GLSL.std.450"
1304 OpMemoryModel Logical GLSL450
1305 OpEntryPoint GLCompute %main "main"
1306 OpExecutionMode %main LocalSize 1 1 1
1307 OpSource GLSL 430
1308 OpDecorate %Output Block
1309 OpMemberDecorate %Output 0 Offset 0
1310 %void = OpTypeVoid
1311 %3 = OpTypeFunction %void
1312 %float = OpTypeFloat 32
1313 %v3float = OpTypeVector %float 3
1314 %matrix = OpTypeMatrix %v3float 4
1315 %int = OpTypeInt 32 1
1316 %int_3 = OpConstant %int 3
1317 %array = OpTypeArray %matrix %int_3
1318 %Output = OpTypeStruct %matrix
1319 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1320 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1321 %main = OpFunction %void None %3
1322 %5 = OpLabel
1323 OpReturn
1324 OpFunctionEnd
1325 )";
1326
1327 CompileSuccessfully(spirv);
1328 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1329 EXPECT_THAT(
1330 getDiagnosticString(),
1331 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1332 }
1333
TEST_F(ValidateDecorations,BufferBlockMissingMatrixStrideArrayBad)1334 TEST_F(ValidateDecorations, BufferBlockMissingMatrixStrideArrayBad) {
1335 std::string spirv = R"(
1336 OpCapability Shader
1337 %1 = OpExtInstImport "GLSL.std.450"
1338 OpMemoryModel Logical GLSL450
1339 OpEntryPoint GLCompute %main "main"
1340 OpExecutionMode %main LocalSize 1 1 1
1341 OpSource GLSL 430
1342 OpDecorate %Output BufferBlock
1343 OpMemberDecorate %Output 0 Offset 0
1344 %void = OpTypeVoid
1345 %3 = OpTypeFunction %void
1346 %float = OpTypeFloat 32
1347 %v3float = OpTypeVector %float 3
1348 %matrix = OpTypeMatrix %v3float 4
1349 %int = OpTypeInt 32 1
1350 %int_3 = OpConstant %int 3
1351 %array = OpTypeArray %matrix %int_3
1352 %Output = OpTypeStruct %matrix
1353 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1354 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1355 %main = OpFunction %void None %3
1356 %5 = OpLabel
1357 OpReturn
1358 OpFunctionEnd
1359 )";
1360
1361 CompileSuccessfully(spirv);
1362 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1363 EXPECT_THAT(
1364 getDiagnosticString(),
1365 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1366 }
1367
TEST_F(ValidateDecorations,BlockNestedStructMissingMatrixStrideBad)1368 TEST_F(ValidateDecorations, BlockNestedStructMissingMatrixStrideBad) {
1369 std::string spirv = R"(
1370 OpCapability Shader
1371 %1 = OpExtInstImport "GLSL.std.450"
1372 OpMemoryModel Logical GLSL450
1373 OpEntryPoint GLCompute %main "main"
1374 OpExecutionMode %main LocalSize 1 1 1
1375 OpSource GLSL 430
1376 OpMemberDecorate %S 0 Offset 0
1377 OpMemberDecorate %Output 0 Offset 0
1378 OpMemberDecorate %Output 1 Offset 16
1379 OpMemberDecorate %Output 2 Offset 32
1380 OpDecorate %Output Block
1381 %void = OpTypeVoid
1382 %3 = OpTypeFunction %void
1383 %float = OpTypeFloat 32
1384 %v3float = OpTypeVector %float 3
1385 %v4float = OpTypeVector %float 4
1386 %matrix = OpTypeMatrix %v3float 4
1387 %S = OpTypeStruct %matrix
1388 %Output = OpTypeStruct %float %v4float %S
1389 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1390 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1391 %main = OpFunction %void None %3
1392 %5 = OpLabel
1393 OpReturn
1394 OpFunctionEnd
1395 )";
1396
1397 CompileSuccessfully(spirv);
1398 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1399 EXPECT_THAT(
1400 getDiagnosticString(),
1401 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1402 }
1403
TEST_F(ValidateDecorations,BufferBlockNestedStructMissingMatrixStrideBad)1404 TEST_F(ValidateDecorations, BufferBlockNestedStructMissingMatrixStrideBad) {
1405 std::string spirv = R"(
1406 OpCapability Shader
1407 %1 = OpExtInstImport "GLSL.std.450"
1408 OpMemoryModel Logical GLSL450
1409 OpEntryPoint GLCompute %main "main"
1410 OpExecutionMode %main LocalSize 1 1 1
1411 OpSource GLSL 430
1412 OpMemberDecorate %S 0 Offset 0
1413 OpMemberDecorate %Output 0 Offset 0
1414 OpMemberDecorate %Output 1 Offset 16
1415 OpMemberDecorate %Output 2 Offset 32
1416 OpDecorate %Output BufferBlock
1417 %void = OpTypeVoid
1418 %3 = OpTypeFunction %void
1419 %float = OpTypeFloat 32
1420 %v3float = OpTypeVector %float 3
1421 %v4float = OpTypeVector %float 4
1422 %matrix = OpTypeMatrix %v3float 4
1423 %S = OpTypeStruct %matrix
1424 %Output = OpTypeStruct %float %v4float %S
1425 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1426 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1427 %main = OpFunction %void None %3
1428 %5 = OpLabel
1429 OpReturn
1430 OpFunctionEnd
1431 )";
1432
1433 CompileSuccessfully(spirv);
1434 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1435 EXPECT_THAT(
1436 getDiagnosticString(),
1437 HasSubstr("must be explicitly laid out with MatrixStride decorations"));
1438 }
1439
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayout)1440 TEST_F(ValidateDecorations, BlockStandardUniformBufferLayout) {
1441 std::string spirv = R"(
1442 OpCapability Shader
1443 %1 = OpExtInstImport "GLSL.std.450"
1444 OpMemoryModel Logical GLSL450
1445 OpEntryPoint GLCompute %main "main"
1446 OpExecutionMode %main LocalSize 1 1 1
1447 OpSource GLSL 430
1448 OpMemberDecorate %F 0 Offset 0
1449 OpMemberDecorate %F 1 Offset 8
1450 OpDecorate %_arr_float_uint_2 ArrayStride 16
1451 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
1452 OpMemberDecorate %O 0 Offset 0
1453 OpMemberDecorate %O 1 Offset 16
1454 OpMemberDecorate %O 2 Offset 32
1455 OpMemberDecorate %O 3 Offset 64
1456 OpMemberDecorate %O 4 ColMajor
1457 OpMemberDecorate %O 4 Offset 80
1458 OpMemberDecorate %O 4 MatrixStride 16
1459 OpDecorate %_arr_O_uint_2 ArrayStride 176
1460 OpMemberDecorate %Output 0 Offset 0
1461 OpMemberDecorate %Output 1 Offset 8
1462 OpMemberDecorate %Output 2 Offset 16
1463 OpMemberDecorate %Output 3 Offset 32
1464 OpMemberDecorate %Output 4 Offset 48
1465 OpMemberDecorate %Output 5 Offset 64
1466 OpMemberDecorate %Output 6 ColMajor
1467 OpMemberDecorate %Output 6 Offset 96
1468 OpMemberDecorate %Output 6 MatrixStride 16
1469 OpMemberDecorate %Output 7 Offset 128
1470 OpDecorate %Output Block
1471 %void = OpTypeVoid
1472 %3 = OpTypeFunction %void
1473 %float = OpTypeFloat 32
1474 %v2float = OpTypeVector %float 2
1475 %v3float = OpTypeVector %float 3
1476 %int = OpTypeInt 32 1
1477 %uint = OpTypeInt 32 0
1478 %v2uint = OpTypeVector %uint 2
1479 %F = OpTypeStruct %int %v2uint
1480 %uint_2 = OpConstant %uint 2
1481 %_arr_float_uint_2 = OpTypeArray %float %uint_2
1482 %mat2v3float = OpTypeMatrix %v3float 2
1483 %v3uint = OpTypeVector %uint 3
1484 %mat3v3float = OpTypeMatrix %v3float 3
1485 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
1486 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
1487 %_arr_O_uint_2 = OpTypeArray %O %uint_2
1488 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
1489 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
1490 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
1491 %main = OpFunction %void None %3
1492 %5 = OpLabel
1493 OpReturn
1494 OpFunctionEnd
1495 )";
1496
1497 CompileSuccessfully(spirv);
1498 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
1499 }
1500
TEST_F(ValidateDecorations,BlockLayoutPermitsTightVec3ScalarPackingGood)1501 TEST_F(ValidateDecorations, BlockLayoutPermitsTightVec3ScalarPackingGood) {
1502 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
1503 std::string spirv = R"(
1504 OpCapability Shader
1505 OpMemoryModel Logical GLSL450
1506 OpEntryPoint Vertex %main "main"
1507 OpSource GLSL 450
1508 OpMemberDecorate %S 0 Offset 0
1509 OpMemberDecorate %S 1 Offset 12
1510 OpDecorate %S Block
1511 OpDecorate %B DescriptorSet 0
1512 OpDecorate %B Binding 0
1513 %void = OpTypeVoid
1514 %3 = OpTypeFunction %void
1515 %float = OpTypeFloat 32
1516 %v3float = OpTypeVector %float 3
1517 %S = OpTypeStruct %v3float %float
1518 %_ptr_Uniform_S = OpTypePointer Uniform %S
1519 %B = OpVariable %_ptr_Uniform_S Uniform
1520 %main = OpFunction %void None %3
1521 %5 = OpLabel
1522 OpReturn
1523 OpFunctionEnd
1524 )";
1525
1526 CompileSuccessfully(spirv);
1527 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
1528 << getDiagnosticString();
1529 }
1530
TEST_F(ValidateDecorations,BlockCantAppearWithinABlockBad)1531 TEST_F(ValidateDecorations, BlockCantAppearWithinABlockBad) {
1532 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1533 std::string spirv = R"(
1534 OpCapability Shader
1535 OpMemoryModel Logical GLSL450
1536 OpEntryPoint Vertex %main "main"
1537 OpSource GLSL 450
1538 OpMemberDecorate %S 0 Offset 0
1539 OpMemberDecorate %S 1 Offset 16
1540 OpMemberDecorate %S2 0 Offset 0
1541 OpMemberDecorate %S2 1 Offset 12
1542 OpDecorate %S Block
1543 OpDecorate %S2 Block
1544 OpDecorate %B DescriptorSet 0
1545 OpDecorate %B Binding 0
1546 %void = OpTypeVoid
1547 %3 = OpTypeFunction %void
1548 %float = OpTypeFloat 32
1549 %S2 = OpTypeStruct %float %float
1550 %S = OpTypeStruct %float %S2
1551 %_ptr_Uniform_S = OpTypePointer Uniform %S
1552 %B = OpVariable %_ptr_Uniform_S Uniform
1553 %main = OpFunction %void None %3
1554 %5 = OpLabel
1555 OpReturn
1556 OpFunctionEnd
1557 )";
1558
1559 CompileSuccessfully(spirv);
1560 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1561 EXPECT_THAT(getDiagnosticString(),
1562 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1563 "another Block or BufferBlock."));
1564 }
1565
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABufferblockBad)1566 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABufferblockBad) {
1567 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1568 std::string spirv = R"(
1569 OpCapability Shader
1570 OpMemoryModel Logical GLSL450
1571 OpEntryPoint Vertex %main "main"
1572 OpSource GLSL 450
1573 OpMemberDecorate %S 0 Offset 0
1574 OpMemberDecorate %S 1 Offset 16
1575 OpMemberDecorate %S2 0 Offset 0
1576 OpMemberDecorate %S2 1 Offset 16
1577 OpMemberDecorate %S3 0 Offset 0
1578 OpMemberDecorate %S3 1 Offset 12
1579 OpDecorate %S BufferBlock
1580 OpDecorate %S3 BufferBlock
1581 OpDecorate %B DescriptorSet 0
1582 OpDecorate %B Binding 0
1583 %void = OpTypeVoid
1584 %3 = OpTypeFunction %void
1585 %float = OpTypeFloat 32
1586 %S3 = OpTypeStruct %float %float
1587 %S2 = OpTypeStruct %float %S3
1588 %S = OpTypeStruct %float %S2
1589 %_ptr_Uniform_S = OpTypePointer Uniform %S
1590 %B = OpVariable %_ptr_Uniform_S Uniform
1591 %main = OpFunction %void None %3
1592 %5 = OpLabel
1593 OpReturn
1594 OpFunctionEnd
1595 )";
1596
1597 CompileSuccessfully(spirv);
1598 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1599 EXPECT_THAT(getDiagnosticString(),
1600 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1601 "another Block or BufferBlock."));
1602 }
1603
TEST_F(ValidateDecorations,BufferblockCantAppearWithinABlockBad)1604 TEST_F(ValidateDecorations, BufferblockCantAppearWithinABlockBad) {
1605 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1606 std::string spirv = R"(
1607 OpCapability Shader
1608 OpMemoryModel Logical GLSL450
1609 OpEntryPoint Vertex %main "main"
1610 OpSource GLSL 450
1611 OpMemberDecorate %S 0 Offset 0
1612 OpMemberDecorate %S 1 Offset 16
1613 OpMemberDecorate %S2 0 Offset 0
1614 OpMemberDecorate %S2 1 Offset 16
1615 OpMemberDecorate %S3 0 Offset 0
1616 OpMemberDecorate %S3 1 Offset 12
1617 OpDecorate %S Block
1618 OpDecorate %S3 BufferBlock
1619 OpDecorate %B DescriptorSet 0
1620 OpDecorate %B Binding 0
1621 %void = OpTypeVoid
1622 %3 = OpTypeFunction %void
1623 %float = OpTypeFloat 32
1624 %S3 = OpTypeStruct %float %float
1625 %S2 = OpTypeStruct %float %S3
1626 %S = OpTypeStruct %float %S2
1627 %_ptr_Uniform_S = OpTypePointer Uniform %S
1628 %B = OpVariable %_ptr_Uniform_S Uniform
1629 %main = OpFunction %void None %3
1630 %5 = OpLabel
1631 OpReturn
1632 OpFunctionEnd
1633 )";
1634
1635 CompileSuccessfully(spirv);
1636 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1637 EXPECT_THAT(getDiagnosticString(),
1638 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1639 "another Block or BufferBlock."));
1640 }
1641
TEST_F(ValidateDecorations,BlockCantAppearWithinABufferblockBad)1642 TEST_F(ValidateDecorations, BlockCantAppearWithinABufferblockBad) {
1643 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1587
1644 std::string spirv = R"(
1645 OpCapability Shader
1646 OpMemoryModel Logical GLSL450
1647 OpEntryPoint Vertex %main "main"
1648 OpSource GLSL 450
1649 OpMemberDecorate %S 0 Offset 0
1650 OpMemberDecorate %S 1 Offset 16
1651 OpMemberDecorate %S2 0 Offset 0
1652 OpMemberDecorate %S2 1 Offset 16
1653 OpMemberDecorate %S3 0 Offset 0
1654 OpMemberDecorate %S3 1 Offset 16
1655 OpMemberDecorate %S4 0 Offset 0
1656 OpMemberDecorate %S4 1 Offset 12
1657 OpDecorate %S BufferBlock
1658 OpDecorate %S4 Block
1659 OpDecorate %B DescriptorSet 0
1660 OpDecorate %B Binding 0
1661 %void = OpTypeVoid
1662 %3 = OpTypeFunction %void
1663 %float = OpTypeFloat 32
1664 %S4 = OpTypeStruct %float %float
1665 %S3 = OpTypeStruct %float %S4
1666 %S2 = OpTypeStruct %float %S3
1667 %S = OpTypeStruct %float %S2
1668 %_ptr_Uniform_S = OpTypePointer Uniform %S
1669 %B = OpVariable %_ptr_Uniform_S Uniform
1670 %main = OpFunction %void None %3
1671 %5 = OpLabel
1672 OpReturn
1673 OpFunctionEnd
1674 )";
1675
1676 CompileSuccessfully(spirv);
1677 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1678 EXPECT_THAT(getDiagnosticString(),
1679 HasSubstr("rules: A Block or BufferBlock cannot be nested within "
1680 "another Block or BufferBlock."));
1681 }
1682
TEST_F(ValidateDecorations,BlockLayoutForbidsTightScalarVec3PackingBad)1683 TEST_F(ValidateDecorations, BlockLayoutForbidsTightScalarVec3PackingBad) {
1684 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
1685 std::string spirv = R"(
1686 OpCapability Shader
1687 OpMemoryModel Logical GLSL450
1688 OpEntryPoint Vertex %main "main"
1689 OpSource GLSL 450
1690 OpMemberDecorate %S 0 Offset 0
1691 OpMemberDecorate %S 1 Offset 4
1692 OpDecorate %S Block
1693 OpDecorate %B DescriptorSet 0
1694 OpDecorate %B Binding 0
1695 %void = OpTypeVoid
1696 %3 = OpTypeFunction %void
1697 %float = OpTypeFloat 32
1698 %v3float = OpTypeVector %float 3
1699 %S = OpTypeStruct %float %v3float
1700 %_ptr_Uniform_S = OpTypePointer Uniform %S
1701 %B = OpVariable %_ptr_Uniform_S Uniform
1702 %main = OpFunction %void None %3
1703 %5 = OpLabel
1704 OpReturn
1705 OpFunctionEnd
1706 )";
1707
1708 CompileSuccessfully(spirv);
1709 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
1710 EXPECT_THAT(
1711 getDiagnosticString(),
1712 HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
1713 "storage class must follow standard uniform buffer layout "
1714 "rules: member 1 at offset 4 is not aligned to 16"));
1715 }
1716
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood)1717 TEST_F(ValidateDecorations,
1718 BlockLayoutPermitsTightScalarVec3PackingWithRelaxedLayoutGood) {
1719 // Same as previous test, but with explicit option to relax block layout.
1720 std::string spirv = R"(
1721 OpCapability Shader
1722 OpMemoryModel Logical GLSL450
1723 OpEntryPoint Vertex %main "main"
1724 OpSource GLSL 450
1725 OpMemberDecorate %S 0 Offset 0
1726 OpMemberDecorate %S 1 Offset 4
1727 OpDecorate %S Block
1728 OpDecorate %B DescriptorSet 0
1729 OpDecorate %B Binding 0
1730 %void = OpTypeVoid
1731 %3 = OpTypeFunction %void
1732 %float = OpTypeFloat 32
1733 %v3float = OpTypeVector %float 3
1734 %S = OpTypeStruct %float %v3float
1735 %_ptr_Uniform_S = OpTypePointer Uniform %S
1736 %B = OpVariable %_ptr_Uniform_S Uniform
1737 %main = OpFunction %void None %3
1738 %5 = OpLabel
1739 OpReturn
1740 OpFunctionEnd
1741 )";
1742
1743 CompileSuccessfully(spirv);
1744 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
1745 EXPECT_EQ(SPV_SUCCESS,
1746 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1747 EXPECT_THAT(getDiagnosticString(), Eq(""));
1748 }
1749
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad)1750 TEST_F(ValidateDecorations,
1751 BlockLayoutPermitsTightScalarVec3PackingBadOffsetWithRelaxedLayoutBad) {
1752 // Same as previous test, but with the vector not aligned to its scalar
1753 // element. Use offset 5 instead of a multiple of 4.
1754 std::string spirv = R"(
1755 OpCapability Shader
1756 OpMemoryModel Logical GLSL450
1757 OpEntryPoint Vertex %main "main"
1758 OpSource GLSL 450
1759 OpMemberDecorate %S 0 Offset 0
1760 OpMemberDecorate %S 1 Offset 5
1761 OpDecorate %S Block
1762 OpDecorate %B DescriptorSet 0
1763 OpDecorate %B Binding 0
1764 %void = OpTypeVoid
1765 %3 = OpTypeFunction %void
1766 %float = OpTypeFloat 32
1767 %v3float = OpTypeVector %float 3
1768 %S = OpTypeStruct %float %v3float
1769 %_ptr_Uniform_S = OpTypePointer Uniform %S
1770 %B = OpVariable %_ptr_Uniform_S Uniform
1771 %main = OpFunction %void None %3
1772 %5 = OpLabel
1773 OpReturn
1774 OpFunctionEnd
1775 )";
1776
1777 CompileSuccessfully(spirv);
1778 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
1779 EXPECT_EQ(SPV_ERROR_INVALID_ID,
1780 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1781 EXPECT_THAT(
1782 getDiagnosticString(),
1783 HasSubstr(
1784 "Structure id 2 decorated as Block for variable in Uniform storage "
1785 "class must follow relaxed uniform buffer layout rules: member 1 at "
1786 "offset 5 is not aligned to scalar element size 4"));
1787 }
1788
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good)1789 TEST_F(ValidateDecorations,
1790 BlockLayoutPermitsTightScalarVec3PackingWithVulkan1_1Good) {
1791 // Same as previous test, but with Vulkan 1.1. Vulkan 1.1 included
1792 // VK_KHR_relaxed_block_layout in core.
1793 std::string spirv = R"(
1794 OpCapability Shader
1795 OpMemoryModel Logical GLSL450
1796 OpEntryPoint Vertex %main "main"
1797 OpSource GLSL 450
1798 OpMemberDecorate %S 0 Offset 0
1799 OpMemberDecorate %S 1 Offset 4
1800 OpDecorate %S Block
1801 OpDecorate %B DescriptorSet 0
1802 OpDecorate %B Binding 0
1803 %void = OpTypeVoid
1804 %3 = OpTypeFunction %void
1805 %float = OpTypeFloat 32
1806 %v3float = OpTypeVector %float 3
1807 %S = OpTypeStruct %float %v3float
1808 %_ptr_Uniform_S = OpTypePointer Uniform %S
1809 %B = OpVariable %_ptr_Uniform_S Uniform
1810 %main = OpFunction %void None %3
1811 %5 = OpLabel
1812 OpReturn
1813 OpFunctionEnd
1814 )";
1815
1816 CompileSuccessfully(spirv);
1817 EXPECT_EQ(SPV_SUCCESS,
1818 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
1819 EXPECT_THAT(getDiagnosticString(), Eq(""));
1820 }
1821
TEST_F(ValidateDecorations,BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood)1822 TEST_F(ValidateDecorations,
1823 BlockLayoutPermitsTightScalarVec3PackingWithScalarLayoutGood) {
1824 // Same as previous test, but with scalar block layout.
1825 std::string spirv = R"(
1826 OpCapability Shader
1827 OpMemoryModel Logical GLSL450
1828 OpEntryPoint Vertex %main "main"
1829 OpSource GLSL 450
1830 OpMemberDecorate %S 0 Offset 0
1831 OpMemberDecorate %S 1 Offset 4
1832 OpDecorate %S Block
1833 OpDecorate %B DescriptorSet 0
1834 OpDecorate %B Binding 0
1835 %void = OpTypeVoid
1836 %3 = OpTypeFunction %void
1837 %float = OpTypeFloat 32
1838 %v3float = OpTypeVector %float 3
1839 %S = OpTypeStruct %float %v3float
1840 %_ptr_Uniform_S = OpTypePointer Uniform %S
1841 %B = OpVariable %_ptr_Uniform_S Uniform
1842 %main = OpFunction %void None %3
1843 %5 = OpLabel
1844 OpReturn
1845 OpFunctionEnd
1846 )";
1847
1848 CompileSuccessfully(spirv);
1849 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
1850 EXPECT_EQ(SPV_SUCCESS,
1851 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1852 EXPECT_THAT(getDiagnosticString(), Eq(""));
1853 }
1854
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood)1855 TEST_F(ValidateDecorations,
1856 BlockLayoutPermitsScalarAlignedArrayWithScalarLayoutGood) {
1857 // The array at offset 4 is ok with scalar block layout.
1858 std::string spirv = R"(
1859 OpCapability Shader
1860 OpMemoryModel Logical GLSL450
1861 OpEntryPoint Vertex %main "main"
1862 OpSource GLSL 450
1863 OpMemberDecorate %S 0 Offset 0
1864 OpMemberDecorate %S 1 Offset 4
1865 OpDecorate %S Block
1866 OpDecorate %B DescriptorSet 0
1867 OpDecorate %B Binding 0
1868 OpDecorate %arr_float ArrayStride 4
1869 %void = OpTypeVoid
1870 %3 = OpTypeFunction %void
1871 %uint = OpTypeInt 32 0
1872 %uint_3 = OpConstant %uint 3
1873 %float = OpTypeFloat 32
1874 %arr_float = OpTypeArray %float %uint_3
1875 %S = OpTypeStruct %float %arr_float
1876 %_ptr_Uniform_S = OpTypePointer Uniform %S
1877 %B = OpVariable %_ptr_Uniform_S Uniform
1878 %main = OpFunction %void None %3
1879 %5 = OpLabel
1880 OpReturn
1881 OpFunctionEnd
1882 )";
1883
1884 CompileSuccessfully(spirv);
1885 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
1886 EXPECT_EQ(SPV_SUCCESS,
1887 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1888 EXPECT_THAT(getDiagnosticString(), Eq(""));
1889 }
1890
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood)1891 TEST_F(ValidateDecorations,
1892 BlockLayoutPermitsScalarAlignedArrayOfVec3WithScalarLayoutGood) {
1893 // The array at offset 4 is ok with scalar block layout, even though
1894 // its elements are vec3.
1895 // This is the same as the previous case, but the array elements are vec3
1896 // instead of float.
1897 std::string spirv = R"(
1898 OpCapability Shader
1899 OpMemoryModel Logical GLSL450
1900 OpEntryPoint Vertex %main "main"
1901 OpSource GLSL 450
1902 OpMemberDecorate %S 0 Offset 0
1903 OpMemberDecorate %S 1 Offset 4
1904 OpDecorate %S Block
1905 OpDecorate %B DescriptorSet 0
1906 OpDecorate %B Binding 0
1907 OpDecorate %arr_vec3 ArrayStride 12
1908 %void = OpTypeVoid
1909 %3 = OpTypeFunction %void
1910 %uint = OpTypeInt 32 0
1911 %uint_3 = OpConstant %uint 3
1912 %float = OpTypeFloat 32
1913 %vec3 = OpTypeVector %float 3
1914 %arr_vec3 = OpTypeArray %vec3 %uint_3
1915 %S = OpTypeStruct %float %arr_vec3
1916 %_ptr_Uniform_S = OpTypePointer Uniform %S
1917 %B = OpVariable %_ptr_Uniform_S Uniform
1918 %main = OpFunction %void None %3
1919 %5 = OpLabel
1920 OpReturn
1921 OpFunctionEnd
1922 )";
1923
1924 CompileSuccessfully(spirv);
1925 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
1926 EXPECT_EQ(SPV_SUCCESS,
1927 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1928 EXPECT_THAT(getDiagnosticString(), Eq(""));
1929 }
1930
TEST_F(ValidateDecorations,BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood)1931 TEST_F(ValidateDecorations,
1932 BlockLayoutPermitsScalarAlignedStructWithScalarLayoutGood) {
1933 // Scalar block layout permits the struct at offset 4, even though
1934 // it contains a vector with base alignment 8 and scalar alignment 4.
1935 std::string spirv = R"(
1936 OpCapability Shader
1937 OpMemoryModel Logical GLSL450
1938 OpEntryPoint Vertex %main "main"
1939 OpSource GLSL 450
1940 OpMemberDecorate %S 0 Offset 0
1941 OpMemberDecorate %S 1 Offset 4
1942 OpMemberDecorate %st 0 Offset 0
1943 OpMemberDecorate %st 1 Offset 8
1944 OpDecorate %S Block
1945 OpDecorate %B DescriptorSet 0
1946 OpDecorate %B Binding 0
1947 %void = OpTypeVoid
1948 %3 = OpTypeFunction %void
1949 %float = OpTypeFloat 32
1950 %vec2 = OpTypeVector %float 2
1951 %st = OpTypeStruct %vec2 %float
1952 %S = OpTypeStruct %float %st
1953 %_ptr_Uniform_S = OpTypePointer Uniform %S
1954 %B = OpVariable %_ptr_Uniform_S Uniform
1955 %main = OpFunction %void None %3
1956 %5 = OpLabel
1957 OpReturn
1958 OpFunctionEnd
1959 )";
1960
1961 CompileSuccessfully(spirv);
1962 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
1963 EXPECT_EQ(SPV_SUCCESS,
1964 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
1965 EXPECT_THAT(getDiagnosticString(), Eq(""));
1966 }
1967
TEST_F(ValidateDecorations,BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood)1968 TEST_F(
1969 ValidateDecorations,
1970 BlockLayoutPermitsFieldsInBaseAlignmentPaddingAtEndOfStructWithScalarLayoutGood) {
1971 // Scalar block layout permits fields in what would normally be the padding at
1972 // the end of a struct.
1973 std::string spirv = R"(
1974 OpCapability Shader
1975 OpCapability Float64
1976 OpMemoryModel Logical GLSL450
1977 OpEntryPoint Vertex %main "main"
1978 OpSource GLSL 450
1979 OpMemberDecorate %st 0 Offset 0
1980 OpMemberDecorate %st 1 Offset 8
1981 OpMemberDecorate %S 0 Offset 0
1982 OpMemberDecorate %S 1 Offset 12
1983 OpDecorate %S Block
1984 OpDecorate %B DescriptorSet 0
1985 OpDecorate %B Binding 0
1986 %void = OpTypeVoid
1987 %3 = OpTypeFunction %void
1988 %float = OpTypeFloat 32
1989 %double = OpTypeFloat 64
1990 %st = OpTypeStruct %double %float
1991 %S = OpTypeStruct %st %float
1992 %_ptr_Uniform_S = OpTypePointer Uniform %S
1993 %B = OpVariable %_ptr_Uniform_S Uniform
1994 %main = OpFunction %void None %3
1995 %5 = OpLabel
1996 OpReturn
1997 OpFunctionEnd
1998 )";
1999
2000 CompileSuccessfully(spirv);
2001 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2002 EXPECT_EQ(SPV_SUCCESS,
2003 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2004 EXPECT_THAT(getDiagnosticString(), Eq(""));
2005 }
2006
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood)2007 TEST_F(
2008 ValidateDecorations,
2009 BlockLayoutPermitsStraddlingVectorWithScalarLayoutOverrideRelaxBlockLayoutGood) {
2010 // Same as previous, but set relaxed block layout first. Scalar layout always
2011 // wins.
2012 std::string spirv = R"(
2013 OpCapability Shader
2014 OpMemoryModel Logical GLSL450
2015 OpEntryPoint Vertex %main "main"
2016 OpSource GLSL 450
2017 OpMemberDecorate %S 0 Offset 0
2018 OpMemberDecorate %S 1 Offset 4
2019 OpDecorate %S Block
2020 OpDecorate %B DescriptorSet 0
2021 OpDecorate %B Binding 0
2022 %void = OpTypeVoid
2023 %3 = OpTypeFunction %void
2024 %float = OpTypeFloat 32
2025 %vec4 = OpTypeVector %float 4
2026 %S = OpTypeStruct %float %vec4
2027 %_ptr_Uniform_S = OpTypePointer Uniform %S
2028 %B = OpVariable %_ptr_Uniform_S Uniform
2029 %main = OpFunction %void None %3
2030 %5 = OpLabel
2031 OpReturn
2032 OpFunctionEnd
2033 )";
2034
2035 CompileSuccessfully(spirv);
2036 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2037 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2038 EXPECT_EQ(SPV_SUCCESS,
2039 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2040 EXPECT_THAT(getDiagnosticString(), Eq(""));
2041 }
2042
TEST_F(ValidateDecorations,BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood)2043 TEST_F(
2044 ValidateDecorations,
2045 BlockLayoutPermitsStraddlingVectorWithRelaxedLayoutOverridenByScalarBlockLayoutGood) {
2046 // Same as previous, but set scalar block layout first. Scalar layout always
2047 // wins.
2048 std::string spirv = R"(
2049 OpCapability Shader
2050 OpMemoryModel Logical GLSL450
2051 OpEntryPoint Vertex %main "main"
2052 OpSource GLSL 450
2053 OpMemberDecorate %S 0 Offset 0
2054 OpMemberDecorate %S 1 Offset 4
2055 OpDecorate %S Block
2056 OpDecorate %B DescriptorSet 0
2057 OpDecorate %B Binding 0
2058 %void = OpTypeVoid
2059 %3 = OpTypeFunction %void
2060 %float = OpTypeFloat 32
2061 %vec4 = OpTypeVector %float 4
2062 %S = OpTypeStruct %float %vec4
2063 %_ptr_Uniform_S = OpTypePointer Uniform %S
2064 %B = OpVariable %_ptr_Uniform_S Uniform
2065 %main = OpFunction %void None %3
2066 %5 = OpLabel
2067 OpReturn
2068 OpFunctionEnd
2069 )";
2070
2071 CompileSuccessfully(spirv);
2072 spvValidatorOptionsSetScalarBlockLayout(getValidatorOptions(), true);
2073 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2074 EXPECT_EQ(SPV_SUCCESS,
2075 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2076 EXPECT_THAT(getDiagnosticString(), Eq(""));
2077 }
2078
TEST_F(ValidateDecorations,BufferBlock16bitStandardStorageBufferLayout)2079 TEST_F(ValidateDecorations, BufferBlock16bitStandardStorageBufferLayout) {
2080 std::string spirv = R"(
2081 OpCapability Shader
2082 OpCapability StorageUniform16
2083 OpExtension "SPV_KHR_16bit_storage"
2084 OpMemoryModel Logical GLSL450
2085 OpEntryPoint GLCompute %main "main"
2086 OpExecutionMode %main LocalSize 1 1 1
2087 OpDecorate %f32arr ArrayStride 4
2088 OpDecorate %f16arr ArrayStride 2
2089 OpMemberDecorate %SSBO32 0 Offset 0
2090 OpMemberDecorate %SSBO16 0 Offset 0
2091 OpDecorate %SSBO32 BufferBlock
2092 OpDecorate %SSBO16 BufferBlock
2093 %void = OpTypeVoid
2094 %voidf = OpTypeFunction %void
2095 %u32 = OpTypeInt 32 0
2096 %i32 = OpTypeInt 32 1
2097 %f32 = OpTypeFloat 32
2098 %uvec3 = OpTypeVector %u32 3
2099 %c_i32_32 = OpConstant %i32 32
2100 %c_i32_128 = OpConstant %i32 128
2101 %f32arr = OpTypeArray %f32 %c_i32_128
2102 %f16 = OpTypeFloat 16
2103 %f16arr = OpTypeArray %f16 %c_i32_128
2104 %SSBO32 = OpTypeStruct %f32arr
2105 %SSBO16 = OpTypeStruct %f16arr
2106 %_ptr_Uniform_SSBO32 = OpTypePointer Uniform %SSBO32
2107 %varSSBO32 = OpVariable %_ptr_Uniform_SSBO32 Uniform
2108 %_ptr_Uniform_SSBO16 = OpTypePointer Uniform %SSBO16
2109 %varSSBO16 = OpVariable %_ptr_Uniform_SSBO16 Uniform
2110 %main = OpFunction %void None %voidf
2111 %label = OpLabel
2112 OpReturn
2113 OpFunctionEnd
2114 )";
2115
2116 CompileSuccessfully(spirv);
2117 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
2118 }
2119
TEST_F(ValidateDecorations,BlockArrayExtendedAlignmentGood)2120 TEST_F(ValidateDecorations, BlockArrayExtendedAlignmentGood) {
2121 // For uniform buffer, Array base alignment is 16, and ArrayStride
2122 // must be a multiple of 16.
2123 std::string spirv = R"(
2124 OpCapability Shader
2125 OpMemoryModel Logical GLSL450
2126 OpEntryPoint Vertex %main "main"
2127 OpSource GLSL 450
2128 OpDecorate %_arr_float_uint_2 ArrayStride 16
2129 OpMemberDecorate %S 0 Offset 0
2130 OpMemberDecorate %S 1 Offset 16
2131 OpDecorate %S Block
2132 %void = OpTypeVoid
2133 %3 = OpTypeFunction %void
2134 %float = OpTypeFloat 32
2135 %v2float = OpTypeVector %float 2
2136 %uint = OpTypeInt 32 0
2137 %uint_2 = OpConstant %uint 2
2138 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2139 %S = OpTypeStruct %v2float %_arr_float_uint_2
2140 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2141 %u = OpVariable %_ptr_PushConstant_S PushConstant
2142 %main = OpFunction %void None %3
2143 %5 = OpLabel
2144 OpReturn
2145 OpFunctionEnd
2146 )";
2147
2148 CompileSuccessfully(spirv);
2149 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2150 << getDiagnosticString();
2151 }
2152
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentBad)2153 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentBad) {
2154 // For uniform buffer, Array base alignment is 16.
2155 std::string spirv = R"(
2156 OpCapability Shader
2157 OpMemoryModel Logical GLSL450
2158 OpEntryPoint Vertex %main "main"
2159 OpSource GLSL 450
2160 OpDecorate %_arr_float_uint_2 ArrayStride 16
2161 OpMemberDecorate %S 0 Offset 0
2162 OpMemberDecorate %S 1 Offset 8
2163 OpDecorate %S Block
2164 %void = OpTypeVoid
2165 %3 = OpTypeFunction %void
2166 %float = OpTypeFloat 32
2167 %v2float = OpTypeVector %float 2
2168 %uint = OpTypeInt 32 0
2169 %uint_2 = OpConstant %uint 2
2170 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2171 %S = OpTypeStruct %v2float %_arr_float_uint_2
2172 %_ptr_Uniform_S = OpTypePointer Uniform %S
2173 %u = OpVariable %_ptr_Uniform_S Uniform
2174 %main = OpFunction %void None %3
2175 %5 = OpLabel
2176 OpReturn
2177 OpFunctionEnd
2178 )";
2179
2180 CompileSuccessfully(spirv);
2181 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2182 EXPECT_THAT(
2183 getDiagnosticString(),
2184 HasSubstr(
2185 "Structure id 3 decorated as Block for variable in Uniform "
2186 "storage class must follow standard uniform buffer layout rules: "
2187 "member 1 at offset 8 is not aligned to 16"));
2188 }
2189
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithRelaxedLayoutStillBad)2190 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithRelaxedLayoutStillBad) {
2191 // For uniform buffer, Array base alignment is 16, and ArrayStride
2192 // must be a multiple of 16. This case uses relaxed block layout. Relaxed
2193 // layout only relaxes rules for vector alignment, not array alignment.
2194 std::string spirv = R"(
2195 OpCapability Shader
2196 OpMemoryModel Logical GLSL450
2197 OpEntryPoint Vertex %main "main"
2198 OpSource GLSL 450
2199 OpDecorate %_arr_float_uint_2 ArrayStride 16
2200 OpDecorate %u DescriptorSet 0
2201 OpDecorate %u Binding 0
2202 OpMemberDecorate %S 0 Offset 0
2203 OpMemberDecorate %S 1 Offset 8
2204 OpDecorate %S Block
2205 %void = OpTypeVoid
2206 %3 = OpTypeFunction %void
2207 %float = OpTypeFloat 32
2208 %v2float = OpTypeVector %float 2
2209 %uint = OpTypeInt 32 0
2210 %uint_2 = OpConstant %uint 2
2211 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2212 %S = OpTypeStruct %v2float %_arr_float_uint_2
2213 %_ptr_Uniform_S = OpTypePointer Uniform %S
2214 %u = OpVariable %_ptr_Uniform_S Uniform
2215 %main = OpFunction %void None %3
2216 %5 = OpLabel
2217 OpReturn
2218 OpFunctionEnd
2219 )";
2220
2221 CompileSuccessfully(spirv);
2222 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2223 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2224 spvValidatorOptionsSetRelaxBlockLayout(getValidatorOptions(), true);
2225 EXPECT_THAT(
2226 getDiagnosticString(),
2227 HasSubstr(
2228 "Structure id 4 decorated as Block for variable in Uniform "
2229 "storage class must follow standard uniform buffer layout rules: "
2230 "member 1 at offset 8 is not aligned to 16"));
2231 }
2232
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithVulkan1_1StillBad)2233 TEST_F(ValidateDecorations, BlockArrayBaseAlignmentWithVulkan1_1StillBad) {
2234 // Same as previous test, but with Vulkan 1.1, which includes
2235 // VK_KHR_relaxed_block_layout in core.
2236 std::string spirv = R"(
2237 OpCapability Shader
2238 OpMemoryModel Logical GLSL450
2239 OpEntryPoint Vertex %main "main"
2240 OpSource GLSL 450
2241 OpDecorate %_arr_float_uint_2 ArrayStride 16
2242 OpDecorate %u DescriptorSet 0
2243 OpDecorate %u Binding 0
2244 OpMemberDecorate %S 0 Offset 0
2245 OpMemberDecorate %S 1 Offset 8
2246 OpDecorate %S Block
2247 %void = OpTypeVoid
2248 %3 = OpTypeFunction %void
2249 %float = OpTypeFloat 32
2250 %v2float = OpTypeVector %float 2
2251 %uint = OpTypeInt 32 0
2252 %uint_2 = OpConstant %uint 2
2253 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2254 %S = OpTypeStruct %v2float %_arr_float_uint_2
2255 %_ptr_Uniform_S = OpTypePointer Uniform %S
2256 %u = OpVariable %_ptr_Uniform_S Uniform
2257 %main = OpFunction %void None %3
2258 %5 = OpLabel
2259 OpReturn
2260 OpFunctionEnd
2261 )";
2262
2263 CompileSuccessfully(spirv);
2264 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2265 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2266 EXPECT_THAT(
2267 getDiagnosticString(),
2268 HasSubstr(
2269 "Structure id 4 decorated as Block for variable in Uniform "
2270 "storage class must follow relaxed uniform buffer layout rules: "
2271 "member 1 at offset 8 is not aligned to 16"));
2272 }
2273
TEST_F(ValidateDecorations,BlockArrayBaseAlignmentWithBlockStandardLayoutGood)2274 TEST_F(ValidateDecorations,
2275 BlockArrayBaseAlignmentWithBlockStandardLayoutGood) {
2276 // Same as previous test, but with VK_KHR_uniform_buffer_standard_layout
2277 std::string spirv = R"(
2278 OpCapability Shader
2279 OpMemoryModel Logical GLSL450
2280 OpEntryPoint Vertex %main "main"
2281 OpSource GLSL 450
2282 OpDecorate %_arr_float_uint_2 ArrayStride 16
2283 OpDecorate %u DescriptorSet 0
2284 OpDecorate %u Binding 0
2285 OpMemberDecorate %S 0 Offset 0
2286 OpMemberDecorate %S 1 Offset 8
2287 OpDecorate %S Block
2288 %void = OpTypeVoid
2289 %3 = OpTypeFunction %void
2290 %float = OpTypeFloat 32
2291 %v2float = OpTypeVector %float 2
2292 %uint = OpTypeInt 32 0
2293 %uint_2 = OpConstant %uint 2
2294 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2295 %S = OpTypeStruct %v2float %_arr_float_uint_2
2296 %_ptr_Uniform_S = OpTypePointer Uniform %S
2297 %u = OpVariable %_ptr_Uniform_S Uniform
2298 %main = OpFunction %void None %3
2299 %5 = OpLabel
2300 OpReturn
2301 OpFunctionEnd
2302 )";
2303
2304 CompileSuccessfully(spirv);
2305 spvValidatorOptionsSetUniformBufferStandardLayout(getValidatorOptions(),
2306 true);
2307 EXPECT_EQ(SPV_SUCCESS,
2308 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
2309 EXPECT_THAT(getDiagnosticString(), Eq(""));
2310 }
2311
TEST_F(ValidateDecorations,VulkanBufferBlockOnStorageBufferBad)2312 TEST_F(ValidateDecorations, VulkanBufferBlockOnStorageBufferBad) {
2313 std::string spirv = R"(
2314 OpCapability Shader
2315 OpExtension "SPV_KHR_storage_buffer_storage_class"
2316 OpMemoryModel Logical GLSL450
2317 OpEntryPoint Fragment %1 "main"
2318 OpExecutionMode %1 OriginUpperLeft
2319
2320 OpDecorate %struct BufferBlock
2321
2322 %void = OpTypeVoid
2323 %voidfn = OpTypeFunction %void
2324 %float = OpTypeFloat 32
2325 %struct = OpTypeStruct %float
2326 %ptr = OpTypePointer StorageBuffer %struct
2327 %var = OpVariable %ptr StorageBuffer
2328
2329 %1 = OpFunction %void None %voidfn
2330 %label = OpLabel
2331 OpReturn
2332 OpFunctionEnd
2333 )";
2334
2335 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2336 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2337 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2338 EXPECT_THAT(getDiagnosticString(),
2339 HasSubstr("In Vulkan, BufferBlock is disallowed on variables in "
2340 "the StorageBuffer storage class"));
2341 }
2342
TEST_F(ValidateDecorations,PushConstantArrayBaseAlignmentGood)2343 TEST_F(ValidateDecorations, PushConstantArrayBaseAlignmentGood) {
2344 // Tests https://github.com/KhronosGroup/SPIRV-Tools/issues/1664
2345 // From GLSL vertex shader:
2346 // #version 450
2347 // layout(push_constant) uniform S { vec2 v; float arr[2]; } u;
2348 // void main() { }
2349
2350 std::string spirv = R"(
2351 OpCapability Shader
2352 OpMemoryModel Logical GLSL450
2353 OpEntryPoint Vertex %main "main"
2354 OpSource GLSL 450
2355 OpDecorate %_arr_float_uint_2 ArrayStride 4
2356 OpMemberDecorate %S 0 Offset 0
2357 OpMemberDecorate %S 1 Offset 8
2358 OpDecorate %S Block
2359 %void = OpTypeVoid
2360 %3 = OpTypeFunction %void
2361 %float = OpTypeFloat 32
2362 %v2float = OpTypeVector %float 2
2363 %uint = OpTypeInt 32 0
2364 %uint_2 = OpConstant %uint 2
2365 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2366 %S = OpTypeStruct %v2float %_arr_float_uint_2
2367 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2368 %u = OpVariable %_ptr_PushConstant_S PushConstant
2369 %main = OpFunction %void None %3
2370 %5 = OpLabel
2371 OpReturn
2372 OpFunctionEnd
2373 )";
2374
2375 CompileSuccessfully(spirv);
2376 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2377 << getDiagnosticString();
2378 }
2379
TEST_F(ValidateDecorations,PushConstantArrayBadAlignmentBad)2380 TEST_F(ValidateDecorations, PushConstantArrayBadAlignmentBad) {
2381 // Like the previous test, but with offset 7 instead of 8.
2382 std::string spirv = R"(
2383 OpCapability Shader
2384 OpMemoryModel Logical GLSL450
2385 OpEntryPoint Vertex %main "main"
2386 OpSource GLSL 450
2387 OpDecorate %_arr_float_uint_2 ArrayStride 4
2388 OpMemberDecorate %S 0 Offset 0
2389 OpMemberDecorate %S 1 Offset 7
2390 OpDecorate %S Block
2391 %void = OpTypeVoid
2392 %3 = OpTypeFunction %void
2393 %float = OpTypeFloat 32
2394 %v2float = OpTypeVector %float 2
2395 %uint = OpTypeInt 32 0
2396 %uint_2 = OpConstant %uint 2
2397 %_arr_float_uint_2 = OpTypeArray %float %uint_2
2398 %S = OpTypeStruct %v2float %_arr_float_uint_2
2399 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2400 %u = OpVariable %_ptr_PushConstant_S PushConstant
2401 %main = OpFunction %void None %3
2402 %5 = OpLabel
2403 OpReturn
2404 OpFunctionEnd
2405 )";
2406
2407 CompileSuccessfully(spirv);
2408 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2409 EXPECT_THAT(
2410 getDiagnosticString(),
2411 HasSubstr(
2412 "Structure id 3 decorated as Block for variable in PushConstant "
2413 "storage class must follow standard storage buffer layout rules: "
2414 "member 1 at offset 7 is not aligned to 4"));
2415 }
2416
TEST_F(ValidateDecorations,PushConstantLayoutPermitsTightVec3ScalarPackingGood)2417 TEST_F(ValidateDecorations,
2418 PushConstantLayoutPermitsTightVec3ScalarPackingGood) {
2419 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2420 std::string spirv = R"(
2421 OpCapability Shader
2422 OpMemoryModel Logical GLSL450
2423 OpEntryPoint Vertex %main "main"
2424 OpSource GLSL 450
2425 OpMemberDecorate %S 0 Offset 0
2426 OpMemberDecorate %S 1 Offset 12
2427 OpDecorate %S Block
2428 %void = OpTypeVoid
2429 %3 = OpTypeFunction %void
2430 %float = OpTypeFloat 32
2431 %v3float = OpTypeVector %float 3
2432 %S = OpTypeStruct %v3float %float
2433 %_ptr_PushConstant_S = OpTypePointer PushConstant %S
2434 %B = OpVariable %_ptr_PushConstant_S PushConstant
2435 %main = OpFunction %void None %3
2436 %5 = OpLabel
2437 OpReturn
2438 OpFunctionEnd
2439 )";
2440
2441 CompileSuccessfully(spirv);
2442 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2443 << getDiagnosticString();
2444 }
2445
TEST_F(ValidateDecorations,PushConstantLayoutForbidsTightScalarVec3PackingBad)2446 TEST_F(ValidateDecorations,
2447 PushConstantLayoutForbidsTightScalarVec3PackingBad) {
2448 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
2449 std::string spirv = R"(
2450 OpCapability Shader
2451 OpMemoryModel Logical GLSL450
2452 OpEntryPoint Vertex %main "main"
2453 OpSource GLSL 450
2454 OpMemberDecorate %S 0 Offset 0
2455 OpMemberDecorate %S 1 Offset 4
2456 OpDecorate %S Block
2457 %void = OpTypeVoid
2458 %3 = OpTypeFunction %void
2459 %float = OpTypeFloat 32
2460 %v3float = OpTypeVector %float 3
2461 %S = OpTypeStruct %float %v3float
2462 %_ptr_Uniform_S = OpTypePointer PushConstant %S
2463 %B = OpVariable %_ptr_Uniform_S PushConstant
2464 %main = OpFunction %void None %3
2465 %5 = OpLabel
2466 OpReturn
2467 OpFunctionEnd
2468 )";
2469
2470 CompileSuccessfully(spirv);
2471 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
2472 EXPECT_THAT(
2473 getDiagnosticString(),
2474 HasSubstr(
2475 "Structure id 2 decorated as Block for variable in PushConstant "
2476 "storage class must follow standard storage buffer layout "
2477 "rules: member 1 at offset 4 is not aligned to 16"));
2478 }
2479
TEST_F(ValidateDecorations,PushConstantMissingBlockGood)2480 TEST_F(ValidateDecorations, PushConstantMissingBlockGood) {
2481 std::string spirv = R"(
2482 OpCapability Shader
2483 OpMemoryModel Logical GLSL450
2484 OpEntryPoint Fragment %1 "main"
2485 OpExecutionMode %1 OriginUpperLeft
2486
2487 OpMemberDecorate %struct 0 Offset 0
2488
2489 %void = OpTypeVoid
2490 %voidfn = OpTypeFunction %void
2491 %float = OpTypeFloat 32
2492 %struct = OpTypeStruct %float
2493 %ptr = OpTypePointer PushConstant %struct
2494 %pc = OpVariable %ptr PushConstant
2495
2496 %1 = OpFunction %void None %voidfn
2497 %label = OpLabel
2498 OpReturn
2499 OpFunctionEnd
2500 )";
2501
2502 CompileSuccessfully(spirv);
2503 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2504 << getDiagnosticString();
2505 }
2506
TEST_F(ValidateDecorations,VulkanPushConstantMissingBlockBad)2507 TEST_F(ValidateDecorations, VulkanPushConstantMissingBlockBad) {
2508 std::string spirv = R"(
2509 OpCapability Shader
2510 OpMemoryModel Logical GLSL450
2511 OpEntryPoint Fragment %1 "main"
2512 OpExecutionMode %1 OriginUpperLeft
2513
2514 OpMemberDecorate %struct 0 Offset 0
2515
2516 %void = OpTypeVoid
2517 %voidfn = OpTypeFunction %void
2518 %float = OpTypeFloat 32
2519 %struct = OpTypeStruct %float
2520 %ptr = OpTypePointer PushConstant %struct
2521 %pc = OpVariable %ptr PushConstant
2522
2523 %1 = OpFunction %void None %voidfn
2524 %label = OpLabel
2525 OpReturn
2526 OpFunctionEnd
2527 )";
2528
2529 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2530 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2531 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2532 EXPECT_THAT(getDiagnosticString(),
2533 HasSubstr("PushConstant id '2' is missing Block decoration.\n"
2534 "From Vulkan spec, section 14.5.1:\n"
2535 "Such variables must be identified with a Block "
2536 "decoration"));
2537 }
2538
TEST_F(ValidateDecorations,MultiplePushConstantsSingleEntryPointGood)2539 TEST_F(ValidateDecorations, MultiplePushConstantsSingleEntryPointGood) {
2540 std::string spirv = R"(
2541 OpCapability Shader
2542 OpMemoryModel Logical GLSL450
2543 OpEntryPoint Fragment %1 "main"
2544 OpExecutionMode %1 OriginUpperLeft
2545
2546 OpDecorate %struct Block
2547 OpMemberDecorate %struct 0 Offset 0
2548
2549 %void = OpTypeVoid
2550 %voidfn = OpTypeFunction %void
2551 %float = OpTypeFloat 32
2552 %int = OpTypeInt 32 0
2553 %int_0 = OpConstant %int 0
2554 %struct = OpTypeStruct %float
2555 %ptr = OpTypePointer PushConstant %struct
2556 %ptr_float = OpTypePointer PushConstant %float
2557 %pc1 = OpVariable %ptr PushConstant
2558 %pc2 = OpVariable %ptr PushConstant
2559
2560 %1 = OpFunction %void None %voidfn
2561 %label = OpLabel
2562 %2 = OpAccessChain %ptr_float %pc1 %int_0
2563 %3 = OpLoad %float %2
2564 %4 = OpAccessChain %ptr_float %pc2 %int_0
2565 %5 = OpLoad %float %4
2566 OpReturn
2567 OpFunctionEnd
2568 )";
2569
2570 CompileSuccessfully(spirv);
2571 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
2572 << getDiagnosticString();
2573 }
2574
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointGood)2575 TEST_F(ValidateDecorations,
2576 VulkanMultiplePushConstantsDifferentEntryPointGood) {
2577 std::string spirv = R"(
2578 OpCapability Shader
2579 OpMemoryModel Logical GLSL450
2580 OpEntryPoint Vertex %1 "func1"
2581 OpEntryPoint Fragment %2 "func2"
2582 OpExecutionMode %2 OriginUpperLeft
2583
2584 OpDecorate %struct Block
2585 OpMemberDecorate %struct 0 Offset 0
2586
2587 %void = OpTypeVoid
2588 %voidfn = OpTypeFunction %void
2589 %float = OpTypeFloat 32
2590 %int = OpTypeInt 32 0
2591 %int_0 = OpConstant %int 0
2592 %struct = OpTypeStruct %float
2593 %ptr = OpTypePointer PushConstant %struct
2594 %ptr_float = OpTypePointer PushConstant %float
2595 %pc1 = OpVariable %ptr PushConstant
2596 %pc2 = OpVariable %ptr PushConstant
2597
2598 %1 = OpFunction %void None %voidfn
2599 %label1 = OpLabel
2600 %3 = OpAccessChain %ptr_float %pc1 %int_0
2601 %4 = OpLoad %float %3
2602 OpReturn
2603 OpFunctionEnd
2604
2605 %2 = OpFunction %void None %voidfn
2606 %label2 = OpLabel
2607 %5 = OpAccessChain %ptr_float %pc2 %int_0
2608 %6 = OpLoad %float %5
2609 OpReturn
2610 OpFunctionEnd
2611 )";
2612
2613 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2614 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
2615 << getDiagnosticString();
2616 }
2617
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsUnusedSingleEntryPointGood)2618 TEST_F(ValidateDecorations,
2619 VulkanMultiplePushConstantsUnusedSingleEntryPointGood) {
2620 std::string spirv = R"(
2621 OpCapability Shader
2622 OpMemoryModel Logical GLSL450
2623 OpEntryPoint Fragment %1 "main"
2624 OpExecutionMode %1 OriginUpperLeft
2625
2626 OpDecorate %struct Block
2627 OpMemberDecorate %struct 0 Offset 0
2628
2629 %void = OpTypeVoid
2630 %voidfn = OpTypeFunction %void
2631 %float = OpTypeFloat 32
2632 %int = OpTypeInt 32 0
2633 %int_0 = OpConstant %int 0
2634 %struct = OpTypeStruct %float
2635 %ptr = OpTypePointer PushConstant %struct
2636 %ptr_float = OpTypePointer PushConstant %float
2637 %pc1 = OpVariable %ptr PushConstant
2638 %pc2 = OpVariable %ptr PushConstant
2639
2640 %1 = OpFunction %void None %voidfn
2641 %label = OpLabel
2642 OpReturn
2643 OpFunctionEnd
2644 )";
2645
2646 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2647 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
2648 << getDiagnosticString();
2649 }
2650
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointBad)2651 TEST_F(ValidateDecorations, VulkanMultiplePushConstantsSingleEntryPointBad) {
2652 std::string spirv = R"(
2653 OpCapability Shader
2654 OpMemoryModel Logical GLSL450
2655 OpEntryPoint Fragment %1 "main"
2656 OpExecutionMode %1 OriginUpperLeft
2657
2658 OpDecorate %struct Block
2659 OpMemberDecorate %struct 0 Offset 0
2660
2661 %void = OpTypeVoid
2662 %voidfn = OpTypeFunction %void
2663 %float = OpTypeFloat 32
2664 %int = OpTypeInt 32 0
2665 %int_0 = OpConstant %int 0
2666 %struct = OpTypeStruct %float
2667 %ptr = OpTypePointer PushConstant %struct
2668 %ptr_float = OpTypePointer PushConstant %float
2669 %pc1 = OpVariable %ptr PushConstant
2670 %pc2 = OpVariable %ptr PushConstant
2671
2672 %1 = OpFunction %void None %voidfn
2673 %label = OpLabel
2674 %2 = OpAccessChain %ptr_float %pc1 %int_0
2675 %3 = OpLoad %float %2
2676 %4 = OpAccessChain %ptr_float %pc2 %int_0
2677 %5 = OpLoad %float %4
2678 OpReturn
2679 OpFunctionEnd
2680 )";
2681
2682 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2683 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2684 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2685 EXPECT_THAT(
2686 getDiagnosticString(),
2687 HasSubstr(
2688 "Entry point id '1' uses more than one PushConstant interface.\n"
2689 "From Vulkan spec, section 14.5.1:\n"
2690 "There must be no more than one push constant block "
2691 "statically used per shader entry point."));
2692 }
2693
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood)2694 TEST_F(ValidateDecorations,
2695 VulkanMultiplePushConstantsDifferentEntryPointSubFunctionGood) {
2696 std::string spirv = R"(
2697 OpCapability Shader
2698 OpMemoryModel Logical GLSL450
2699 OpEntryPoint Vertex %1 "func1"
2700 OpEntryPoint Fragment %2 "func2"
2701 OpExecutionMode %2 OriginUpperLeft
2702
2703 OpDecorate %struct Block
2704 OpMemberDecorate %struct 0 Offset 0
2705
2706 %void = OpTypeVoid
2707 %voidfn = OpTypeFunction %void
2708 %float = OpTypeFloat 32
2709 %int = OpTypeInt 32 0
2710 %int_0 = OpConstant %int 0
2711 %struct = OpTypeStruct %float
2712 %ptr = OpTypePointer PushConstant %struct
2713 %ptr_float = OpTypePointer PushConstant %float
2714 %pc1 = OpVariable %ptr PushConstant
2715 %pc2 = OpVariable %ptr PushConstant
2716
2717 %sub1 = OpFunction %void None %voidfn
2718 %label_sub1 = OpLabel
2719 %3 = OpAccessChain %ptr_float %pc1 %int_0
2720 %4 = OpLoad %float %3
2721 OpReturn
2722 OpFunctionEnd
2723
2724 %sub2 = OpFunction %void None %voidfn
2725 %label_sub2 = OpLabel
2726 %5 = OpAccessChain %ptr_float %pc2 %int_0
2727 %6 = OpLoad %float %5
2728 OpReturn
2729 OpFunctionEnd
2730
2731 %1 = OpFunction %void None %voidfn
2732 %label1 = OpLabel
2733 %call1 = OpFunctionCall %void %sub1
2734 OpReturn
2735 OpFunctionEnd
2736
2737 %2 = OpFunction %void None %voidfn
2738 %label2 = OpLabel
2739 %call2 = OpFunctionCall %void %sub2
2740 OpReturn
2741 OpFunctionEnd
2742 )";
2743
2744 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2745 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
2746 << getDiagnosticString();
2747 }
2748
TEST_F(ValidateDecorations,VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad)2749 TEST_F(ValidateDecorations,
2750 VulkanMultiplePushConstantsSingleEntryPointSubFunctionBad) {
2751 std::string spirv = R"(
2752 OpCapability Shader
2753 OpMemoryModel Logical GLSL450
2754 OpEntryPoint Fragment %1 "main"
2755 OpExecutionMode %1 OriginUpperLeft
2756
2757 OpDecorate %struct Block
2758 OpMemberDecorate %struct 0 Offset 0
2759
2760 %void = OpTypeVoid
2761 %voidfn = OpTypeFunction %void
2762 %float = OpTypeFloat 32
2763 %int = OpTypeInt 32 0
2764 %int_0 = OpConstant %int 0
2765 %struct = OpTypeStruct %float
2766 %ptr = OpTypePointer PushConstant %struct
2767 %ptr_float = OpTypePointer PushConstant %float
2768 %pc1 = OpVariable %ptr PushConstant
2769 %pc2 = OpVariable %ptr PushConstant
2770
2771 %sub1 = OpFunction %void None %voidfn
2772 %label_sub1 = OpLabel
2773 %3 = OpAccessChain %ptr_float %pc1 %int_0
2774 %4 = OpLoad %float %3
2775 OpReturn
2776 OpFunctionEnd
2777
2778 %sub2 = OpFunction %void None %voidfn
2779 %label_sub2 = OpLabel
2780 %5 = OpAccessChain %ptr_float %pc2 %int_0
2781 %6 = OpLoad %float %5
2782 OpReturn
2783 OpFunctionEnd
2784
2785 %1 = OpFunction %void None %voidfn
2786 %label1 = OpLabel
2787 %call1 = OpFunctionCall %void %sub1
2788 %call2 = OpFunctionCall %void %sub2
2789 OpReturn
2790 OpFunctionEnd
2791 )";
2792
2793 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2794 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2795 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2796 EXPECT_THAT(
2797 getDiagnosticString(),
2798 HasSubstr(
2799 "Entry point id '1' uses more than one PushConstant interface.\n"
2800 "From Vulkan spec, section 14.5.1:\n"
2801 "There must be no more than one push constant block "
2802 "statically used per shader entry point."));
2803 }
2804
TEST_F(ValidateDecorations,VulkanUniformMissingDescriptorSetBad)2805 TEST_F(ValidateDecorations, VulkanUniformMissingDescriptorSetBad) {
2806 std::string spirv = R"(
2807 OpCapability Shader
2808 OpMemoryModel Logical GLSL450
2809 OpEntryPoint Fragment %1 "main"
2810 OpExecutionMode %1 OriginUpperLeft
2811
2812 OpDecorate %struct Block
2813 OpMemberDecorate %struct 0 Offset 0
2814 OpDecorate %var Binding 0
2815
2816 %void = OpTypeVoid
2817 %voidfn = OpTypeFunction %void
2818 %float = OpTypeFloat 32
2819 %struct = OpTypeStruct %float
2820 %ptr = OpTypePointer Uniform %struct
2821 %ptr_float = OpTypePointer Uniform %float
2822 %var = OpVariable %ptr Uniform
2823 %int = OpTypeInt 32 0
2824 %int_0 = OpConstant %int 0
2825
2826 %1 = OpFunction %void None %voidfn
2827 %label = OpLabel
2828 %2 = OpAccessChain %ptr_float %var %int_0
2829 %3 = OpLoad %float %2
2830 OpReturn
2831 OpFunctionEnd
2832 )";
2833
2834 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2835 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2836 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2837 EXPECT_THAT(getDiagnosticString(),
2838 HasSubstr("Uniform id '3' is missing DescriptorSet decoration.\n"
2839 "From Vulkan spec, section 14.5.2:\n"
2840 "These variables must have DescriptorSet and Binding "
2841 "decorations specified"));
2842 }
2843
TEST_F(ValidateDecorations,VulkanUniformMissingBindingBad)2844 TEST_F(ValidateDecorations, VulkanUniformMissingBindingBad) {
2845 std::string spirv = R"(
2846 OpCapability Shader
2847 OpMemoryModel Logical GLSL450
2848 OpEntryPoint Fragment %1 "main"
2849 OpExecutionMode %1 OriginUpperLeft
2850
2851 OpDecorate %struct Block
2852 OpMemberDecorate %struct 0 Offset 0
2853 OpDecorate %var DescriptorSet 0
2854
2855 %void = OpTypeVoid
2856 %voidfn = OpTypeFunction %void
2857 %float = OpTypeFloat 32
2858 %struct = OpTypeStruct %float
2859 %ptr = OpTypePointer Uniform %struct
2860 %ptr_float = OpTypePointer Uniform %float
2861 %var = OpVariable %ptr Uniform
2862 %int = OpTypeInt 32 0
2863 %int_0 = OpConstant %int 0
2864
2865 %1 = OpFunction %void None %voidfn
2866 %label = OpLabel
2867 %2 = OpAccessChain %ptr_float %var %int_0
2868 %3 = OpLoad %float %2
2869 OpReturn
2870 OpFunctionEnd
2871 )";
2872
2873 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2874 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2875 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2876 EXPECT_THAT(getDiagnosticString(),
2877 HasSubstr("Uniform id '3' is missing Binding decoration.\n"
2878 "From Vulkan spec, section 14.5.2:\n"
2879 "These variables must have DescriptorSet and Binding "
2880 "decorations specified"));
2881 }
2882
TEST_F(ValidateDecorations,VulkanUniformConstantMissingDescriptorSetBad)2883 TEST_F(ValidateDecorations, VulkanUniformConstantMissingDescriptorSetBad) {
2884 std::string spirv = R"(
2885 OpCapability Shader
2886 OpMemoryModel Logical GLSL450
2887 OpEntryPoint Fragment %1 "main"
2888 OpExecutionMode %1 OriginUpperLeft
2889
2890 OpDecorate %var Binding 0
2891
2892 %void = OpTypeVoid
2893 %voidfn = OpTypeFunction %void
2894 %sampler = OpTypeSampler
2895 %ptr = OpTypePointer UniformConstant %sampler
2896 %var = OpVariable %ptr UniformConstant
2897
2898 %1 = OpFunction %void None %voidfn
2899 %label = OpLabel
2900 %2 = OpLoad %sampler %var
2901 OpReturn
2902 OpFunctionEnd
2903 )";
2904
2905 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2906 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2907 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2908 EXPECT_THAT(
2909 getDiagnosticString(),
2910 HasSubstr("UniformConstant id '2' is missing DescriptorSet decoration.\n"
2911 "From Vulkan spec, section 14.5.2:\n"
2912 "These variables must have DescriptorSet and Binding "
2913 "decorations specified"));
2914 }
2915
TEST_F(ValidateDecorations,VulkanUniformConstantMissingBindingBad)2916 TEST_F(ValidateDecorations, VulkanUniformConstantMissingBindingBad) {
2917 std::string spirv = R"(
2918 OpCapability Shader
2919 OpMemoryModel Logical GLSL450
2920 OpEntryPoint Fragment %1 "main"
2921 OpExecutionMode %1 OriginUpperLeft
2922
2923 OpDecorate %var DescriptorSet 0
2924
2925 %void = OpTypeVoid
2926 %voidfn = OpTypeFunction %void
2927 %sampler = OpTypeSampler
2928 %ptr = OpTypePointer UniformConstant %sampler
2929 %var = OpVariable %ptr UniformConstant
2930
2931 %1 = OpFunction %void None %voidfn
2932 %label = OpLabel
2933 %2 = OpLoad %sampler %var
2934 OpReturn
2935 OpFunctionEnd
2936 )";
2937
2938 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2939 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2940 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2941 EXPECT_THAT(
2942 getDiagnosticString(),
2943 HasSubstr("UniformConstant id '2' is missing Binding decoration.\n"
2944 "From Vulkan spec, section 14.5.2:\n"
2945 "These variables must have DescriptorSet and Binding "
2946 "decorations specified"));
2947 }
2948
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetBad)2949 TEST_F(ValidateDecorations, VulkanStorageBufferMissingDescriptorSetBad) {
2950 std::string spirv = R"(
2951 OpCapability Shader
2952 OpExtension "SPV_KHR_storage_buffer_storage_class"
2953 OpMemoryModel Logical GLSL450
2954 OpEntryPoint Fragment %1 "main"
2955 OpExecutionMode %1 OriginUpperLeft
2956
2957 OpDecorate %struct Block
2958 OpDecorate %var Binding 0
2959
2960 %void = OpTypeVoid
2961 %voidfn = OpTypeFunction %void
2962 %float = OpTypeFloat 32
2963 %struct = OpTypeStruct %float
2964 %ptr = OpTypePointer StorageBuffer %struct
2965 %var = OpVariable %ptr StorageBuffer
2966 %ptr_float = OpTypePointer StorageBuffer %float
2967 %int = OpTypeInt 32 0
2968 %int_0 = OpConstant %int 0
2969
2970 %1 = OpFunction %void None %voidfn
2971 %label = OpLabel
2972 %2 = OpAccessChain %ptr_float %var %int_0
2973 %3 = OpLoad %float %2
2974 OpReturn
2975 OpFunctionEnd
2976 )";
2977
2978 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
2979 EXPECT_EQ(SPV_ERROR_INVALID_ID,
2980 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
2981 EXPECT_THAT(
2982 getDiagnosticString(),
2983 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
2984 "From Vulkan spec, section 14.5.2:\n"
2985 "These variables must have DescriptorSet and Binding "
2986 "decorations specified"));
2987 }
2988
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBindingBad)2989 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBindingBad) {
2990 std::string spirv = R"(
2991 OpCapability Shader
2992 OpExtension "SPV_KHR_storage_buffer_storage_class"
2993 OpMemoryModel Logical GLSL450
2994 OpEntryPoint Fragment %1 "main"
2995 OpExecutionMode %1 OriginUpperLeft
2996
2997 OpDecorate %struct Block
2998 OpDecorate %var DescriptorSet 0
2999
3000 %void = OpTypeVoid
3001 %voidfn = OpTypeFunction %void
3002 %float = OpTypeFloat 32
3003 %struct = OpTypeStruct %float
3004 %ptr = OpTypePointer StorageBuffer %struct
3005 %var = OpVariable %ptr StorageBuffer
3006 %ptr_float = OpTypePointer StorageBuffer %float
3007 %int = OpTypeInt 32 0
3008 %int_0 = OpConstant %int 0
3009
3010 %1 = OpFunction %void None %voidfn
3011 %label = OpLabel
3012 %2 = OpAccessChain %ptr_float %var %int_0
3013 %3 = OpLoad %float %2
3014 OpReturn
3015 OpFunctionEnd
3016 )";
3017
3018 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3019 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3020 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3021 EXPECT_THAT(getDiagnosticString(),
3022 HasSubstr("StorageBuffer id '3' is missing Binding decoration.\n"
3023 "From Vulkan spec, section 14.5.2:\n"
3024 "These variables must have DescriptorSet and Binding "
3025 "decorations specified"));
3026 }
3027
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorSetSubFunctionBad)3028 TEST_F(ValidateDecorations,
3029 VulkanStorageBufferMissingDescriptorSetSubFunctionBad) {
3030 std::string spirv = R"(
3031 OpCapability Shader
3032 OpExtension "SPV_KHR_storage_buffer_storage_class"
3033 OpMemoryModel Logical GLSL450
3034 OpEntryPoint Fragment %1 "main"
3035 OpExecutionMode %1 OriginUpperLeft
3036
3037 OpDecorate %struct Block
3038 OpDecorate %var Binding 0
3039
3040 %void = OpTypeVoid
3041 %voidfn = OpTypeFunction %void
3042 %float = OpTypeFloat 32
3043 %struct = OpTypeStruct %float
3044 %ptr = OpTypePointer StorageBuffer %struct
3045 %var = OpVariable %ptr StorageBuffer
3046 %ptr_float = OpTypePointer StorageBuffer %float
3047 %int = OpTypeInt 32 0
3048 %int_0 = OpConstant %int 0
3049
3050 %1 = OpFunction %void None %voidfn
3051 %label = OpLabel
3052 %call = OpFunctionCall %void %2
3053 OpReturn
3054 OpFunctionEnd
3055 %2 = OpFunction %void None %voidfn
3056 %label2 = OpLabel
3057 %3 = OpAccessChain %ptr_float %var %int_0
3058 %4 = OpLoad %float %3
3059 OpReturn
3060 OpFunctionEnd
3061 )";
3062
3063 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3064 EXPECT_EQ(SPV_ERROR_INVALID_ID,
3065 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3066 EXPECT_THAT(
3067 getDiagnosticString(),
3068 HasSubstr("StorageBuffer id '3' is missing DescriptorSet decoration.\n"
3069 "From Vulkan spec, section 14.5.2:\n"
3070 "These variables must have DescriptorSet and Binding "
3071 "decorations specified"));
3072 }
3073
TEST_F(ValidateDecorations,VulkanStorageBufferMissingDescriptorAndBindingUnusedGood)3074 TEST_F(ValidateDecorations,
3075 VulkanStorageBufferMissingDescriptorAndBindingUnusedGood) {
3076 std::string spirv = R"(
3077 OpCapability Shader
3078 OpExtension "SPV_KHR_storage_buffer_storage_class"
3079 OpMemoryModel Logical GLSL450
3080 OpEntryPoint Fragment %1 "main"
3081 OpExecutionMode %1 OriginUpperLeft
3082 OpDecorate %struct Block
3083 OpMemberDecorate %struct 0 Offset 0
3084
3085 %void = OpTypeVoid
3086 %voidfn = OpTypeFunction %void
3087 %float = OpTypeFloat 32
3088 %struct = OpTypeStruct %float
3089 %ptr = OpTypePointer StorageBuffer %struct
3090 %var = OpVariable %ptr StorageBuffer
3091
3092 %1 = OpFunction %void None %voidfn
3093 %label = OpLabel
3094 OpReturn
3095 OpFunctionEnd
3096 )";
3097
3098 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3099 EXPECT_EQ(SPV_SUCCESS,
3100 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
3101 }
3102
TEST_F(ValidateDecorations,UniformMissingDescriptorSetGood)3103 TEST_F(ValidateDecorations, UniformMissingDescriptorSetGood) {
3104 std::string spirv = R"(
3105 OpCapability Shader
3106 OpMemoryModel Logical GLSL450
3107 OpEntryPoint Fragment %1 "main"
3108 OpExecutionMode %1 OriginUpperLeft
3109
3110 OpDecorate %struct Block
3111 OpMemberDecorate %struct 0 Offset 0
3112 OpDecorate %var Binding 0
3113
3114 %void = OpTypeVoid
3115 %voidfn = OpTypeFunction %void
3116 %float = OpTypeFloat 32
3117 %struct = OpTypeStruct %float
3118 %ptr = OpTypePointer Uniform %struct
3119 %var = OpVariable %ptr Uniform
3120
3121 %1 = OpFunction %void None %voidfn
3122 %label = OpLabel
3123 OpReturn
3124 OpFunctionEnd
3125 )";
3126
3127 CompileSuccessfully(spirv);
3128 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3129 << getDiagnosticString();
3130 }
3131
TEST_F(ValidateDecorations,UniformMissingBindingGood)3132 TEST_F(ValidateDecorations, UniformMissingBindingGood) {
3133 std::string spirv = R"(
3134 OpCapability Shader
3135 OpMemoryModel Logical GLSL450
3136 OpEntryPoint Fragment %1 "main"
3137 OpExecutionMode %1 OriginUpperLeft
3138
3139 OpDecorate %struct Block
3140 OpMemberDecorate %struct 0 Offset 0
3141 OpDecorate %var DescriptorSet 0
3142
3143 %void = OpTypeVoid
3144 %voidfn = OpTypeFunction %void
3145 %float = OpTypeFloat 32
3146 %struct = OpTypeStruct %float
3147 %ptr = OpTypePointer Uniform %struct
3148 %var = OpVariable %ptr Uniform
3149
3150 %1 = OpFunction %void None %voidfn
3151 %label = OpLabel
3152 OpReturn
3153 OpFunctionEnd
3154 )";
3155
3156 CompileSuccessfully(spirv);
3157 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3158 << getDiagnosticString();
3159 }
3160
TEST_F(ValidateDecorations,UniformConstantMissingDescriptorSetGood)3161 TEST_F(ValidateDecorations, UniformConstantMissingDescriptorSetGood) {
3162 std::string spirv = R"(
3163 OpCapability Shader
3164 OpMemoryModel Logical GLSL450
3165 OpEntryPoint Fragment %1 "main"
3166 OpExecutionMode %1 OriginUpperLeft
3167
3168 OpDecorate %var Binding 0
3169
3170 %void = OpTypeVoid
3171 %voidfn = OpTypeFunction %void
3172 %sampler = OpTypeSampler
3173 %ptr = OpTypePointer UniformConstant %sampler
3174 %var = OpVariable %ptr UniformConstant
3175
3176 %1 = OpFunction %void None %voidfn
3177 %label = OpLabel
3178 OpReturn
3179 OpFunctionEnd
3180 )";
3181
3182 CompileSuccessfully(spirv);
3183 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3184 << getDiagnosticString();
3185 }
3186
TEST_F(ValidateDecorations,UniformConstantMissingBindingGood)3187 TEST_F(ValidateDecorations, UniformConstantMissingBindingGood) {
3188 std::string spirv = R"(
3189 OpCapability Shader
3190 OpMemoryModel Logical GLSL450
3191 OpEntryPoint Fragment %1 "main"
3192 OpExecutionMode %1 OriginUpperLeft
3193
3194 OpDecorate %var DescriptorSet 0
3195
3196 %void = OpTypeVoid
3197 %voidfn = OpTypeFunction %void
3198 %sampler = OpTypeSampler
3199 %ptr = OpTypePointer UniformConstant %sampler
3200 %var = OpVariable %ptr UniformConstant
3201
3202 %1 = OpFunction %void None %voidfn
3203 %label = OpLabel
3204 OpReturn
3205 OpFunctionEnd
3206 )";
3207
3208 CompileSuccessfully(spirv);
3209 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3210 << getDiagnosticString();
3211 }
3212
TEST_F(ValidateDecorations,StorageBufferMissingDescriptorSetGood)3213 TEST_F(ValidateDecorations, StorageBufferMissingDescriptorSetGood) {
3214 std::string spirv = R"(
3215 OpCapability Shader
3216 OpExtension "SPV_KHR_storage_buffer_storage_class"
3217 OpMemoryModel Logical GLSL450
3218 OpEntryPoint Fragment %1 "main"
3219 OpExecutionMode %1 OriginUpperLeft
3220
3221 OpDecorate %struct BufferBlock
3222 OpDecorate %var Binding 0
3223
3224 %void = OpTypeVoid
3225 %voidfn = OpTypeFunction %void
3226 %float = OpTypeFloat 32
3227 %struct = OpTypeStruct %float
3228 %ptr = OpTypePointer StorageBuffer %struct
3229 %var = OpVariable %ptr StorageBuffer
3230
3231 %1 = OpFunction %void None %voidfn
3232 %label = OpLabel
3233 OpReturn
3234 OpFunctionEnd
3235 )";
3236
3237 CompileSuccessfully(spirv);
3238 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3239 << getDiagnosticString();
3240 }
3241
TEST_F(ValidateDecorations,StorageBufferMissingBindingGood)3242 TEST_F(ValidateDecorations, StorageBufferMissingBindingGood) {
3243 std::string spirv = R"(
3244 OpCapability Shader
3245 OpExtension "SPV_KHR_storage_buffer_storage_class"
3246 OpMemoryModel Logical GLSL450
3247 OpEntryPoint Fragment %1 "main"
3248 OpExecutionMode %1 OriginUpperLeft
3249
3250 OpDecorate %struct BufferBlock
3251 OpDecorate %var DescriptorSet 0
3252
3253 %void = OpTypeVoid
3254 %voidfn = OpTypeFunction %void
3255 %float = OpTypeFloat 32
3256 %struct = OpTypeStruct %float
3257 %ptr = OpTypePointer StorageBuffer %struct
3258 %var = OpVariable %ptr StorageBuffer
3259
3260 %1 = OpFunction %void None %voidfn
3261 %label = OpLabel
3262 OpReturn
3263 OpFunctionEnd
3264 )";
3265
3266 CompileSuccessfully(spirv);
3267 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3268 << getDiagnosticString();
3269 }
3270
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBaseAlignmentGood)3271 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBaseAlignmentGood) {
3272 // Spot check buffer rules when using StorageBuffer storage class with Block
3273 // decoration.
3274 std::string spirv = R"(
3275 OpCapability Shader
3276 OpExtension "SPV_KHR_storage_buffer_storage_class"
3277 OpMemoryModel Logical GLSL450
3278 OpEntryPoint Vertex %main "main"
3279 OpSource GLSL 450
3280 OpDecorate %_arr_float_uint_2 ArrayStride 4
3281 OpMemberDecorate %S 0 Offset 0
3282 OpMemberDecorate %S 1 Offset 8
3283 OpDecorate %S Block
3284 OpDecorate %u DescriptorSet 0
3285 OpDecorate %u Binding 0
3286 %void = OpTypeVoid
3287 %3 = OpTypeFunction %void
3288 %float = OpTypeFloat 32
3289 %v2float = OpTypeVector %float 2
3290 %uint = OpTypeInt 32 0
3291 %uint_2 = OpConstant %uint 2
3292 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3293 %S = OpTypeStruct %v2float %_arr_float_uint_2
3294 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3295 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3296 %main = OpFunction %void None %3
3297 %5 = OpLabel
3298 OpReturn
3299 OpFunctionEnd
3300 )";
3301
3302 CompileSuccessfully(spirv);
3303 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3304 << getDiagnosticString();
3305 }
3306
TEST_F(ValidateDecorations,StorageBufferStorageClassArrayBadAlignmentBad)3307 TEST_F(ValidateDecorations, StorageBufferStorageClassArrayBadAlignmentBad) {
3308 // Like the previous test, but with offset 7.
3309 std::string spirv = R"(
3310 OpCapability Shader
3311 OpExtension "SPV_KHR_storage_buffer_storage_class"
3312 OpMemoryModel Logical GLSL450
3313 OpEntryPoint Vertex %main "main"
3314 OpSource GLSL 450
3315 OpDecorate %_arr_float_uint_2 ArrayStride 4
3316 OpMemberDecorate %S 0 Offset 0
3317 OpMemberDecorate %S 1 Offset 7
3318 OpDecorate %S Block
3319 OpDecorate %u DescriptorSet 0
3320 OpDecorate %u Binding 0
3321 %void = OpTypeVoid
3322 %3 = OpTypeFunction %void
3323 %float = OpTypeFloat 32
3324 %v2float = OpTypeVector %float 2
3325 %uint = OpTypeInt 32 0
3326 %uint_2 = OpConstant %uint 2
3327 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3328 %S = OpTypeStruct %v2float %_arr_float_uint_2
3329 %_ptr_Uniform_S = OpTypePointer StorageBuffer %S
3330 %u = OpVariable %_ptr_Uniform_S StorageBuffer
3331 %main = OpFunction %void None %3
3332 %5 = OpLabel
3333 OpReturn
3334 OpFunctionEnd
3335 )";
3336
3337 CompileSuccessfully(spirv);
3338 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3339 EXPECT_THAT(
3340 getDiagnosticString(),
3341 HasSubstr(
3342 "Structure id 3 decorated as Block for variable in StorageBuffer "
3343 "storage class must follow standard storage buffer layout rules: "
3344 "member 1 at offset 7 is not aligned to 4"));
3345 }
3346
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayout)3347 TEST_F(ValidateDecorations, BufferBlockStandardStorageBufferLayout) {
3348 std::string spirv = R"(
3349 OpCapability Shader
3350 %1 = OpExtInstImport "GLSL.std.450"
3351 OpMemoryModel Logical GLSL450
3352 OpEntryPoint GLCompute %main "main"
3353 OpExecutionMode %main LocalSize 1 1 1
3354 OpSource GLSL 430
3355 OpMemberDecorate %F 0 Offset 0
3356 OpMemberDecorate %F 1 Offset 8
3357 OpDecorate %_arr_float_uint_2 ArrayStride 4
3358 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3359 OpMemberDecorate %O 0 Offset 0
3360 OpMemberDecorate %O 1 Offset 16
3361 OpMemberDecorate %O 2 Offset 24
3362 OpMemberDecorate %O 3 Offset 32
3363 OpMemberDecorate %O 4 ColMajor
3364 OpMemberDecorate %O 4 Offset 48
3365 OpMemberDecorate %O 4 MatrixStride 16
3366 OpDecorate %_arr_O_uint_2 ArrayStride 144
3367 OpMemberDecorate %Output 0 Offset 0
3368 OpMemberDecorate %Output 1 Offset 8
3369 OpMemberDecorate %Output 2 Offset 16
3370 OpMemberDecorate %Output 3 Offset 32
3371 OpMemberDecorate %Output 4 Offset 48
3372 OpMemberDecorate %Output 5 Offset 52
3373 OpMemberDecorate %Output 6 ColMajor
3374 OpMemberDecorate %Output 6 Offset 64
3375 OpMemberDecorate %Output 6 MatrixStride 16
3376 OpMemberDecorate %Output 7 Offset 96
3377 OpDecorate %Output BufferBlock
3378 %void = OpTypeVoid
3379 %3 = OpTypeFunction %void
3380 %float = OpTypeFloat 32
3381 %v2float = OpTypeVector %float 2
3382 %v3float = OpTypeVector %float 3
3383 %int = OpTypeInt 32 1
3384 %uint = OpTypeInt 32 0
3385 %v2uint = OpTypeVector %uint 2
3386 %F = OpTypeStruct %int %v2uint
3387 %uint_2 = OpConstant %uint 2
3388 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3389 %mat2v3float = OpTypeMatrix %v3float 2
3390 %v3uint = OpTypeVector %uint 3
3391 %mat3v3float = OpTypeMatrix %v3float 3
3392 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3393 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3394 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3395 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3396 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3397 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3398 %main = OpFunction %void None %3
3399 %5 = OpLabel
3400 OpReturn
3401 OpFunctionEnd
3402 )";
3403
3404 CompileSuccessfully(spirv);
3405 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
3406 }
3407
TEST_F(ValidateDecorations,StorageBufferLayoutPermitsTightVec3ScalarPackingGood)3408 TEST_F(ValidateDecorations,
3409 StorageBufferLayoutPermitsTightVec3ScalarPackingGood) {
3410 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3411 std::string spirv = R"(
3412 OpCapability Shader
3413 OpExtension "SPV_KHR_storage_buffer_storage_class"
3414 OpMemoryModel Logical GLSL450
3415 OpEntryPoint Vertex %main "main"
3416 OpSource GLSL 450
3417 OpMemberDecorate %S 0 Offset 0
3418 OpMemberDecorate %S 1 Offset 12
3419 OpDecorate %S Block
3420 OpDecorate %B DescriptorSet 0
3421 OpDecorate %B Binding 0
3422 %void = OpTypeVoid
3423 %3 = OpTypeFunction %void
3424 %float = OpTypeFloat 32
3425 %v3float = OpTypeVector %float 3
3426 %S = OpTypeStruct %v3float %float
3427 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3428 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3429 %main = OpFunction %void None %3
3430 %5 = OpLabel
3431 OpReturn
3432 OpFunctionEnd
3433 )";
3434
3435 CompileSuccessfully(spirv);
3436 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3437 << getDiagnosticString();
3438 }
3439
TEST_F(ValidateDecorations,StorageBufferLayoutForbidsTightScalarVec3PackingBad)3440 TEST_F(ValidateDecorations,
3441 StorageBufferLayoutForbidsTightScalarVec3PackingBad) {
3442 // See https://github.com/KhronosGroup/SPIRV-Tools/issues/1666
3443 std::string spirv = R"(
3444 OpCapability Shader
3445 OpExtension "SPV_KHR_storage_buffer_storage_class"
3446 OpMemoryModel Logical GLSL450
3447 OpEntryPoint Vertex %main "main"
3448 OpSource GLSL 450
3449 OpMemberDecorate %S 0 Offset 0
3450 OpMemberDecorate %S 1 Offset 4
3451 OpDecorate %S Block
3452 OpDecorate %B DescriptorSet 0
3453 OpDecorate %B Binding 0
3454 %void = OpTypeVoid
3455 %3 = OpTypeFunction %void
3456 %float = OpTypeFloat 32
3457 %v3float = OpTypeVector %float 3
3458 %S = OpTypeStruct %float %v3float
3459 %_ptr_StorageBuffer_S = OpTypePointer StorageBuffer %S
3460 %B = OpVariable %_ptr_StorageBuffer_S StorageBuffer
3461 %main = OpFunction %void None %3
3462 %5 = OpLabel
3463 OpReturn
3464 OpFunctionEnd
3465 )";
3466
3467 CompileSuccessfully(spirv);
3468 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3469 EXPECT_THAT(
3470 getDiagnosticString(),
3471 HasSubstr(
3472 "Structure id 2 decorated as Block for variable in StorageBuffer "
3473 "storage class must follow standard storage buffer layout "
3474 "rules: member 1 at offset 4 is not aligned to 16"));
3475 }
3476
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset0Bad)3477 TEST_F(ValidateDecorations,
3478 BlockStandardUniformBufferLayoutIncorrectOffset0Bad) {
3479 std::string spirv = R"(
3480 OpCapability Shader
3481 %1 = OpExtInstImport "GLSL.std.450"
3482 OpMemoryModel Logical GLSL450
3483 OpEntryPoint GLCompute %main "main"
3484 OpExecutionMode %main LocalSize 1 1 1
3485 OpSource GLSL 430
3486 OpMemberDecorate %F 0 Offset 0
3487 OpMemberDecorate %F 1 Offset 8
3488 OpDecorate %_arr_float_uint_2 ArrayStride 16
3489 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3490 OpMemberDecorate %O 0 Offset 0
3491 OpMemberDecorate %O 1 Offset 16
3492 OpMemberDecorate %O 2 Offset 24
3493 OpMemberDecorate %O 3 Offset 33
3494 OpMemberDecorate %O 4 ColMajor
3495 OpMemberDecorate %O 4 Offset 80
3496 OpMemberDecorate %O 4 MatrixStride 16
3497 OpDecorate %_arr_O_uint_2 ArrayStride 176
3498 OpMemberDecorate %Output 0 Offset 0
3499 OpMemberDecorate %Output 1 Offset 8
3500 OpMemberDecorate %Output 2 Offset 16
3501 OpMemberDecorate %Output 3 Offset 32
3502 OpMemberDecorate %Output 4 Offset 48
3503 OpMemberDecorate %Output 5 Offset 64
3504 OpMemberDecorate %Output 6 ColMajor
3505 OpMemberDecorate %Output 6 Offset 96
3506 OpMemberDecorate %Output 6 MatrixStride 16
3507 OpMemberDecorate %Output 7 Offset 128
3508 OpDecorate %Output Block
3509 %void = OpTypeVoid
3510 %3 = OpTypeFunction %void
3511 %float = OpTypeFloat 32
3512 %v2float = OpTypeVector %float 2
3513 %v3float = OpTypeVector %float 3
3514 %int = OpTypeInt 32 1
3515 %uint = OpTypeInt 32 0
3516 %v2uint = OpTypeVector %uint 2
3517 %F = OpTypeStruct %int %v2uint
3518 %uint_2 = OpConstant %uint 2
3519 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3520 %mat2v3float = OpTypeMatrix %v3float 2
3521 %v3uint = OpTypeVector %uint 3
3522 %mat3v3float = OpTypeMatrix %v3float 3
3523 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3524 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3525 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3526 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3527 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3528 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3529 %main = OpFunction %void None %3
3530 %5 = OpLabel
3531 OpReturn
3532 OpFunctionEnd
3533 )";
3534
3535 CompileSuccessfully(spirv);
3536 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3537 EXPECT_THAT(
3538 getDiagnosticString(),
3539 HasSubstr("Structure id 6 decorated as Block for variable in Uniform "
3540 "storage class must follow standard uniform buffer layout "
3541 "rules: member 2 at offset 152 is not aligned to 16"));
3542 }
3543
TEST_F(ValidateDecorations,BlockStandardUniformBufferLayoutIncorrectOffset1Bad)3544 TEST_F(ValidateDecorations,
3545 BlockStandardUniformBufferLayoutIncorrectOffset1Bad) {
3546 std::string spirv = R"(
3547 OpCapability Shader
3548 %1 = OpExtInstImport "GLSL.std.450"
3549 OpMemoryModel Logical GLSL450
3550 OpEntryPoint GLCompute %main "main"
3551 OpExecutionMode %main LocalSize 1 1 1
3552 OpSource GLSL 430
3553 OpMemberDecorate %F 0 Offset 0
3554 OpMemberDecorate %F 1 Offset 8
3555 OpDecorate %_arr_float_uint_2 ArrayStride 16
3556 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 48
3557 OpMemberDecorate %O 0 Offset 0
3558 OpMemberDecorate %O 1 Offset 16
3559 OpMemberDecorate %O 2 Offset 32
3560 OpMemberDecorate %O 3 Offset 64
3561 OpMemberDecorate %O 4 ColMajor
3562 OpMemberDecorate %O 4 Offset 80
3563 OpMemberDecorate %O 4 MatrixStride 16
3564 OpDecorate %_arr_O_uint_2 ArrayStride 176
3565 OpMemberDecorate %Output 0 Offset 0
3566 OpMemberDecorate %Output 1 Offset 8
3567 OpMemberDecorate %Output 2 Offset 16
3568 OpMemberDecorate %Output 3 Offset 32
3569 OpMemberDecorate %Output 4 Offset 48
3570 OpMemberDecorate %Output 5 Offset 71
3571 OpMemberDecorate %Output 6 ColMajor
3572 OpMemberDecorate %Output 6 Offset 96
3573 OpMemberDecorate %Output 6 MatrixStride 16
3574 OpMemberDecorate %Output 7 Offset 128
3575 OpDecorate %Output Block
3576 %void = OpTypeVoid
3577 %3 = OpTypeFunction %void
3578 %float = OpTypeFloat 32
3579 %v2float = OpTypeVector %float 2
3580 %v3float = OpTypeVector %float 3
3581 %int = OpTypeInt 32 1
3582 %uint = OpTypeInt 32 0
3583 %v2uint = OpTypeVector %uint 2
3584 %F = OpTypeStruct %int %v2uint
3585 %uint_2 = OpConstant %uint 2
3586 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3587 %mat2v3float = OpTypeMatrix %v3float 2
3588 %v3uint = OpTypeVector %uint 3
3589 %mat3v3float = OpTypeMatrix %v3float 3
3590 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3591 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3592 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3593 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3594 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3595 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3596 %main = OpFunction %void None %3
3597 %5 = OpLabel
3598 OpReturn
3599 OpFunctionEnd
3600 )";
3601
3602 CompileSuccessfully(spirv);
3603 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3604 EXPECT_THAT(
3605 getDiagnosticString(),
3606 HasSubstr("Structure id 8 decorated as Block for variable in Uniform "
3607 "storage class must follow standard uniform buffer layout "
3608 "rules: member 5 at offset 71 is not aligned to 16"));
3609 }
3610
TEST_F(ValidateDecorations,BlockUniformBufferLayoutIncorrectArrayStrideBad)3611 TEST_F(ValidateDecorations, BlockUniformBufferLayoutIncorrectArrayStrideBad) {
3612 std::string spirv = R"(
3613 OpCapability Shader
3614 %1 = OpExtInstImport "GLSL.std.450"
3615 OpMemoryModel Logical GLSL450
3616 OpEntryPoint GLCompute %main "main"
3617 OpExecutionMode %main LocalSize 1 1 1
3618 OpSource GLSL 430
3619 OpMemberDecorate %F 0 Offset 0
3620 OpMemberDecorate %F 1 Offset 8
3621 OpDecorate %_arr_float_uint_2 ArrayStride 16
3622 OpDecorate %_arr_mat3v3float_uint_2 ArrayStride 49
3623 OpMemberDecorate %O 0 Offset 0
3624 OpMemberDecorate %O 1 Offset 16
3625 OpMemberDecorate %O 2 Offset 32
3626 OpMemberDecorate %O 3 Offset 64
3627 OpMemberDecorate %O 4 ColMajor
3628 OpMemberDecorate %O 4 Offset 80
3629 OpMemberDecorate %O 4 MatrixStride 16
3630 OpDecorate %_arr_O_uint_2 ArrayStride 176
3631 OpMemberDecorate %Output 0 Offset 0
3632 OpMemberDecorate %Output 1 Offset 8
3633 OpMemberDecorate %Output 2 Offset 16
3634 OpMemberDecorate %Output 3 Offset 32
3635 OpMemberDecorate %Output 4 Offset 48
3636 OpMemberDecorate %Output 5 Offset 64
3637 OpMemberDecorate %Output 6 ColMajor
3638 OpMemberDecorate %Output 6 Offset 96
3639 OpMemberDecorate %Output 6 MatrixStride 16
3640 OpMemberDecorate %Output 7 Offset 128
3641 OpDecorate %Output Block
3642 %void = OpTypeVoid
3643 %3 = OpTypeFunction %void
3644 %float = OpTypeFloat 32
3645 %v2float = OpTypeVector %float 2
3646 %v3float = OpTypeVector %float 3
3647 %int = OpTypeInt 32 1
3648 %uint = OpTypeInt 32 0
3649 %v2uint = OpTypeVector %uint 2
3650 %F = OpTypeStruct %int %v2uint
3651 %uint_2 = OpConstant %uint 2
3652 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3653 %mat2v3float = OpTypeMatrix %v3float 2
3654 %v3uint = OpTypeVector %uint 3
3655 %mat3v3float = OpTypeMatrix %v3float 3
3656 %_arr_mat3v3float_uint_2 = OpTypeArray %mat3v3float %uint_2
3657 %O = OpTypeStruct %v3uint %v2float %_arr_float_uint_2 %v2float %_arr_mat3v3float_uint_2
3658 %_arr_O_uint_2 = OpTypeArray %O %uint_2
3659 %Output = OpTypeStruct %float %v2float %v3float %F %float %_arr_float_uint_2 %mat2v3float %_arr_O_uint_2
3660 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3661 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3662 %main = OpFunction %void None %3
3663 %5 = OpLabel
3664 OpReturn
3665 OpFunctionEnd
3666 )";
3667
3668 CompileSuccessfully(spirv);
3669 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3670 EXPECT_THAT(
3671 getDiagnosticString(),
3672 HasSubstr(
3673 "Structure id 6 decorated as Block for variable in Uniform storage "
3674 "class must follow standard uniform buffer layout rules: member 4 "
3675 "contains "
3676 "an array with stride 49 not satisfying alignment to 16"));
3677 }
3678
TEST_F(ValidateDecorations,BufferBlockStandardStorageBufferLayoutImproperStraddleBad)3679 TEST_F(ValidateDecorations,
3680 BufferBlockStandardStorageBufferLayoutImproperStraddleBad) {
3681 std::string spirv = R"(
3682 OpCapability Shader
3683 %1 = OpExtInstImport "GLSL.std.450"
3684 OpMemoryModel Logical GLSL450
3685 OpEntryPoint GLCompute %main "main"
3686 OpExecutionMode %main LocalSize 1 1 1
3687 OpSource GLSL 430
3688 OpMemberDecorate %Output 0 Offset 0
3689 OpMemberDecorate %Output 1 Offset 8
3690 OpDecorate %Output BufferBlock
3691 %void = OpTypeVoid
3692 %3 = OpTypeFunction %void
3693 %float = OpTypeFloat 32
3694 %v3float = OpTypeVector %float 3
3695 %Output = OpTypeStruct %float %v3float
3696 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3697 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3698 %main = OpFunction %void None %3
3699 %5 = OpLabel
3700 OpReturn
3701 OpFunctionEnd
3702 )";
3703
3704 CompileSuccessfully(spirv);
3705 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3706 EXPECT_THAT(
3707 getDiagnosticString(),
3708 HasSubstr("Structure id 3 decorated as BufferBlock for variable in "
3709 "Uniform storage class must follow standard storage buffer "
3710 "layout rules: member 1 at offset 8 is not aligned to 16"));
3711 }
3712
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideArrayPaddingBad)3713 TEST_F(ValidateDecorations,
3714 BlockUniformBufferLayoutOffsetInsideArrayPaddingBad) {
3715 // In this case the 2nd member fits entirely within the padding.
3716 std::string spirv = R"(
3717 OpCapability Shader
3718 %1 = OpExtInstImport "GLSL.std.450"
3719 OpMemoryModel Logical GLSL450
3720 OpEntryPoint GLCompute %main "main"
3721 OpExecutionMode %main LocalSize 1 1 1
3722 OpSource GLSL 430
3723 OpDecorate %_arr_float_uint_2 ArrayStride 16
3724 OpMemberDecorate %Output 0 Offset 0
3725 OpMemberDecorate %Output 1 Offset 20
3726 OpDecorate %Output Block
3727 %void = OpTypeVoid
3728 %3 = OpTypeFunction %void
3729 %float = OpTypeFloat 32
3730 %uint = OpTypeInt 32 0
3731 %v2uint = OpTypeVector %uint 2
3732 %uint_2 = OpConstant %uint 2
3733 %_arr_float_uint_2 = OpTypeArray %float %uint_2
3734 %Output = OpTypeStruct %_arr_float_uint_2 %float
3735 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3736 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3737 %main = OpFunction %void None %3
3738 %5 = OpLabel
3739 OpReturn
3740 OpFunctionEnd
3741 )";
3742
3743 CompileSuccessfully(spirv);
3744 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3745 EXPECT_THAT(
3746 getDiagnosticString(),
3747 HasSubstr(
3748 "Structure id 4 decorated as Block for variable in Uniform storage "
3749 "class must follow standard uniform buffer layout rules: member 1 at "
3750 "offset 20 overlaps previous member ending at offset 31"));
3751 }
3752
TEST_F(ValidateDecorations,BlockUniformBufferLayoutOffsetInsideStructPaddingBad)3753 TEST_F(ValidateDecorations,
3754 BlockUniformBufferLayoutOffsetInsideStructPaddingBad) {
3755 // In this case the 2nd member fits entirely within the padding.
3756 std::string spirv = R"(
3757 OpCapability Shader
3758 OpMemoryModel Logical GLSL450
3759 OpEntryPoint GLCompute %1 "main"
3760 OpMemberDecorate %_struct_6 0 Offset 0
3761 OpMemberDecorate %_struct_2 0 Offset 0
3762 OpMemberDecorate %_struct_2 1 Offset 4
3763 OpDecorate %_struct_2 Block
3764 %void = OpTypeVoid
3765 %4 = OpTypeFunction %void
3766 %float = OpTypeFloat 32
3767 %_struct_6 = OpTypeStruct %float
3768 %_struct_2 = OpTypeStruct %_struct_6 %float
3769 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
3770 %8 = OpVariable %_ptr_Uniform__struct_2 Uniform
3771 %1 = OpFunction %void None %4
3772 %9 = OpLabel
3773 OpReturn
3774 OpFunctionEnd
3775 )";
3776
3777 CompileSuccessfully(spirv);
3778 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3779 EXPECT_THAT(
3780 getDiagnosticString(),
3781 HasSubstr(
3782 "Structure id 3 decorated as Block for variable in Uniform storage "
3783 "class must follow standard uniform buffer layout rules: member 1 at "
3784 "offset 4 overlaps previous member ending at offset 15"));
3785 }
3786
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodUniversal1_0)3787 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodUniversal1_0) {
3788 std::string spirv = R"(
3789 OpCapability Shader
3790 %1 = OpExtInstImport "GLSL.std.450"
3791 OpMemoryModel Logical GLSL450
3792 OpEntryPoint GLCompute %main "main"
3793 OpExecutionMode %main LocalSize 1 1 1
3794 OpMemberDecorate %Outer 0 Offset 4
3795 OpMemberDecorate %Outer 1 Offset 0
3796 OpDecorate %Outer Block
3797 OpDecorate %O DescriptorSet 0
3798 OpDecorate %O Binding 0
3799 %void = OpTypeVoid
3800 %3 = OpTypeFunction %void
3801 %uint = OpTypeInt 32 0
3802 %Outer = OpTypeStruct %uint %uint
3803 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
3804 %O = OpVariable %_ptr_Uniform_Outer Uniform
3805 %main = OpFunction %void None %3
3806 %5 = OpLabel
3807 OpReturn
3808 OpFunctionEnd
3809 )";
3810
3811 CompileSuccessfully(spirv);
3812 EXPECT_EQ(SPV_SUCCESS,
3813 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_0));
3814 }
3815
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodOpenGL4_5)3816 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodOpenGL4_5) {
3817 std::string spirv = R"(
3818 OpCapability Shader
3819 %1 = OpExtInstImport "GLSL.std.450"
3820 OpMemoryModel Logical GLSL450
3821 OpEntryPoint GLCompute %main "main"
3822 OpExecutionMode %main LocalSize 1 1 1
3823 OpMemberDecorate %Outer 0 Offset 4
3824 OpMemberDecorate %Outer 1 Offset 0
3825 OpDecorate %Outer Block
3826 OpDecorate %O DescriptorSet 0
3827 OpDecorate %O Binding 0
3828 %void = OpTypeVoid
3829 %3 = OpTypeFunction %void
3830 %uint = OpTypeInt 32 0
3831 %Outer = OpTypeStruct %uint %uint
3832 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
3833 %O = OpVariable %_ptr_Uniform_Outer Uniform
3834 %main = OpFunction %void None %3
3835 %5 = OpLabel
3836 OpReturn
3837 OpFunctionEnd
3838 )";
3839
3840 CompileSuccessfully(spirv);
3841 EXPECT_EQ(SPV_SUCCESS,
3842 ValidateAndRetrieveValidationState(SPV_ENV_OPENGL_4_5));
3843 }
3844
TEST_F(ValidateDecorations,BlockLayoutOffsetOutOfOrderGoodVulkan1_1)3845 TEST_F(ValidateDecorations, BlockLayoutOffsetOutOfOrderGoodVulkan1_1) {
3846 std::string spirv = R"(
3847 OpCapability Shader
3848 %1 = OpExtInstImport "GLSL.std.450"
3849 OpMemoryModel Logical GLSL450
3850 OpEntryPoint GLCompute %main "main"
3851 OpExecutionMode %main LocalSize 1 1 1
3852 OpMemberDecorate %Outer 0 Offset 4
3853 OpMemberDecorate %Outer 1 Offset 0
3854 OpDecorate %Outer Block
3855 OpDecorate %O DescriptorSet 0
3856 OpDecorate %O Binding 0
3857 %void = OpTypeVoid
3858 %3 = OpTypeFunction %void
3859 %uint = OpTypeInt 32 0
3860 %Outer = OpTypeStruct %uint %uint
3861 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
3862 %O = OpVariable %_ptr_Uniform_Outer Uniform
3863 %main = OpFunction %void None %3
3864 %5 = OpLabel
3865 OpReturn
3866 OpFunctionEnd
3867 )";
3868
3869 CompileSuccessfully(spirv);
3870 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1))
3871 << getDiagnosticString();
3872 EXPECT_THAT(getDiagnosticString(), Eq(""));
3873 }
3874
TEST_F(ValidateDecorations,BlockLayoutOffsetOverlapBad)3875 TEST_F(ValidateDecorations, BlockLayoutOffsetOverlapBad) {
3876 std::string spirv = R"(
3877 OpCapability Shader
3878 %1 = OpExtInstImport "GLSL.std.450"
3879 OpMemoryModel Logical GLSL450
3880 OpEntryPoint GLCompute %main "main"
3881 OpExecutionMode %main LocalSize 1 1 1
3882 OpMemberDecorate %Outer 0 Offset 0
3883 OpMemberDecorate %Outer 1 Offset 16
3884 OpMemberDecorate %Inner 0 Offset 0
3885 OpMemberDecorate %Inner 1 Offset 16
3886 OpDecorate %Outer Block
3887 OpDecorate %O DescriptorSet 0
3888 OpDecorate %O Binding 0
3889 %void = OpTypeVoid
3890 %3 = OpTypeFunction %void
3891 %uint = OpTypeInt 32 0
3892 %Inner = OpTypeStruct %uint %uint
3893 %Outer = OpTypeStruct %Inner %uint
3894 %_ptr_Uniform_Outer = OpTypePointer Uniform %Outer
3895 %O = OpVariable %_ptr_Uniform_Outer Uniform
3896 %main = OpFunction %void None %3
3897 %5 = OpLabel
3898 OpReturn
3899 OpFunctionEnd
3900 )";
3901
3902 CompileSuccessfully(spirv);
3903 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
3904 EXPECT_THAT(
3905 getDiagnosticString(),
3906 HasSubstr(
3907 "Structure id 3 decorated as Block for variable in Uniform storage "
3908 "class must follow standard uniform buffer layout rules: member 1 at "
3909 "offset 16 overlaps previous member ending at offset 31"));
3910 }
3911
TEST_F(ValidateDecorations,BufferBlockEmptyStruct)3912 TEST_F(ValidateDecorations, BufferBlockEmptyStruct) {
3913 std::string spirv = R"(
3914 OpCapability Shader
3915 %1 = OpExtInstImport "GLSL.std.450"
3916 OpMemoryModel Logical GLSL450
3917 OpEntryPoint GLCompute %main "main"
3918 OpExecutionMode %main LocalSize 1 1 1
3919 OpSource GLSL 430
3920 OpMemberDecorate %Output 0 Offset 0
3921 OpDecorate %Output BufferBlock
3922 %void = OpTypeVoid
3923 %3 = OpTypeFunction %void
3924 %S = OpTypeStruct
3925 %Output = OpTypeStruct %S
3926 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
3927 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
3928 %main = OpFunction %void None %3
3929 %5 = OpLabel
3930 OpReturn
3931 OpFunctionEnd
3932 )";
3933
3934 CompileSuccessfully(spirv);
3935 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
3936 }
3937
TEST_F(ValidateDecorations,RowMajorMatrixTightPackingGood)3938 TEST_F(ValidateDecorations, RowMajorMatrixTightPackingGood) {
3939 // Row major matrix rule:
3940 // A row-major matrix of C columns has a base alignment equal to
3941 // the base alignment of a vector of C matrix components.
3942 // Note: The "matrix component" is the scalar element type.
3943
3944 // The matrix has 3 columns and 2 rows (C=3, R=2).
3945 // So the base alignment of b is the same as a vector of 3 floats, which is 16
3946 // bytes. The matrix consists of two of these, and therefore occupies 2 x 16
3947 // bytes, or 32 bytes.
3948 //
3949 // So the offsets can be:
3950 // a -> 0
3951 // b -> 16
3952 // c -> 48
3953 // d -> 60 ; d fits at bytes 12-15 after offset of c. Tight (vec3;float)
3954 // packing
3955
3956 std::string spirv = R"(
3957 OpCapability Shader
3958 OpMemoryModel Logical GLSL450
3959 OpEntryPoint Vertex %1 "main"
3960 OpSource GLSL 450
3961 OpMemberDecorate %_struct_2 0 Offset 0
3962 OpMemberDecorate %_struct_2 1 RowMajor
3963 OpMemberDecorate %_struct_2 1 Offset 16
3964 OpMemberDecorate %_struct_2 1 MatrixStride 16
3965 OpMemberDecorate %_struct_2 2 Offset 48
3966 OpMemberDecorate %_struct_2 3 Offset 60
3967 OpDecorate %_struct_2 Block
3968 OpDecorate %3 DescriptorSet 0
3969 OpDecorate %3 Binding 0
3970 %void = OpTypeVoid
3971 %5 = OpTypeFunction %void
3972 %float = OpTypeFloat 32
3973 %v4float = OpTypeVector %float 4
3974 %v2float = OpTypeVector %float 2
3975 %mat3v2float = OpTypeMatrix %v2float 3
3976 %v3float = OpTypeVector %float 3
3977 %_struct_2 = OpTypeStruct %v4float %mat3v2float %v3float %float
3978 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
3979 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
3980 %1 = OpFunction %void None %5
3981 %12 = OpLabel
3982 OpReturn
3983 OpFunctionEnd
3984 )";
3985
3986 CompileSuccessfully(spirv);
3987 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
3988 << getDiagnosticString();
3989 }
3990
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixTightPackingGood)3991 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixTightPackingGood) {
3992 // Like the previous case, but we have an array of arrays of matrices.
3993 // The RowMajor decoration goes on the struct member (surprisingly).
3994
3995 std::string spirv = R"(
3996 OpCapability Shader
3997 OpMemoryModel Logical GLSL450
3998 OpEntryPoint Vertex %1 "main"
3999 OpSource GLSL 450
4000 OpMemberDecorate %_struct_2 0 Offset 0
4001 OpMemberDecorate %_struct_2 1 RowMajor
4002 OpMemberDecorate %_struct_2 1 Offset 16
4003 OpMemberDecorate %_struct_2 1 MatrixStride 16
4004 OpMemberDecorate %_struct_2 2 Offset 80
4005 OpMemberDecorate %_struct_2 3 Offset 92
4006 OpDecorate %arr_mat ArrayStride 32
4007 OpDecorate %arr_arr_mat ArrayStride 32
4008 OpDecorate %_struct_2 Block
4009 OpDecorate %3 DescriptorSet 0
4010 OpDecorate %3 Binding 0
4011 %void = OpTypeVoid
4012 %5 = OpTypeFunction %void
4013 %float = OpTypeFloat 32
4014 %v4float = OpTypeVector %float 4
4015 %v2float = OpTypeVector %float 2
4016 %mat3v2float = OpTypeMatrix %v2float 3
4017 %uint = OpTypeInt 32 0
4018 %uint_1 = OpConstant %uint 1
4019 %uint_2 = OpConstant %uint 2
4020 %arr_mat = OpTypeArray %mat3v2float %uint_1
4021 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4022 %v3float = OpTypeVector %float 3
4023 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4024 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4025 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4026 %1 = OpFunction %void None %5
4027 %12 = OpLabel
4028 OpReturn
4029 OpFunctionEnd
4030 )";
4031
4032 CompileSuccessfully(spirv);
4033 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState())
4034 << getDiagnosticString();
4035 }
4036
TEST_F(ValidateDecorations,ArrayArrayRowMajorMatrixNextMemberOverlapsBad)4037 TEST_F(ValidateDecorations, ArrayArrayRowMajorMatrixNextMemberOverlapsBad) {
4038 // Like the previous case, but the offset of member 2 overlaps the matrix.
4039 std::string spirv = R"(
4040 OpCapability Shader
4041 OpMemoryModel Logical GLSL450
4042 OpEntryPoint Vertex %1 "main"
4043 OpSource GLSL 450
4044 OpMemberDecorate %_struct_2 0 Offset 0
4045 OpMemberDecorate %_struct_2 1 RowMajor
4046 OpMemberDecorate %_struct_2 1 Offset 16
4047 OpMemberDecorate %_struct_2 1 MatrixStride 16
4048 OpMemberDecorate %_struct_2 2 Offset 64
4049 OpMemberDecorate %_struct_2 3 Offset 92
4050 OpDecorate %arr_mat ArrayStride 32
4051 OpDecorate %arr_arr_mat ArrayStride 32
4052 OpDecorate %_struct_2 Block
4053 OpDecorate %3 DescriptorSet 0
4054 OpDecorate %3 Binding 0
4055 %void = OpTypeVoid
4056 %5 = OpTypeFunction %void
4057 %float = OpTypeFloat 32
4058 %v4float = OpTypeVector %float 4
4059 %v2float = OpTypeVector %float 2
4060 %mat3v2float = OpTypeMatrix %v2float 3
4061 %uint = OpTypeInt 32 0
4062 %uint_1 = OpConstant %uint 1
4063 %uint_2 = OpConstant %uint 2
4064 %arr_mat = OpTypeArray %mat3v2float %uint_1
4065 %arr_arr_mat = OpTypeArray %arr_mat %uint_2
4066 %v3float = OpTypeVector %float 3
4067 %_struct_2 = OpTypeStruct %v4float %arr_arr_mat %v3float %float
4068 %_ptr_Uniform__struct_2 = OpTypePointer Uniform %_struct_2
4069 %3 = OpVariable %_ptr_Uniform__struct_2 Uniform
4070 %1 = OpFunction %void None %5
4071 %12 = OpLabel
4072 OpReturn
4073 OpFunctionEnd
4074 )";
4075
4076 CompileSuccessfully(spirv);
4077 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4078 EXPECT_THAT(
4079 getDiagnosticString(),
4080 HasSubstr(
4081 "Structure id 2 decorated as Block for variable in Uniform storage "
4082 "class must follow standard uniform buffer layout rules: member 2 at "
4083 "offset 64 overlaps previous member ending at offset 79"));
4084 }
4085
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackGood)4086 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackGood) {
4087 // Original GLSL
4088
4089 // #version 450
4090 // layout (set=0,binding=0) buffer S {
4091 // uvec3 arr[2][2]; // first 3 elements are 16 bytes, last is 12
4092 // uint i; // Can have offset 60 = 3x16 + 12
4093 // } B;
4094 // void main() {}
4095
4096 std::string spirv = R"(
4097 OpCapability Shader
4098 OpMemoryModel Logical GLSL450
4099 OpEntryPoint Vertex %1 "main"
4100 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4101 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4102 OpMemberDecorate %_struct_4 0 Offset 0
4103 OpMemberDecorate %_struct_4 1 Offset 60
4104 OpDecorate %_struct_4 BufferBlock
4105 OpDecorate %5 DescriptorSet 0
4106 OpDecorate %5 Binding 0
4107 %void = OpTypeVoid
4108 %7 = OpTypeFunction %void
4109 %uint = OpTypeInt 32 0
4110 %v3uint = OpTypeVector %uint 3
4111 %uint_2 = OpConstant %uint 2
4112 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4113 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4114 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4115 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4116 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4117 %1 = OpFunction %void None %7
4118 %12 = OpLabel
4119 OpReturn
4120 OpFunctionEnd
4121 )";
4122
4123 CompileSuccessfully(spirv);
4124 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4125 }
4126
TEST_F(ValidateDecorations,StorageBufferArraySizeCalculationPackBad)4127 TEST_F(ValidateDecorations, StorageBufferArraySizeCalculationPackBad) {
4128 // Like previous but, the offset of the second member is too small.
4129
4130 std::string spirv = R"(
4131 OpCapability Shader
4132 OpMemoryModel Logical GLSL450
4133 OpEntryPoint Vertex %1 "main"
4134 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4135 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4136 OpMemberDecorate %_struct_4 0 Offset 0
4137 OpMemberDecorate %_struct_4 1 Offset 56
4138 OpDecorate %_struct_4 BufferBlock
4139 OpDecorate %5 DescriptorSet 0
4140 OpDecorate %5 Binding 0
4141 %void = OpTypeVoid
4142 %7 = OpTypeFunction %void
4143 %uint = OpTypeInt 32 0
4144 %v3uint = OpTypeVector %uint 3
4145 %uint_2 = OpConstant %uint 2
4146 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4147 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4148 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4149 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4150 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4151 %1 = OpFunction %void None %7
4152 %12 = OpLabel
4153 OpReturn
4154 OpFunctionEnd
4155 )";
4156
4157 CompileSuccessfully(spirv);
4158 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4159 EXPECT_THAT(getDiagnosticString(),
4160 HasSubstr("Structure id 4 decorated as BufferBlock for variable "
4161 "in Uniform storage class must follow standard storage "
4162 "buffer layout rules: member 1 at offset 56 overlaps "
4163 "previous member ending at offset 59"));
4164 }
4165
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackGood)4166 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackGood) {
4167 // Like the corresponding buffer block case, but the array padding must
4168 // count for the last element as well, and so the offset of the second
4169 // member must be at least 64.
4170 std::string spirv = R"(
4171 OpCapability Shader
4172 OpMemoryModel Logical GLSL450
4173 OpEntryPoint Vertex %1 "main"
4174 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4175 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4176 OpMemberDecorate %_struct_4 0 Offset 0
4177 OpMemberDecorate %_struct_4 1 Offset 64
4178 OpDecorate %_struct_4 Block
4179 OpDecorate %5 DescriptorSet 0
4180 OpDecorate %5 Binding 0
4181 %void = OpTypeVoid
4182 %7 = OpTypeFunction %void
4183 %uint = OpTypeInt 32 0
4184 %v3uint = OpTypeVector %uint 3
4185 %uint_2 = OpConstant %uint 2
4186 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4187 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4188 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4189 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4190 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4191 %1 = OpFunction %void None %7
4192 %12 = OpLabel
4193 OpReturn
4194 OpFunctionEnd
4195 )";
4196
4197 CompileSuccessfully(spirv);
4198 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4199 }
4200
TEST_F(ValidateDecorations,UniformBufferArraySizeCalculationPackBad)4201 TEST_F(ValidateDecorations, UniformBufferArraySizeCalculationPackBad) {
4202 // Like previous but, the offset of the second member is too small.
4203
4204 std::string spirv = R"(
4205 OpCapability Shader
4206 OpMemoryModel Logical GLSL450
4207 OpEntryPoint Vertex %1 "main"
4208 OpDecorate %_arr_v3uint_uint_2 ArrayStride 16
4209 OpDecorate %_arr__arr_v3uint_uint_2_uint_2 ArrayStride 32
4210 OpMemberDecorate %_struct_4 0 Offset 0
4211 OpMemberDecorate %_struct_4 1 Offset 60
4212 OpDecorate %_struct_4 Block
4213 OpDecorate %5 DescriptorSet 0
4214 OpDecorate %5 Binding 0
4215 %void = OpTypeVoid
4216 %7 = OpTypeFunction %void
4217 %uint = OpTypeInt 32 0
4218 %v3uint = OpTypeVector %uint 3
4219 %uint_2 = OpConstant %uint 2
4220 %_arr_v3uint_uint_2 = OpTypeArray %v3uint %uint_2
4221 %_arr__arr_v3uint_uint_2_uint_2 = OpTypeArray %_arr_v3uint_uint_2 %uint_2
4222 %_struct_4 = OpTypeStruct %_arr__arr_v3uint_uint_2_uint_2 %uint
4223 %_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
4224 %5 = OpVariable %_ptr_Uniform__struct_4 Uniform
4225 %1 = OpFunction %void None %7
4226 %12 = OpLabel
4227 OpReturn
4228 OpFunctionEnd
4229 )";
4230
4231 CompileSuccessfully(spirv);
4232 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4233 EXPECT_THAT(
4234 getDiagnosticString(),
4235 HasSubstr(
4236 "Structure id 4 decorated as Block for variable in Uniform storage "
4237 "class must follow standard uniform buffer layout rules: member 1 at "
4238 "offset 60 overlaps previous member ending at offset 63"));
4239 }
4240
TEST_F(ValidateDecorations,LayoutNotCheckedWhenSkipBlockLayout)4241 TEST_F(ValidateDecorations, LayoutNotCheckedWhenSkipBlockLayout) {
4242 // Checks that block layout is not verified in skipping block layout mode.
4243 // Even for obviously wrong layout.
4244 std::string spirv = R"(
4245 OpCapability Shader
4246 OpMemoryModel Logical GLSL450
4247 OpEntryPoint Vertex %main "main"
4248 OpSource GLSL 450
4249 OpMemberDecorate %S 0 Offset 3 ; wrong alignment
4250 OpMemberDecorate %S 1 Offset 3 ; same offset as before!
4251 OpDecorate %S Block
4252 OpDecorate %B DescriptorSet 0
4253 OpDecorate %B Binding 0
4254 %void = OpTypeVoid
4255 %3 = OpTypeFunction %void
4256 %float = OpTypeFloat 32
4257 %v3float = OpTypeVector %float 3
4258 %S = OpTypeStruct %float %v3float
4259 %_ptr_Uniform_S = OpTypePointer Uniform %S
4260 %B = OpVariable %_ptr_Uniform_S Uniform
4261 %main = OpFunction %void None %3
4262 %5 = OpLabel
4263 OpReturn
4264 OpFunctionEnd
4265 )";
4266
4267 CompileSuccessfully(spirv);
4268 spvValidatorOptionsSetSkipBlockLayout(getValidatorOptions(), true);
4269 EXPECT_EQ(SPV_SUCCESS,
4270 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_0));
4271 EXPECT_THAT(getDiagnosticString(), Eq(""));
4272 }
4273
TEST_F(ValidateDecorations,EntryPointVariableWrongStorageClass)4274 TEST_F(ValidateDecorations, EntryPointVariableWrongStorageClass) {
4275 const std::string spirv = R"(
4276 OpCapability Shader
4277 OpMemoryModel Logical GLSL450
4278 OpEntryPoint Fragment %1 "func" %var
4279 OpExecutionMode %1 OriginUpperLeft
4280 %void = OpTypeVoid
4281 %int = OpTypeInt 32 0
4282 %ptr_int_Workgroup = OpTypePointer Workgroup %int
4283 %var = OpVariable %ptr_int_Workgroup Workgroup
4284 %func_ty = OpTypeFunction %void
4285 %1 = OpFunction %void None %func_ty
4286 %2 = OpLabel
4287 OpReturn
4288 OpFunctionEnd
4289 )";
4290
4291 CompileSuccessfully(spirv);
4292 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4293 EXPECT_THAT(getDiagnosticString(),
4294 HasSubstr("OpEntryPoint interfaces must be OpVariables with "
4295 "Storage Class of Input(1) or Output(3). Found Storage "
4296 "Class 4 for Entry Point id 1."));
4297 }
4298
TEST_F(ValidateDecorations,VulkanMemoryModelNonCoherent)4299 TEST_F(ValidateDecorations, VulkanMemoryModelNonCoherent) {
4300 const std::string spirv = R"(
4301 OpCapability Shader
4302 OpCapability VulkanMemoryModelKHR
4303 OpCapability Linkage
4304 OpExtension "SPV_KHR_vulkan_memory_model"
4305 OpExtension "SPV_KHR_storage_buffer_storage_class"
4306 OpMemoryModel Logical VulkanKHR
4307 OpDecorate %1 Coherent
4308 %2 = OpTypeInt 32 0
4309 %3 = OpTypePointer StorageBuffer %2
4310 %1 = OpVariable %3 StorageBuffer
4311 )";
4312
4313 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4314 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4315 EXPECT_THAT(getDiagnosticString(),
4316 HasSubstr("Coherent decoration targeting 1[%1] is "
4317 "banned when using the Vulkan memory model."));
4318 }
4319
TEST_F(ValidateDecorations,VulkanMemoryModelNoCoherentMember)4320 TEST_F(ValidateDecorations, VulkanMemoryModelNoCoherentMember) {
4321 const std::string spirv = R"(
4322 OpCapability Shader
4323 OpCapability VulkanMemoryModelKHR
4324 OpCapability Linkage
4325 OpExtension "SPV_KHR_vulkan_memory_model"
4326 OpMemoryModel Logical VulkanKHR
4327 OpMemberDecorate %1 0 Coherent
4328 %2 = OpTypeInt 32 0
4329 %1 = OpTypeStruct %2 %2
4330 )";
4331
4332 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4333 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4334 EXPECT_THAT(
4335 getDiagnosticString(),
4336 HasSubstr("Coherent decoration targeting 1[%_struct_1] (member index 0) "
4337 "is banned when using the Vulkan memory model."));
4338 }
4339
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatile)4340 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatile) {
4341 const std::string spirv = R"(
4342 OpCapability Shader
4343 OpCapability VulkanMemoryModelKHR
4344 OpCapability Linkage
4345 OpExtension "SPV_KHR_vulkan_memory_model"
4346 OpExtension "SPV_KHR_storage_buffer_storage_class"
4347 OpMemoryModel Logical VulkanKHR
4348 OpDecorate %1 Volatile
4349 %2 = OpTypeInt 32 0
4350 %3 = OpTypePointer StorageBuffer %2
4351 %1 = OpVariable %3 StorageBuffer
4352 )";
4353
4354 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4355 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4356 EXPECT_THAT(getDiagnosticString(),
4357 HasSubstr("Volatile decoration targeting 1[%1] is banned when "
4358 "using the Vulkan memory model."));
4359 }
4360
TEST_F(ValidateDecorations,VulkanMemoryModelNoVolatileMember)4361 TEST_F(ValidateDecorations, VulkanMemoryModelNoVolatileMember) {
4362 const std::string spirv = R"(
4363 OpCapability Shader
4364 OpCapability VulkanMemoryModelKHR
4365 OpCapability Linkage
4366 OpExtension "SPV_KHR_vulkan_memory_model"
4367 OpMemoryModel Logical VulkanKHR
4368 OpMemberDecorate %1 1 Volatile
4369 %2 = OpTypeInt 32 0
4370 %1 = OpTypeStruct %2 %2
4371 )";
4372
4373 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4374 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4375 EXPECT_THAT(getDiagnosticString(),
4376 HasSubstr("Volatile decoration targeting 1[%_struct_1] (member "
4377 "index 1) is banned when using the Vulkan memory "
4378 "model."));
4379 }
4380
TEST_F(ValidateDecorations,FPRoundingModeGood)4381 TEST_F(ValidateDecorations, FPRoundingModeGood) {
4382 std::string spirv = R"(
4383 OpCapability Shader
4384 OpCapability Linkage
4385 OpCapability StorageBuffer16BitAccess
4386 OpExtension "SPV_KHR_storage_buffer_storage_class"
4387 OpExtension "SPV_KHR_variable_pointers"
4388 OpExtension "SPV_KHR_16bit_storage"
4389 OpMemoryModel Logical GLSL450
4390 OpEntryPoint GLCompute %main "main"
4391 OpDecorate %_ FPRoundingMode RTE
4392 %half = OpTypeFloat 16
4393 %float = OpTypeFloat 32
4394 %float_1_25 = OpConstant %float 1.25
4395 %half_ptr = OpTypePointer StorageBuffer %half
4396 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4397 %void = OpTypeVoid
4398 %func = OpTypeFunction %void
4399 %main = OpFunction %void None %func
4400 %main_entry = OpLabel
4401 %_ = OpFConvert %half %float_1_25
4402 OpStore %half_ptr_var %_
4403 OpReturn
4404 OpFunctionEnd
4405 )";
4406
4407 CompileSuccessfully(spirv);
4408 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4409 }
4410
TEST_F(ValidateDecorations,FPRoundingModeVectorGood)4411 TEST_F(ValidateDecorations, FPRoundingModeVectorGood) {
4412 std::string spirv = R"(
4413 OpCapability Shader
4414 OpCapability Linkage
4415 OpCapability StorageBuffer16BitAccess
4416 OpExtension "SPV_KHR_storage_buffer_storage_class"
4417 OpExtension "SPV_KHR_variable_pointers"
4418 OpExtension "SPV_KHR_16bit_storage"
4419 OpMemoryModel Logical GLSL450
4420 OpEntryPoint GLCompute %main "main"
4421 OpDecorate %_ FPRoundingMode RTE
4422 %half = OpTypeFloat 16
4423 %float = OpTypeFloat 32
4424 %v2half = OpTypeVector %half 2
4425 %v2float = OpTypeVector %float 2
4426 %float_1_25 = OpConstant %float 1.25
4427 %floats = OpConstantComposite %v2float %float_1_25 %float_1_25
4428 %halfs_ptr = OpTypePointer StorageBuffer %v2half
4429 %halfs_ptr_var = OpVariable %halfs_ptr StorageBuffer
4430 %void = OpTypeVoid
4431 %func = OpTypeFunction %void
4432 %main = OpFunction %void None %func
4433 %main_entry = OpLabel
4434 %_ = OpFConvert %v2half %floats
4435 OpStore %halfs_ptr_var %_
4436 OpReturn
4437 OpFunctionEnd
4438 )";
4439
4440 CompileSuccessfully(spirv);
4441 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4442 }
4443
TEST_F(ValidateDecorations,FPRoundingModeNotOpFConvert)4444 TEST_F(ValidateDecorations, FPRoundingModeNotOpFConvert) {
4445 std::string spirv = R"(
4446 OpCapability Shader
4447 OpCapability Linkage
4448 OpCapability StorageBuffer16BitAccess
4449 OpExtension "SPV_KHR_storage_buffer_storage_class"
4450 OpExtension "SPV_KHR_variable_pointers"
4451 OpExtension "SPV_KHR_16bit_storage"
4452 OpMemoryModel Logical GLSL450
4453 OpEntryPoint GLCompute %main "main"
4454 OpDecorate %_ FPRoundingMode RTE
4455 %short = OpTypeInt 16 1
4456 %int = OpTypeInt 32 1
4457 %int_17 = OpConstant %int 17
4458 %short_ptr = OpTypePointer StorageBuffer %short
4459 %short_ptr_var = OpVariable %short_ptr StorageBuffer
4460 %void = OpTypeVoid
4461 %func = OpTypeFunction %void
4462 %main = OpFunction %void None %func
4463 %main_entry = OpLabel
4464 %_ = OpSConvert %short %int_17
4465 OpStore %short_ptr_var %_
4466 OpReturn
4467 OpFunctionEnd
4468 )";
4469
4470 CompileSuccessfully(spirv);
4471 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4472 EXPECT_THAT(getDiagnosticString(),
4473 HasSubstr("FPRoundingMode decoration can be applied only to a "
4474 "width-only conversion instruction for floating-point "
4475 "object."));
4476 }
4477
TEST_F(ValidateDecorations,FPRoundingModeNoOpStoreGood)4478 TEST_F(ValidateDecorations, FPRoundingModeNoOpStoreGood) {
4479 std::string spirv = R"(
4480 OpCapability Shader
4481 OpCapability Linkage
4482 OpCapability StorageBuffer16BitAccess
4483 OpExtension "SPV_KHR_storage_buffer_storage_class"
4484 OpExtension "SPV_KHR_variable_pointers"
4485 OpExtension "SPV_KHR_16bit_storage"
4486 OpMemoryModel Logical GLSL450
4487 OpEntryPoint GLCompute %main "main"
4488 OpDecorate %_ FPRoundingMode RTE
4489 %half = OpTypeFloat 16
4490 %float = OpTypeFloat 32
4491 %float_1_25 = OpConstant %float 1.25
4492 %half_ptr = OpTypePointer StorageBuffer %half
4493 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4494 %void = OpTypeVoid
4495 %func = OpTypeFunction %void
4496 %main = OpFunction %void None %func
4497 %main_entry = OpLabel
4498 %_ = OpFConvert %half %float_1_25
4499 OpReturn
4500 OpFunctionEnd
4501 )";
4502
4503 CompileSuccessfully(spirv);
4504 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4505 }
4506
TEST_F(ValidateDecorations,FPRoundingModeFConvert64to16Good)4507 TEST_F(ValidateDecorations, FPRoundingModeFConvert64to16Good) {
4508 std::string spirv = R"(
4509 OpCapability Shader
4510 OpCapability Linkage
4511 OpCapability StorageBuffer16BitAccess
4512 OpCapability Float64
4513 OpExtension "SPV_KHR_storage_buffer_storage_class"
4514 OpExtension "SPV_KHR_variable_pointers"
4515 OpExtension "SPV_KHR_16bit_storage"
4516 OpMemoryModel Logical GLSL450
4517 OpEntryPoint GLCompute %main "main"
4518 OpDecorate %_ FPRoundingMode RTE
4519 %half = OpTypeFloat 16
4520 %double = OpTypeFloat 64
4521 %double_1_25 = OpConstant %double 1.25
4522 %half_ptr = OpTypePointer StorageBuffer %half
4523 %half_ptr_var = OpVariable %half_ptr StorageBuffer
4524 %void = OpTypeVoid
4525 %func = OpTypeFunction %void
4526 %main = OpFunction %void None %func
4527 %main_entry = OpLabel
4528 %_ = OpFConvert %half %double_1_25
4529 OpStore %half_ptr_var %_
4530 OpReturn
4531 OpFunctionEnd
4532 )";
4533
4534 CompileSuccessfully(spirv);
4535 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4536 }
4537
TEST_F(ValidateDecorations,FPRoundingModeNotStoreInFloat16)4538 TEST_F(ValidateDecorations, FPRoundingModeNotStoreInFloat16) {
4539 std::string spirv = R"(
4540 OpCapability Shader
4541 OpCapability Linkage
4542 OpCapability StorageBuffer16BitAccess
4543 OpCapability Float64
4544 OpExtension "SPV_KHR_storage_buffer_storage_class"
4545 OpExtension "SPV_KHR_variable_pointers"
4546 OpExtension "SPV_KHR_16bit_storage"
4547 OpMemoryModel Logical GLSL450
4548 OpEntryPoint GLCompute %main "main"
4549 OpDecorate %_ FPRoundingMode RTE
4550 %float = OpTypeFloat 32
4551 %double = OpTypeFloat 64
4552 %double_1_25 = OpConstant %double 1.25
4553 %float_ptr = OpTypePointer StorageBuffer %float
4554 %float_ptr_var = OpVariable %float_ptr StorageBuffer
4555 %void = OpTypeVoid
4556 %func = OpTypeFunction %void
4557 %main = OpFunction %void None %func
4558 %main_entry = OpLabel
4559 %_ = OpFConvert %float %double_1_25
4560 OpStore %float_ptr_var %_
4561 OpReturn
4562 OpFunctionEnd
4563 )";
4564
4565 CompileSuccessfully(spirv);
4566 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4567 EXPECT_THAT(
4568 getDiagnosticString(),
4569 HasSubstr("FPRoundingMode decoration can be applied only to the "
4570 "Object operand of an OpStore storing through a "
4571 "pointer to a 16-bit floating-point scalar or vector object."));
4572 }
4573
TEST_F(ValidateDecorations,FPRoundingModeMultipleOpStoreGood)4574 TEST_F(ValidateDecorations, FPRoundingModeMultipleOpStoreGood) {
4575 std::string spirv = R"(
4576 OpCapability Shader
4577 OpCapability Linkage
4578 OpCapability StorageBuffer16BitAccess
4579 OpExtension "SPV_KHR_storage_buffer_storage_class"
4580 OpExtension "SPV_KHR_variable_pointers"
4581 OpExtension "SPV_KHR_16bit_storage"
4582 OpMemoryModel Logical GLSL450
4583 OpEntryPoint GLCompute %main "main"
4584 OpDecorate %_ FPRoundingMode RTE
4585 %half = OpTypeFloat 16
4586 %float = OpTypeFloat 32
4587 %float_1_25 = OpConstant %float 1.25
4588 %half_ptr = OpTypePointer StorageBuffer %half
4589 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
4590 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
4591 %half_ptr_var_2 = OpVariable %half_ptr StorageBuffer
4592 %void = OpTypeVoid
4593 %func = OpTypeFunction %void
4594 %main = OpFunction %void None %func
4595 %main_entry = OpLabel
4596 %_ = OpFConvert %half %float_1_25
4597 OpStore %half_ptr_var_0 %_
4598 OpStore %half_ptr_var_1 %_
4599 OpStore %half_ptr_var_2 %_
4600 OpReturn
4601 OpFunctionEnd
4602 )";
4603
4604 CompileSuccessfully(spirv);
4605 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
4606 }
4607
TEST_F(ValidateDecorations,FPRoundingModeMultipleUsesBad)4608 TEST_F(ValidateDecorations, FPRoundingModeMultipleUsesBad) {
4609 std::string spirv = R"(
4610 OpCapability Shader
4611 OpCapability Linkage
4612 OpCapability StorageBuffer16BitAccess
4613 OpExtension "SPV_KHR_storage_buffer_storage_class"
4614 OpExtension "SPV_KHR_variable_pointers"
4615 OpExtension "SPV_KHR_16bit_storage"
4616 OpMemoryModel Logical GLSL450
4617 OpEntryPoint GLCompute %main "main"
4618 OpDecorate %_ FPRoundingMode RTE
4619 %half = OpTypeFloat 16
4620 %float = OpTypeFloat 32
4621 %float_1_25 = OpConstant %float 1.25
4622 %half_ptr = OpTypePointer StorageBuffer %half
4623 %half_ptr_var_0 = OpVariable %half_ptr StorageBuffer
4624 %half_ptr_var_1 = OpVariable %half_ptr StorageBuffer
4625 %void = OpTypeVoid
4626 %func = OpTypeFunction %void
4627 %main = OpFunction %void None %func
4628 %main_entry = OpLabel
4629 %_ = OpFConvert %half %float_1_25
4630 OpStore %half_ptr_var_0 %_
4631 %result = OpFAdd %half %_ %_
4632 OpStore %half_ptr_var_1 %_
4633 OpReturn
4634 OpFunctionEnd
4635 )";
4636
4637 CompileSuccessfully(spirv);
4638 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
4639 EXPECT_THAT(getDiagnosticString(),
4640 HasSubstr("FPRoundingMode decoration can be applied only to the "
4641 "Object operand of an OpStore."));
4642 }
4643
TEST_F(ValidateDecorations,VulkanFPRoundingModeGood)4644 TEST_F(ValidateDecorations, VulkanFPRoundingModeGood) {
4645 std::string spirv = R"(
4646 OpCapability Shader
4647 OpCapability StorageBuffer16BitAccess
4648 %1 = OpExtInstImport "GLSL.std.450"
4649 OpMemoryModel Logical GLSL450
4650 OpEntryPoint GLCompute %main "main" %_
4651 OpExecutionMode %main LocalSize 1 1 1
4652 OpMemberDecorate %ssbo 0 Offset 0
4653 OpDecorate %ssbo Block
4654 OpDecorate %_ DescriptorSet 0
4655 OpDecorate %_ Binding 0
4656 OpDecorate %17 FPRoundingMode RTE
4657 %void = OpTypeVoid
4658 %3 = OpTypeFunction %void
4659 %float = OpTypeFloat 32
4660 %_ptr_Function_float = OpTypePointer Function %float
4661 %float_1 = OpConstant %float 1
4662 %half = OpTypeFloat 16
4663 %ssbo = OpTypeStruct %half
4664 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
4665 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
4666 %int = OpTypeInt 32 1
4667 %int_0 = OpConstant %int 0
4668 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
4669 %main = OpFunction %void None %3
4670 %5 = OpLabel
4671 %b = OpVariable %_ptr_Function_float Function
4672 OpStore %b %float_1
4673 %16 = OpLoad %float %b
4674 %17 = OpFConvert %half %16
4675 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
4676 OpStore %19 %17
4677 OpReturn
4678 OpFunctionEnd
4679 )";
4680
4681 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
4682 EXPECT_EQ(SPV_SUCCESS,
4683 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
4684 }
4685
TEST_F(ValidateDecorations,VulkanFPRoundingModeBadMode)4686 TEST_F(ValidateDecorations, VulkanFPRoundingModeBadMode) {
4687 std::string spirv = R"(
4688 OpCapability Shader
4689 OpCapability StorageBuffer16BitAccess
4690 %1 = OpExtInstImport "GLSL.std.450"
4691 OpMemoryModel Logical GLSL450
4692 OpEntryPoint GLCompute %main "main" %_
4693 OpExecutionMode %main LocalSize 1 1 1
4694 OpMemberDecorate %ssbo 0 Offset 0
4695 OpDecorate %ssbo Block
4696 OpDecorate %_ DescriptorSet 0
4697 OpDecorate %_ Binding 0
4698 OpDecorate %17 FPRoundingMode RTP
4699 %void = OpTypeVoid
4700 %3 = OpTypeFunction %void
4701 %float = OpTypeFloat 32
4702 %_ptr_Function_float = OpTypePointer Function %float
4703 %float_1 = OpConstant %float 1
4704 %half = OpTypeFloat 16
4705 %ssbo = OpTypeStruct %half
4706 %_ptr_StorageBuffer_ssbo = OpTypePointer StorageBuffer %ssbo
4707 %_ = OpVariable %_ptr_StorageBuffer_ssbo StorageBuffer
4708 %int = OpTypeInt 32 1
4709 %int_0 = OpConstant %int 0
4710 %_ptr_StorageBuffer_half = OpTypePointer StorageBuffer %half
4711 %main = OpFunction %void None %3
4712 %5 = OpLabel
4713 %b = OpVariable %_ptr_Function_float Function
4714 OpStore %b %float_1
4715 %16 = OpLoad %float %b
4716 %17 = OpFConvert %half %16
4717 %19 = OpAccessChain %_ptr_StorageBuffer_half %_ %int_0
4718 OpStore %19 %17
4719 OpReturn
4720 OpFunctionEnd
4721 )";
4722
4723 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
4724 EXPECT_EQ(SPV_ERROR_INVALID_ID,
4725 ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_2));
4726 EXPECT_THAT(getDiagnosticString(),
4727 AnyVUID("VUID-StandaloneSpirv-FPRoundingMode-04675"));
4728 EXPECT_THAT(
4729 getDiagnosticString(),
4730 HasSubstr("In Vulkan, the FPRoundingMode mode must only by RTE or RTZ."));
4731 }
4732
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup)4733 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup) {
4734 std::string spirv = R"(
4735 OpCapability Shader
4736 OpCapability Linkage
4737 OpMemoryModel Logical GLSL450
4738 %1 = OpDecorationGroup
4739 OpGroupDecorate %1 %1
4740 )";
4741
4742 CompileSuccessfully(spirv);
4743 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4744 EXPECT_THAT(getDiagnosticString(),
4745 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
4746 "'1[%1]'"));
4747 }
4748
TEST_F(ValidateDecorations,GroupDecorateTargetsDecorationGroup2)4749 TEST_F(ValidateDecorations, GroupDecorateTargetsDecorationGroup2) {
4750 std::string spirv = R"(
4751 OpCapability Shader
4752 OpCapability Linkage
4753 OpMemoryModel Logical GLSL450
4754 %1 = OpDecorationGroup
4755 OpGroupDecorate %1 %2 %1
4756 %2 = OpTypeVoid
4757 )";
4758
4759 CompileSuccessfully(spirv);
4760 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4761 EXPECT_THAT(getDiagnosticString(),
4762 HasSubstr("OpGroupDecorate may not target OpDecorationGroup <id> "
4763 "'1[%1]'"));
4764 }
4765
TEST_F(ValidateDecorations,RecurseThroughRuntimeArray)4766 TEST_F(ValidateDecorations, RecurseThroughRuntimeArray) {
4767 const std::string spirv = R"(
4768 OpCapability Shader
4769 OpCapability Linkage
4770 OpMemoryModel Logical GLSL450
4771 OpDecorate %outer Block
4772 OpMemberDecorate %inner 0 Offset 0
4773 OpMemberDecorate %inner 1 Offset 1
4774 OpDecorate %runtime ArrayStride 16
4775 OpMemberDecorate %outer 0 Offset 0
4776 %int = OpTypeInt 32 0
4777 %inner = OpTypeStruct %int %int
4778 %runtime = OpTypeRuntimeArray %inner
4779 %outer = OpTypeStruct %runtime
4780 %outer_ptr = OpTypePointer Uniform %outer
4781 %var = OpVariable %outer_ptr Uniform
4782 )";
4783
4784 CompileSuccessfully(spirv);
4785 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4786 EXPECT_THAT(
4787 getDiagnosticString(),
4788 HasSubstr("Structure id 2 decorated as Block for variable in Uniform "
4789 "storage class must follow standard uniform buffer layout "
4790 "rules: member 1 at offset 1 is not aligned to 4"));
4791 }
4792
TEST_F(ValidateDecorations,EmptyStructAtNonZeroOffsetGood)4793 TEST_F(ValidateDecorations, EmptyStructAtNonZeroOffsetGood) {
4794 const std::string spirv = R"(
4795 OpCapability Shader
4796 OpMemoryModel Logical GLSL450
4797 OpEntryPoint GLCompute %main "main"
4798 OpExecutionMode %main LocalSize 1 1 1
4799 OpDecorate %struct Block
4800 OpMemberDecorate %struct 0 Offset 0
4801 OpMemberDecorate %struct 1 Offset 16
4802 OpDecorate %var DescriptorSet 0
4803 OpDecorate %var Binding 0
4804 %void = OpTypeVoid
4805 %float = OpTypeFloat 32
4806 %empty = OpTypeStruct
4807 %struct = OpTypeStruct %float %empty
4808 %ptr_struct_ubo = OpTypePointer Uniform %struct
4809 %var = OpVariable %ptr_struct_ubo Uniform
4810 %voidfn = OpTypeFunction %void
4811 %main = OpFunction %void None %voidfn
4812 %entry = OpLabel
4813 OpReturn
4814 OpFunctionEnd
4815 )";
4816
4817 CompileSuccessfully(spirv);
4818 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4819 }
4820
4821 // Uniform and UniformId decorations
4822
TEST_F(ValidateDecorations,UniformDecorationGood)4823 TEST_F(ValidateDecorations, UniformDecorationGood) {
4824 const std::string spirv = R"(
4825 OpCapability Shader
4826 OpMemoryModel Logical Simple
4827 OpEntryPoint GLCompute %main "main"
4828 OpExecutionMode %main LocalSize 1 1 1
4829 OpDecorate %int0 Uniform
4830 OpDecorate %var Uniform
4831 OpDecorate %val Uniform
4832 %void = OpTypeVoid
4833 %int = OpTypeInt 32 1
4834 %int0 = OpConstantNull %int
4835 %intptr = OpTypePointer Private %int
4836 %var = OpVariable %intptr Private
4837 %fn = OpTypeFunction %void
4838 %main = OpFunction %void None %fn
4839 %entry = OpLabel
4840 %val = OpLoad %int %var
4841 OpReturn
4842 OpFunctionEnd
4843 )";
4844
4845 CompileSuccessfully(spirv);
4846 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4847 EXPECT_THAT(getDiagnosticString(), Eq(""));
4848 }
4849
4850 // Returns SPIR-V assembly for a shader that uses a given decoration
4851 // instruction.
ShaderWithUniformLikeDecoration(const std::string & inst)4852 std::string ShaderWithUniformLikeDecoration(const std::string& inst) {
4853 return std::string(R"(
4854 OpCapability Shader
4855 OpMemoryModel Logical Simple
4856 OpEntryPoint GLCompute %main "main"
4857 OpExecutionMode %main LocalSize 1 1 1
4858 OpName %subgroupscope "subgroupscope"
4859 OpName %call "call"
4860 OpName %myfunc "myfunc"
4861 OpName %int0 "int0"
4862 OpName %float0 "float0"
4863 OpName %fn "fn"
4864 )") + inst +
4865 R"(
4866 %void = OpTypeVoid
4867 %float = OpTypeFloat 32
4868 %int = OpTypeInt 32 1
4869 %int0 = OpConstantNull %int
4870 %int_99 = OpConstant %int 99
4871 %subgroupscope = OpConstant %int 3
4872 %float0 = OpConstantNull %float
4873 %fn = OpTypeFunction %void
4874 %myfunc = OpFunction %void None %fn
4875 %myfuncentry = OpLabel
4876 OpReturn
4877 OpFunctionEnd
4878 %main = OpFunction %void None %fn
4879 %entry = OpLabel
4880 %call = OpFunctionCall %void %myfunc
4881 OpReturn
4882 OpFunctionEnd
4883 )";
4884 }
4885
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13Bad)4886 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13Bad) {
4887 const std::string spirv = ShaderWithUniformLikeDecoration(
4888 "OpDecorateId %int0 UniformId %subgroupscope");
4889 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4890 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
4891 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4892 EXPECT_THAT(getDiagnosticString(),
4893 HasSubstr("requires SPIR-V version 1.4 or later\n"
4894 " OpDecorateId %int0 UniformId %subgroupscope"))
4895 << spirv;
4896 }
4897
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV13BadTargetV14)4898 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV13BadTargetV14) {
4899 const std::string spirv = ShaderWithUniformLikeDecoration(
4900 "OpDecorateId %int0 UniformId %subgroupscope");
4901 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4902 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
4903 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4904 EXPECT_THAT(getDiagnosticString(),
4905 HasSubstr("requires SPIR-V version 1.4 or later"));
4906 }
4907
TEST_F(ValidateDecorations,UniformIdDecorationWithScopeIdV14Good)4908 TEST_F(ValidateDecorations, UniformIdDecorationWithScopeIdV14Good) {
4909 const std::string spirv = ShaderWithUniformLikeDecoration(
4910 "OpDecorateId %int0 UniformId %subgroupscope");
4911 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
4912 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4913 EXPECT_THAT(getDiagnosticString(), Eq(""));
4914 }
4915
TEST_F(ValidateDecorations,UniformDecorationTargetsTypeBad)4916 TEST_F(ValidateDecorations, UniformDecorationTargetsTypeBad) {
4917 const std::string spirv =
4918 ShaderWithUniformLikeDecoration("OpDecorate %fn Uniform");
4919
4920 CompileSuccessfully(spirv);
4921 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4922 EXPECT_THAT(getDiagnosticString(),
4923 HasSubstr("Uniform decoration applied to a non-object"));
4924 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
4925 }
4926
TEST_F(ValidateDecorations,UniformIdDecorationTargetsTypeBad)4927 TEST_F(ValidateDecorations, UniformIdDecorationTargetsTypeBad) {
4928 const std::string spirv = ShaderWithUniformLikeDecoration(
4929 "OpDecorateId %fn UniformId %subgroupscope");
4930
4931 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
4932 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4933 EXPECT_THAT(getDiagnosticString(),
4934 HasSubstr("UniformId decoration applied to a non-object"));
4935 EXPECT_THAT(getDiagnosticString(), HasSubstr("%fn = OpTypeFunction %void"));
4936 }
4937
TEST_F(ValidateDecorations,UniformDecorationTargetsVoidValueBad)4938 TEST_F(ValidateDecorations, UniformDecorationTargetsVoidValueBad) {
4939 const std::string spirv =
4940 ShaderWithUniformLikeDecoration("OpDecorate %call Uniform");
4941
4942 CompileSuccessfully(spirv);
4943 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4944 EXPECT_THAT(getDiagnosticString(),
4945 HasSubstr("Uniform decoration applied to a value with void type\n"
4946 " %call = OpFunctionCall %void %myfunc"));
4947 }
4948
TEST_F(ValidateDecorations,UniformIdDecorationTargetsVoidValueBad)4949 TEST_F(ValidateDecorations, UniformIdDecorationTargetsVoidValueBad) {
4950 const std::string spirv = ShaderWithUniformLikeDecoration(
4951 "OpDecorateId %call UniformId %subgroupscope");
4952
4953 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
4954 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4))
4955 << spirv;
4956 EXPECT_THAT(
4957 getDiagnosticString(),
4958 HasSubstr("UniformId decoration applied to a value with void type\n"
4959 " %call = OpFunctionCall %void %myfunc"));
4960 }
4961
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsFloatValueIsBad)4962 TEST_F(ValidateDecorations,
4963 UniformDecorationWithScopeIdV14IdIsFloatValueIsBad) {
4964 const std::string spirv =
4965 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %float0");
4966
4967 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
4968 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
4969 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4970 EXPECT_THAT(getDiagnosticString(),
4971 HasSubstr("ConstantNull: expected scope to be a 32-bit int"));
4972 }
4973
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad)4974 TEST_F(ValidateDecorations,
4975 UniformDecorationWithScopeIdV14IdIsInvalidIntValueBad) {
4976 const std::string spirv =
4977 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int_99");
4978
4979 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
4980 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
4981 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
4982 EXPECT_THAT(
4983 getDiagnosticString(),
4984 HasSubstr("Invalid scope value:\n %int_99 = OpConstant %int 99\n"));
4985 }
4986
TEST_F(ValidateDecorations,UniformDecorationWithScopeIdV14VulkanEnv)4987 TEST_F(ValidateDecorations, UniformDecorationWithScopeIdV14VulkanEnv) {
4988 const std::string spirv =
4989 ShaderWithUniformLikeDecoration("OpDecorateId %int0 UniformId %int0");
4990
4991 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1_SPIRV_1_4);
4992 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
4993 ValidateInstructions(SPV_ENV_VULKAN_1_1_SPIRV_1_4));
4994 EXPECT_THAT(getDiagnosticString(),
4995 AnyVUID("VUID-StandaloneSpirv-None-04636"));
4996 EXPECT_THAT(getDiagnosticString(),
4997 HasSubstr(": in Vulkan environment Execution Scope is limited to "
4998 "Workgroup and Subgroup"));
4999 }
5000
TEST_F(ValidateDecorations,UniformDecorationWithWrongInstructionBad)5001 TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) {
5002 const std::string spirv =
5003 ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform");
5004
5005 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
5006 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
5007 EXPECT_THAT(getDiagnosticString(),
5008 HasSubstr("Decorations that don't take ID parameters may not be "
5009 "used with OpDecorateId\n"
5010 " OpDecorateId %int0 Uniform"));
5011 }
5012
TEST_F(ValidateDecorations,UniformIdDecorationWithWrongInstructionBad)5013 TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) {
5014 const std::string spirv = ShaderWithUniformLikeDecoration(
5015 "OpDecorate %int0 UniformId %subgroupscope");
5016
5017 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5018 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5019 EXPECT_THAT(
5020 getDiagnosticString(),
5021 HasSubstr(
5022 "Decorations taking ID parameters may not be used with OpDecorateId\n"
5023 " OpDecorate %int0 UniformId %subgroupscope"));
5024 }
5025
TEST_F(ValidateDecorations,MultipleOffsetDecorationsOnSameID)5026 TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) {
5027 std::string spirv = R"(
5028 OpCapability Shader
5029 OpMemoryModel Logical GLSL450
5030 OpEntryPoint Fragment %1 "main"
5031 OpExecutionMode %1 OriginUpperLeft
5032
5033 OpMemberDecorate %struct 0 Offset 0
5034 OpMemberDecorate %struct 0 Offset 0
5035
5036 %void = OpTypeVoid
5037 %voidfn = OpTypeFunction %void
5038 %float = OpTypeFloat 32
5039 %struct = OpTypeStruct %float
5040
5041 %1 = OpFunction %void None %voidfn
5042 %label = OpLabel
5043 OpReturn
5044 OpFunctionEnd
5045 )";
5046
5047 CompileSuccessfully(spirv);
5048 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5049 EXPECT_THAT(getDiagnosticString(),
5050 HasSubstr("ID '2', member '0' decorated with Offset multiple "
5051 "times is not allowed."));
5052 }
5053
TEST_F(ValidateDecorations,MultipleArrayStrideDecorationsOnSameID)5054 TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) {
5055 std::string spirv = R"(
5056 OpCapability Shader
5057 OpMemoryModel Logical GLSL450
5058 OpEntryPoint Fragment %1 "main"
5059 OpExecutionMode %1 OriginUpperLeft
5060
5061 OpDecorate %array ArrayStride 4
5062 OpDecorate %array ArrayStride 4
5063
5064 %void = OpTypeVoid
5065 %voidfn = OpTypeFunction %void
5066 %float = OpTypeFloat 32
5067 %uint = OpTypeInt 32 0
5068 %uint_4 = OpConstant %uint 4
5069 %array = OpTypeArray %float %uint_4
5070
5071 %1 = OpFunction %void None %voidfn
5072 %label = OpLabel
5073 OpReturn
5074 OpFunctionEnd
5075 )";
5076
5077 CompileSuccessfully(spirv);
5078 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5079 EXPECT_THAT(getDiagnosticString(),
5080 HasSubstr("ID '2' decorated with ArrayStride multiple "
5081 "times is not allowed."));
5082 }
5083
TEST_F(ValidateDecorations,MultipleMatrixStrideDecorationsOnSameID)5084 TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) {
5085 std::string spirv = R"(
5086 OpCapability Shader
5087 OpMemoryModel Logical GLSL450
5088 OpEntryPoint Fragment %1 "main"
5089 OpExecutionMode %1 OriginUpperLeft
5090
5091 OpMemberDecorate %struct 0 Offset 0
5092 OpMemberDecorate %struct 0 ColMajor
5093 OpMemberDecorate %struct 0 MatrixStride 16
5094 OpMemberDecorate %struct 0 MatrixStride 16
5095
5096 %void = OpTypeVoid
5097 %voidfn = OpTypeFunction %void
5098 %float = OpTypeFloat 32
5099 %fvec4 = OpTypeVector %float 4
5100 %fmat4 = OpTypeMatrix %fvec4 4
5101 %struct = OpTypeStruct %fmat4
5102
5103 %1 = OpFunction %void None %voidfn
5104 %label = OpLabel
5105 OpReturn
5106 OpFunctionEnd
5107 )";
5108
5109 CompileSuccessfully(spirv);
5110 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5111 EXPECT_THAT(getDiagnosticString(),
5112 HasSubstr("ID '2', member '0' decorated with MatrixStride "
5113 "multiple times is not allowed."));
5114 }
5115
TEST_F(ValidateDecorations,MultipleRowMajorDecorationsOnSameID)5116 TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) {
5117 std::string spirv = R"(
5118 OpCapability Shader
5119 OpMemoryModel Logical GLSL450
5120 OpEntryPoint Fragment %1 "main"
5121 OpExecutionMode %1 OriginUpperLeft
5122
5123 OpMemberDecorate %struct 0 Offset 0
5124 OpMemberDecorate %struct 0 MatrixStride 16
5125 OpMemberDecorate %struct 0 RowMajor
5126 OpMemberDecorate %struct 0 RowMajor
5127
5128 %void = OpTypeVoid
5129 %voidfn = OpTypeFunction %void
5130 %float = OpTypeFloat 32
5131 %fvec4 = OpTypeVector %float 4
5132 %fmat4 = OpTypeMatrix %fvec4 4
5133 %struct = OpTypeStruct %fmat4
5134
5135 %1 = OpFunction %void None %voidfn
5136 %label = OpLabel
5137 OpReturn
5138 OpFunctionEnd
5139 )";
5140
5141 CompileSuccessfully(spirv);
5142 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5143 EXPECT_THAT(getDiagnosticString(),
5144 HasSubstr("ID '2', member '0' decorated with RowMajor multiple "
5145 "times is not allowed."));
5146 }
5147
TEST_F(ValidateDecorations,MultipleColMajorDecorationsOnSameID)5148 TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) {
5149 std::string spirv = R"(
5150 OpCapability Shader
5151 OpMemoryModel Logical GLSL450
5152 OpEntryPoint Fragment %1 "main"
5153 OpExecutionMode %1 OriginUpperLeft
5154
5155 OpMemberDecorate %struct 0 Offset 0
5156 OpMemberDecorate %struct 0 MatrixStride 16
5157 OpMemberDecorate %struct 0 ColMajor
5158 OpMemberDecorate %struct 0 ColMajor
5159
5160 %void = OpTypeVoid
5161 %voidfn = OpTypeFunction %void
5162 %float = OpTypeFloat 32
5163 %fvec4 = OpTypeVector %float 4
5164 %fmat4 = OpTypeMatrix %fvec4 4
5165 %struct = OpTypeStruct %fmat4
5166
5167 %1 = OpFunction %void None %voidfn
5168 %label = OpLabel
5169 OpReturn
5170 OpFunctionEnd
5171 )";
5172
5173 CompileSuccessfully(spirv);
5174 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5175 EXPECT_THAT(getDiagnosticString(),
5176 HasSubstr("ID '2', member '0' decorated with ColMajor multiple "
5177 "times is not allowed."));
5178 }
5179
TEST_F(ValidateDecorations,RowMajorAndColMajorDecorationsOnSameID)5180 TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) {
5181 std::string spirv = R"(
5182 OpCapability Shader
5183 OpMemoryModel Logical GLSL450
5184 OpEntryPoint Fragment %1 "main"
5185 OpExecutionMode %1 OriginUpperLeft
5186
5187 OpMemberDecorate %struct 0 Offset 0
5188 OpMemberDecorate %struct 0 MatrixStride 16
5189 OpMemberDecorate %struct 0 ColMajor
5190 OpMemberDecorate %struct 0 RowMajor
5191
5192 %void = OpTypeVoid
5193 %voidfn = OpTypeFunction %void
5194 %float = OpTypeFloat 32
5195 %fvec4 = OpTypeVector %float 4
5196 %fmat4 = OpTypeMatrix %fvec4 4
5197 %struct = OpTypeStruct %fmat4
5198
5199 %1 = OpFunction %void None %voidfn
5200 %label = OpLabel
5201 OpReturn
5202 OpFunctionEnd
5203 )";
5204
5205 CompileSuccessfully(spirv);
5206 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5207 EXPECT_THAT(getDiagnosticString(),
5208 HasSubstr("ID '2', member '0' decorated with both RowMajor and "
5209 "ColMajor is not allowed."));
5210 }
5211
TEST_F(ValidateDecorations,BlockAndBufferBlockDecorationsOnSameID)5212 TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
5213 std::string spirv = R"(
5214 OpCapability Shader
5215 OpMemoryModel Logical GLSL450
5216 OpEntryPoint Fragment %1 "main"
5217 OpExecutionMode %1 OriginUpperLeft
5218
5219 OpDecorate %struct Block
5220 OpDecorate %struct BufferBlock
5221 OpMemberDecorate %struct 0 Offset 0
5222 OpMemberDecorate %struct 0 MatrixStride 16
5223 OpMemberDecorate %struct 0 RowMajor
5224
5225 %void = OpTypeVoid
5226 %voidfn = OpTypeFunction %void
5227 %float = OpTypeFloat 32
5228 %fvec4 = OpTypeVector %float 4
5229 %fmat4 = OpTypeMatrix %fvec4 4
5230 %struct = OpTypeStruct %fmat4
5231
5232 %1 = OpFunction %void None %voidfn
5233 %label = OpLabel
5234 OpReturn
5235 OpFunctionEnd
5236 )";
5237
5238 CompileSuccessfully(spirv);
5239 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5240 EXPECT_THAT(
5241 getDiagnosticString(),
5242 HasSubstr(
5243 "ID '2' decorated with both BufferBlock and Block is not allowed."));
5244 }
5245
MakeIntegerShader(const std::string & decoration,const std::string & inst,const std::string & extension="OpExtension \\"SPV_KHR_no_integer_wrap_decoration\\"")5246 std::string MakeIntegerShader(
5247 const std::string& decoration, const std::string& inst,
5248 const std::string& extension =
5249 "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
5250 return R"(
5251 OpCapability Shader
5252 OpCapability Linkage
5253 )" + extension +
5254 R"(
5255 %glsl = OpExtInstImport "GLSL.std.450"
5256 %opencl = OpExtInstImport "OpenCL.std"
5257 OpMemoryModel Logical GLSL450
5258 OpEntryPoint GLCompute %main "main"
5259 OpName %entry "entry"
5260 )" + decoration +
5261 R"(
5262 %void = OpTypeVoid
5263 %voidfn = OpTypeFunction %void
5264 %int = OpTypeInt 32 1
5265 %zero = OpConstantNull %int
5266 %float = OpTypeFloat 32
5267 %float0 = OpConstantNull %float
5268 %main = OpFunction %void None %voidfn
5269 %entry = OpLabel
5270 )" + inst +
5271 R"(
5272 OpReturn
5273 OpFunctionEnd)";
5274 }
5275
5276 // NoSignedWrap
5277
TEST_F(ValidateDecorations,NoSignedWrapOnTypeBad)5278 TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
5279 std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
5280
5281 CompileSuccessfully(spirv);
5282 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5283 EXPECT_THAT(
5284 getDiagnosticString(),
5285 HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
5286 }
5287
TEST_F(ValidateDecorations,NoSignedWrapOnLabelBad)5288 TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
5289 std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
5290
5291 CompileSuccessfully(spirv);
5292 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5293 EXPECT_THAT(getDiagnosticString(),
5294 HasSubstr("NoSignedWrap decoration may not be applied to Label"));
5295 }
5296
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionBad)5297 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
5298 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5299 "%val = OpIAdd %int %zero %zero", "");
5300
5301 CompileSuccessfully(spirv);
5302 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5303 EXPECT_THAT(getDiagnosticString(),
5304 HasSubstr("requires one of these extensions: "
5305 "SPV_KHR_no_integer_wrap_decoration"));
5306 }
5307
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionV13Bad)5308 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) {
5309 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5310 "%val = OpIAdd %int %zero %zero", "");
5311
5312 CompileSuccessfully(spirv);
5313 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5314 EXPECT_THAT(getDiagnosticString(),
5315 HasSubstr("requires one of these extensions: "
5316 "SPV_KHR_no_integer_wrap_decoration"));
5317 }
5318
TEST_F(ValidateDecorations,NoSignedWrapOkInSPV14Good)5319 TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) {
5320 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5321 "%val = OpIAdd %int %zero %zero", "");
5322
5323 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5324 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5325 EXPECT_THAT(getDiagnosticString(), Eq(""));
5326 }
5327
TEST_F(ValidateDecorations,NoSignedWrapIAddGood)5328 TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
5329 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5330 "%val = OpIAdd %int %zero %zero");
5331
5332 CompileSuccessfully(spirv);
5333 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5334 EXPECT_THAT(getDiagnosticString(), Eq(""));
5335 }
5336
TEST_F(ValidateDecorations,NoSignedWrapISubGood)5337 TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
5338 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5339 "%val = OpISub %int %zero %zero");
5340
5341 CompileSuccessfully(spirv);
5342 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5343 EXPECT_THAT(getDiagnosticString(), Eq(""));
5344 }
5345
TEST_F(ValidateDecorations,NoSignedWrapIMulGood)5346 TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
5347 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5348 "%val = OpIMul %int %zero %zero");
5349
5350 CompileSuccessfully(spirv);
5351 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5352 EXPECT_THAT(getDiagnosticString(), Eq(""));
5353 }
5354
TEST_F(ValidateDecorations,NoSignedWrapShiftLeftLogicalGood)5355 TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
5356 std::string spirv =
5357 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5358 "%val = OpShiftLeftLogical %int %zero %zero");
5359
5360 CompileSuccessfully(spirv);
5361 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5362 EXPECT_THAT(getDiagnosticString(), Eq(""));
5363 }
5364
TEST_F(ValidateDecorations,NoSignedWrapSNegateGood)5365 TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
5366 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5367 "%val = OpSNegate %int %zero");
5368
5369 CompileSuccessfully(spirv);
5370 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5371 EXPECT_THAT(getDiagnosticString(), Eq(""));
5372 }
5373
TEST_F(ValidateDecorations,NoSignedWrapSRemBad)5374 TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
5375 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5376 "%val = OpSRem %int %zero %zero");
5377
5378 CompileSuccessfully(spirv);
5379 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5380 EXPECT_THAT(getDiagnosticString(),
5381 HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
5382 }
5383
TEST_F(ValidateDecorations,NoSignedWrapFAddBad)5384 TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
5385 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5386 "%val = OpFAdd %float %float0 %float0");
5387
5388 CompileSuccessfully(spirv);
5389 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5390 EXPECT_THAT(getDiagnosticString(),
5391 HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
5392 }
5393
TEST_F(ValidateDecorations,NoSignedWrapExtInstOpenCLGood)5394 TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
5395 std::string spirv =
5396 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5397 "%val = OpExtInst %int %opencl s_abs %zero");
5398
5399 CompileSuccessfully(spirv);
5400 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5401 EXPECT_THAT(getDiagnosticString(), Eq(""));
5402 }
5403
TEST_F(ValidateDecorations,NoSignedWrapExtInstGLSLGood)5404 TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
5405 std::string spirv = MakeIntegerShader(
5406 "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
5407
5408 CompileSuccessfully(spirv);
5409 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5410 EXPECT_THAT(getDiagnosticString(), Eq(""));
5411 }
5412
5413 // TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
5414 // "OpExtInst for instruction numbers specified in the extended
5415 // instruction-set specifications as accepting this decoration."
5416
5417 // NoUnignedWrap
5418
TEST_F(ValidateDecorations,NoUnsignedWrapOnTypeBad)5419 TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
5420 std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
5421
5422 CompileSuccessfully(spirv);
5423 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5424 EXPECT_THAT(
5425 getDiagnosticString(),
5426 HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
5427 }
5428
TEST_F(ValidateDecorations,NoUnsignedWrapOnLabelBad)5429 TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
5430 std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
5431
5432 CompileSuccessfully(spirv);
5433 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5434 EXPECT_THAT(
5435 getDiagnosticString(),
5436 HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
5437 }
5438
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionBad)5439 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
5440 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5441 "%val = OpIAdd %int %zero %zero", "");
5442
5443 CompileSuccessfully(spirv);
5444 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5445 EXPECT_THAT(getDiagnosticString(),
5446 HasSubstr("requires one of these extensions: "
5447 "SPV_KHR_no_integer_wrap_decoration"));
5448 }
5449
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionV13Bad)5450 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) {
5451 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5452 "%val = OpIAdd %int %zero %zero", "");
5453
5454 CompileSuccessfully(spirv);
5455 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5456 EXPECT_THAT(getDiagnosticString(),
5457 HasSubstr("requires one of these extensions: "
5458 "SPV_KHR_no_integer_wrap_decoration"));
5459 }
5460
TEST_F(ValidateDecorations,NoUnsignedWrapOkInSPV14Good)5461 TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) {
5462 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5463 "%val = OpIAdd %int %zero %zero", "");
5464
5465 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5466 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5467 EXPECT_THAT(getDiagnosticString(), Eq(""));
5468 }
5469
TEST_F(ValidateDecorations,NoUnsignedWrapIAddGood)5470 TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
5471 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5472 "%val = OpIAdd %int %zero %zero");
5473
5474 CompileSuccessfully(spirv);
5475 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5476 EXPECT_THAT(getDiagnosticString(), Eq(""));
5477 }
5478
TEST_F(ValidateDecorations,NoUnsignedWrapISubGood)5479 TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
5480 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5481 "%val = OpISub %int %zero %zero");
5482
5483 CompileSuccessfully(spirv);
5484 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5485 EXPECT_THAT(getDiagnosticString(), Eq(""));
5486 }
5487
TEST_F(ValidateDecorations,NoUnsignedWrapIMulGood)5488 TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
5489 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5490 "%val = OpIMul %int %zero %zero");
5491
5492 CompileSuccessfully(spirv);
5493 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5494 EXPECT_THAT(getDiagnosticString(), Eq(""));
5495 }
5496
TEST_F(ValidateDecorations,NoUnsignedWrapShiftLeftLogicalGood)5497 TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
5498 std::string spirv =
5499 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5500 "%val = OpShiftLeftLogical %int %zero %zero");
5501
5502 CompileSuccessfully(spirv);
5503 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5504 EXPECT_THAT(getDiagnosticString(), Eq(""));
5505 }
5506
TEST_F(ValidateDecorations,NoUnsignedWrapSNegateGood)5507 TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
5508 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5509 "%val = OpSNegate %int %zero");
5510
5511 CompileSuccessfully(spirv);
5512 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5513 EXPECT_THAT(getDiagnosticString(), Eq(""));
5514 }
5515
TEST_F(ValidateDecorations,NoUnsignedWrapSRemBad)5516 TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
5517 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5518 "%val = OpSRem %int %zero %zero");
5519
5520 CompileSuccessfully(spirv);
5521 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5522 EXPECT_THAT(
5523 getDiagnosticString(),
5524 HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
5525 }
5526
TEST_F(ValidateDecorations,NoUnsignedWrapFAddBad)5527 TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
5528 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5529 "%val = OpFAdd %float %float0 %float0");
5530
5531 CompileSuccessfully(spirv);
5532 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5533 EXPECT_THAT(
5534 getDiagnosticString(),
5535 HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
5536 }
5537
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstOpenCLGood)5538 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
5539 std::string spirv =
5540 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5541 "%val = OpExtInst %int %opencl s_abs %zero");
5542
5543 CompileSuccessfully(spirv);
5544 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5545 EXPECT_THAT(getDiagnosticString(), Eq(""));
5546 }
5547
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstGLSLGood)5548 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
5549 std::string spirv =
5550 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5551 "%val = OpExtInst %int %glsl SAbs %zero");
5552
5553 CompileSuccessfully(spirv);
5554 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5555 EXPECT_THAT(getDiagnosticString(), Eq(""));
5556 }
5557
TEST_F(ValidateDecorations,AliasedandRestrictBad)5558 TEST_F(ValidateDecorations, AliasedandRestrictBad) {
5559 const std::string body = R"(
5560 OpCapability Shader
5561 %1 = OpExtInstImport "GLSL.std.450"
5562 OpMemoryModel Logical GLSL450
5563 OpEntryPoint GLCompute %main "main"
5564 OpExecutionMode %main LocalSize 1 1 1
5565 OpSource GLSL 430
5566 OpMemberDecorate %Output 0 Offset 0
5567 OpDecorate %Output BufferBlock
5568 OpDecorate %dataOutput Restrict
5569 OpDecorate %dataOutput Aliased
5570 %void = OpTypeVoid
5571 %3 = OpTypeFunction %void
5572 %float = OpTypeFloat 32
5573 %Output = OpTypeStruct %float
5574 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
5575 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
5576 %main = OpFunction %void None %3
5577 %5 = OpLabel
5578 OpReturn
5579 OpFunctionEnd
5580 )";
5581
5582 CompileSuccessfully(body.c_str());
5583 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5584 EXPECT_THAT(
5585 getDiagnosticString(),
5586 HasSubstr("decorated with both Aliased and Restrict is not allowed"));
5587 }
5588
5589 // TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
5590 // "OpExtInst for instruction numbers specified in the extended
5591 // instruction-set specifications as accepting this decoration."
5592
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerSuccess)5593 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
5594 const std::string body = R"(
5595 OpCapability PhysicalStorageBufferAddressesEXT
5596 OpCapability Int64
5597 OpCapability Shader
5598 OpExtension "SPV_EXT_physical_storage_buffer"
5599 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5600 OpEntryPoint Fragment %main "main"
5601 OpExecutionMode %main OriginUpperLeft
5602 OpDecorate %val1 RestrictPointerEXT
5603 %uint64 = OpTypeInt 64 0
5604 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5605 %pptr_f = OpTypePointer Function %ptr
5606 %void = OpTypeVoid
5607 %voidfn = OpTypeFunction %void
5608 %main = OpFunction %void None %voidfn
5609 %entry = OpLabel
5610 %val1 = OpVariable %pptr_f Function
5611 OpReturn
5612 OpFunctionEnd
5613 )";
5614
5615 CompileSuccessfully(body.c_str());
5616 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5617 }
5618
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerMissing)5619 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) {
5620 const std::string body = R"(
5621 OpCapability PhysicalStorageBufferAddressesEXT
5622 OpCapability Int64
5623 OpCapability Shader
5624 OpExtension "SPV_EXT_physical_storage_buffer"
5625 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5626 OpEntryPoint Fragment %main "main"
5627 OpExecutionMode %main OriginUpperLeft
5628 %uint64 = OpTypeInt 64 0
5629 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5630 %pptr_f = OpTypePointer Function %ptr
5631 %void = OpTypeVoid
5632 %voidfn = OpTypeFunction %void
5633 %main = OpFunction %void None %voidfn
5634 %entry = OpLabel
5635 %val1 = OpVariable %pptr_f Function
5636 OpReturn
5637 OpFunctionEnd
5638 )";
5639
5640 CompileSuccessfully(body.c_str());
5641 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5642 EXPECT_THAT(getDiagnosticString(),
5643 HasSubstr("expected AliasedPointerEXT or RestrictPointerEXT for "
5644 "PhysicalStorageBufferEXT pointer"));
5645 }
5646
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerBoth)5647 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) {
5648 const std::string body = R"(
5649 OpCapability PhysicalStorageBufferAddressesEXT
5650 OpCapability Int64
5651 OpCapability Shader
5652 OpExtension "SPV_EXT_physical_storage_buffer"
5653 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5654 OpEntryPoint Fragment %main "main"
5655 OpExecutionMode %main OriginUpperLeft
5656 OpDecorate %val1 RestrictPointerEXT
5657 OpDecorate %val1 AliasedPointerEXT
5658 %uint64 = OpTypeInt 64 0
5659 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5660 %pptr_f = OpTypePointer Function %ptr
5661 %void = OpTypeVoid
5662 %voidfn = OpTypeFunction %void
5663 %main = OpFunction %void None %voidfn
5664 %entry = OpLabel
5665 %val1 = OpVariable %pptr_f Function
5666 OpReturn
5667 OpFunctionEnd
5668 )";
5669
5670 CompileSuccessfully(body.c_str());
5671 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5672 EXPECT_THAT(
5673 getDiagnosticString(),
5674 HasSubstr("can't specify both AliasedPointerEXT and RestrictPointerEXT "
5675 "for PhysicalStorageBufferEXT pointer"));
5676 }
5677
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamSuccess)5678 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) {
5679 const std::string body = R"(
5680 OpCapability PhysicalStorageBufferAddressesEXT
5681 OpCapability Int64
5682 OpCapability Shader
5683 OpExtension "SPV_EXT_physical_storage_buffer"
5684 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5685 OpEntryPoint Fragment %main "main"
5686 OpExecutionMode %main OriginUpperLeft
5687 OpDecorate %fparam Restrict
5688 %uint64 = OpTypeInt 64 0
5689 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5690 %void = OpTypeVoid
5691 %voidfn = OpTypeFunction %void
5692 %fnptr = OpTypeFunction %void %ptr
5693 %main = OpFunction %void None %voidfn
5694 %entry = OpLabel
5695 OpReturn
5696 OpFunctionEnd
5697 %fn = OpFunction %void None %fnptr
5698 %fparam = OpFunctionParameter %ptr
5699 %lab = OpLabel
5700 OpReturn
5701 OpFunctionEnd
5702 )";
5703
5704 CompileSuccessfully(body.c_str());
5705 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5706 }
5707
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamMissing)5708 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) {
5709 const std::string body = R"(
5710 OpCapability PhysicalStorageBufferAddressesEXT
5711 OpCapability Int64
5712 OpCapability Shader
5713 OpExtension "SPV_EXT_physical_storage_buffer"
5714 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5715 OpEntryPoint Fragment %main "main"
5716 OpExecutionMode %main OriginUpperLeft
5717 %uint64 = OpTypeInt 64 0
5718 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5719 %void = OpTypeVoid
5720 %voidfn = OpTypeFunction %void
5721 %fnptr = OpTypeFunction %void %ptr
5722 %main = OpFunction %void None %voidfn
5723 %entry = OpLabel
5724 OpReturn
5725 OpFunctionEnd
5726 %fn = OpFunction %void None %fnptr
5727 %fparam = OpFunctionParameter %ptr
5728 %lab = OpLabel
5729 OpReturn
5730 OpFunctionEnd
5731 )";
5732
5733 CompileSuccessfully(body.c_str());
5734 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5735 EXPECT_THAT(getDiagnosticString(),
5736 HasSubstr("expected Aliased or Restrict for "
5737 "PhysicalStorageBufferEXT pointer"));
5738 }
5739
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamBoth)5740 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
5741 const std::string body = R"(
5742 OpCapability PhysicalStorageBufferAddressesEXT
5743 OpCapability Int64
5744 OpCapability Shader
5745 OpExtension "SPV_EXT_physical_storage_buffer"
5746 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5747 OpEntryPoint Fragment %main "main"
5748 OpExecutionMode %main OriginUpperLeft
5749 OpDecorate %fparam Restrict
5750 OpDecorate %fparam Aliased
5751 %uint64 = OpTypeInt 64 0
5752 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5753 %void = OpTypeVoid
5754 %voidfn = OpTypeFunction %void
5755 %fnptr = OpTypeFunction %void %ptr
5756 %main = OpFunction %void None %voidfn
5757 %entry = OpLabel
5758 OpReturn
5759 OpFunctionEnd
5760 %fn = OpFunction %void None %fnptr
5761 %fparam = OpFunctionParameter %ptr
5762 %lab = OpLabel
5763 OpReturn
5764 OpFunctionEnd
5765 )";
5766
5767 CompileSuccessfully(body.c_str());
5768 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5769 EXPECT_THAT(getDiagnosticString(),
5770 HasSubstr("can't specify both Aliased and Restrict for "
5771 "PhysicalStorageBufferEXT pointer"));
5772 }
5773
TEST_F(ValidateDecorations,PSBFPRoundingModeSuccess)5774 TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) {
5775 std::string spirv = R"(
5776 OpCapability PhysicalStorageBufferAddressesEXT
5777 OpCapability Shader
5778 OpCapability Linkage
5779 OpCapability StorageBuffer16BitAccess
5780 OpExtension "SPV_EXT_physical_storage_buffer"
5781 OpExtension "SPV_KHR_storage_buffer_storage_class"
5782 OpExtension "SPV_KHR_variable_pointers"
5783 OpExtension "SPV_KHR_16bit_storage"
5784 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5785 OpEntryPoint GLCompute %main "main"
5786 OpDecorate %_ FPRoundingMode RTE
5787 OpDecorate %half_ptr_var AliasedPointerEXT
5788 %half = OpTypeFloat 16
5789 %float = OpTypeFloat 32
5790 %float_1_25 = OpConstant %float 1.25
5791 %half_ptr = OpTypePointer PhysicalStorageBufferEXT %half
5792 %half_pptr_f = OpTypePointer Function %half_ptr
5793 %void = OpTypeVoid
5794 %func = OpTypeFunction %void
5795 %main = OpFunction %void None %func
5796 %main_entry = OpLabel
5797 %half_ptr_var = OpVariable %half_pptr_f Function
5798 %val1 = OpLoad %half_ptr %half_ptr_var
5799 %_ = OpFConvert %half %float_1_25
5800 OpStore %val1 %_ Aligned 2
5801 OpReturn
5802 OpFunctionEnd
5803 )";
5804
5805 CompileSuccessfully(spirv);
5806 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5807 }
5808
TEST_F(ValidateDecorations,InvalidStraddle)5809 TEST_F(ValidateDecorations, InvalidStraddle) {
5810 const std::string spirv = R"(
5811 OpCapability Shader
5812 OpMemoryModel Logical GLSL450
5813 OpEntryPoint GLCompute %main "main"
5814 OpExecutionMode %main LocalSize 1 1 1
5815 OpMemberDecorate %inner_struct 0 Offset 0
5816 OpMemberDecorate %inner_struct 1 Offset 4
5817 OpDecorate %outer_struct Block
5818 OpMemberDecorate %outer_struct 0 Offset 0
5819 OpMemberDecorate %outer_struct 1 Offset 8
5820 OpDecorate %var DescriptorSet 0
5821 OpDecorate %var Binding 0
5822 %void = OpTypeVoid
5823 %float = OpTypeFloat 32
5824 %float2 = OpTypeVector %float 2
5825 %inner_struct = OpTypeStruct %float %float2
5826 %outer_struct = OpTypeStruct %float2 %inner_struct
5827 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct
5828 %var = OpVariable %ptr_ssbo_outer StorageBuffer
5829 %void_fn = OpTypeFunction %void
5830 %main = OpFunction %void None %void_fn
5831 %entry = OpLabel
5832 OpReturn
5833 OpFunctionEnd
5834 )";
5835
5836 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
5837 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5838 EXPECT_THAT(getDiagnosticString(),
5839 HasSubstr("Structure id 2 decorated as Block for variable in "
5840 "StorageBuffer storage class must follow relaxed "
5841 "storage buffer layout rules: member 1 is an "
5842 "improperly straddling vector at offset 12"));
5843 }
5844
TEST_F(ValidateDecorations,DescriptorArray)5845 TEST_F(ValidateDecorations, DescriptorArray) {
5846 const std::string spirv = R"(
5847 OpCapability Shader
5848 OpExtension "SPV_KHR_storage_buffer_storage_class"
5849 OpMemoryModel Logical GLSL450
5850 OpEntryPoint GLCompute %main "main"
5851 OpExecutionMode %main LocalSize 1 1 1
5852 OpDecorate %struct Block
5853 OpMemberDecorate %struct 0 Offset 0
5854 OpMemberDecorate %struct 1 Offset 1
5855 OpDecorate %var DescriptorSet 0
5856 OpDecorate %var Binding 0
5857 %void = OpTypeVoid
5858 %float = OpTypeFloat 32
5859 %int = OpTypeInt 32 0
5860 %int_2 = OpConstant %int 2
5861 %float2 = OpTypeVector %float 2
5862 %struct = OpTypeStruct %float %float2
5863 %struct_array = OpTypeArray %struct %int_2
5864 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
5865 %var = OpVariable %ptr_ssbo_array StorageBuffer
5866 %void_fn = OpTypeFunction %void
5867 %main = OpFunction %void None %void_fn
5868 %entry = OpLabel
5869 OpReturn
5870 OpFunctionEnd
5871 )";
5872
5873 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5874 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5875 EXPECT_THAT(getDiagnosticString(),
5876 HasSubstr("Structure id 2 decorated as Block for variable in "
5877 "StorageBuffer storage class must follow standard "
5878 "storage buffer layout rules: member 1 at offset 1 is "
5879 "not aligned to 8"));
5880 }
5881
TEST_F(ValidateDecorations,DescriptorRuntimeArray)5882 TEST_F(ValidateDecorations, DescriptorRuntimeArray) {
5883 const std::string spirv = R"(
5884 OpCapability Shader
5885 OpCapability RuntimeDescriptorArrayEXT
5886 OpExtension "SPV_KHR_storage_buffer_storage_class"
5887 OpExtension "SPV_EXT_descriptor_indexing"
5888 OpMemoryModel Logical GLSL450
5889 OpEntryPoint GLCompute %main "main"
5890 OpExecutionMode %main LocalSize 1 1 1
5891 OpDecorate %struct Block
5892 OpMemberDecorate %struct 0 Offset 0
5893 OpMemberDecorate %struct 1 Offset 1
5894 OpDecorate %var DescriptorSet 0
5895 OpDecorate %var Binding 0
5896 %void = OpTypeVoid
5897 %float = OpTypeFloat 32
5898 %int = OpTypeInt 32 0
5899 %float2 = OpTypeVector %float 2
5900 %struct = OpTypeStruct %float %float2
5901 %struct_array = OpTypeRuntimeArray %struct
5902 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
5903 %var = OpVariable %ptr_ssbo_array StorageBuffer
5904 %void_fn = OpTypeFunction %void
5905 %main = OpFunction %void None %void_fn
5906 %entry = OpLabel
5907 OpReturn
5908 OpFunctionEnd
5909 )";
5910
5911 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5912 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5913 EXPECT_THAT(getDiagnosticString(),
5914 HasSubstr("Structure id 2 decorated as Block for variable in "
5915 "StorageBuffer storage class must follow standard "
5916 "storage buffer layout rules: member 1 at offset 1 is "
5917 "not aligned to 8"));
5918 }
5919
TEST_F(ValidateDecorations,MultiDimensionalArray)5920 TEST_F(ValidateDecorations, MultiDimensionalArray) {
5921 const std::string spirv = R"(
5922 OpCapability Shader
5923 OpMemoryModel Logical GLSL450
5924 OpEntryPoint GLCompute %main "main"
5925 OpExecutionMode %main LocalSize 1 1 1
5926 OpDecorate %struct Block
5927 OpMemberDecorate %struct 0 Offset 0
5928 OpDecorate %array_4 ArrayStride 4
5929 OpDecorate %array_3 ArrayStride 48
5930 OpDecorate %var DescriptorSet 0
5931 OpDecorate %var Binding 0
5932 %void = OpTypeVoid
5933 %int = OpTypeInt 32 0
5934 %int_3 = OpConstant %int 3
5935 %int_4 = OpConstant %int 4
5936 %array_4 = OpTypeArray %int %int_4
5937 %array_3 = OpTypeArray %array_4 %int_3
5938 %struct = OpTypeStruct %array_3
5939 %ptr_struct = OpTypePointer Uniform %struct
5940 %var = OpVariable %ptr_struct Uniform
5941 %void_fn = OpTypeFunction %void
5942 %main = OpFunction %void None %void_fn
5943 %entry = OpLabel
5944 OpReturn
5945 OpFunctionEnd
5946 )";
5947
5948 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5949 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5950 EXPECT_THAT(getDiagnosticString(),
5951 HasSubstr("Structure id 2 decorated as Block for variable in "
5952 "Uniform storage class must follow standard uniform "
5953 "buffer layout rules: member 0 contains an array with "
5954 "stride 4 not satisfying alignment to 16"));
5955 }
5956
TEST_F(ValidateDecorations,ImproperStraddleInArray)5957 TEST_F(ValidateDecorations, ImproperStraddleInArray) {
5958 const std::string spirv = R"(
5959 OpCapability Shader
5960 OpMemoryModel Logical GLSL450
5961 OpEntryPoint GLCompute %main "main"
5962 OpExecutionMode %main LocalSize 1 1 1
5963 OpDecorate %struct Block
5964 OpMemberDecorate %struct 0 Offset 0
5965 OpDecorate %array ArrayStride 24
5966 OpMemberDecorate %inner 0 Offset 0
5967 OpMemberDecorate %inner 1 Offset 4
5968 OpMemberDecorate %inner 2 Offset 12
5969 OpMemberDecorate %inner 3 Offset 16
5970 OpDecorate %var DescriptorSet 0
5971 OpDecorate %var Binding 0
5972 %void = OpTypeVoid
5973 %int = OpTypeInt 32 0
5974 %int_2 = OpConstant %int 2
5975 %int2 = OpTypeVector %int 2
5976 %inner = OpTypeStruct %int %int2 %int %int
5977 %array = OpTypeArray %inner %int_2
5978 %struct = OpTypeStruct %array
5979 %ptr_struct = OpTypePointer StorageBuffer %struct
5980 %var = OpVariable %ptr_struct StorageBuffer
5981 %void_fn = OpTypeFunction %void
5982 %main = OpFunction %void None %void_fn
5983 %entry = OpLabel
5984 OpReturn
5985 OpFunctionEnd
5986 )";
5987
5988 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
5989 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5990 EXPECT_THAT(getDiagnosticString(),
5991 HasSubstr("Structure id 4 decorated as Block for variable in "
5992 "StorageBuffer storage class must follow relaxed "
5993 "storage buffer layout rules: member 1 is an "
5994 "improperly straddling vector at offset 28"));
5995 }
5996
TEST_F(ValidateDecorations,LargeArray)5997 TEST_F(ValidateDecorations, LargeArray) {
5998 const std::string spirv = R"(
5999 OpCapability Shader
6000 OpMemoryModel Logical GLSL450
6001 OpEntryPoint GLCompute %main "main"
6002 OpExecutionMode %main LocalSize 1 1 1
6003 OpDecorate %struct Block
6004 OpMemberDecorate %struct 0 Offset 0
6005 OpDecorate %array ArrayStride 24
6006 OpMemberDecorate %inner 0 Offset 0
6007 OpMemberDecorate %inner 1 Offset 8
6008 OpMemberDecorate %inner 2 Offset 16
6009 OpMemberDecorate %inner 3 Offset 20
6010 OpDecorate %var DescriptorSet 0
6011 OpDecorate %var Binding 0
6012 %void = OpTypeVoid
6013 %int = OpTypeInt 32 0
6014 %int_2000000 = OpConstant %int 2000000
6015 %int2 = OpTypeVector %int 2
6016 %inner = OpTypeStruct %int %int2 %int %int
6017 %array = OpTypeArray %inner %int_2000000
6018 %struct = OpTypeStruct %array
6019 %ptr_struct = OpTypePointer StorageBuffer %struct
6020 %var = OpVariable %ptr_struct StorageBuffer
6021 %void_fn = OpTypeFunction %void
6022 %main = OpFunction %void None %void_fn
6023 %entry = OpLabel
6024 OpReturn
6025 OpFunctionEnd
6026 )";
6027
6028 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6029 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6030 }
6031
6032 // NonWritable
6033
6034 // Returns a SPIR-V shader module with variables in various storage classes,
6035 // parameterizable by which ID should be decorated as NonWritable.
ShaderWithNonWritableTarget(const std::string & target,bool member_decorate=false)6036 std::string ShaderWithNonWritableTarget(const std::string& target,
6037 bool member_decorate = false) {
6038 const std::string decoration_inst =
6039 std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") +
6040 target + (member_decorate ? " 0" : "");
6041
6042 return std::string(R"(
6043 OpCapability Shader
6044 OpCapability RuntimeDescriptorArrayEXT
6045 OpExtension "SPV_EXT_descriptor_indexing"
6046 OpExtension "SPV_KHR_storage_buffer_storage_class"
6047 OpMemoryModel Logical GLSL450
6048 OpEntryPoint Vertex %main "main"
6049 OpName %label "label"
6050 OpName %param_f "param_f"
6051 OpName %param_p "param_p"
6052 OpName %_ptr_imstor "_ptr_imstor"
6053 OpName %_ptr_imsam "_ptr_imsam"
6054 OpName %var_wg "var_wg"
6055 OpName %var_imsam "var_imsam"
6056 OpName %var_priv "var_priv"
6057 OpName %var_func "var_func"
6058 OpName %simple_struct "simple_struct"
6059
6060 OpDecorate %struct_b Block
6061 OpDecorate %struct_b_rtarr Block
6062 OpMemberDecorate %struct_b 0 Offset 0
6063 OpMemberDecorate %struct_b_rtarr 0 Offset 0
6064 OpDecorate %rtarr ArrayStride 4
6065 )") + decoration_inst +
6066
6067 R"( NonWritable
6068
6069 %void = OpTypeVoid
6070 %void_fn = OpTypeFunction %void
6071 %float = OpTypeFloat 32
6072 %float_0 = OpConstant %float 0
6073 %int = OpTypeInt 32 0
6074 %int_2 = OpConstant %int 2
6075 %struct_b = OpTypeStruct %float
6076 %rtarr = OpTypeRuntimeArray %float
6077 %struct_b_rtarr = OpTypeStruct %rtarr
6078 %simple_struct = OpTypeStruct %float
6079 ; storage image
6080 %imstor = OpTypeImage %float 2D 0 0 0 2 R32f
6081 ; sampled image
6082 %imsam = OpTypeImage %float 2D 0 0 0 1 R32f
6083 %array_imstor = OpTypeArray %imstor %int_2
6084 %rta_imstor = OpTypeRuntimeArray %imstor
6085
6086 %_ptr_Uniform_stb = OpTypePointer Uniform %struct_b
6087 %_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b
6088 %_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr
6089 %_ptr_Workgroup = OpTypePointer Workgroup %float
6090 %_ptr_Private = OpTypePointer Private %float
6091 %_ptr_Function = OpTypePointer Function %float
6092 %_ptr_imstor = OpTypePointer UniformConstant %imstor
6093 %_ptr_imsam = OpTypePointer UniformConstant %imsam
6094 %_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor
6095 %_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor
6096
6097 %extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor
6098
6099 %var_ubo = OpVariable %_ptr_Uniform_stb Uniform
6100 %var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer
6101 %var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer
6102 %var_wg = OpVariable %_ptr_Workgroup Workgroup
6103 %var_priv = OpVariable %_ptr_Private Private
6104 %var_imstor = OpVariable %_ptr_imstor UniformConstant
6105 %var_imsam = OpVariable %_ptr_imsam UniformConstant
6106 %var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant
6107 %var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant
6108
6109 %helper = OpFunction %void None %extra_fn
6110 %param_f = OpFunctionParameter %float
6111 %param_p = OpFunctionParameter %_ptr_Private
6112 %param_pimstor = OpFunctionParameter %_ptr_imstor
6113 %helper_label = OpLabel
6114 %helper_func_var = OpVariable %_ptr_Function Function
6115 OpReturn
6116 OpFunctionEnd
6117
6118 %main = OpFunction %void None %void_fn
6119 %label = OpLabel
6120 %var_func = OpVariable %_ptr_Function Function
6121 OpReturn
6122 OpFunctionEnd
6123 )";
6124 }
6125
TEST_F(ValidateDecorations,NonWritableLabelTargetBad)6126 TEST_F(ValidateDecorations, NonWritableLabelTargetBad) {
6127 std::string spirv = ShaderWithNonWritableTarget("%label");
6128
6129 CompileSuccessfully(spirv);
6130 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6131 EXPECT_THAT(getDiagnosticString(),
6132 HasSubstr("Target of NonWritable decoration must be a "
6133 "memory object declaration (a variable or a function "
6134 "parameter)\n %label = OpLabel"));
6135 }
6136
TEST_F(ValidateDecorations,NonWritableTypeTargetBad)6137 TEST_F(ValidateDecorations, NonWritableTypeTargetBad) {
6138 std::string spirv = ShaderWithNonWritableTarget("%void");
6139
6140 CompileSuccessfully(spirv);
6141 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6142 EXPECT_THAT(getDiagnosticString(),
6143 HasSubstr("Target of NonWritable decoration must be a "
6144 "memory object declaration (a variable or a function "
6145 "parameter)\n %void = OpTypeVoid"));
6146 }
6147
TEST_F(ValidateDecorations,NonWritableValueTargetBad)6148 TEST_F(ValidateDecorations, NonWritableValueTargetBad) {
6149 std::string spirv = ShaderWithNonWritableTarget("%float_0");
6150
6151 CompileSuccessfully(spirv);
6152 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6153 EXPECT_THAT(getDiagnosticString(),
6154 HasSubstr("Target of NonWritable decoration must be a "
6155 "memory object declaration (a variable or a function "
6156 "parameter)\n %float_0 = OpConstant %float 0"));
6157 }
6158
TEST_F(ValidateDecorations,NonWritableValueParamBad)6159 TEST_F(ValidateDecorations, NonWritableValueParamBad) {
6160 std::string spirv = ShaderWithNonWritableTarget("%param_f");
6161
6162 CompileSuccessfully(spirv);
6163 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6164 EXPECT_THAT(getDiagnosticString(),
6165 HasSubstr("Target of NonWritable decoration is invalid: must "
6166 "point to a storage image, uniform block, or storage "
6167 "buffer\n %param_f = OpFunctionParameter %float"));
6168 }
6169
TEST_F(ValidateDecorations,NonWritablePointerParamButWrongTypeBad)6170 TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) {
6171 std::string spirv = ShaderWithNonWritableTarget("%param_p");
6172
6173 CompileSuccessfully(spirv);
6174 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6175 EXPECT_THAT(
6176 getDiagnosticString(),
6177 HasSubstr(
6178 "Target of NonWritable decoration is invalid: must "
6179 "point to a storage image, uniform block, or storage "
6180 "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float"));
6181 }
6182
TEST_F(ValidateDecorations,NonWritablePointerParamStorageImageGood)6183 TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) {
6184 std::string spirv = ShaderWithNonWritableTarget("%param_pimstor");
6185
6186 CompileSuccessfully(spirv);
6187 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6188 EXPECT_THAT(getDiagnosticString(), Eq(""));
6189 }
6190
TEST_F(ValidateDecorations,NonWritableVarStorageImageGood)6191 TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) {
6192 std::string spirv = ShaderWithNonWritableTarget("%var_imstor");
6193
6194 CompileSuccessfully(spirv);
6195 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6196 EXPECT_THAT(getDiagnosticString(), Eq(""));
6197 }
6198
TEST_F(ValidateDecorations,NonWritableVarSampledImageBad)6199 TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) {
6200 std::string spirv = ShaderWithNonWritableTarget("%var_imsam");
6201
6202 CompileSuccessfully(spirv);
6203 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6204 EXPECT_THAT(getDiagnosticString(),
6205 HasSubstr("Target of NonWritable decoration is invalid: must "
6206 "point to a storage image, uniform block, or storage "
6207 "buffer\n %var_imsam"));
6208 }
6209
TEST_F(ValidateDecorations,NonWritableVarUboGood)6210 TEST_F(ValidateDecorations, NonWritableVarUboGood) {
6211 std::string spirv = ShaderWithNonWritableTarget("%var_ubo");
6212
6213 CompileSuccessfully(spirv);
6214 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6215 EXPECT_THAT(getDiagnosticString(), Eq(""));
6216 }
6217
TEST_F(ValidateDecorations,NonWritableVarSsboInUniformGood)6218 TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) {
6219 const std::string spirv = R"(
6220 OpCapability Shader
6221 OpMemoryModel Logical GLSL450
6222 OpEntryPoint Vertex %main "main"
6223 OpDecorate %struct_bb BufferBlock
6224 OpMemberDecorate %struct_bb 0 Offset 0
6225 OpDecorate %var_ssbo_u NonWritable
6226 %void = OpTypeVoid
6227 %void_fn = OpTypeFunction %void
6228 %float = OpTypeFloat 32
6229 %struct_bb = OpTypeStruct %float
6230 %_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb
6231 %var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform
6232 %main = OpFunction %void None %void_fn
6233 %label = OpLabel
6234 OpReturn
6235 OpFunctionEnd
6236 )";
6237
6238 CompileSuccessfully(spirv);
6239 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6240 EXPECT_THAT(getDiagnosticString(), Eq(""));
6241 }
6242
TEST_F(ValidateDecorations,NonWritableVarSsboInStorageBufferGood)6243 TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) {
6244 std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb");
6245
6246 CompileSuccessfully(spirv);
6247 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6248 EXPECT_THAT(getDiagnosticString(), Eq(""));
6249 }
6250
TEST_F(ValidateDecorations,NonWritableMemberOfSsboInStorageBufferGood)6251 TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) {
6252 std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true);
6253
6254 CompileSuccessfully(spirv);
6255 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6256 EXPECT_THAT(getDiagnosticString(), Eq(""));
6257 }
6258
TEST_F(ValidateDecorations,NonWritableMemberOfStructGood)6259 TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) {
6260 std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true);
6261
6262 CompileSuccessfully(spirv);
6263 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6264 }
6265
TEST_F(ValidateDecorations,NonWritableVarWorkgroupBad)6266 TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) {
6267 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6268
6269 CompileSuccessfully(spirv);
6270 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6271 EXPECT_THAT(getDiagnosticString(),
6272 HasSubstr("Target of NonWritable decoration is invalid: must "
6273 "point to a storage image, uniform block, or storage "
6274 "buffer\n %var_wg"));
6275 }
6276
TEST_F(ValidateDecorations,NonWritableVarWorkgroupV14Bad)6277 TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) {
6278 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6279
6280 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6281 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6282 EXPECT_THAT(getDiagnosticString(),
6283 HasSubstr("Target of NonWritable decoration is invalid: must "
6284 "point to a storage image, uniform block, storage "
6285 "buffer, or variable in Private or Function storage "
6286 "class\n %var_wg"));
6287 }
6288
TEST_F(ValidateDecorations,NonWritableVarPrivateBad)6289 TEST_F(ValidateDecorations, NonWritableVarPrivateBad) {
6290 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6291
6292 CompileSuccessfully(spirv);
6293 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6294 EXPECT_THAT(getDiagnosticString(),
6295 HasSubstr("Target of NonWritable decoration is invalid: must "
6296 "point to a storage image, uniform block, or storage "
6297 "buffer\n %var_priv"));
6298 }
6299
TEST_F(ValidateDecorations,NonWritableVarPrivateV13Bad)6300 TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) {
6301 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6302
6303 CompileSuccessfully(spirv);
6304 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6305 EXPECT_THAT(getDiagnosticString(),
6306 HasSubstr("Target of NonWritable decoration is invalid: must "
6307 "point to a storage image, uniform block, or storage "
6308 "buffer\n %var_priv"));
6309 }
6310
TEST_F(ValidateDecorations,NonWritableVarPrivateV14Good)6311 TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) {
6312 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6313
6314 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6315 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6316 EXPECT_THAT(getDiagnosticString(), Eq(""));
6317 }
6318
TEST_F(ValidateDecorations,NonWritableVarPrivateV13TargetV14Bad)6319 TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) {
6320 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6321
6322 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6323 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6324 EXPECT_THAT(getDiagnosticString(),
6325 HasSubstr("Target of NonWritable decoration is invalid: must "
6326 "point to a storage image, uniform block, or storage "
6327 "buffer\n %var_priv"));
6328 }
6329
TEST_F(ValidateDecorations,NonWritableVarFunctionBad)6330 TEST_F(ValidateDecorations, NonWritableVarFunctionBad) {
6331 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6332
6333 CompileSuccessfully(spirv);
6334 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6335 EXPECT_THAT(getDiagnosticString(),
6336 HasSubstr("Target of NonWritable decoration is invalid: must "
6337 "point to a storage image, uniform block, or storage "
6338 "buffer\n %var_func"));
6339 }
6340
TEST_F(ValidateDecorations,NonWritableArrayGood)6341 TEST_F(ValidateDecorations, NonWritableArrayGood) {
6342 std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor");
6343
6344 CompileSuccessfully(spirv);
6345 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6346 }
6347
TEST_F(ValidateDecorations,NonWritableRuntimeArrayGood)6348 TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) {
6349 std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor");
6350
6351 CompileSuccessfully(spirv);
6352 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6353 }
6354
TEST_P(ValidateVulkanCombineDecorationResult,Decorate)6355 TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
6356 const char* const decoration = std::get<0>(GetParam());
6357 const char* const vuid = std::get<1>(GetParam());
6358 const TestResult& test_result = std::get<2>(GetParam());
6359
6360 CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
6361 generator.before_types_ = "OpDecorate %u32 ";
6362 generator.before_types_ += decoration;
6363 generator.before_types_ += "\n";
6364
6365 EntryPoint entry_point;
6366 entry_point.name = "main";
6367 entry_point.execution_model = "Vertex";
6368 generator.entry_points_.push_back(std::move(entry_point));
6369
6370 CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
6371 ASSERT_EQ(test_result.validation_result,
6372 ValidateInstructions(SPV_ENV_VULKAN_1_0));
6373 if (!test_result.error_str.empty()) {
6374 EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
6375 }
6376 if (vuid) {
6377 EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
6378 }
6379 }
6380
6381 INSTANTIATE_TEST_SUITE_P(
6382 DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
6383 Combine(Values("GLSLShared", "GLSLPacked"),
6384 Values("VUID-StandaloneSpirv-GLSLShared-04669"),
6385 Values(TestResult(
6386 SPV_ERROR_INVALID_ID,
6387 "is not valid for the Vulkan execution environment."))));
6388
TEST_F(ValidateDecorations,NonWritableVarFunctionV13Bad)6389 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
6390 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6391
6392 CompileSuccessfully(spirv);
6393 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6394 EXPECT_THAT(getDiagnosticString(),
6395 HasSubstr("Target of NonWritable decoration is invalid: must "
6396 "point to a storage image, uniform block, or storage "
6397 "buffer\n %var_func"));
6398 }
6399
TEST_F(ValidateDecorations,NonWritableVarFunctionV14Good)6400 TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) {
6401 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6402
6403 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6404 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6405 EXPECT_THAT(getDiagnosticString(), Eq(""));
6406 }
6407
TEST_F(ValidateDecorations,NonWritableVarFunctionV13TargetV14Bad)6408 TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) {
6409 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6410
6411 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6412 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6413 EXPECT_THAT(getDiagnosticString(),
6414 HasSubstr("Target of NonWritable decoration is invalid: must "
6415 "point to a storage image, uniform block, or storage "
6416 "buffer\n %var_func"));
6417 }
6418
TEST_F(ValidateDecorations,BufferBlockV13ValV14Good)6419 TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) {
6420 std::string spirv = R"(
6421 OpCapability Shader
6422 OpCapability Linkage
6423 OpMemoryModel Logical GLSL450
6424 OpDecorate %1 BufferBlock
6425 %1 = OpTypeStruct
6426 )";
6427
6428 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6429 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6430 }
6431
TEST_F(ValidateDecorations,BufferBlockV14Bad)6432 TEST_F(ValidateDecorations, BufferBlockV14Bad) {
6433 std::string spirv = R"(
6434 OpCapability Shader
6435 OpCapability Linkage
6436 OpMemoryModel Logical GLSL450
6437 OpDecorate %1 BufferBlock
6438 %1 = OpTypeStruct
6439 )";
6440
6441 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6442 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
6443 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6444 EXPECT_THAT(getDiagnosticString(),
6445 HasSubstr("2nd operand of Decorate: operand BufferBlock(3) "
6446 "requires SPIR-V version 1.3 or earlier"));
6447 }
6448
6449 // Component
6450
TEST_F(ValidateDecorations,ComponentDecorationBadTarget)6451 TEST_F(ValidateDecorations, ComponentDecorationBadTarget) {
6452 std::string spirv = R"(
6453 OpCapability Shader
6454 OpMemoryModel Logical GLSL450
6455 OpEntryPoint Vertex %main "main"
6456 OpDecorate %t Component 0
6457 %void = OpTypeVoid
6458 %3 = OpTypeFunction %void
6459 %float = OpTypeFloat 32
6460 %t = OpTypeVector %float 2
6461 %main = OpFunction %void None %3
6462 %5 = OpLabel
6463 OpReturn
6464 OpFunctionEnd
6465 )";
6466
6467 CompileSuccessfully(spirv);
6468 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6469 EXPECT_THAT(getDiagnosticString(),
6470 HasSubstr("Target of Component decoration must be "
6471 "a memory object declaration"));
6472 }
6473
TEST_F(ValidateDecorations,ComponentDecorationBadStorageClass)6474 TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) {
6475 std::string spirv = R"(
6476 OpCapability Shader
6477 OpMemoryModel Logical GLSL450
6478 OpEntryPoint Vertex %main "main"
6479 OpDecorate %v Component 0
6480 %void = OpTypeVoid
6481 %3 = OpTypeFunction %void
6482 %float = OpTypeFloat 32
6483 %t = OpTypeVector %float 2
6484 %ptr_private = OpTypePointer Private %t
6485 %v = OpVariable %ptr_private Private
6486 %main = OpFunction %void None %3
6487 %5 = OpLabel
6488 OpReturn
6489 OpFunctionEnd
6490 )";
6491
6492 CompileSuccessfully(spirv);
6493 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6494 EXPECT_THAT(getDiagnosticString(),
6495 HasSubstr("Target of Component decoration is invalid: must "
6496 "point to a Storage Class of Input(1) or Output(3)"));
6497 }
6498
TEST_F(ValidateDecorations,ComponentDecorationBadTypeVulkan)6499 TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) {
6500 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6501 std::string spirv = R"(
6502 OpCapability Shader
6503 OpCapability Matrix
6504 OpMemoryModel Logical GLSL450
6505 OpEntryPoint Vertex %main "main"
6506 OpDecorate %v Component 0
6507 %void = OpTypeVoid
6508 %3 = OpTypeFunction %void
6509 %float = OpTypeFloat 32
6510 %vtype = OpTypeVector %float 4
6511 %t = OpTypeMatrix %vtype 4
6512 %ptr_input = OpTypePointer Input %t
6513 %v = OpVariable %ptr_input Input
6514 %main = OpFunction %void None %3
6515 %5 = OpLabel
6516 OpReturn
6517 OpFunctionEnd
6518 )";
6519
6520 CompileSuccessfully(spirv, env);
6521 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6522 EXPECT_THAT(getDiagnosticString(),
6523 HasSubstr("Component decoration specified for type"));
6524 EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
6525 }
6526
ShaderWithComponentDecoration(const std::string & type,const std::string & decoration)6527 std::string ShaderWithComponentDecoration(const std::string& type,
6528 const std::string& decoration) {
6529 return R"(
6530 OpCapability Shader
6531 OpMemoryModel Logical GLSL450
6532 OpEntryPoint Fragment %main "main" %entryPointOutput
6533 OpExecutionMode %main OriginUpperLeft
6534 OpDecorate %entryPointOutput Location 0
6535 OpDecorate %entryPointOutput )" +
6536 decoration + R"(
6537 %void = OpTypeVoid
6538 %3 = OpTypeFunction %void
6539 %float = OpTypeFloat 32
6540 %v3float = OpTypeVector %float 3
6541 %v4float = OpTypeVector %float 4
6542 %uint = OpTypeInt 32 0
6543 %uint_2 = OpConstant %uint 2
6544 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
6545 %float_0 = OpConstant %float 0
6546 %_ptr_Output_type = OpTypePointer Output %)" + type + R"(
6547 %entryPointOutput = OpVariable %_ptr_Output_type Output
6548 %main = OpFunction %void None %3
6549 %5 = OpLabel
6550 OpReturn
6551 OpFunctionEnd
6552 )";
6553 }
6554
TEST_F(ValidateDecorations,ComponentDecorationIntGood0Vulkan)6555 TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
6556 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6557 std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
6558
6559 CompileSuccessfully(spirv, env);
6560 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6561 EXPECT_THAT(getDiagnosticString(), Eq(""));
6562 }
6563
TEST_F(ValidateDecorations,ComponentDecorationIntGood1Vulkan)6564 TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
6565 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6566 std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
6567
6568 CompileSuccessfully(spirv, env);
6569 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6570 EXPECT_THAT(getDiagnosticString(), Eq(""));
6571 }
6572
TEST_F(ValidateDecorations,ComponentDecorationIntGood2Vulkan)6573 TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
6574 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6575 std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
6576
6577 CompileSuccessfully(spirv, env);
6578 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6579 EXPECT_THAT(getDiagnosticString(), Eq(""));
6580 }
6581
TEST_F(ValidateDecorations,ComponentDecorationIntGood3Vulkan)6582 TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
6583 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6584 std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
6585
6586 CompileSuccessfully(spirv, env);
6587 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6588 EXPECT_THAT(getDiagnosticString(), Eq(""));
6589 }
6590
TEST_F(ValidateDecorations,ComponentDecorationIntBad4Vulkan)6591 TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
6592 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6593 std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
6594
6595 CompileSuccessfully(spirv, env);
6596 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6597 EXPECT_THAT(getDiagnosticString(),
6598 HasSubstr("Sequence of components starting with 4 "
6599 "and ending with 4 gets larger than 3"));
6600 }
6601
TEST_F(ValidateDecorations,ComponentDecorationVector3GoodVulkan)6602 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
6603 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6604 std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
6605
6606 CompileSuccessfully(spirv, env);
6607 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6608 EXPECT_THAT(getDiagnosticString(), Eq(""));
6609 }
6610
TEST_F(ValidateDecorations,ComponentDecorationVector4GoodVulkan)6611 TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
6612 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6613 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
6614
6615 CompileSuccessfully(spirv, env);
6616 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6617 EXPECT_THAT(getDiagnosticString(), Eq(""));
6618 }
6619
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad1Vulkan)6620 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
6621 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6622 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
6623
6624 CompileSuccessfully(spirv, env);
6625 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6626 EXPECT_THAT(getDiagnosticString(),
6627 HasSubstr("Sequence of components starting with 1 "
6628 "and ending with 4 gets larger than 3"));
6629 }
6630
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad3Vulkan)6631 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
6632 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6633 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
6634
6635 CompileSuccessfully(spirv, env);
6636 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6637 EXPECT_THAT(getDiagnosticString(),
6638 HasSubstr("Sequence of components starting with 3 "
6639 "and ending with 6 gets larger than 3"));
6640 }
6641
TEST_F(ValidateDecorations,ComponentDecorationArrayGoodVulkan)6642 TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
6643 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6644 std::string spirv =
6645 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
6646
6647 CompileSuccessfully(spirv, env);
6648 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6649 EXPECT_THAT(getDiagnosticString(), Eq(""));
6650 }
6651
TEST_F(ValidateDecorations,ComponentDecorationArrayBadVulkan)6652 TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
6653 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6654 std::string spirv =
6655 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
6656
6657 CompileSuccessfully(spirv, env);
6658 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6659 EXPECT_THAT(getDiagnosticString(),
6660 HasSubstr("Sequence of components starting with 2 "
6661 "and ending with 4 gets larger than 3"));
6662 }
6663
TEST_F(ValidateDecorations,ComponentDecorationBlockGood)6664 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
6665 std::string spirv = R"(
6666 OpCapability Shader
6667 OpMemoryModel Logical GLSL450
6668 OpEntryPoint Fragment %4 "main" %9 %12
6669 OpExecutionMode %4 OriginUpperLeft
6670 OpDecorate %9 Location 0
6671 OpMemberDecorate %block 0 Location 2
6672 OpMemberDecorate %block 0 Component 1
6673 OpDecorate %block Block
6674 %2 = OpTypeVoid
6675 %3 = OpTypeFunction %2
6676 %float = OpTypeFloat 32
6677 %vec3 = OpTypeVector %float 3
6678 %8 = OpTypePointer Output %vec3
6679 %9 = OpVariable %8 Output
6680 %block = OpTypeStruct %vec3
6681 %11 = OpTypePointer Input %block
6682 %12 = OpVariable %11 Input
6683 %int = OpTypeInt 32 1
6684 %14 = OpConstant %int 0
6685 %15 = OpTypePointer Input %vec3
6686 %4 = OpFunction %2 None %3
6687 %5 = OpLabel
6688 %16 = OpAccessChain %15 %12 %14
6689 %17 = OpLoad %vec3 %16
6690 OpStore %9 %17
6691 OpReturn
6692 OpFunctionEnd
6693 )";
6694
6695 CompileSuccessfully(spirv);
6696 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6697 EXPECT_THAT(getDiagnosticString(), Eq(""));
6698 }
6699
TEST_F(ValidateDecorations,ComponentDecorationBlockBadVulkan)6700 TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) {
6701 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6702 std::string spirv = R"(
6703 OpCapability Shader
6704 OpMemoryModel Logical GLSL450
6705 OpEntryPoint Fragment %4 "main" %9 %12
6706 OpExecutionMode %4 OriginUpperLeft
6707 OpDecorate %9 Location 0
6708 OpMemberDecorate %block 0 Location 2
6709 OpMemberDecorate %block 0 Component 2
6710 OpDecorate %block Block
6711 %2 = OpTypeVoid
6712 %3 = OpTypeFunction %2
6713 %float = OpTypeFloat 32
6714 %vec3 = OpTypeVector %float 3
6715 %8 = OpTypePointer Output %vec3
6716 %9 = OpVariable %8 Output
6717 %block = OpTypeStruct %vec3
6718 %11 = OpTypePointer Input %block
6719 %12 = OpVariable %11 Input
6720 %int = OpTypeInt 32 1
6721 %14 = OpConstant %int 0
6722 %15 = OpTypePointer Input %vec3
6723 %4 = OpFunction %2 None %3
6724 %5 = OpLabel
6725 %16 = OpAccessChain %15 %12 %14
6726 %17 = OpLoad %vec3 %16
6727 OpStore %9 %17
6728 OpReturn
6729 OpFunctionEnd
6730 )";
6731
6732 CompileSuccessfully(spirv, env);
6733 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6734 EXPECT_THAT(getDiagnosticString(),
6735 HasSubstr("Sequence of components starting with 2 "
6736 "and ending with 4 gets larger than 3"));
6737 }
6738
TEST_F(ValidateDecorations,ComponentDecorationFunctionParameter)6739 TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
6740 std::string spirv = R"(
6741 OpCapability Shader
6742 OpMemoryModel Logical GLSL450
6743 OpEntryPoint Vertex %main "main"
6744
6745 OpDecorate %param_f Component 0
6746
6747 %void = OpTypeVoid
6748 %void_fn = OpTypeFunction %void
6749 %float = OpTypeFloat 32
6750 %float_0 = OpConstant %float 0
6751 %int = OpTypeInt 32 0
6752 %int_2 = OpConstant %int 2
6753 %struct_b = OpTypeStruct %float
6754
6755 %extra_fn = OpTypeFunction %void %float
6756
6757 %helper = OpFunction %void None %extra_fn
6758 %param_f = OpFunctionParameter %float
6759 %helper_label = OpLabel
6760 OpReturn
6761 OpFunctionEnd
6762
6763 %main = OpFunction %void None %void_fn
6764 %label = OpLabel
6765 OpReturn
6766 OpFunctionEnd
6767 )";
6768
6769 CompileSuccessfully(spirv);
6770 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6771 EXPECT_THAT(getDiagnosticString(), Eq(""));
6772 }
6773
TEST_F(ValidateDecorations,VulkanStorageBufferBlock)6774 TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
6775 const std::string spirv = R"(
6776 OpCapability Shader
6777 OpExtension "SPV_KHR_storage_buffer_storage_class"
6778 OpMemoryModel Logical GLSL450
6779 OpEntryPoint GLCompute %main "main"
6780 OpExecutionMode %main LocalSize 1 1 1
6781 OpDecorate %struct Block
6782 OpMemberDecorate %struct 0 Offset 0
6783 %void = OpTypeVoid
6784 %uint = OpTypeInt 32 0
6785 %struct = OpTypeStruct %uint
6786 %ptr_ssbo = OpTypePointer StorageBuffer %struct
6787 %var = OpVariable %ptr_ssbo StorageBuffer
6788 %void_fn = OpTypeFunction %void
6789 %main = OpFunction %void None %void_fn
6790 %entry = OpLabel
6791 OpReturn
6792 OpFunctionEnd
6793 )";
6794
6795 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6796 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6797 }
6798
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBlock)6799 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
6800 const std::string spirv = R"(
6801 OpCapability Shader
6802 OpExtension "SPV_KHR_storage_buffer_storage_class"
6803 OpMemoryModel Logical GLSL450
6804 OpEntryPoint GLCompute %main "main"
6805 OpExecutionMode %main LocalSize 1 1 1
6806 %void = OpTypeVoid
6807 %uint = OpTypeInt 32 0
6808 %struct = OpTypeStruct %uint
6809 %ptr_ssbo = OpTypePointer StorageBuffer %struct
6810 %var = OpVariable %ptr_ssbo StorageBuffer
6811 %void_fn = OpTypeFunction %void
6812 %main = OpFunction %void None %void_fn
6813 %entry = OpLabel
6814 OpReturn
6815 OpFunctionEnd
6816 )";
6817
6818 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6819 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6820 EXPECT_THAT(getDiagnosticString(),
6821 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6822 "must be identified with a Block decoration"));
6823 }
6824
TEST_F(ValidateDecorations,VulkanStorageBufferArrayMissingBlock)6825 TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
6826 const std::string spirv = R"(
6827 OpCapability Shader
6828 OpExtension "SPV_KHR_storage_buffer_storage_class"
6829 OpMemoryModel Logical GLSL450
6830 OpEntryPoint GLCompute %main "main"
6831 OpExecutionMode %main LocalSize 1 1 1
6832 %void = OpTypeVoid
6833 %uint = OpTypeInt 32 0
6834 %uint_4 = OpConstant %uint 4
6835 %struct = OpTypeStruct %uint
6836 %array = OpTypeArray %struct %uint_4
6837 %ptr_ssbo = OpTypePointer StorageBuffer %array
6838 %var = OpVariable %ptr_ssbo StorageBuffer
6839 %void_fn = OpTypeFunction %void
6840 %main = OpFunction %void None %void_fn
6841 %entry = OpLabel
6842 OpReturn
6843 OpFunctionEnd
6844 )";
6845
6846 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6847 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6848 EXPECT_THAT(getDiagnosticString(),
6849 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6850 "must be identified with a Block decoration"));
6851 }
6852
TEST_F(ValidateDecorations,VulkanStorageBufferRuntimeArrayMissingBlock)6853 TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
6854 const std::string spirv = R"(
6855 OpCapability Shader
6856 OpCapability RuntimeDescriptorArrayEXT
6857 OpExtension "SPV_EXT_descriptor_indexing"
6858 OpExtension "SPV_KHR_storage_buffer_storage_class"
6859 OpMemoryModel Logical GLSL450
6860 OpEntryPoint GLCompute %main "main"
6861 OpExecutionMode %main LocalSize 1 1 1
6862 %void = OpTypeVoid
6863 %uint = OpTypeInt 32 0
6864 %struct = OpTypeStruct %uint
6865 %array = OpTypeRuntimeArray %struct
6866 %ptr_ssbo = OpTypePointer StorageBuffer %array
6867 %var = OpVariable %ptr_ssbo StorageBuffer
6868 %void_fn = OpTypeFunction %void
6869 %main = OpFunction %void None %void_fn
6870 %entry = OpLabel
6871 OpReturn
6872 OpFunctionEnd
6873 )";
6874
6875 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6876 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6877 EXPECT_THAT(getDiagnosticString(),
6878 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6879 "must be identified with a Block decoration"));
6880 }
6881
TEST_F(ValidateDecorations,VulkanUniformBlock)6882 TEST_F(ValidateDecorations, VulkanUniformBlock) {
6883 const std::string spirv = R"(
6884 OpCapability Shader
6885 OpMemoryModel Logical GLSL450
6886 OpEntryPoint GLCompute %main "main"
6887 OpExecutionMode %main LocalSize 1 1 1
6888 OpDecorate %struct Block
6889 OpMemberDecorate %struct 0 Offset 0
6890 %void = OpTypeVoid
6891 %uint = OpTypeInt 32 0
6892 %struct = OpTypeStruct %uint
6893 %ptr_ubo = OpTypePointer Uniform %struct
6894 %var = OpVariable %ptr_ubo Uniform
6895 %void_fn = OpTypeFunction %void
6896 %main = OpFunction %void None %void_fn
6897 %entry = OpLabel
6898 OpReturn
6899 OpFunctionEnd
6900 )";
6901
6902 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6903 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6904 }
6905
TEST_F(ValidateDecorations,VulkanUniformBufferBlock)6906 TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
6907 const std::string spirv = R"(
6908 OpCapability Shader
6909 OpMemoryModel Logical GLSL450
6910 OpEntryPoint GLCompute %main "main"
6911 OpExecutionMode %main LocalSize 1 1 1
6912 OpDecorate %struct BufferBlock
6913 OpMemberDecorate %struct 0 Offset 0
6914 %void = OpTypeVoid
6915 %uint = OpTypeInt 32 0
6916 %struct = OpTypeStruct %uint
6917 %ptr_ubo = OpTypePointer Uniform %struct
6918 %var = OpVariable %ptr_ubo Uniform
6919 %void_fn = OpTypeFunction %void
6920 %main = OpFunction %void None %void_fn
6921 %entry = OpLabel
6922 OpReturn
6923 OpFunctionEnd
6924 )";
6925
6926 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6927 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6928 }
6929
TEST_F(ValidateDecorations,VulkanUniformMissingBlock)6930 TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
6931 const std::string spirv = R"(
6932 OpCapability Shader
6933 OpMemoryModel Logical GLSL450
6934 OpEntryPoint GLCompute %main "main"
6935 OpExecutionMode %main LocalSize 1 1 1
6936 %void = OpTypeVoid
6937 %uint = OpTypeInt 32 0
6938 %struct = OpTypeStruct %uint
6939 %ptr_ubo = OpTypePointer Uniform %struct
6940 %var = OpVariable %ptr_ubo Uniform
6941 %void_fn = OpTypeFunction %void
6942 %main = OpFunction %void None %void_fn
6943 %entry = OpLabel
6944 OpReturn
6945 OpFunctionEnd
6946 )";
6947
6948 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6949 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6950 EXPECT_THAT(
6951 getDiagnosticString(),
6952 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
6953 "identified with a Block or BufferBlock decoration"));
6954 }
6955
TEST_F(ValidateDecorations,VulkanUniformArrayMissingBlock)6956 TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
6957 const std::string spirv = R"(
6958 OpCapability Shader
6959 OpMemoryModel Logical GLSL450
6960 OpEntryPoint GLCompute %main "main"
6961 OpExecutionMode %main LocalSize 1 1 1
6962 %void = OpTypeVoid
6963 %uint = OpTypeInt 32 0
6964 %uint_4 = OpConstant %uint 4
6965 %struct = OpTypeStruct %uint
6966 %array = OpTypeArray %struct %uint_4
6967 %ptr_ubo = OpTypePointer Uniform %array
6968 %var = OpVariable %ptr_ubo Uniform
6969 %void_fn = OpTypeFunction %void
6970 %main = OpFunction %void None %void_fn
6971 %entry = OpLabel
6972 OpReturn
6973 OpFunctionEnd
6974 )";
6975
6976 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6977 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6978 EXPECT_THAT(
6979 getDiagnosticString(),
6980 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
6981 "identified with a Block or BufferBlock decoration"));
6982 }
6983
TEST_F(ValidateDecorations,VulkanUniformRuntimeArrayMissingBlock)6984 TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
6985 const std::string spirv = R"(
6986 OpCapability Shader
6987 OpCapability RuntimeDescriptorArrayEXT
6988 OpExtension "SPV_EXT_descriptor_indexing"
6989 OpMemoryModel Logical GLSL450
6990 OpEntryPoint GLCompute %main "main"
6991 OpExecutionMode %main LocalSize 1 1 1
6992 %void = OpTypeVoid
6993 %uint = OpTypeInt 32 0
6994 %struct = OpTypeStruct %uint
6995 %array = OpTypeRuntimeArray %struct
6996 %ptr_ubo = OpTypePointer Uniform %array
6997 %var = OpVariable %ptr_ubo Uniform
6998 %void_fn = OpTypeFunction %void
6999 %main = OpFunction %void None %void_fn
7000 %entry = OpLabel
7001 OpReturn
7002 OpFunctionEnd
7003 )";
7004
7005 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7006 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7007 EXPECT_THAT(
7008 getDiagnosticString(),
7009 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
7010 "identified with a Block or BufferBlock decoration"));
7011 }
7012
TEST_F(ValidateDecorations,VulkanArrayStrideZero)7013 TEST_F(ValidateDecorations, VulkanArrayStrideZero) {
7014 const std::string spirv = R"(
7015 OpCapability Shader
7016 OpMemoryModel Logical GLSL450
7017 OpEntryPoint GLCompute %main "main"
7018 OpExecutionMode %main LocalSize 1 1 1
7019 OpDecorate %var DescriptorSet 0
7020 OpDecorate %var Binding 0
7021 OpDecorate %struct Block
7022 OpMemberDecorate %struct 0 Offset 0
7023 OpDecorate %array ArrayStride 0
7024 %void = OpTypeVoid
7025 %int = OpTypeInt 32 0
7026 %int_4 = OpConstant %int 4
7027 %array = OpTypeArray %int %int_4
7028 %struct = OpTypeStruct %array
7029 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7030 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7031 %void_fn = OpTypeFunction %void
7032 %main = OpFunction %void None %void_fn
7033 %entry = OpLabel
7034 OpReturn
7035 OpFunctionEnd
7036 )";
7037
7038 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7039 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7040 EXPECT_THAT(getDiagnosticString(),
7041 HasSubstr("contains an array with stride 0"));
7042 }
7043
TEST_F(ValidateDecorations,VulkanArrayStrideTooSmall)7044 TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) {
7045 const std::string spirv = R"(
7046 OpCapability Shader
7047 OpMemoryModel Logical GLSL450
7048 OpEntryPoint GLCompute %main "main"
7049 OpExecutionMode %main LocalSize 1 1 1
7050 OpDecorate %var DescriptorSet 0
7051 OpDecorate %var Binding 0
7052 OpDecorate %struct Block
7053 OpMemberDecorate %struct 0 Offset 0
7054 OpDecorate %inner ArrayStride 4
7055 OpDecorate %outer ArrayStride 4
7056 %void = OpTypeVoid
7057 %int = OpTypeInt 32 0
7058 %int_4 = OpConstant %int 4
7059 %inner = OpTypeArray %int %int_4
7060 %outer = OpTypeArray %inner %int_4
7061 %struct = OpTypeStruct %outer
7062 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7063 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7064 %void_fn = OpTypeFunction %void
7065 %main = OpFunction %void None %void_fn
7066 %entry = OpLabel
7067 OpReturn
7068 OpFunctionEnd
7069 )";
7070
7071 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7072 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7073 EXPECT_THAT(
7074 getDiagnosticString(),
7075 HasSubstr(
7076 "contains an array with stride 4, but with an element size of 16"));
7077 }
7078
TEST_F(ValidateDecorations,FunctionsWithOpGroupDecorate)7079 TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate) {
7080 std::string spirv = R"(
7081 OpCapability Addresses
7082 OpCapability Linkage
7083 OpCapability Kernel
7084 OpCapability Int8
7085 %1 = OpExtInstImport "OpenCL.std"
7086 OpMemoryModel Physical32 OpenCL
7087 OpName %foo "foo"
7088 OpName %entry "entry"
7089 OpName %bar "bar"
7090 OpName %entry_0 "entry"
7091 OpName %k "k"
7092 OpName %entry_1 "entry"
7093 OpName %b "b"
7094 OpDecorate %28 FuncParamAttr Zext
7095 %28 = OpDecorationGroup
7096 OpDecorate %k LinkageAttributes "k" Export
7097 OpDecorate %foo LinkageAttributes "foo" Export
7098 OpDecorate %bar LinkageAttributes "bar" Export
7099 OpDecorate %b Alignment 1
7100 OpGroupDecorate %28 %foo %bar
7101 %uchar = OpTypeInt 8 0
7102 %bool = OpTypeBool
7103 %3 = OpTypeFunction %bool
7104 %void = OpTypeVoid
7105 %10 = OpTypeFunction %void
7106 %_ptr_Function_uchar = OpTypePointer Function %uchar
7107 %true = OpConstantTrue %bool
7108 %foo = OpFunction %bool DontInline %3
7109 %entry = OpLabel
7110 OpReturnValue %true
7111 OpFunctionEnd
7112 %bar = OpFunction %bool DontInline %3
7113 %entry_0 = OpLabel
7114 OpReturnValue %true
7115 OpFunctionEnd
7116 %k = OpFunction %void DontInline %10
7117 %entry_1 = OpLabel
7118 %b = OpVariable %_ptr_Function_uchar Function
7119 OpReturn
7120 OpFunctionEnd
7121 )";
7122 CompileSuccessfully(spirv);
7123 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7124 }
7125
TEST_F(ValidateDecorations,LocationVariableGood)7126 TEST_F(ValidateDecorations, LocationVariableGood) {
7127 const std::string spirv = R"(
7128 OpCapability Shader
7129 OpCapability Linkage
7130 OpMemoryModel Logical GLSL450
7131 OpDecorate %in_var Location 0
7132 %float = OpTypeFloat 32
7133 %ptr_input_float = OpTypePointer Input %float
7134 %in_var = OpVariable %ptr_input_float Input
7135 )";
7136
7137 CompileSuccessfully(spirv);
7138 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7139 }
7140
TEST_F(ValidateDecorations,LocationStructMemberGood)7141 TEST_F(ValidateDecorations, LocationStructMemberGood) {
7142 const std::string spirv = R"(
7143 OpCapability Shader
7144 OpCapability Linkage
7145 OpMemoryModel Logical GLSL450
7146 OpMemberDecorate %struct 0 Location 0
7147 %float = OpTypeFloat 32
7148 %struct = OpTypeStruct %float
7149 )";
7150
7151 CompileSuccessfully(spirv);
7152 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7153 }
7154
TEST_F(ValidateDecorations,LocationStructBad)7155 TEST_F(ValidateDecorations, LocationStructBad) {
7156 const std::string spirv = R"(
7157 OpCapability Shader
7158 OpCapability Linkage
7159 OpMemoryModel Logical GLSL450
7160 OpDecorate %struct Location 0
7161 %float = OpTypeFloat 32
7162 %struct = OpTypeStruct %float
7163 )";
7164
7165 CompileSuccessfully(spirv);
7166 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7167 EXPECT_THAT(getDiagnosticString(),
7168 HasSubstr("Location decoration can only be applied to a variable "
7169 "or member of a structure type"));
7170 }
7171
TEST_F(ValidateDecorations,LocationFloatBad)7172 TEST_F(ValidateDecorations, LocationFloatBad) {
7173 const std::string spirv = R"(
7174 OpCapability Shader
7175 OpCapability Linkage
7176 OpMemoryModel Logical GLSL450
7177 OpDecorate %float Location 0
7178 %float = OpTypeFloat 32
7179 )";
7180
7181 CompileSuccessfully(spirv);
7182 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7183 EXPECT_THAT(getDiagnosticString(),
7184 HasSubstr("Location decoration can only be applied to a variable "
7185 "or member of a structure type"));
7186 }
7187
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariable)7188 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable) {
7189 std::string spirv = R"(
7190 OpCapability Shader
7191 OpCapability WorkgroupMemoryExplicitLayoutKHR
7192 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7193 OpMemoryModel Logical GLSL450
7194 OpEntryPoint GLCompute %main "main" %_
7195 OpExecutionMode %main LocalSize 8 1 1
7196 OpMemberDecorate %first 0 Offset 0
7197 OpDecorate %first Block
7198 %void = OpTypeVoid
7199 %3 = OpTypeFunction %void
7200 %int = OpTypeInt 32 1
7201 %first = OpTypeStruct %int
7202 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7203 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7204 %int_0 = OpConstant %int 0
7205 %int_2 = OpConstant %int 2
7206 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7207 %main = OpFunction %void None %3
7208 %5 = OpLabel
7209 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7210 OpStore %13 %int_2
7211 OpReturn
7212 OpFunctionEnd
7213 )";
7214
7215 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7216 EXPECT_EQ(SPV_SUCCESS,
7217 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7218 }
7219
TEST_F(ValidateDecorations,WorkgroupBlockVariableRequiresV14)7220 TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14) {
7221 std::string spirv = R"(
7222 OpCapability Shader
7223 OpCapability WorkgroupMemoryExplicitLayoutKHR
7224 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7225 OpMemoryModel Logical GLSL450
7226 OpEntryPoint GLCompute %main "main" %_
7227 OpExecutionMode %main LocalSize 8 1 1
7228 OpMemberDecorate %first 0 Offset 0
7229 OpDecorate %first Block
7230 %void = OpTypeVoid
7231 %3 = OpTypeFunction %void
7232 %int = OpTypeInt 32 1
7233 %first = OpTypeStruct %int
7234 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7235 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7236 %int_0 = OpConstant %int 0
7237 %int_2 = OpConstant %int 2
7238 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7239 %main = OpFunction %void None %3
7240 %5 = OpLabel
7241 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7242 OpStore %13 %int_2
7243 OpReturn
7244 OpFunctionEnd
7245 )";
7246
7247 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7248 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
7249 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7250 EXPECT_THAT(getDiagnosticString(),
7251 HasSubstr("requires SPIR-V version 1.4 or later"));
7252 }
7253
TEST_F(ValidateDecorations,WorkgroupSingleNonBlockVariable)7254 TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable) {
7255 std::string spirv = R"(
7256 OpCapability Shader
7257 OpMemoryModel Logical GLSL450
7258 OpEntryPoint GLCompute %main "main" %a
7259 OpExecutionMode %main LocalSize 8 1 1
7260 %void = OpTypeVoid
7261 %3 = OpTypeFunction %void
7262 %int = OpTypeInt 32 1
7263 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7264 %a = OpVariable %_ptr_Workgroup_int Workgroup
7265 %int_2 = OpConstant %int 2
7266 %main = OpFunction %void None %3
7267 %5 = OpLabel
7268 OpStore %a %int_2
7269 OpReturn
7270 OpFunctionEnd
7271 )";
7272
7273 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7274 EXPECT_EQ(SPV_SUCCESS,
7275 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7276 }
7277
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariable)7278 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable) {
7279 std::string spirv = R"(
7280 OpCapability Shader
7281 OpCapability WorkgroupMemoryExplicitLayoutKHR
7282 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7283 OpMemoryModel Logical GLSL450
7284 OpEntryPoint GLCompute %main "main" %_ %__0
7285 OpExecutionMode %main LocalSize 8 1 1
7286 OpMemberDecorate %first 0 Offset 0
7287 OpDecorate %first Block
7288 OpMemberDecorate %second 0 Offset 0
7289 OpDecorate %second Block
7290 OpDecorate %_ Aliased
7291 OpDecorate %__0 Aliased
7292 %void = OpTypeVoid
7293 %3 = OpTypeFunction %void
7294 %int = OpTypeInt 32 1
7295 %first = OpTypeStruct %int
7296 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7297 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7298 %int_0 = OpConstant %int 0
7299 %int_2 = OpConstant %int 2
7300 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7301 %second = OpTypeStruct %int
7302 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7303 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7304 %int_3 = OpConstant %int 3
7305 %main = OpFunction %void None %3
7306 %5 = OpLabel
7307 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7308 OpStore %13 %int_2
7309 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7310 OpStore %18 %int_3
7311 OpReturn
7312 OpFunctionEnd
7313 )";
7314
7315 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7316 EXPECT_EQ(SPV_SUCCESS,
7317 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7318 }
7319
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith8BitType)7320 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith8BitType) {
7321 std::string spirv = R"(
7322 OpCapability Shader
7323 OpCapability Int8
7324 OpCapability WorkgroupMemoryExplicitLayout8BitAccessKHR
7325 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7326 OpMemoryModel Logical GLSL450
7327 OpEntryPoint GLCompute %main "main" %_
7328 OpExecutionMode %main LocalSize 2 1 1
7329 OpMemberDecorate %first 0 Offset 0
7330 OpDecorate %first Block
7331 %void = OpTypeVoid
7332 %3 = OpTypeFunction %void
7333 %char = OpTypeInt 8 1
7334 %first = OpTypeStruct %char
7335 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7336 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7337 %int = OpTypeInt 32 1
7338 %int_0 = OpConstant %int 0
7339 %char_2 = OpConstant %char 2
7340 %_ptr_Workgroup_char = OpTypePointer Workgroup %char
7341 %main = OpFunction %void None %3
7342 %5 = OpLabel
7343 %14 = OpAccessChain %_ptr_Workgroup_char %_ %int_0
7344 OpStore %14 %char_2
7345 OpReturn
7346 OpFunctionEnd
7347 )";
7348
7349 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7350 EXPECT_EQ(SPV_SUCCESS,
7351 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7352 }
7353
TEST_F(ValidateDecorations,WorkgroupMultiNonBlockVariable)7354 TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable) {
7355 std::string spirv = R"(
7356 OpCapability Shader
7357 OpMemoryModel Logical GLSL450
7358 OpEntryPoint GLCompute %main "main" %a %b
7359 OpExecutionMode %main LocalSize 8 1 1
7360 %void = OpTypeVoid
7361 %3 = OpTypeFunction %void
7362 %int = OpTypeInt 32 1
7363 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7364 %a = OpVariable %_ptr_Workgroup_int Workgroup
7365 %int_2 = OpConstant %int 2
7366 %b = OpVariable %_ptr_Workgroup_int Workgroup
7367 %int_3 = OpConstant %int 3
7368 %main = OpFunction %void None %3
7369 %5 = OpLabel
7370 OpStore %a %int_2
7371 OpStore %b %int_3
7372 OpReturn
7373 OpFunctionEnd
7374 )";
7375
7376 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7377 EXPECT_EQ(SPV_SUCCESS,
7378 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7379 }
7380
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith16BitType)7381 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType) {
7382 std::string spirv = R"(
7383 OpCapability Shader
7384 OpCapability Float16
7385 OpCapability Int16
7386 OpCapability WorkgroupMemoryExplicitLayout16BitAccessKHR
7387 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7388 OpMemoryModel Logical GLSL450
7389 OpEntryPoint GLCompute %main "main" %_
7390 OpExecutionMode %main LocalSize 2 1 1
7391 OpMemberDecorate %first 0 Offset 0
7392 OpMemberDecorate %first 1 Offset 2
7393 OpDecorate %first Block
7394 %void = OpTypeVoid
7395 %3 = OpTypeFunction %void
7396 %short = OpTypeInt 16 1
7397 %half = OpTypeFloat 16
7398 %first = OpTypeStruct %short %half
7399 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7400 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7401 %int = OpTypeInt 32 1
7402 %int_0 = OpConstant %int 0
7403 %short_3 = OpConstant %short 3
7404 %_ptr_Workgroup_short = OpTypePointer Workgroup %short
7405 %int_1 = OpConstant %int 1
7406 %half_0x1_898p_3 = OpConstant %half 0x1.898p+3
7407 %_ptr_Workgroup_half = OpTypePointer Workgroup %half
7408 %main = OpFunction %void None %3
7409 %5 = OpLabel
7410 %15 = OpAccessChain %_ptr_Workgroup_short %_ %int_0
7411 OpStore %15 %short_3
7412 %19 = OpAccessChain %_ptr_Workgroup_half %_ %int_1
7413 OpStore %19 %half_0x1_898p_3
7414 OpReturn
7415 OpFunctionEnd
7416 )";
7417
7418 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7419 EXPECT_EQ(SPV_SUCCESS,
7420 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7421 }
7422
TEST_F(ValidateDecorations,WorkgroupBlockVariableScalarLayout)7423 TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout) {
7424 std::string spirv = R"(
7425 OpCapability Shader
7426 OpCapability WorkgroupMemoryExplicitLayoutKHR
7427 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7428 OpMemoryModel Logical GLSL450
7429 OpEntryPoint Vertex %main "main" %B
7430 OpSource GLSL 450
7431 OpMemberDecorate %S 0 Offset 0
7432 OpMemberDecorate %S 1 Offset 4
7433 OpMemberDecorate %S 2 Offset 16
7434 OpMemberDecorate %S 3 Offset 28
7435 OpDecorate %S Block
7436 OpDecorate %B Aliased
7437 %void = OpTypeVoid
7438 %3 = OpTypeFunction %void
7439 %float = OpTypeFloat 32
7440 %v3float = OpTypeVector %float 3
7441 %S = OpTypeStruct %float %v3float %v3float %v3float
7442 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
7443 %B = OpVariable %_ptr_Workgroup_S Workgroup
7444 %main = OpFunction %void None %3
7445 %5 = OpLabel
7446 OpReturn
7447 OpFunctionEnd
7448 )";
7449
7450 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7451 spvValidatorOptionsSetWorkgroupScalarBlockLayout(getValidatorOptions(), true);
7452 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4))
7453 << getDiagnosticString();
7454 }
7455
TEST_F(ValidateDecorations,WorkgroupMixBlockAndNonBlockBad)7456 TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad) {
7457 std::string spirv = R"(
7458 OpCapability Shader
7459 OpCapability WorkgroupMemoryExplicitLayoutKHR
7460 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7461 OpMemoryModel Logical GLSL450
7462 OpEntryPoint GLCompute %main "main" %_ %b
7463 OpExecutionMode %main LocalSize 8 1 1
7464 OpMemberDecorate %first 0 Offset 0
7465 OpDecorate %first Block
7466 OpDecorate %_ Aliased
7467 OpDecorate %b Aliased
7468 %void = OpTypeVoid
7469 %3 = OpTypeFunction %void
7470 %int = OpTypeInt 32 1
7471 %first = OpTypeStruct %int
7472 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7473 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7474 %int_0 = OpConstant %int 0
7475 %int_2 = OpConstant %int 2
7476 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7477 %b = OpVariable %_ptr_Workgroup_int Workgroup
7478 %int_3 = OpConstant %int 3
7479 %main = OpFunction %void None %3
7480 %5 = OpLabel
7481 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7482 OpStore %13 %int_2
7483 OpStore %b %int_3
7484 OpReturn
7485 OpFunctionEnd
7486 )";
7487
7488 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7489 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7490 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7491 EXPECT_THAT(
7492 getDiagnosticString(),
7493 HasSubstr("either all or none of the Workgroup Storage Class variables "
7494 "in the entry point interface must point to struct types "
7495 "decorated with Block"));
7496 }
7497
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariableMissingAliased)7498 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased) {
7499 std::string spirv = R"(
7500 OpCapability Shader
7501 OpCapability WorkgroupMemoryExplicitLayoutKHR
7502 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7503 OpMemoryModel Logical GLSL450
7504 OpEntryPoint GLCompute %main "main" %_ %__0
7505 OpExecutionMode %main LocalSize 8 1 1
7506 OpMemberDecorate %first 0 Offset 0
7507 OpDecorate %first Block
7508 OpMemberDecorate %second 0 Offset 0
7509 OpDecorate %second Block
7510 OpDecorate %_ Aliased
7511 %void = OpTypeVoid
7512 %3 = OpTypeFunction %void
7513 %int = OpTypeInt 32 1
7514 %first = OpTypeStruct %int
7515 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7516 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7517 %int_0 = OpConstant %int 0
7518 %int_2 = OpConstant %int 2
7519 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7520 %second = OpTypeStruct %int
7521 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7522 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7523 %int_3 = OpConstant %int 3
7524 %main = OpFunction %void None %3
7525 %5 = OpLabel
7526 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7527 OpStore %13 %int_2
7528 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7529 OpStore %18 %int_3
7530 OpReturn
7531 OpFunctionEnd
7532 )";
7533
7534 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7535 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7536 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7537 EXPECT_THAT(
7538 getDiagnosticString(),
7539 HasSubstr("more than one Workgroup Storage Class variable in the "
7540 "entry point interface point to a type decorated with Block, "
7541 "all of them must be decorated with Aliased"));
7542 }
7543
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableNotAStruct)7544 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct) {
7545 std::string spirv = R"(
7546 OpCapability Shader
7547 OpCapability WorkgroupMemoryExplicitLayoutKHR
7548 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7549 OpMemoryModel Logical GLSL450
7550 OpEntryPoint GLCompute %main "main" %_
7551 OpExecutionMode %main LocalSize 8 1 1
7552 OpDecorate %first Block
7553 %void = OpTypeVoid
7554 %3 = OpTypeFunction %void
7555 %int = OpTypeInt 32 1
7556 %int_3 = OpConstant %int 3
7557 %first = OpTypeArray %int %int_3
7558 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7559 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7560 %int_0 = OpConstant %int 0
7561 %int_2 = OpConstant %int 2
7562 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7563 %main = OpFunction %void None %3
7564 %5 = OpLabel
7565 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7566 OpStore %13 %int_2
7567 OpReturn
7568 OpFunctionEnd
7569 )";
7570
7571 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7572 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7573 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7574 EXPECT_THAT(
7575 getDiagnosticString(),
7576 HasSubstr("Block decoration on a non-struct type"));
7577 }
7578
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableMissingLayout)7579 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout) {
7580 std::string spirv = R"(
7581 OpCapability Shader
7582 OpCapability WorkgroupMemoryExplicitLayoutKHR
7583 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7584 OpMemoryModel Logical GLSL450
7585 OpEntryPoint GLCompute %main "main" %_
7586 OpExecutionMode %main LocalSize 8 1 1
7587 OpDecorate %first Block
7588 %void = OpTypeVoid
7589 %3 = OpTypeFunction %void
7590 %int = OpTypeInt 32 1
7591 %first = OpTypeStruct %int
7592 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7593 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7594 %int_0 = OpConstant %int 0
7595 %int_2 = OpConstant %int 2
7596 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7597 %main = OpFunction %void None %3
7598 %5 = OpLabel
7599 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7600 OpStore %13 %int_2
7601 OpReturn
7602 OpFunctionEnd
7603 )";
7604
7605 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7606 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7607 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7608 EXPECT_THAT(
7609 getDiagnosticString(),
7610 HasSubstr("Block must be explicitly laid out with Offset decorations"));
7611 }
7612
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableBadLayout)7613 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout) {
7614 std::string spirv = R"(
7615 OpCapability Shader
7616 OpCapability WorkgroupMemoryExplicitLayoutKHR
7617 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7618 OpMemoryModel Logical GLSL450
7619 OpEntryPoint GLCompute %main "main" %_
7620 OpExecutionMode %main LocalSize 8 1 1
7621 OpMemberDecorate %first 0 Offset 1
7622 OpDecorate %first Block
7623 %void = OpTypeVoid
7624 %3 = OpTypeFunction %void
7625 %int = OpTypeInt 32 1
7626 %first = OpTypeStruct %int
7627 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7628 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7629 %int_0 = OpConstant %int 0
7630 %int_2 = OpConstant %int 2
7631 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7632 %main = OpFunction %void None %3
7633 %5 = OpLabel
7634 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7635 OpStore %13 %int_2
7636 OpReturn
7637 OpFunctionEnd
7638 )";
7639
7640 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7641 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7642 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7643 EXPECT_THAT(
7644 getDiagnosticString(),
7645 HasSubstr(
7646 "Block for variable in Workgroup storage class must follow "
7647 "standard storage buffer layout rules: "
7648 "member 0 at offset 1 is not aligned to 4"));
7649 }
7650
7651 } // namespace
7652 } // namespace val
7653 } // namespace spvtools
7654