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::__anon081788260111::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 HasSubstr(": in Vulkan environment Execution Scope is limited to "
4996 "Workgroup and Subgroup"));
4997 }
4998
TEST_F(ValidateDecorations,UniformDecorationWithWrongInstructionBad)4999 TEST_F(ValidateDecorations, UniformDecorationWithWrongInstructionBad) {
5000 const std::string spirv =
5001 ShaderWithUniformLikeDecoration("OpDecorateId %int0 Uniform");
5002
5003 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_2);
5004 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_2));
5005 EXPECT_THAT(getDiagnosticString(),
5006 HasSubstr("Decorations that don't take ID parameters may not be "
5007 "used with OpDecorateId\n"
5008 " OpDecorateId %int0 Uniform"));
5009 }
5010
TEST_F(ValidateDecorations,UniformIdDecorationWithWrongInstructionBad)5011 TEST_F(ValidateDecorations, UniformIdDecorationWithWrongInstructionBad) {
5012 const std::string spirv = ShaderWithUniformLikeDecoration(
5013 "OpDecorate %int0 UniformId %subgroupscope");
5014
5015 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5016 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5017 EXPECT_THAT(
5018 getDiagnosticString(),
5019 HasSubstr(
5020 "Decorations taking ID parameters may not be used with OpDecorateId\n"
5021 " OpDecorate %int0 UniformId %subgroupscope"));
5022 }
5023
TEST_F(ValidateDecorations,MultipleOffsetDecorationsOnSameID)5024 TEST_F(ValidateDecorations, MultipleOffsetDecorationsOnSameID) {
5025 std::string spirv = R"(
5026 OpCapability Shader
5027 OpMemoryModel Logical GLSL450
5028 OpEntryPoint Fragment %1 "main"
5029 OpExecutionMode %1 OriginUpperLeft
5030
5031 OpMemberDecorate %struct 0 Offset 0
5032 OpMemberDecorate %struct 0 Offset 0
5033
5034 %void = OpTypeVoid
5035 %voidfn = OpTypeFunction %void
5036 %float = OpTypeFloat 32
5037 %struct = OpTypeStruct %float
5038
5039 %1 = OpFunction %void None %voidfn
5040 %label = OpLabel
5041 OpReturn
5042 OpFunctionEnd
5043 )";
5044
5045 CompileSuccessfully(spirv);
5046 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5047 EXPECT_THAT(getDiagnosticString(),
5048 HasSubstr("ID '2', member '0' decorated with Offset multiple "
5049 "times is not allowed."));
5050 }
5051
TEST_F(ValidateDecorations,MultipleArrayStrideDecorationsOnSameID)5052 TEST_F(ValidateDecorations, MultipleArrayStrideDecorationsOnSameID) {
5053 std::string spirv = R"(
5054 OpCapability Shader
5055 OpMemoryModel Logical GLSL450
5056 OpEntryPoint Fragment %1 "main"
5057 OpExecutionMode %1 OriginUpperLeft
5058
5059 OpDecorate %array ArrayStride 4
5060 OpDecorate %array ArrayStride 4
5061
5062 %void = OpTypeVoid
5063 %voidfn = OpTypeFunction %void
5064 %float = OpTypeFloat 32
5065 %uint = OpTypeInt 32 0
5066 %uint_4 = OpConstant %uint 4
5067 %array = OpTypeArray %float %uint_4
5068
5069 %1 = OpFunction %void None %voidfn
5070 %label = OpLabel
5071 OpReturn
5072 OpFunctionEnd
5073 )";
5074
5075 CompileSuccessfully(spirv);
5076 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5077 EXPECT_THAT(getDiagnosticString(),
5078 HasSubstr("ID '2' decorated with ArrayStride multiple "
5079 "times is not allowed."));
5080 }
5081
TEST_F(ValidateDecorations,MultipleMatrixStrideDecorationsOnSameID)5082 TEST_F(ValidateDecorations, MultipleMatrixStrideDecorationsOnSameID) {
5083 std::string spirv = R"(
5084 OpCapability Shader
5085 OpMemoryModel Logical GLSL450
5086 OpEntryPoint Fragment %1 "main"
5087 OpExecutionMode %1 OriginUpperLeft
5088
5089 OpMemberDecorate %struct 0 Offset 0
5090 OpMemberDecorate %struct 0 ColMajor
5091 OpMemberDecorate %struct 0 MatrixStride 16
5092 OpMemberDecorate %struct 0 MatrixStride 16
5093
5094 %void = OpTypeVoid
5095 %voidfn = OpTypeFunction %void
5096 %float = OpTypeFloat 32
5097 %fvec4 = OpTypeVector %float 4
5098 %fmat4 = OpTypeMatrix %fvec4 4
5099 %struct = OpTypeStruct %fmat4
5100
5101 %1 = OpFunction %void None %voidfn
5102 %label = OpLabel
5103 OpReturn
5104 OpFunctionEnd
5105 )";
5106
5107 CompileSuccessfully(spirv);
5108 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5109 EXPECT_THAT(getDiagnosticString(),
5110 HasSubstr("ID '2', member '0' decorated with MatrixStride "
5111 "multiple times is not allowed."));
5112 }
5113
TEST_F(ValidateDecorations,MultipleRowMajorDecorationsOnSameID)5114 TEST_F(ValidateDecorations, MultipleRowMajorDecorationsOnSameID) {
5115 std::string spirv = R"(
5116 OpCapability Shader
5117 OpMemoryModel Logical GLSL450
5118 OpEntryPoint Fragment %1 "main"
5119 OpExecutionMode %1 OriginUpperLeft
5120
5121 OpMemberDecorate %struct 0 Offset 0
5122 OpMemberDecorate %struct 0 MatrixStride 16
5123 OpMemberDecorate %struct 0 RowMajor
5124 OpMemberDecorate %struct 0 RowMajor
5125
5126 %void = OpTypeVoid
5127 %voidfn = OpTypeFunction %void
5128 %float = OpTypeFloat 32
5129 %fvec4 = OpTypeVector %float 4
5130 %fmat4 = OpTypeMatrix %fvec4 4
5131 %struct = OpTypeStruct %fmat4
5132
5133 %1 = OpFunction %void None %voidfn
5134 %label = OpLabel
5135 OpReturn
5136 OpFunctionEnd
5137 )";
5138
5139 CompileSuccessfully(spirv);
5140 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5141 EXPECT_THAT(getDiagnosticString(),
5142 HasSubstr("ID '2', member '0' decorated with RowMajor multiple "
5143 "times is not allowed."));
5144 }
5145
TEST_F(ValidateDecorations,MultipleColMajorDecorationsOnSameID)5146 TEST_F(ValidateDecorations, MultipleColMajorDecorationsOnSameID) {
5147 std::string spirv = R"(
5148 OpCapability Shader
5149 OpMemoryModel Logical GLSL450
5150 OpEntryPoint Fragment %1 "main"
5151 OpExecutionMode %1 OriginUpperLeft
5152
5153 OpMemberDecorate %struct 0 Offset 0
5154 OpMemberDecorate %struct 0 MatrixStride 16
5155 OpMemberDecorate %struct 0 ColMajor
5156 OpMemberDecorate %struct 0 ColMajor
5157
5158 %void = OpTypeVoid
5159 %voidfn = OpTypeFunction %void
5160 %float = OpTypeFloat 32
5161 %fvec4 = OpTypeVector %float 4
5162 %fmat4 = OpTypeMatrix %fvec4 4
5163 %struct = OpTypeStruct %fmat4
5164
5165 %1 = OpFunction %void None %voidfn
5166 %label = OpLabel
5167 OpReturn
5168 OpFunctionEnd
5169 )";
5170
5171 CompileSuccessfully(spirv);
5172 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5173 EXPECT_THAT(getDiagnosticString(),
5174 HasSubstr("ID '2', member '0' decorated with ColMajor multiple "
5175 "times is not allowed."));
5176 }
5177
TEST_F(ValidateDecorations,RowMajorAndColMajorDecorationsOnSameID)5178 TEST_F(ValidateDecorations, RowMajorAndColMajorDecorationsOnSameID) {
5179 std::string spirv = R"(
5180 OpCapability Shader
5181 OpMemoryModel Logical GLSL450
5182 OpEntryPoint Fragment %1 "main"
5183 OpExecutionMode %1 OriginUpperLeft
5184
5185 OpMemberDecorate %struct 0 Offset 0
5186 OpMemberDecorate %struct 0 MatrixStride 16
5187 OpMemberDecorate %struct 0 ColMajor
5188 OpMemberDecorate %struct 0 RowMajor
5189
5190 %void = OpTypeVoid
5191 %voidfn = OpTypeFunction %void
5192 %float = OpTypeFloat 32
5193 %fvec4 = OpTypeVector %float 4
5194 %fmat4 = OpTypeMatrix %fvec4 4
5195 %struct = OpTypeStruct %fmat4
5196
5197 %1 = OpFunction %void None %voidfn
5198 %label = OpLabel
5199 OpReturn
5200 OpFunctionEnd
5201 )";
5202
5203 CompileSuccessfully(spirv);
5204 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5205 EXPECT_THAT(getDiagnosticString(),
5206 HasSubstr("ID '2', member '0' decorated with both RowMajor and "
5207 "ColMajor is not allowed."));
5208 }
5209
TEST_F(ValidateDecorations,BlockAndBufferBlockDecorationsOnSameID)5210 TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
5211 std::string spirv = R"(
5212 OpCapability Shader
5213 OpMemoryModel Logical GLSL450
5214 OpEntryPoint Fragment %1 "main"
5215 OpExecutionMode %1 OriginUpperLeft
5216
5217 OpDecorate %struct Block
5218 OpDecorate %struct BufferBlock
5219 OpMemberDecorate %struct 0 Offset 0
5220 OpMemberDecorate %struct 0 MatrixStride 16
5221 OpMemberDecorate %struct 0 RowMajor
5222
5223 %void = OpTypeVoid
5224 %voidfn = OpTypeFunction %void
5225 %float = OpTypeFloat 32
5226 %fvec4 = OpTypeVector %float 4
5227 %fmat4 = OpTypeMatrix %fvec4 4
5228 %struct = OpTypeStruct %fmat4
5229
5230 %1 = OpFunction %void None %voidfn
5231 %label = OpLabel
5232 OpReturn
5233 OpFunctionEnd
5234 )";
5235
5236 CompileSuccessfully(spirv);
5237 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
5238 EXPECT_THAT(
5239 getDiagnosticString(),
5240 HasSubstr(
5241 "ID '2' decorated with both BufferBlock and Block is not allowed."));
5242 }
5243
MakeIntegerShader(const std::string & decoration,const std::string & inst,const std::string & extension="OpExtension \\"SPV_KHR_no_integer_wrap_decoration\\"")5244 std::string MakeIntegerShader(
5245 const std::string& decoration, const std::string& inst,
5246 const std::string& extension =
5247 "OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
5248 return R"(
5249 OpCapability Shader
5250 OpCapability Linkage
5251 )" + extension +
5252 R"(
5253 %glsl = OpExtInstImport "GLSL.std.450"
5254 %opencl = OpExtInstImport "OpenCL.std"
5255 OpMemoryModel Logical GLSL450
5256 OpEntryPoint GLCompute %main "main"
5257 OpName %entry "entry"
5258 )" + decoration +
5259 R"(
5260 %void = OpTypeVoid
5261 %voidfn = OpTypeFunction %void
5262 %int = OpTypeInt 32 1
5263 %zero = OpConstantNull %int
5264 %float = OpTypeFloat 32
5265 %float0 = OpConstantNull %float
5266 %main = OpFunction %void None %voidfn
5267 %entry = OpLabel
5268 )" + inst +
5269 R"(
5270 OpReturn
5271 OpFunctionEnd)";
5272 }
5273
5274 // NoSignedWrap
5275
TEST_F(ValidateDecorations,NoSignedWrapOnTypeBad)5276 TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
5277 std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
5278
5279 CompileSuccessfully(spirv);
5280 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5281 EXPECT_THAT(
5282 getDiagnosticString(),
5283 HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
5284 }
5285
TEST_F(ValidateDecorations,NoSignedWrapOnLabelBad)5286 TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
5287 std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
5288
5289 CompileSuccessfully(spirv);
5290 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5291 EXPECT_THAT(getDiagnosticString(),
5292 HasSubstr("NoSignedWrap decoration may not be applied to Label"));
5293 }
5294
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionBad)5295 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
5296 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5297 "%val = OpIAdd %int %zero %zero", "");
5298
5299 CompileSuccessfully(spirv);
5300 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5301 EXPECT_THAT(getDiagnosticString(),
5302 HasSubstr("requires one of these extensions: "
5303 "SPV_KHR_no_integer_wrap_decoration"));
5304 }
5305
TEST_F(ValidateDecorations,NoSignedWrapRequiresExtensionV13Bad)5306 TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionV13Bad) {
5307 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5308 "%val = OpIAdd %int %zero %zero", "");
5309
5310 CompileSuccessfully(spirv);
5311 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5312 EXPECT_THAT(getDiagnosticString(),
5313 HasSubstr("requires one of these extensions: "
5314 "SPV_KHR_no_integer_wrap_decoration"));
5315 }
5316
TEST_F(ValidateDecorations,NoSignedWrapOkInSPV14Good)5317 TEST_F(ValidateDecorations, NoSignedWrapOkInSPV14Good) {
5318 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5319 "%val = OpIAdd %int %zero %zero", "");
5320
5321 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5322 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5323 EXPECT_THAT(getDiagnosticString(), Eq(""));
5324 }
5325
TEST_F(ValidateDecorations,NoSignedWrapIAddGood)5326 TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
5327 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5328 "%val = OpIAdd %int %zero %zero");
5329
5330 CompileSuccessfully(spirv);
5331 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5332 EXPECT_THAT(getDiagnosticString(), Eq(""));
5333 }
5334
TEST_F(ValidateDecorations,NoSignedWrapISubGood)5335 TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
5336 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5337 "%val = OpISub %int %zero %zero");
5338
5339 CompileSuccessfully(spirv);
5340 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5341 EXPECT_THAT(getDiagnosticString(), Eq(""));
5342 }
5343
TEST_F(ValidateDecorations,NoSignedWrapIMulGood)5344 TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
5345 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5346 "%val = OpIMul %int %zero %zero");
5347
5348 CompileSuccessfully(spirv);
5349 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5350 EXPECT_THAT(getDiagnosticString(), Eq(""));
5351 }
5352
TEST_F(ValidateDecorations,NoSignedWrapShiftLeftLogicalGood)5353 TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
5354 std::string spirv =
5355 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5356 "%val = OpShiftLeftLogical %int %zero %zero");
5357
5358 CompileSuccessfully(spirv);
5359 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5360 EXPECT_THAT(getDiagnosticString(), Eq(""));
5361 }
5362
TEST_F(ValidateDecorations,NoSignedWrapSNegateGood)5363 TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
5364 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5365 "%val = OpSNegate %int %zero");
5366
5367 CompileSuccessfully(spirv);
5368 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5369 EXPECT_THAT(getDiagnosticString(), Eq(""));
5370 }
5371
TEST_F(ValidateDecorations,NoSignedWrapSRemBad)5372 TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
5373 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5374 "%val = OpSRem %int %zero %zero");
5375
5376 CompileSuccessfully(spirv);
5377 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5378 EXPECT_THAT(getDiagnosticString(),
5379 HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
5380 }
5381
TEST_F(ValidateDecorations,NoSignedWrapFAddBad)5382 TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
5383 std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
5384 "%val = OpFAdd %float %float0 %float0");
5385
5386 CompileSuccessfully(spirv);
5387 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5388 EXPECT_THAT(getDiagnosticString(),
5389 HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
5390 }
5391
TEST_F(ValidateDecorations,NoSignedWrapExtInstOpenCLGood)5392 TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
5393 std::string spirv =
5394 MakeIntegerShader("OpDecorate %val NoSignedWrap",
5395 "%val = OpExtInst %int %opencl s_abs %zero");
5396
5397 CompileSuccessfully(spirv);
5398 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5399 EXPECT_THAT(getDiagnosticString(), Eq(""));
5400 }
5401
TEST_F(ValidateDecorations,NoSignedWrapExtInstGLSLGood)5402 TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
5403 std::string spirv = MakeIntegerShader(
5404 "OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
5405
5406 CompileSuccessfully(spirv);
5407 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5408 EXPECT_THAT(getDiagnosticString(), Eq(""));
5409 }
5410
5411 // TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
5412 // "OpExtInst for instruction numbers specified in the extended
5413 // instruction-set specifications as accepting this decoration."
5414
5415 // NoUnignedWrap
5416
TEST_F(ValidateDecorations,NoUnsignedWrapOnTypeBad)5417 TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
5418 std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
5419
5420 CompileSuccessfully(spirv);
5421 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5422 EXPECT_THAT(
5423 getDiagnosticString(),
5424 HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
5425 }
5426
TEST_F(ValidateDecorations,NoUnsignedWrapOnLabelBad)5427 TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
5428 std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
5429
5430 CompileSuccessfully(spirv);
5431 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5432 EXPECT_THAT(
5433 getDiagnosticString(),
5434 HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
5435 }
5436
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionBad)5437 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
5438 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5439 "%val = OpIAdd %int %zero %zero", "");
5440
5441 CompileSuccessfully(spirv);
5442 EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
5443 EXPECT_THAT(getDiagnosticString(),
5444 HasSubstr("requires one of these extensions: "
5445 "SPV_KHR_no_integer_wrap_decoration"));
5446 }
5447
TEST_F(ValidateDecorations,NoUnsignedWrapRequiresExtensionV13Bad)5448 TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionV13Bad) {
5449 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5450 "%val = OpIAdd %int %zero %zero", "");
5451
5452 CompileSuccessfully(spirv);
5453 EXPECT_NE(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5454 EXPECT_THAT(getDiagnosticString(),
5455 HasSubstr("requires one of these extensions: "
5456 "SPV_KHR_no_integer_wrap_decoration"));
5457 }
5458
TEST_F(ValidateDecorations,NoUnsignedWrapOkInSPV14Good)5459 TEST_F(ValidateDecorations, NoUnsignedWrapOkInSPV14Good) {
5460 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5461 "%val = OpIAdd %int %zero %zero", "");
5462
5463 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
5464 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
5465 EXPECT_THAT(getDiagnosticString(), Eq(""));
5466 }
5467
TEST_F(ValidateDecorations,NoUnsignedWrapIAddGood)5468 TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
5469 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5470 "%val = OpIAdd %int %zero %zero");
5471
5472 CompileSuccessfully(spirv);
5473 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5474 EXPECT_THAT(getDiagnosticString(), Eq(""));
5475 }
5476
TEST_F(ValidateDecorations,NoUnsignedWrapISubGood)5477 TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
5478 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5479 "%val = OpISub %int %zero %zero");
5480
5481 CompileSuccessfully(spirv);
5482 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5483 EXPECT_THAT(getDiagnosticString(), Eq(""));
5484 }
5485
TEST_F(ValidateDecorations,NoUnsignedWrapIMulGood)5486 TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
5487 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5488 "%val = OpIMul %int %zero %zero");
5489
5490 CompileSuccessfully(spirv);
5491 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5492 EXPECT_THAT(getDiagnosticString(), Eq(""));
5493 }
5494
TEST_F(ValidateDecorations,NoUnsignedWrapShiftLeftLogicalGood)5495 TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
5496 std::string spirv =
5497 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5498 "%val = OpShiftLeftLogical %int %zero %zero");
5499
5500 CompileSuccessfully(spirv);
5501 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5502 EXPECT_THAT(getDiagnosticString(), Eq(""));
5503 }
5504
TEST_F(ValidateDecorations,NoUnsignedWrapSNegateGood)5505 TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
5506 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5507 "%val = OpSNegate %int %zero");
5508
5509 CompileSuccessfully(spirv);
5510 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5511 EXPECT_THAT(getDiagnosticString(), Eq(""));
5512 }
5513
TEST_F(ValidateDecorations,NoUnsignedWrapSRemBad)5514 TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
5515 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5516 "%val = OpSRem %int %zero %zero");
5517
5518 CompileSuccessfully(spirv);
5519 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5520 EXPECT_THAT(
5521 getDiagnosticString(),
5522 HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
5523 }
5524
TEST_F(ValidateDecorations,NoUnsignedWrapFAddBad)5525 TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
5526 std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5527 "%val = OpFAdd %float %float0 %float0");
5528
5529 CompileSuccessfully(spirv);
5530 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5531 EXPECT_THAT(
5532 getDiagnosticString(),
5533 HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
5534 }
5535
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstOpenCLGood)5536 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
5537 std::string spirv =
5538 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5539 "%val = OpExtInst %int %opencl s_abs %zero");
5540
5541 CompileSuccessfully(spirv);
5542 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5543 EXPECT_THAT(getDiagnosticString(), Eq(""));
5544 }
5545
TEST_F(ValidateDecorations,NoUnsignedWrapExtInstGLSLGood)5546 TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
5547 std::string spirv =
5548 MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
5549 "%val = OpExtInst %int %glsl SAbs %zero");
5550
5551 CompileSuccessfully(spirv);
5552 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5553 EXPECT_THAT(getDiagnosticString(), Eq(""));
5554 }
5555
TEST_F(ValidateDecorations,AliasedandRestrictBad)5556 TEST_F(ValidateDecorations, AliasedandRestrictBad) {
5557 const std::string body = R"(
5558 OpCapability Shader
5559 %1 = OpExtInstImport "GLSL.std.450"
5560 OpMemoryModel Logical GLSL450
5561 OpEntryPoint GLCompute %main "main"
5562 OpExecutionMode %main LocalSize 1 1 1
5563 OpSource GLSL 430
5564 OpMemberDecorate %Output 0 Offset 0
5565 OpDecorate %Output BufferBlock
5566 OpDecorate %dataOutput Restrict
5567 OpDecorate %dataOutput Aliased
5568 %void = OpTypeVoid
5569 %3 = OpTypeFunction %void
5570 %float = OpTypeFloat 32
5571 %Output = OpTypeStruct %float
5572 %_ptr_Uniform_Output = OpTypePointer Uniform %Output
5573 %dataOutput = OpVariable %_ptr_Uniform_Output Uniform
5574 %main = OpFunction %void None %3
5575 %5 = OpLabel
5576 OpReturn
5577 OpFunctionEnd
5578 )";
5579
5580 CompileSuccessfully(body.c_str());
5581 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5582 EXPECT_THAT(
5583 getDiagnosticString(),
5584 HasSubstr("decorated with both Aliased and Restrict is not allowed"));
5585 }
5586
5587 // TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
5588 // "OpExtInst for instruction numbers specified in the extended
5589 // instruction-set specifications as accepting this decoration."
5590
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerSuccess)5591 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
5592 const std::string body = R"(
5593 OpCapability PhysicalStorageBufferAddressesEXT
5594 OpCapability Int64
5595 OpCapability Shader
5596 OpExtension "SPV_EXT_physical_storage_buffer"
5597 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5598 OpEntryPoint Fragment %main "main"
5599 OpExecutionMode %main OriginUpperLeft
5600 OpDecorate %val1 RestrictPointerEXT
5601 %uint64 = OpTypeInt 64 0
5602 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5603 %pptr_f = OpTypePointer Function %ptr
5604 %void = OpTypeVoid
5605 %voidfn = OpTypeFunction %void
5606 %main = OpFunction %void None %voidfn
5607 %entry = OpLabel
5608 %val1 = OpVariable %pptr_f Function
5609 OpReturn
5610 OpFunctionEnd
5611 )";
5612
5613 CompileSuccessfully(body.c_str());
5614 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5615 }
5616
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerMissing)5617 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerMissing) {
5618 const std::string body = R"(
5619 OpCapability PhysicalStorageBufferAddressesEXT
5620 OpCapability Int64
5621 OpCapability Shader
5622 OpExtension "SPV_EXT_physical_storage_buffer"
5623 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5624 OpEntryPoint Fragment %main "main"
5625 OpExecutionMode %main OriginUpperLeft
5626 %uint64 = OpTypeInt 64 0
5627 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5628 %pptr_f = OpTypePointer Function %ptr
5629 %void = OpTypeVoid
5630 %voidfn = OpTypeFunction %void
5631 %main = OpFunction %void None %voidfn
5632 %entry = OpLabel
5633 %val1 = OpVariable %pptr_f Function
5634 OpReturn
5635 OpFunctionEnd
5636 )";
5637
5638 CompileSuccessfully(body.c_str());
5639 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5640 EXPECT_THAT(getDiagnosticString(),
5641 HasSubstr("expected AliasedPointerEXT or RestrictPointerEXT for "
5642 "PhysicalStorageBufferEXT pointer"));
5643 }
5644
TEST_F(ValidateDecorations,PSBAliasedRestrictPointerBoth)5645 TEST_F(ValidateDecorations, PSBAliasedRestrictPointerBoth) {
5646 const std::string body = R"(
5647 OpCapability PhysicalStorageBufferAddressesEXT
5648 OpCapability Int64
5649 OpCapability Shader
5650 OpExtension "SPV_EXT_physical_storage_buffer"
5651 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5652 OpEntryPoint Fragment %main "main"
5653 OpExecutionMode %main OriginUpperLeft
5654 OpDecorate %val1 RestrictPointerEXT
5655 OpDecorate %val1 AliasedPointerEXT
5656 %uint64 = OpTypeInt 64 0
5657 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5658 %pptr_f = OpTypePointer Function %ptr
5659 %void = OpTypeVoid
5660 %voidfn = OpTypeFunction %void
5661 %main = OpFunction %void None %voidfn
5662 %entry = OpLabel
5663 %val1 = OpVariable %pptr_f Function
5664 OpReturn
5665 OpFunctionEnd
5666 )";
5667
5668 CompileSuccessfully(body.c_str());
5669 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5670 EXPECT_THAT(
5671 getDiagnosticString(),
5672 HasSubstr("can't specify both AliasedPointerEXT and RestrictPointerEXT "
5673 "for PhysicalStorageBufferEXT pointer"));
5674 }
5675
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamSuccess)5676 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamSuccess) {
5677 const std::string body = R"(
5678 OpCapability PhysicalStorageBufferAddressesEXT
5679 OpCapability Int64
5680 OpCapability Shader
5681 OpExtension "SPV_EXT_physical_storage_buffer"
5682 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5683 OpEntryPoint Fragment %main "main"
5684 OpExecutionMode %main OriginUpperLeft
5685 OpDecorate %fparam Restrict
5686 %uint64 = OpTypeInt 64 0
5687 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5688 %void = OpTypeVoid
5689 %voidfn = OpTypeFunction %void
5690 %fnptr = OpTypeFunction %void %ptr
5691 %main = OpFunction %void None %voidfn
5692 %entry = OpLabel
5693 OpReturn
5694 OpFunctionEnd
5695 %fn = OpFunction %void None %fnptr
5696 %fparam = OpFunctionParameter %ptr
5697 %lab = OpLabel
5698 OpReturn
5699 OpFunctionEnd
5700 )";
5701
5702 CompileSuccessfully(body.c_str());
5703 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
5704 }
5705
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamMissing)5706 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamMissing) {
5707 const std::string body = R"(
5708 OpCapability PhysicalStorageBufferAddressesEXT
5709 OpCapability Int64
5710 OpCapability Shader
5711 OpExtension "SPV_EXT_physical_storage_buffer"
5712 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5713 OpEntryPoint Fragment %main "main"
5714 OpExecutionMode %main OriginUpperLeft
5715 %uint64 = OpTypeInt 64 0
5716 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5717 %void = OpTypeVoid
5718 %voidfn = OpTypeFunction %void
5719 %fnptr = OpTypeFunction %void %ptr
5720 %main = OpFunction %void None %voidfn
5721 %entry = OpLabel
5722 OpReturn
5723 OpFunctionEnd
5724 %fn = OpFunction %void None %fnptr
5725 %fparam = OpFunctionParameter %ptr
5726 %lab = OpLabel
5727 OpReturn
5728 OpFunctionEnd
5729 )";
5730
5731 CompileSuccessfully(body.c_str());
5732 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5733 EXPECT_THAT(getDiagnosticString(),
5734 HasSubstr("expected Aliased or Restrict for "
5735 "PhysicalStorageBufferEXT pointer"));
5736 }
5737
TEST_F(ValidateDecorations,PSBAliasedRestrictFunctionParamBoth)5738 TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
5739 const std::string body = R"(
5740 OpCapability PhysicalStorageBufferAddressesEXT
5741 OpCapability Int64
5742 OpCapability Shader
5743 OpExtension "SPV_EXT_physical_storage_buffer"
5744 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5745 OpEntryPoint Fragment %main "main"
5746 OpExecutionMode %main OriginUpperLeft
5747 OpDecorate %fparam Restrict
5748 OpDecorate %fparam Aliased
5749 %uint64 = OpTypeInt 64 0
5750 %ptr = OpTypePointer PhysicalStorageBufferEXT %uint64
5751 %void = OpTypeVoid
5752 %voidfn = OpTypeFunction %void
5753 %fnptr = OpTypeFunction %void %ptr
5754 %main = OpFunction %void None %voidfn
5755 %entry = OpLabel
5756 OpReturn
5757 OpFunctionEnd
5758 %fn = OpFunction %void None %fnptr
5759 %fparam = OpFunctionParameter %ptr
5760 %lab = OpLabel
5761 OpReturn
5762 OpFunctionEnd
5763 )";
5764
5765 CompileSuccessfully(body.c_str());
5766 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5767 EXPECT_THAT(getDiagnosticString(),
5768 HasSubstr("can't specify both Aliased and Restrict for "
5769 "PhysicalStorageBufferEXT pointer"));
5770 }
5771
TEST_F(ValidateDecorations,PSBFPRoundingModeSuccess)5772 TEST_F(ValidateDecorations, PSBFPRoundingModeSuccess) {
5773 std::string spirv = R"(
5774 OpCapability PhysicalStorageBufferAddressesEXT
5775 OpCapability Shader
5776 OpCapability Linkage
5777 OpCapability StorageBuffer16BitAccess
5778 OpExtension "SPV_EXT_physical_storage_buffer"
5779 OpExtension "SPV_KHR_storage_buffer_storage_class"
5780 OpExtension "SPV_KHR_variable_pointers"
5781 OpExtension "SPV_KHR_16bit_storage"
5782 OpMemoryModel PhysicalStorageBuffer64EXT GLSL450
5783 OpEntryPoint GLCompute %main "main"
5784 OpDecorate %_ FPRoundingMode RTE
5785 OpDecorate %half_ptr_var AliasedPointerEXT
5786 %half = OpTypeFloat 16
5787 %float = OpTypeFloat 32
5788 %float_1_25 = OpConstant %float 1.25
5789 %half_ptr = OpTypePointer PhysicalStorageBufferEXT %half
5790 %half_pptr_f = OpTypePointer Function %half_ptr
5791 %void = OpTypeVoid
5792 %func = OpTypeFunction %void
5793 %main = OpFunction %void None %func
5794 %main_entry = OpLabel
5795 %half_ptr_var = OpVariable %half_pptr_f Function
5796 %val1 = OpLoad %half_ptr %half_ptr_var
5797 %_ = OpFConvert %half %float_1_25
5798 OpStore %val1 %_ Aligned 2
5799 OpReturn
5800 OpFunctionEnd
5801 )";
5802
5803 CompileSuccessfully(spirv);
5804 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5805 }
5806
TEST_F(ValidateDecorations,InvalidStraddle)5807 TEST_F(ValidateDecorations, InvalidStraddle) {
5808 const std::string spirv = R"(
5809 OpCapability Shader
5810 OpMemoryModel Logical GLSL450
5811 OpEntryPoint GLCompute %main "main"
5812 OpExecutionMode %main LocalSize 1 1 1
5813 OpMemberDecorate %inner_struct 0 Offset 0
5814 OpMemberDecorate %inner_struct 1 Offset 4
5815 OpDecorate %outer_struct Block
5816 OpMemberDecorate %outer_struct 0 Offset 0
5817 OpMemberDecorate %outer_struct 1 Offset 8
5818 OpDecorate %var DescriptorSet 0
5819 OpDecorate %var Binding 0
5820 %void = OpTypeVoid
5821 %float = OpTypeFloat 32
5822 %float2 = OpTypeVector %float 2
5823 %inner_struct = OpTypeStruct %float %float2
5824 %outer_struct = OpTypeStruct %float2 %inner_struct
5825 %ptr_ssbo_outer = OpTypePointer StorageBuffer %outer_struct
5826 %var = OpVariable %ptr_ssbo_outer StorageBuffer
5827 %void_fn = OpTypeFunction %void
5828 %main = OpFunction %void None %void_fn
5829 %entry = OpLabel
5830 OpReturn
5831 OpFunctionEnd
5832 )";
5833
5834 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
5835 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5836 EXPECT_THAT(getDiagnosticString(),
5837 HasSubstr("Structure id 2 decorated as Block for variable in "
5838 "StorageBuffer storage class must follow relaxed "
5839 "storage buffer layout rules: member 1 is an "
5840 "improperly straddling vector at offset 12"));
5841 }
5842
TEST_F(ValidateDecorations,DescriptorArray)5843 TEST_F(ValidateDecorations, DescriptorArray) {
5844 const std::string spirv = R"(
5845 OpCapability Shader
5846 OpExtension "SPV_KHR_storage_buffer_storage_class"
5847 OpMemoryModel Logical GLSL450
5848 OpEntryPoint GLCompute %main "main"
5849 OpExecutionMode %main LocalSize 1 1 1
5850 OpDecorate %struct Block
5851 OpMemberDecorate %struct 0 Offset 0
5852 OpMemberDecorate %struct 1 Offset 1
5853 OpDecorate %var DescriptorSet 0
5854 OpDecorate %var Binding 0
5855 %void = OpTypeVoid
5856 %float = OpTypeFloat 32
5857 %int = OpTypeInt 32 0
5858 %int_2 = OpConstant %int 2
5859 %float2 = OpTypeVector %float 2
5860 %struct = OpTypeStruct %float %float2
5861 %struct_array = OpTypeArray %struct %int_2
5862 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
5863 %var = OpVariable %ptr_ssbo_array StorageBuffer
5864 %void_fn = OpTypeFunction %void
5865 %main = OpFunction %void None %void_fn
5866 %entry = OpLabel
5867 OpReturn
5868 OpFunctionEnd
5869 )";
5870
5871 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5872 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5873 EXPECT_THAT(getDiagnosticString(),
5874 HasSubstr("Structure id 2 decorated as Block for variable in "
5875 "StorageBuffer storage class must follow standard "
5876 "storage buffer layout rules: member 1 at offset 1 is "
5877 "not aligned to 8"));
5878 }
5879
TEST_F(ValidateDecorations,DescriptorRuntimeArray)5880 TEST_F(ValidateDecorations, DescriptorRuntimeArray) {
5881 const std::string spirv = R"(
5882 OpCapability Shader
5883 OpCapability RuntimeDescriptorArrayEXT
5884 OpExtension "SPV_KHR_storage_buffer_storage_class"
5885 OpExtension "SPV_EXT_descriptor_indexing"
5886 OpMemoryModel Logical GLSL450
5887 OpEntryPoint GLCompute %main "main"
5888 OpExecutionMode %main LocalSize 1 1 1
5889 OpDecorate %struct Block
5890 OpMemberDecorate %struct 0 Offset 0
5891 OpMemberDecorate %struct 1 Offset 1
5892 OpDecorate %var DescriptorSet 0
5893 OpDecorate %var Binding 0
5894 %void = OpTypeVoid
5895 %float = OpTypeFloat 32
5896 %int = OpTypeInt 32 0
5897 %float2 = OpTypeVector %float 2
5898 %struct = OpTypeStruct %float %float2
5899 %struct_array = OpTypeRuntimeArray %struct
5900 %ptr_ssbo_array = OpTypePointer StorageBuffer %struct_array
5901 %var = OpVariable %ptr_ssbo_array StorageBuffer
5902 %void_fn = OpTypeFunction %void
5903 %main = OpFunction %void None %void_fn
5904 %entry = OpLabel
5905 OpReturn
5906 OpFunctionEnd
5907 )";
5908
5909 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5910 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5911 EXPECT_THAT(getDiagnosticString(),
5912 HasSubstr("Structure id 2 decorated as Block for variable in "
5913 "StorageBuffer storage class must follow standard "
5914 "storage buffer layout rules: member 1 at offset 1 is "
5915 "not aligned to 8"));
5916 }
5917
TEST_F(ValidateDecorations,MultiDimensionalArray)5918 TEST_F(ValidateDecorations, MultiDimensionalArray) {
5919 const std::string spirv = R"(
5920 OpCapability Shader
5921 OpMemoryModel Logical GLSL450
5922 OpEntryPoint GLCompute %main "main"
5923 OpExecutionMode %main LocalSize 1 1 1
5924 OpDecorate %struct Block
5925 OpMemberDecorate %struct 0 Offset 0
5926 OpDecorate %array_4 ArrayStride 4
5927 OpDecorate %array_3 ArrayStride 48
5928 OpDecorate %var DescriptorSet 0
5929 OpDecorate %var Binding 0
5930 %void = OpTypeVoid
5931 %int = OpTypeInt 32 0
5932 %int_3 = OpConstant %int 3
5933 %int_4 = OpConstant %int 4
5934 %array_4 = OpTypeArray %int %int_4
5935 %array_3 = OpTypeArray %array_4 %int_3
5936 %struct = OpTypeStruct %array_3
5937 %ptr_struct = OpTypePointer Uniform %struct
5938 %var = OpVariable %ptr_struct Uniform
5939 %void_fn = OpTypeFunction %void
5940 %main = OpFunction %void None %void_fn
5941 %entry = OpLabel
5942 OpReturn
5943 OpFunctionEnd
5944 )";
5945
5946 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
5947 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
5948 EXPECT_THAT(getDiagnosticString(),
5949 HasSubstr("Structure id 2 decorated as Block for variable in "
5950 "Uniform storage class must follow standard uniform "
5951 "buffer layout rules: member 0 contains an array with "
5952 "stride 4 not satisfying alignment to 16"));
5953 }
5954
TEST_F(ValidateDecorations,ImproperStraddleInArray)5955 TEST_F(ValidateDecorations, ImproperStraddleInArray) {
5956 const std::string spirv = R"(
5957 OpCapability Shader
5958 OpMemoryModel Logical GLSL450
5959 OpEntryPoint GLCompute %main "main"
5960 OpExecutionMode %main LocalSize 1 1 1
5961 OpDecorate %struct Block
5962 OpMemberDecorate %struct 0 Offset 0
5963 OpDecorate %array ArrayStride 24
5964 OpMemberDecorate %inner 0 Offset 0
5965 OpMemberDecorate %inner 1 Offset 4
5966 OpMemberDecorate %inner 2 Offset 12
5967 OpMemberDecorate %inner 3 Offset 16
5968 OpDecorate %var DescriptorSet 0
5969 OpDecorate %var Binding 0
5970 %void = OpTypeVoid
5971 %int = OpTypeInt 32 0
5972 %int_2 = OpConstant %int 2
5973 %int2 = OpTypeVector %int 2
5974 %inner = OpTypeStruct %int %int2 %int %int
5975 %array = OpTypeArray %inner %int_2
5976 %struct = OpTypeStruct %array
5977 %ptr_struct = OpTypePointer StorageBuffer %struct
5978 %var = OpVariable %ptr_struct StorageBuffer
5979 %void_fn = OpTypeFunction %void
5980 %main = OpFunction %void None %void_fn
5981 %entry = OpLabel
5982 OpReturn
5983 OpFunctionEnd
5984 )";
5985
5986 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
5987 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
5988 EXPECT_THAT(getDiagnosticString(),
5989 HasSubstr("Structure id 4 decorated as Block for variable in "
5990 "StorageBuffer storage class must follow relaxed "
5991 "storage buffer layout rules: member 1 is an "
5992 "improperly straddling vector at offset 28"));
5993 }
5994
TEST_F(ValidateDecorations,LargeArray)5995 TEST_F(ValidateDecorations, LargeArray) {
5996 const std::string spirv = R"(
5997 OpCapability Shader
5998 OpMemoryModel Logical GLSL450
5999 OpEntryPoint GLCompute %main "main"
6000 OpExecutionMode %main LocalSize 1 1 1
6001 OpDecorate %struct Block
6002 OpMemberDecorate %struct 0 Offset 0
6003 OpDecorate %array ArrayStride 24
6004 OpMemberDecorate %inner 0 Offset 0
6005 OpMemberDecorate %inner 1 Offset 8
6006 OpMemberDecorate %inner 2 Offset 16
6007 OpMemberDecorate %inner 3 Offset 20
6008 OpDecorate %var DescriptorSet 0
6009 OpDecorate %var Binding 0
6010 %void = OpTypeVoid
6011 %int = OpTypeInt 32 0
6012 %int_2000000 = OpConstant %int 2000000
6013 %int2 = OpTypeVector %int 2
6014 %inner = OpTypeStruct %int %int2 %int %int
6015 %array = OpTypeArray %inner %int_2000000
6016 %struct = OpTypeStruct %array
6017 %ptr_struct = OpTypePointer StorageBuffer %struct
6018 %var = OpVariable %ptr_struct StorageBuffer
6019 %void_fn = OpTypeFunction %void
6020 %main = OpFunction %void None %void_fn
6021 %entry = OpLabel
6022 OpReturn
6023 OpFunctionEnd
6024 )";
6025
6026 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
6027 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
6028 }
6029
6030 // NonWritable
6031
6032 // Returns a SPIR-V shader module with variables in various storage classes,
6033 // parameterizable by which ID should be decorated as NonWritable.
ShaderWithNonWritableTarget(const std::string & target,bool member_decorate=false)6034 std::string ShaderWithNonWritableTarget(const std::string& target,
6035 bool member_decorate = false) {
6036 const std::string decoration_inst =
6037 std::string(member_decorate ? "OpMemberDecorate " : "OpDecorate ") +
6038 target + (member_decorate ? " 0" : "");
6039
6040 return std::string(R"(
6041 OpCapability Shader
6042 OpCapability RuntimeDescriptorArrayEXT
6043 OpExtension "SPV_EXT_descriptor_indexing"
6044 OpExtension "SPV_KHR_storage_buffer_storage_class"
6045 OpMemoryModel Logical GLSL450
6046 OpEntryPoint Vertex %main "main"
6047 OpName %label "label"
6048 OpName %param_f "param_f"
6049 OpName %param_p "param_p"
6050 OpName %_ptr_imstor "_ptr_imstor"
6051 OpName %_ptr_imsam "_ptr_imsam"
6052 OpName %var_wg "var_wg"
6053 OpName %var_imsam "var_imsam"
6054 OpName %var_priv "var_priv"
6055 OpName %var_func "var_func"
6056 OpName %simple_struct "simple_struct"
6057
6058 OpDecorate %struct_b Block
6059 OpDecorate %struct_b_rtarr Block
6060 OpMemberDecorate %struct_b 0 Offset 0
6061 OpMemberDecorate %struct_b_rtarr 0 Offset 0
6062 OpDecorate %rtarr ArrayStride 4
6063 )") + decoration_inst +
6064
6065 R"( NonWritable
6066
6067 %void = OpTypeVoid
6068 %void_fn = OpTypeFunction %void
6069 %float = OpTypeFloat 32
6070 %float_0 = OpConstant %float 0
6071 %int = OpTypeInt 32 0
6072 %int_2 = OpConstant %int 2
6073 %struct_b = OpTypeStruct %float
6074 %rtarr = OpTypeRuntimeArray %float
6075 %struct_b_rtarr = OpTypeStruct %rtarr
6076 %simple_struct = OpTypeStruct %float
6077 ; storage image
6078 %imstor = OpTypeImage %float 2D 0 0 0 2 R32f
6079 ; sampled image
6080 %imsam = OpTypeImage %float 2D 0 0 0 1 R32f
6081 %array_imstor = OpTypeArray %imstor %int_2
6082 %rta_imstor = OpTypeRuntimeArray %imstor
6083
6084 %_ptr_Uniform_stb = OpTypePointer Uniform %struct_b
6085 %_ptr_StorageBuffer_stb = OpTypePointer StorageBuffer %struct_b
6086 %_ptr_StorageBuffer_stb_rtarr = OpTypePointer StorageBuffer %struct_b_rtarr
6087 %_ptr_Workgroup = OpTypePointer Workgroup %float
6088 %_ptr_Private = OpTypePointer Private %float
6089 %_ptr_Function = OpTypePointer Function %float
6090 %_ptr_imstor = OpTypePointer UniformConstant %imstor
6091 %_ptr_imsam = OpTypePointer UniformConstant %imsam
6092 %_ptr_array_imstor = OpTypePointer UniformConstant %array_imstor
6093 %_ptr_rta_imstor = OpTypePointer UniformConstant %rta_imstor
6094
6095 %extra_fn = OpTypeFunction %void %float %_ptr_Private %_ptr_imstor
6096
6097 %var_ubo = OpVariable %_ptr_Uniform_stb Uniform
6098 %var_ssbo_sb = OpVariable %_ptr_StorageBuffer_stb StorageBuffer
6099 %var_ssbo_sb_rtarr = OpVariable %_ptr_StorageBuffer_stb_rtarr StorageBuffer
6100 %var_wg = OpVariable %_ptr_Workgroup Workgroup
6101 %var_priv = OpVariable %_ptr_Private Private
6102 %var_imstor = OpVariable %_ptr_imstor UniformConstant
6103 %var_imsam = OpVariable %_ptr_imsam UniformConstant
6104 %var_array_imstor = OpVariable %_ptr_array_imstor UniformConstant
6105 %var_rta_imstor = OpVariable %_ptr_rta_imstor UniformConstant
6106
6107 %helper = OpFunction %void None %extra_fn
6108 %param_f = OpFunctionParameter %float
6109 %param_p = OpFunctionParameter %_ptr_Private
6110 %param_pimstor = OpFunctionParameter %_ptr_imstor
6111 %helper_label = OpLabel
6112 %helper_func_var = OpVariable %_ptr_Function Function
6113 OpReturn
6114 OpFunctionEnd
6115
6116 %main = OpFunction %void None %void_fn
6117 %label = OpLabel
6118 %var_func = OpVariable %_ptr_Function Function
6119 OpReturn
6120 OpFunctionEnd
6121 )";
6122 }
6123
TEST_F(ValidateDecorations,NonWritableLabelTargetBad)6124 TEST_F(ValidateDecorations, NonWritableLabelTargetBad) {
6125 std::string spirv = ShaderWithNonWritableTarget("%label");
6126
6127 CompileSuccessfully(spirv);
6128 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6129 EXPECT_THAT(getDiagnosticString(),
6130 HasSubstr("Target of NonWritable decoration must be a "
6131 "memory object declaration (a variable or a function "
6132 "parameter)\n %label = OpLabel"));
6133 }
6134
TEST_F(ValidateDecorations,NonWritableTypeTargetBad)6135 TEST_F(ValidateDecorations, NonWritableTypeTargetBad) {
6136 std::string spirv = ShaderWithNonWritableTarget("%void");
6137
6138 CompileSuccessfully(spirv);
6139 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6140 EXPECT_THAT(getDiagnosticString(),
6141 HasSubstr("Target of NonWritable decoration must be a "
6142 "memory object declaration (a variable or a function "
6143 "parameter)\n %void = OpTypeVoid"));
6144 }
6145
TEST_F(ValidateDecorations,NonWritableValueTargetBad)6146 TEST_F(ValidateDecorations, NonWritableValueTargetBad) {
6147 std::string spirv = ShaderWithNonWritableTarget("%float_0");
6148
6149 CompileSuccessfully(spirv);
6150 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6151 EXPECT_THAT(getDiagnosticString(),
6152 HasSubstr("Target of NonWritable decoration must be a "
6153 "memory object declaration (a variable or a function "
6154 "parameter)\n %float_0 = OpConstant %float 0"));
6155 }
6156
TEST_F(ValidateDecorations,NonWritableValueParamBad)6157 TEST_F(ValidateDecorations, NonWritableValueParamBad) {
6158 std::string spirv = ShaderWithNonWritableTarget("%param_f");
6159
6160 CompileSuccessfully(spirv);
6161 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6162 EXPECT_THAT(getDiagnosticString(),
6163 HasSubstr("Target of NonWritable decoration is invalid: must "
6164 "point to a storage image, uniform block, or storage "
6165 "buffer\n %param_f = OpFunctionParameter %float"));
6166 }
6167
TEST_F(ValidateDecorations,NonWritablePointerParamButWrongTypeBad)6168 TEST_F(ValidateDecorations, NonWritablePointerParamButWrongTypeBad) {
6169 std::string spirv = ShaderWithNonWritableTarget("%param_p");
6170
6171 CompileSuccessfully(spirv);
6172 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6173 EXPECT_THAT(
6174 getDiagnosticString(),
6175 HasSubstr(
6176 "Target of NonWritable decoration is invalid: must "
6177 "point to a storage image, uniform block, or storage "
6178 "buffer\n %param_p = OpFunctionParameter %_ptr_Private_float"));
6179 }
6180
TEST_F(ValidateDecorations,NonWritablePointerParamStorageImageGood)6181 TEST_F(ValidateDecorations, NonWritablePointerParamStorageImageGood) {
6182 std::string spirv = ShaderWithNonWritableTarget("%param_pimstor");
6183
6184 CompileSuccessfully(spirv);
6185 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6186 EXPECT_THAT(getDiagnosticString(), Eq(""));
6187 }
6188
TEST_F(ValidateDecorations,NonWritableVarStorageImageGood)6189 TEST_F(ValidateDecorations, NonWritableVarStorageImageGood) {
6190 std::string spirv = ShaderWithNonWritableTarget("%var_imstor");
6191
6192 CompileSuccessfully(spirv);
6193 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6194 EXPECT_THAT(getDiagnosticString(), Eq(""));
6195 }
6196
TEST_F(ValidateDecorations,NonWritableVarSampledImageBad)6197 TEST_F(ValidateDecorations, NonWritableVarSampledImageBad) {
6198 std::string spirv = ShaderWithNonWritableTarget("%var_imsam");
6199
6200 CompileSuccessfully(spirv);
6201 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6202 EXPECT_THAT(getDiagnosticString(),
6203 HasSubstr("Target of NonWritable decoration is invalid: must "
6204 "point to a storage image, uniform block, or storage "
6205 "buffer\n %var_imsam"));
6206 }
6207
TEST_F(ValidateDecorations,NonWritableVarUboGood)6208 TEST_F(ValidateDecorations, NonWritableVarUboGood) {
6209 std::string spirv = ShaderWithNonWritableTarget("%var_ubo");
6210
6211 CompileSuccessfully(spirv);
6212 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6213 EXPECT_THAT(getDiagnosticString(), Eq(""));
6214 }
6215
TEST_F(ValidateDecorations,NonWritableVarSsboInUniformGood)6216 TEST_F(ValidateDecorations, NonWritableVarSsboInUniformGood) {
6217 const std::string spirv = R"(
6218 OpCapability Shader
6219 OpMemoryModel Logical GLSL450
6220 OpEntryPoint Vertex %main "main"
6221 OpDecorate %struct_bb BufferBlock
6222 OpMemberDecorate %struct_bb 0 Offset 0
6223 OpDecorate %var_ssbo_u NonWritable
6224 %void = OpTypeVoid
6225 %void_fn = OpTypeFunction %void
6226 %float = OpTypeFloat 32
6227 %struct_bb = OpTypeStruct %float
6228 %_ptr_Uniform_stbb = OpTypePointer Uniform %struct_bb
6229 %var_ssbo_u = OpVariable %_ptr_Uniform_stbb Uniform
6230 %main = OpFunction %void None %void_fn
6231 %label = OpLabel
6232 OpReturn
6233 OpFunctionEnd
6234 )";
6235
6236 CompileSuccessfully(spirv);
6237 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6238 EXPECT_THAT(getDiagnosticString(), Eq(""));
6239 }
6240
TEST_F(ValidateDecorations,NonWritableVarSsboInStorageBufferGood)6241 TEST_F(ValidateDecorations, NonWritableVarSsboInStorageBufferGood) {
6242 std::string spirv = ShaderWithNonWritableTarget("%var_ssbo_sb");
6243
6244 CompileSuccessfully(spirv);
6245 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6246 EXPECT_THAT(getDiagnosticString(), Eq(""));
6247 }
6248
TEST_F(ValidateDecorations,NonWritableMemberOfSsboInStorageBufferGood)6249 TEST_F(ValidateDecorations, NonWritableMemberOfSsboInStorageBufferGood) {
6250 std::string spirv = ShaderWithNonWritableTarget("%struct_b_rtarr", true);
6251
6252 CompileSuccessfully(spirv);
6253 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6254 EXPECT_THAT(getDiagnosticString(), Eq(""));
6255 }
6256
TEST_F(ValidateDecorations,NonWritableMemberOfStructGood)6257 TEST_F(ValidateDecorations, NonWritableMemberOfStructGood) {
6258 std::string spirv = ShaderWithNonWritableTarget("%simple_struct", true);
6259
6260 CompileSuccessfully(spirv);
6261 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6262 }
6263
TEST_F(ValidateDecorations,NonWritableVarWorkgroupBad)6264 TEST_F(ValidateDecorations, NonWritableVarWorkgroupBad) {
6265 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6266
6267 CompileSuccessfully(spirv);
6268 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6269 EXPECT_THAT(getDiagnosticString(),
6270 HasSubstr("Target of NonWritable decoration is invalid: must "
6271 "point to a storage image, uniform block, or storage "
6272 "buffer\n %var_wg"));
6273 }
6274
TEST_F(ValidateDecorations,NonWritableVarWorkgroupV14Bad)6275 TEST_F(ValidateDecorations, NonWritableVarWorkgroupV14Bad) {
6276 std::string spirv = ShaderWithNonWritableTarget("%var_wg");
6277
6278 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6279 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6280 EXPECT_THAT(getDiagnosticString(),
6281 HasSubstr("Target of NonWritable decoration is invalid: must "
6282 "point to a storage image, uniform block, storage "
6283 "buffer, or variable in Private or Function storage "
6284 "class\n %var_wg"));
6285 }
6286
TEST_F(ValidateDecorations,NonWritableVarPrivateBad)6287 TEST_F(ValidateDecorations, NonWritableVarPrivateBad) {
6288 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6289
6290 CompileSuccessfully(spirv);
6291 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6292 EXPECT_THAT(getDiagnosticString(),
6293 HasSubstr("Target of NonWritable decoration is invalid: must "
6294 "point to a storage image, uniform block, or storage "
6295 "buffer\n %var_priv"));
6296 }
6297
TEST_F(ValidateDecorations,NonWritableVarPrivateV13Bad)6298 TEST_F(ValidateDecorations, NonWritableVarPrivateV13Bad) {
6299 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6300
6301 CompileSuccessfully(spirv);
6302 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6303 EXPECT_THAT(getDiagnosticString(),
6304 HasSubstr("Target of NonWritable decoration is invalid: must "
6305 "point to a storage image, uniform block, or storage "
6306 "buffer\n %var_priv"));
6307 }
6308
TEST_F(ValidateDecorations,NonWritableVarPrivateV14Good)6309 TEST_F(ValidateDecorations, NonWritableVarPrivateV14Good) {
6310 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6311
6312 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6313 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6314 EXPECT_THAT(getDiagnosticString(), Eq(""));
6315 }
6316
TEST_F(ValidateDecorations,NonWritableVarPrivateV13TargetV14Bad)6317 TEST_F(ValidateDecorations, NonWritableVarPrivateV13TargetV14Bad) {
6318 std::string spirv = ShaderWithNonWritableTarget("%var_priv");
6319
6320 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6321 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6322 EXPECT_THAT(getDiagnosticString(),
6323 HasSubstr("Target of NonWritable decoration is invalid: must "
6324 "point to a storage image, uniform block, or storage "
6325 "buffer\n %var_priv"));
6326 }
6327
TEST_F(ValidateDecorations,NonWritableVarFunctionBad)6328 TEST_F(ValidateDecorations, NonWritableVarFunctionBad) {
6329 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6330
6331 CompileSuccessfully(spirv);
6332 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6333 EXPECT_THAT(getDiagnosticString(),
6334 HasSubstr("Target of NonWritable decoration is invalid: must "
6335 "point to a storage image, uniform block, or storage "
6336 "buffer\n %var_func"));
6337 }
6338
TEST_F(ValidateDecorations,NonWritableArrayGood)6339 TEST_F(ValidateDecorations, NonWritableArrayGood) {
6340 std::string spirv = ShaderWithNonWritableTarget("%var_array_imstor");
6341
6342 CompileSuccessfully(spirv);
6343 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6344 }
6345
TEST_F(ValidateDecorations,NonWritableRuntimeArrayGood)6346 TEST_F(ValidateDecorations, NonWritableRuntimeArrayGood) {
6347 std::string spirv = ShaderWithNonWritableTarget("%var_rta_imstor");
6348
6349 CompileSuccessfully(spirv);
6350 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
6351 }
6352
TEST_P(ValidateVulkanCombineDecorationResult,Decorate)6353 TEST_P(ValidateVulkanCombineDecorationResult, Decorate) {
6354 const char* const decoration = std::get<0>(GetParam());
6355 const char* const vuid = std::get<1>(GetParam());
6356 const TestResult& test_result = std::get<2>(GetParam());
6357
6358 CodeGenerator generator = CodeGenerator::GetDefaultShaderCodeGenerator();
6359 generator.before_types_ = "OpDecorate %u32 ";
6360 generator.before_types_ += decoration;
6361 generator.before_types_ += "\n";
6362
6363 EntryPoint entry_point;
6364 entry_point.name = "main";
6365 entry_point.execution_model = "Vertex";
6366 generator.entry_points_.push_back(std::move(entry_point));
6367
6368 CompileSuccessfully(generator.Build(), SPV_ENV_VULKAN_1_0);
6369 ASSERT_EQ(test_result.validation_result,
6370 ValidateInstructions(SPV_ENV_VULKAN_1_0));
6371 if (!test_result.error_str.empty()) {
6372 EXPECT_THAT(getDiagnosticString(), HasSubstr(test_result.error_str));
6373 }
6374 if (vuid) {
6375 EXPECT_THAT(getDiagnosticString(), AnyVUID(vuid));
6376 }
6377 }
6378
6379 INSTANTIATE_TEST_SUITE_P(
6380 DecorationAllowListFailure, ValidateVulkanCombineDecorationResult,
6381 Combine(Values("GLSLShared", "GLSLPacked"),
6382 Values("VUID-StandaloneSpirv-GLSLShared-04669"),
6383 Values(TestResult(
6384 SPV_ERROR_INVALID_ID,
6385 "is not valid for the Vulkan execution environment."))));
6386
TEST_F(ValidateDecorations,NonWritableVarFunctionV13Bad)6387 TEST_F(ValidateDecorations, NonWritableVarFunctionV13Bad) {
6388 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6389
6390 CompileSuccessfully(spirv);
6391 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6392 EXPECT_THAT(getDiagnosticString(),
6393 HasSubstr("Target of NonWritable decoration is invalid: must "
6394 "point to a storage image, uniform block, or storage "
6395 "buffer\n %var_func"));
6396 }
6397
TEST_F(ValidateDecorations,NonWritableVarFunctionV14Good)6398 TEST_F(ValidateDecorations, NonWritableVarFunctionV14Good) {
6399 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6400
6401 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6402 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6403 EXPECT_THAT(getDiagnosticString(), Eq(""));
6404 }
6405
TEST_F(ValidateDecorations,NonWritableVarFunctionV13TargetV14Bad)6406 TEST_F(ValidateDecorations, NonWritableVarFunctionV13TargetV14Bad) {
6407 std::string spirv = ShaderWithNonWritableTarget("%var_func");
6408
6409 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6410 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6411 EXPECT_THAT(getDiagnosticString(),
6412 HasSubstr("Target of NonWritable decoration is invalid: must "
6413 "point to a storage image, uniform block, or storage "
6414 "buffer\n %var_func"));
6415 }
6416
TEST_F(ValidateDecorations,BufferBlockV13ValV14Good)6417 TEST_F(ValidateDecorations, BufferBlockV13ValV14Good) {
6418 std::string spirv = R"(
6419 OpCapability Shader
6420 OpCapability Linkage
6421 OpMemoryModel Logical GLSL450
6422 OpDecorate %1 BufferBlock
6423 %1 = OpTypeStruct
6424 )";
6425
6426 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6427 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6428 }
6429
TEST_F(ValidateDecorations,BufferBlockV14Bad)6430 TEST_F(ValidateDecorations, BufferBlockV14Bad) {
6431 std::string spirv = R"(
6432 OpCapability Shader
6433 OpCapability Linkage
6434 OpMemoryModel Logical GLSL450
6435 OpDecorate %1 BufferBlock
6436 %1 = OpTypeStruct
6437 )";
6438
6439 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
6440 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
6441 ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
6442 EXPECT_THAT(getDiagnosticString(),
6443 HasSubstr("2nd operand of Decorate: operand BufferBlock(3) "
6444 "requires SPIR-V version 1.3 or earlier"));
6445 }
6446
6447 // Component
6448
TEST_F(ValidateDecorations,ComponentDecorationBadTarget)6449 TEST_F(ValidateDecorations, ComponentDecorationBadTarget) {
6450 std::string spirv = R"(
6451 OpCapability Shader
6452 OpMemoryModel Logical GLSL450
6453 OpEntryPoint Vertex %main "main"
6454 OpDecorate %t Component 0
6455 %void = OpTypeVoid
6456 %3 = OpTypeFunction %void
6457 %float = OpTypeFloat 32
6458 %t = OpTypeVector %float 2
6459 %main = OpFunction %void None %3
6460 %5 = OpLabel
6461 OpReturn
6462 OpFunctionEnd
6463 )";
6464
6465 CompileSuccessfully(spirv);
6466 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6467 EXPECT_THAT(getDiagnosticString(),
6468 HasSubstr("Target of Component decoration must be "
6469 "a memory object declaration"));
6470 }
6471
TEST_F(ValidateDecorations,ComponentDecorationBadStorageClass)6472 TEST_F(ValidateDecorations, ComponentDecorationBadStorageClass) {
6473 std::string spirv = R"(
6474 OpCapability Shader
6475 OpMemoryModel Logical GLSL450
6476 OpEntryPoint Vertex %main "main"
6477 OpDecorate %v Component 0
6478 %void = OpTypeVoid
6479 %3 = OpTypeFunction %void
6480 %float = OpTypeFloat 32
6481 %t = OpTypeVector %float 2
6482 %ptr_private = OpTypePointer Private %t
6483 %v = OpVariable %ptr_private Private
6484 %main = OpFunction %void None %3
6485 %5 = OpLabel
6486 OpReturn
6487 OpFunctionEnd
6488 )";
6489
6490 CompileSuccessfully(spirv);
6491 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState());
6492 EXPECT_THAT(getDiagnosticString(),
6493 HasSubstr("Target of Component decoration is invalid: must "
6494 "point to a Storage Class of Input(1) or Output(3)"));
6495 }
6496
TEST_F(ValidateDecorations,ComponentDecorationBadTypeVulkan)6497 TEST_F(ValidateDecorations, ComponentDecorationBadTypeVulkan) {
6498 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6499 std::string spirv = R"(
6500 OpCapability Shader
6501 OpCapability Matrix
6502 OpMemoryModel Logical GLSL450
6503 OpEntryPoint Vertex %main "main"
6504 OpDecorate %v Component 0
6505 %void = OpTypeVoid
6506 %3 = OpTypeFunction %void
6507 %float = OpTypeFloat 32
6508 %vtype = OpTypeVector %float 4
6509 %t = OpTypeMatrix %vtype 4
6510 %ptr_input = OpTypePointer Input %t
6511 %v = OpVariable %ptr_input Input
6512 %main = OpFunction %void None %3
6513 %5 = OpLabel
6514 OpReturn
6515 OpFunctionEnd
6516 )";
6517
6518 CompileSuccessfully(spirv, env);
6519 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6520 EXPECT_THAT(getDiagnosticString(),
6521 HasSubstr("Component decoration specified for type"));
6522 EXPECT_THAT(getDiagnosticString(), HasSubstr("is not a scalar or vector"));
6523 }
6524
ShaderWithComponentDecoration(const std::string & type,const std::string & decoration)6525 std::string ShaderWithComponentDecoration(const std::string& type,
6526 const std::string& decoration) {
6527 return R"(
6528 OpCapability Shader
6529 OpMemoryModel Logical GLSL450
6530 OpEntryPoint Fragment %main "main" %entryPointOutput
6531 OpExecutionMode %main OriginUpperLeft
6532 OpDecorate %entryPointOutput Location 0
6533 OpDecorate %entryPointOutput )" +
6534 decoration + R"(
6535 %void = OpTypeVoid
6536 %3 = OpTypeFunction %void
6537 %float = OpTypeFloat 32
6538 %v3float = OpTypeVector %float 3
6539 %v4float = OpTypeVector %float 4
6540 %uint = OpTypeInt 32 0
6541 %uint_2 = OpConstant %uint 2
6542 %arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
6543 %float_0 = OpConstant %float 0
6544 %_ptr_Output_type = OpTypePointer Output %)" + type + R"(
6545 %entryPointOutput = OpVariable %_ptr_Output_type Output
6546 %main = OpFunction %void None %3
6547 %5 = OpLabel
6548 OpReturn
6549 OpFunctionEnd
6550 )";
6551 }
6552
TEST_F(ValidateDecorations,ComponentDecorationIntGood0Vulkan)6553 TEST_F(ValidateDecorations, ComponentDecorationIntGood0Vulkan) {
6554 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6555 std::string spirv = ShaderWithComponentDecoration("uint", "Component 0");
6556
6557 CompileSuccessfully(spirv, env);
6558 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6559 EXPECT_THAT(getDiagnosticString(), Eq(""));
6560 }
6561
TEST_F(ValidateDecorations,ComponentDecorationIntGood1Vulkan)6562 TEST_F(ValidateDecorations, ComponentDecorationIntGood1Vulkan) {
6563 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6564 std::string spirv = ShaderWithComponentDecoration("uint", "Component 1");
6565
6566 CompileSuccessfully(spirv, env);
6567 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6568 EXPECT_THAT(getDiagnosticString(), Eq(""));
6569 }
6570
TEST_F(ValidateDecorations,ComponentDecorationIntGood2Vulkan)6571 TEST_F(ValidateDecorations, ComponentDecorationIntGood2Vulkan) {
6572 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6573 std::string spirv = ShaderWithComponentDecoration("uint", "Component 2");
6574
6575 CompileSuccessfully(spirv, env);
6576 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6577 EXPECT_THAT(getDiagnosticString(), Eq(""));
6578 }
6579
TEST_F(ValidateDecorations,ComponentDecorationIntGood3Vulkan)6580 TEST_F(ValidateDecorations, ComponentDecorationIntGood3Vulkan) {
6581 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6582 std::string spirv = ShaderWithComponentDecoration("uint", "Component 3");
6583
6584 CompileSuccessfully(spirv, env);
6585 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6586 EXPECT_THAT(getDiagnosticString(), Eq(""));
6587 }
6588
TEST_F(ValidateDecorations,ComponentDecorationIntBad4Vulkan)6589 TEST_F(ValidateDecorations, ComponentDecorationIntBad4Vulkan) {
6590 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6591 std::string spirv = ShaderWithComponentDecoration("uint", "Component 4");
6592
6593 CompileSuccessfully(spirv, env);
6594 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6595 EXPECT_THAT(getDiagnosticString(),
6596 HasSubstr("Sequence of components starting with 4 "
6597 "and ending with 4 gets larger than 3"));
6598 }
6599
TEST_F(ValidateDecorations,ComponentDecorationVector3GoodVulkan)6600 TEST_F(ValidateDecorations, ComponentDecorationVector3GoodVulkan) {
6601 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6602 std::string spirv = ShaderWithComponentDecoration("v3float", "Component 1");
6603
6604 CompileSuccessfully(spirv, env);
6605 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6606 EXPECT_THAT(getDiagnosticString(), Eq(""));
6607 }
6608
TEST_F(ValidateDecorations,ComponentDecorationVector4GoodVulkan)6609 TEST_F(ValidateDecorations, ComponentDecorationVector4GoodVulkan) {
6610 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6611 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 0");
6612
6613 CompileSuccessfully(spirv, env);
6614 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6615 EXPECT_THAT(getDiagnosticString(), Eq(""));
6616 }
6617
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad1Vulkan)6618 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad1Vulkan) {
6619 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6620 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 1");
6621
6622 CompileSuccessfully(spirv, env);
6623 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6624 EXPECT_THAT(getDiagnosticString(),
6625 HasSubstr("Sequence of components starting with 1 "
6626 "and ending with 4 gets larger than 3"));
6627 }
6628
TEST_F(ValidateDecorations,ComponentDecorationVector4Bad3Vulkan)6629 TEST_F(ValidateDecorations, ComponentDecorationVector4Bad3Vulkan) {
6630 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6631 std::string spirv = ShaderWithComponentDecoration("v4float", "Component 3");
6632
6633 CompileSuccessfully(spirv, env);
6634 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6635 EXPECT_THAT(getDiagnosticString(),
6636 HasSubstr("Sequence of components starting with 3 "
6637 "and ending with 6 gets larger than 3"));
6638 }
6639
TEST_F(ValidateDecorations,ComponentDecorationArrayGoodVulkan)6640 TEST_F(ValidateDecorations, ComponentDecorationArrayGoodVulkan) {
6641 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6642 std::string spirv =
6643 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 1");
6644
6645 CompileSuccessfully(spirv, env);
6646 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(env));
6647 EXPECT_THAT(getDiagnosticString(), Eq(""));
6648 }
6649
TEST_F(ValidateDecorations,ComponentDecorationArrayBadVulkan)6650 TEST_F(ValidateDecorations, ComponentDecorationArrayBadVulkan) {
6651 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6652 std::string spirv =
6653 ShaderWithComponentDecoration("arr_v3float_uint_2", "Component 2");
6654
6655 CompileSuccessfully(spirv, env);
6656 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6657 EXPECT_THAT(getDiagnosticString(),
6658 HasSubstr("Sequence of components starting with 2 "
6659 "and ending with 4 gets larger than 3"));
6660 }
6661
TEST_F(ValidateDecorations,ComponentDecorationBlockGood)6662 TEST_F(ValidateDecorations, ComponentDecorationBlockGood) {
6663 std::string spirv = R"(
6664 OpCapability Shader
6665 OpMemoryModel Logical GLSL450
6666 OpEntryPoint Fragment %4 "main" %9 %12
6667 OpExecutionMode %4 OriginUpperLeft
6668 OpDecorate %9 Location 0
6669 OpMemberDecorate %block 0 Location 2
6670 OpMemberDecorate %block 0 Component 1
6671 OpDecorate %block Block
6672 %2 = OpTypeVoid
6673 %3 = OpTypeFunction %2
6674 %float = OpTypeFloat 32
6675 %vec3 = OpTypeVector %float 3
6676 %8 = OpTypePointer Output %vec3
6677 %9 = OpVariable %8 Output
6678 %block = OpTypeStruct %vec3
6679 %11 = OpTypePointer Input %block
6680 %12 = OpVariable %11 Input
6681 %int = OpTypeInt 32 1
6682 %14 = OpConstant %int 0
6683 %15 = OpTypePointer Input %vec3
6684 %4 = OpFunction %2 None %3
6685 %5 = OpLabel
6686 %16 = OpAccessChain %15 %12 %14
6687 %17 = OpLoad %vec3 %16
6688 OpStore %9 %17
6689 OpReturn
6690 OpFunctionEnd
6691 )";
6692
6693 CompileSuccessfully(spirv);
6694 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6695 EXPECT_THAT(getDiagnosticString(), Eq(""));
6696 }
6697
TEST_F(ValidateDecorations,ComponentDecorationBlockBadVulkan)6698 TEST_F(ValidateDecorations, ComponentDecorationBlockBadVulkan) {
6699 const spv_target_env env = SPV_ENV_VULKAN_1_0;
6700 std::string spirv = R"(
6701 OpCapability Shader
6702 OpMemoryModel Logical GLSL450
6703 OpEntryPoint Fragment %4 "main" %9 %12
6704 OpExecutionMode %4 OriginUpperLeft
6705 OpDecorate %9 Location 0
6706 OpMemberDecorate %block 0 Location 2
6707 OpMemberDecorate %block 0 Component 2
6708 OpDecorate %block Block
6709 %2 = OpTypeVoid
6710 %3 = OpTypeFunction %2
6711 %float = OpTypeFloat 32
6712 %vec3 = OpTypeVector %float 3
6713 %8 = OpTypePointer Output %vec3
6714 %9 = OpVariable %8 Output
6715 %block = OpTypeStruct %vec3
6716 %11 = OpTypePointer Input %block
6717 %12 = OpVariable %11 Input
6718 %int = OpTypeInt 32 1
6719 %14 = OpConstant %int 0
6720 %15 = OpTypePointer Input %vec3
6721 %4 = OpFunction %2 None %3
6722 %5 = OpLabel
6723 %16 = OpAccessChain %15 %12 %14
6724 %17 = OpLoad %vec3 %16
6725 OpStore %9 %17
6726 OpReturn
6727 OpFunctionEnd
6728 )";
6729
6730 CompileSuccessfully(spirv, env);
6731 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateAndRetrieveValidationState(env));
6732 EXPECT_THAT(getDiagnosticString(),
6733 HasSubstr("Sequence of components starting with 2 "
6734 "and ending with 4 gets larger than 3"));
6735 }
6736
TEST_F(ValidateDecorations,ComponentDecorationFunctionParameter)6737 TEST_F(ValidateDecorations, ComponentDecorationFunctionParameter) {
6738 std::string spirv = R"(
6739 OpCapability Shader
6740 OpMemoryModel Logical GLSL450
6741 OpEntryPoint Vertex %main "main"
6742
6743 OpDecorate %param_f Component 0
6744
6745 %void = OpTypeVoid
6746 %void_fn = OpTypeFunction %void
6747 %float = OpTypeFloat 32
6748 %float_0 = OpConstant %float 0
6749 %int = OpTypeInt 32 0
6750 %int_2 = OpConstant %int 2
6751 %struct_b = OpTypeStruct %float
6752
6753 %extra_fn = OpTypeFunction %void %float
6754
6755 %helper = OpFunction %void None %extra_fn
6756 %param_f = OpFunctionParameter %float
6757 %helper_label = OpLabel
6758 OpReturn
6759 OpFunctionEnd
6760
6761 %main = OpFunction %void None %void_fn
6762 %label = OpLabel
6763 OpReturn
6764 OpFunctionEnd
6765 )";
6766
6767 CompileSuccessfully(spirv);
6768 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
6769 EXPECT_THAT(getDiagnosticString(), Eq(""));
6770 }
6771
TEST_F(ValidateDecorations,VulkanStorageBufferBlock)6772 TEST_F(ValidateDecorations, VulkanStorageBufferBlock) {
6773 const std::string spirv = R"(
6774 OpCapability Shader
6775 OpExtension "SPV_KHR_storage_buffer_storage_class"
6776 OpMemoryModel Logical GLSL450
6777 OpEntryPoint GLCompute %main "main"
6778 OpExecutionMode %main LocalSize 1 1 1
6779 OpDecorate %struct Block
6780 OpMemberDecorate %struct 0 Offset 0
6781 %void = OpTypeVoid
6782 %uint = OpTypeInt 32 0
6783 %struct = OpTypeStruct %uint
6784 %ptr_ssbo = OpTypePointer StorageBuffer %struct
6785 %var = OpVariable %ptr_ssbo StorageBuffer
6786 %void_fn = OpTypeFunction %void
6787 %main = OpFunction %void None %void_fn
6788 %entry = OpLabel
6789 OpReturn
6790 OpFunctionEnd
6791 )";
6792
6793 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6794 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6795 }
6796
TEST_F(ValidateDecorations,VulkanStorageBufferMissingBlock)6797 TEST_F(ValidateDecorations, VulkanStorageBufferMissingBlock) {
6798 const std::string spirv = R"(
6799 OpCapability Shader
6800 OpExtension "SPV_KHR_storage_buffer_storage_class"
6801 OpMemoryModel Logical GLSL450
6802 OpEntryPoint GLCompute %main "main"
6803 OpExecutionMode %main LocalSize 1 1 1
6804 %void = OpTypeVoid
6805 %uint = OpTypeInt 32 0
6806 %struct = OpTypeStruct %uint
6807 %ptr_ssbo = OpTypePointer StorageBuffer %struct
6808 %var = OpVariable %ptr_ssbo StorageBuffer
6809 %void_fn = OpTypeFunction %void
6810 %main = OpFunction %void None %void_fn
6811 %entry = OpLabel
6812 OpReturn
6813 OpFunctionEnd
6814 )";
6815
6816 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6817 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6818 EXPECT_THAT(getDiagnosticString(),
6819 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6820 "must be identified with a Block decoration"));
6821 }
6822
TEST_F(ValidateDecorations,VulkanStorageBufferArrayMissingBlock)6823 TEST_F(ValidateDecorations, VulkanStorageBufferArrayMissingBlock) {
6824 const std::string spirv = R"(
6825 OpCapability Shader
6826 OpExtension "SPV_KHR_storage_buffer_storage_class"
6827 OpMemoryModel Logical GLSL450
6828 OpEntryPoint GLCompute %main "main"
6829 OpExecutionMode %main LocalSize 1 1 1
6830 %void = OpTypeVoid
6831 %uint = OpTypeInt 32 0
6832 %uint_4 = OpConstant %uint 4
6833 %struct = OpTypeStruct %uint
6834 %array = OpTypeArray %struct %uint_4
6835 %ptr_ssbo = OpTypePointer StorageBuffer %array
6836 %var = OpVariable %ptr_ssbo StorageBuffer
6837 %void_fn = OpTypeFunction %void
6838 %main = OpFunction %void None %void_fn
6839 %entry = OpLabel
6840 OpReturn
6841 OpFunctionEnd
6842 )";
6843
6844 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6845 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6846 EXPECT_THAT(getDiagnosticString(),
6847 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6848 "must be identified with a Block decoration"));
6849 }
6850
TEST_F(ValidateDecorations,VulkanStorageBufferRuntimeArrayMissingBlock)6851 TEST_F(ValidateDecorations, VulkanStorageBufferRuntimeArrayMissingBlock) {
6852 const std::string spirv = R"(
6853 OpCapability Shader
6854 OpCapability RuntimeDescriptorArrayEXT
6855 OpExtension "SPV_EXT_descriptor_indexing"
6856 OpExtension "SPV_KHR_storage_buffer_storage_class"
6857 OpMemoryModel Logical GLSL450
6858 OpEntryPoint GLCompute %main "main"
6859 OpExecutionMode %main LocalSize 1 1 1
6860 %void = OpTypeVoid
6861 %uint = OpTypeInt 32 0
6862 %struct = OpTypeStruct %uint
6863 %array = OpTypeRuntimeArray %struct
6864 %ptr_ssbo = OpTypePointer StorageBuffer %array
6865 %var = OpVariable %ptr_ssbo StorageBuffer
6866 %void_fn = OpTypeFunction %void
6867 %main = OpFunction %void None %void_fn
6868 %entry = OpLabel
6869 OpReturn
6870 OpFunctionEnd
6871 )";
6872
6873 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6874 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6875 EXPECT_THAT(getDiagnosticString(),
6876 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables "
6877 "must be identified with a Block decoration"));
6878 }
6879
TEST_F(ValidateDecorations,VulkanUniformBlock)6880 TEST_F(ValidateDecorations, VulkanUniformBlock) {
6881 const std::string spirv = R"(
6882 OpCapability Shader
6883 OpMemoryModel Logical GLSL450
6884 OpEntryPoint GLCompute %main "main"
6885 OpExecutionMode %main LocalSize 1 1 1
6886 OpDecorate %struct Block
6887 OpMemberDecorate %struct 0 Offset 0
6888 %void = OpTypeVoid
6889 %uint = OpTypeInt 32 0
6890 %struct = OpTypeStruct %uint
6891 %ptr_ubo = OpTypePointer Uniform %struct
6892 %var = OpVariable %ptr_ubo Uniform
6893 %void_fn = OpTypeFunction %void
6894 %main = OpFunction %void None %void_fn
6895 %entry = OpLabel
6896 OpReturn
6897 OpFunctionEnd
6898 )";
6899
6900 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6901 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6902 }
6903
TEST_F(ValidateDecorations,VulkanUniformBufferBlock)6904 TEST_F(ValidateDecorations, VulkanUniformBufferBlock) {
6905 const std::string spirv = R"(
6906 OpCapability Shader
6907 OpMemoryModel Logical GLSL450
6908 OpEntryPoint GLCompute %main "main"
6909 OpExecutionMode %main LocalSize 1 1 1
6910 OpDecorate %struct BufferBlock
6911 OpMemberDecorate %struct 0 Offset 0
6912 %void = OpTypeVoid
6913 %uint = OpTypeInt 32 0
6914 %struct = OpTypeStruct %uint
6915 %ptr_ubo = OpTypePointer Uniform %struct
6916 %var = OpVariable %ptr_ubo Uniform
6917 %void_fn = OpTypeFunction %void
6918 %main = OpFunction %void None %void_fn
6919 %entry = OpLabel
6920 OpReturn
6921 OpFunctionEnd
6922 )";
6923
6924 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6925 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6926 }
6927
TEST_F(ValidateDecorations,VulkanUniformMissingBlock)6928 TEST_F(ValidateDecorations, VulkanUniformMissingBlock) {
6929 const std::string spirv = R"(
6930 OpCapability Shader
6931 OpMemoryModel Logical GLSL450
6932 OpEntryPoint GLCompute %main "main"
6933 OpExecutionMode %main LocalSize 1 1 1
6934 %void = OpTypeVoid
6935 %uint = OpTypeInt 32 0
6936 %struct = OpTypeStruct %uint
6937 %ptr_ubo = OpTypePointer Uniform %struct
6938 %var = OpVariable %ptr_ubo Uniform
6939 %void_fn = OpTypeFunction %void
6940 %main = OpFunction %void None %void_fn
6941 %entry = OpLabel
6942 OpReturn
6943 OpFunctionEnd
6944 )";
6945
6946 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6947 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6948 EXPECT_THAT(
6949 getDiagnosticString(),
6950 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
6951 "identified with a Block or BufferBlock decoration"));
6952 }
6953
TEST_F(ValidateDecorations,VulkanUniformArrayMissingBlock)6954 TEST_F(ValidateDecorations, VulkanUniformArrayMissingBlock) {
6955 const std::string spirv = R"(
6956 OpCapability Shader
6957 OpMemoryModel Logical GLSL450
6958 OpEntryPoint GLCompute %main "main"
6959 OpExecutionMode %main LocalSize 1 1 1
6960 %void = OpTypeVoid
6961 %uint = OpTypeInt 32 0
6962 %uint_4 = OpConstant %uint 4
6963 %struct = OpTypeStruct %uint
6964 %array = OpTypeArray %struct %uint_4
6965 %ptr_ubo = OpTypePointer Uniform %array
6966 %var = OpVariable %ptr_ubo Uniform
6967 %void_fn = OpTypeFunction %void
6968 %main = OpFunction %void None %void_fn
6969 %entry = OpLabel
6970 OpReturn
6971 OpFunctionEnd
6972 )";
6973
6974 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
6975 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
6976 EXPECT_THAT(
6977 getDiagnosticString(),
6978 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
6979 "identified with a Block or BufferBlock decoration"));
6980 }
6981
TEST_F(ValidateDecorations,VulkanUniformRuntimeArrayMissingBlock)6982 TEST_F(ValidateDecorations, VulkanUniformRuntimeArrayMissingBlock) {
6983 const std::string spirv = R"(
6984 OpCapability Shader
6985 OpCapability RuntimeDescriptorArrayEXT
6986 OpExtension "SPV_EXT_descriptor_indexing"
6987 OpMemoryModel Logical GLSL450
6988 OpEntryPoint GLCompute %main "main"
6989 OpExecutionMode %main LocalSize 1 1 1
6990 %void = OpTypeVoid
6991 %uint = OpTypeInt 32 0
6992 %struct = OpTypeStruct %uint
6993 %array = OpTypeRuntimeArray %struct
6994 %ptr_ubo = OpTypePointer Uniform %array
6995 %var = OpVariable %ptr_ubo Uniform
6996 %void_fn = OpTypeFunction %void
6997 %main = OpFunction %void None %void_fn
6998 %entry = OpLabel
6999 OpReturn
7000 OpFunctionEnd
7001 )";
7002
7003 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
7004 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
7005 EXPECT_THAT(
7006 getDiagnosticString(),
7007 HasSubstr("From Vulkan spec, section 14.5.2:\nSuch variables must be "
7008 "identified with a Block or BufferBlock decoration"));
7009 }
7010
TEST_F(ValidateDecorations,VulkanArrayStrideZero)7011 TEST_F(ValidateDecorations, VulkanArrayStrideZero) {
7012 const std::string spirv = R"(
7013 OpCapability Shader
7014 OpMemoryModel Logical GLSL450
7015 OpEntryPoint GLCompute %main "main"
7016 OpExecutionMode %main LocalSize 1 1 1
7017 OpDecorate %var DescriptorSet 0
7018 OpDecorate %var Binding 0
7019 OpDecorate %struct Block
7020 OpMemberDecorate %struct 0 Offset 0
7021 OpDecorate %array ArrayStride 0
7022 %void = OpTypeVoid
7023 %int = OpTypeInt 32 0
7024 %int_4 = OpConstant %int 4
7025 %array = OpTypeArray %int %int_4
7026 %struct = OpTypeStruct %array
7027 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7028 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7029 %void_fn = OpTypeFunction %void
7030 %main = OpFunction %void None %void_fn
7031 %entry = OpLabel
7032 OpReturn
7033 OpFunctionEnd
7034 )";
7035
7036 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7037 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7038 EXPECT_THAT(getDiagnosticString(),
7039 HasSubstr("contains an array with stride 0"));
7040 }
7041
TEST_F(ValidateDecorations,VulkanArrayStrideTooSmall)7042 TEST_F(ValidateDecorations, VulkanArrayStrideTooSmall) {
7043 const std::string spirv = R"(
7044 OpCapability Shader
7045 OpMemoryModel Logical GLSL450
7046 OpEntryPoint GLCompute %main "main"
7047 OpExecutionMode %main LocalSize 1 1 1
7048 OpDecorate %var DescriptorSet 0
7049 OpDecorate %var Binding 0
7050 OpDecorate %struct Block
7051 OpMemberDecorate %struct 0 Offset 0
7052 OpDecorate %inner ArrayStride 4
7053 OpDecorate %outer ArrayStride 4
7054 %void = OpTypeVoid
7055 %int = OpTypeInt 32 0
7056 %int_4 = OpConstant %int 4
7057 %inner = OpTypeArray %int %int_4
7058 %outer = OpTypeArray %inner %int_4
7059 %struct = OpTypeStruct %outer
7060 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
7061 %var = OpVariable %ptr_ssbo_struct StorageBuffer
7062 %void_fn = OpTypeFunction %void
7063 %main = OpFunction %void None %void_fn
7064 %entry = OpLabel
7065 OpReturn
7066 OpFunctionEnd
7067 )";
7068
7069 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
7070 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
7071 EXPECT_THAT(
7072 getDiagnosticString(),
7073 HasSubstr(
7074 "contains an array with stride 4, but with an element size of 16"));
7075 }
7076
TEST_F(ValidateDecorations,FunctionsWithOpGroupDecorate)7077 TEST_F(ValidateDecorations, FunctionsWithOpGroupDecorate) {
7078 std::string spirv = R"(
7079 OpCapability Addresses
7080 OpCapability Linkage
7081 OpCapability Kernel
7082 OpCapability Int8
7083 %1 = OpExtInstImport "OpenCL.std"
7084 OpMemoryModel Physical32 OpenCL
7085 OpName %foo "foo"
7086 OpName %entry "entry"
7087 OpName %bar "bar"
7088 OpName %entry_0 "entry"
7089 OpName %k "k"
7090 OpName %entry_1 "entry"
7091 OpName %b "b"
7092 OpDecorate %28 FuncParamAttr Zext
7093 %28 = OpDecorationGroup
7094 OpDecorate %k LinkageAttributes "k" Export
7095 OpDecorate %foo LinkageAttributes "foo" Export
7096 OpDecorate %bar LinkageAttributes "bar" Export
7097 OpDecorate %b Alignment 1
7098 OpGroupDecorate %28 %foo %bar
7099 %uchar = OpTypeInt 8 0
7100 %bool = OpTypeBool
7101 %3 = OpTypeFunction %bool
7102 %void = OpTypeVoid
7103 %10 = OpTypeFunction %void
7104 %_ptr_Function_uchar = OpTypePointer Function %uchar
7105 %true = OpConstantTrue %bool
7106 %foo = OpFunction %bool DontInline %3
7107 %entry = OpLabel
7108 OpReturnValue %true
7109 OpFunctionEnd
7110 %bar = OpFunction %bool DontInline %3
7111 %entry_0 = OpLabel
7112 OpReturnValue %true
7113 OpFunctionEnd
7114 %k = OpFunction %void DontInline %10
7115 %entry_1 = OpLabel
7116 %b = OpVariable %_ptr_Function_uchar Function
7117 OpReturn
7118 OpFunctionEnd
7119 )";
7120 CompileSuccessfully(spirv);
7121 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
7122 }
7123
TEST_F(ValidateDecorations,LocationVariableGood)7124 TEST_F(ValidateDecorations, LocationVariableGood) {
7125 const std::string spirv = R"(
7126 OpCapability Shader
7127 OpCapability Linkage
7128 OpMemoryModel Logical GLSL450
7129 OpDecorate %in_var Location 0
7130 %float = OpTypeFloat 32
7131 %ptr_input_float = OpTypePointer Input %float
7132 %in_var = OpVariable %ptr_input_float Input
7133 )";
7134
7135 CompileSuccessfully(spirv);
7136 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7137 }
7138
TEST_F(ValidateDecorations,LocationStructMemberGood)7139 TEST_F(ValidateDecorations, LocationStructMemberGood) {
7140 const std::string spirv = R"(
7141 OpCapability Shader
7142 OpCapability Linkage
7143 OpMemoryModel Logical GLSL450
7144 OpMemberDecorate %struct 0 Location 0
7145 %float = OpTypeFloat 32
7146 %struct = OpTypeStruct %float
7147 )";
7148
7149 CompileSuccessfully(spirv);
7150 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
7151 }
7152
TEST_F(ValidateDecorations,LocationStructBad)7153 TEST_F(ValidateDecorations, LocationStructBad) {
7154 const std::string spirv = R"(
7155 OpCapability Shader
7156 OpCapability Linkage
7157 OpMemoryModel Logical GLSL450
7158 OpDecorate %struct Location 0
7159 %float = OpTypeFloat 32
7160 %struct = OpTypeStruct %float
7161 )";
7162
7163 CompileSuccessfully(spirv);
7164 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7165 EXPECT_THAT(getDiagnosticString(),
7166 HasSubstr("Location decoration can only be applied to a variable "
7167 "or member of a structure type"));
7168 }
7169
TEST_F(ValidateDecorations,LocationFloatBad)7170 TEST_F(ValidateDecorations, LocationFloatBad) {
7171 const std::string spirv = R"(
7172 OpCapability Shader
7173 OpCapability Linkage
7174 OpMemoryModel Logical GLSL450
7175 OpDecorate %float Location 0
7176 %float = OpTypeFloat 32
7177 )";
7178
7179 CompileSuccessfully(spirv);
7180 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
7181 EXPECT_THAT(getDiagnosticString(),
7182 HasSubstr("Location decoration can only be applied to a variable "
7183 "or member of a structure type"));
7184 }
7185
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariable)7186 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariable) {
7187 std::string spirv = R"(
7188 OpCapability Shader
7189 OpCapability WorkgroupMemoryExplicitLayoutKHR
7190 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7191 OpMemoryModel Logical GLSL450
7192 OpEntryPoint GLCompute %main "main" %_
7193 OpExecutionMode %main LocalSize 8 1 1
7194 OpMemberDecorate %first 0 Offset 0
7195 OpDecorate %first Block
7196 %void = OpTypeVoid
7197 %3 = OpTypeFunction %void
7198 %int = OpTypeInt 32 1
7199 %first = OpTypeStruct %int
7200 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7201 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7202 %int_0 = OpConstant %int 0
7203 %int_2 = OpConstant %int 2
7204 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7205 %main = OpFunction %void None %3
7206 %5 = OpLabel
7207 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7208 OpStore %13 %int_2
7209 OpReturn
7210 OpFunctionEnd
7211 )";
7212
7213 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7214 EXPECT_EQ(SPV_SUCCESS,
7215 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7216 }
7217
TEST_F(ValidateDecorations,WorkgroupBlockVariableRequiresV14)7218 TEST_F(ValidateDecorations, WorkgroupBlockVariableRequiresV14) {
7219 std::string spirv = R"(
7220 OpCapability Shader
7221 OpCapability WorkgroupMemoryExplicitLayoutKHR
7222 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7223 OpMemoryModel Logical GLSL450
7224 OpEntryPoint GLCompute %main "main" %_
7225 OpExecutionMode %main LocalSize 8 1 1
7226 OpMemberDecorate %first 0 Offset 0
7227 OpDecorate %first Block
7228 %void = OpTypeVoid
7229 %3 = OpTypeFunction %void
7230 %int = OpTypeInt 32 1
7231 %first = OpTypeStruct %int
7232 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7233 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7234 %int_0 = OpConstant %int 0
7235 %int_2 = OpConstant %int 2
7236 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7237 %main = OpFunction %void None %3
7238 %5 = OpLabel
7239 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7240 OpStore %13 %int_2
7241 OpReturn
7242 OpFunctionEnd
7243 )";
7244
7245 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
7246 EXPECT_EQ(SPV_ERROR_WRONG_VERSION,
7247 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7248 EXPECT_THAT(getDiagnosticString(),
7249 HasSubstr("requires SPIR-V version 1.4 or later"));
7250 }
7251
TEST_F(ValidateDecorations,WorkgroupSingleNonBlockVariable)7252 TEST_F(ValidateDecorations, WorkgroupSingleNonBlockVariable) {
7253 std::string spirv = R"(
7254 OpCapability Shader
7255 OpMemoryModel Logical GLSL450
7256 OpEntryPoint GLCompute %main "main" %a
7257 OpExecutionMode %main LocalSize 8 1 1
7258 %void = OpTypeVoid
7259 %3 = OpTypeFunction %void
7260 %int = OpTypeInt 32 1
7261 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7262 %a = OpVariable %_ptr_Workgroup_int Workgroup
7263 %int_2 = OpConstant %int 2
7264 %main = OpFunction %void None %3
7265 %5 = OpLabel
7266 OpStore %a %int_2
7267 OpReturn
7268 OpFunctionEnd
7269 )";
7270
7271 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7272 EXPECT_EQ(SPV_SUCCESS,
7273 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7274 }
7275
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariable)7276 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariable) {
7277 std::string spirv = R"(
7278 OpCapability Shader
7279 OpCapability WorkgroupMemoryExplicitLayoutKHR
7280 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7281 OpMemoryModel Logical GLSL450
7282 OpEntryPoint GLCompute %main "main" %_ %__0
7283 OpExecutionMode %main LocalSize 8 1 1
7284 OpMemberDecorate %first 0 Offset 0
7285 OpDecorate %first Block
7286 OpMemberDecorate %second 0 Offset 0
7287 OpDecorate %second Block
7288 OpDecorate %_ Aliased
7289 OpDecorate %__0 Aliased
7290 %void = OpTypeVoid
7291 %3 = OpTypeFunction %void
7292 %int = OpTypeInt 32 1
7293 %first = OpTypeStruct %int
7294 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7295 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7296 %int_0 = OpConstant %int 0
7297 %int_2 = OpConstant %int 2
7298 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7299 %second = OpTypeStruct %int
7300 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7301 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7302 %int_3 = OpConstant %int 3
7303 %main = OpFunction %void None %3
7304 %5 = OpLabel
7305 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7306 OpStore %13 %int_2
7307 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7308 OpStore %18 %int_3
7309 OpReturn
7310 OpFunctionEnd
7311 )";
7312
7313 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7314 EXPECT_EQ(SPV_SUCCESS,
7315 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7316 }
7317
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith8BitType)7318 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith8BitType) {
7319 std::string spirv = R"(
7320 OpCapability Shader
7321 OpCapability Int8
7322 OpCapability WorkgroupMemoryExplicitLayout8BitAccessKHR
7323 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7324 OpMemoryModel Logical GLSL450
7325 OpEntryPoint GLCompute %main "main" %_
7326 OpExecutionMode %main LocalSize 2 1 1
7327 OpMemberDecorate %first 0 Offset 0
7328 OpDecorate %first Block
7329 %void = OpTypeVoid
7330 %3 = OpTypeFunction %void
7331 %char = OpTypeInt 8 1
7332 %first = OpTypeStruct %char
7333 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7334 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7335 %int = OpTypeInt 32 1
7336 %int_0 = OpConstant %int 0
7337 %char_2 = OpConstant %char 2
7338 %_ptr_Workgroup_char = OpTypePointer Workgroup %char
7339 %main = OpFunction %void None %3
7340 %5 = OpLabel
7341 %14 = OpAccessChain %_ptr_Workgroup_char %_ %int_0
7342 OpStore %14 %char_2
7343 OpReturn
7344 OpFunctionEnd
7345 )";
7346
7347 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7348 EXPECT_EQ(SPV_SUCCESS,
7349 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7350 }
7351
TEST_F(ValidateDecorations,WorkgroupMultiNonBlockVariable)7352 TEST_F(ValidateDecorations, WorkgroupMultiNonBlockVariable) {
7353 std::string spirv = R"(
7354 OpCapability Shader
7355 OpMemoryModel Logical GLSL450
7356 OpEntryPoint GLCompute %main "main" %a %b
7357 OpExecutionMode %main LocalSize 8 1 1
7358 %void = OpTypeVoid
7359 %3 = OpTypeFunction %void
7360 %int = OpTypeInt 32 1
7361 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7362 %a = OpVariable %_ptr_Workgroup_int Workgroup
7363 %int_2 = OpConstant %int 2
7364 %b = OpVariable %_ptr_Workgroup_int Workgroup
7365 %int_3 = OpConstant %int 3
7366 %main = OpFunction %void None %3
7367 %5 = OpLabel
7368 OpStore %a %int_2
7369 OpStore %b %int_3
7370 OpReturn
7371 OpFunctionEnd
7372 )";
7373
7374 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7375 EXPECT_EQ(SPV_SUCCESS,
7376 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7377 }
7378
TEST_F(ValidateDecorations,WorkgroupBlockVariableWith16BitType)7379 TEST_F(ValidateDecorations, WorkgroupBlockVariableWith16BitType) {
7380 std::string spirv = R"(
7381 OpCapability Shader
7382 OpCapability Float16
7383 OpCapability Int16
7384 OpCapability WorkgroupMemoryExplicitLayout16BitAccessKHR
7385 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7386 OpMemoryModel Logical GLSL450
7387 OpEntryPoint GLCompute %main "main" %_
7388 OpExecutionMode %main LocalSize 2 1 1
7389 OpMemberDecorate %first 0 Offset 0
7390 OpMemberDecorate %first 1 Offset 2
7391 OpDecorate %first Block
7392 %void = OpTypeVoid
7393 %3 = OpTypeFunction %void
7394 %short = OpTypeInt 16 1
7395 %half = OpTypeFloat 16
7396 %first = OpTypeStruct %short %half
7397 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7398 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7399 %int = OpTypeInt 32 1
7400 %int_0 = OpConstant %int 0
7401 %short_3 = OpConstant %short 3
7402 %_ptr_Workgroup_short = OpTypePointer Workgroup %short
7403 %int_1 = OpConstant %int 1
7404 %half_0x1_898p_3 = OpConstant %half 0x1.898p+3
7405 %_ptr_Workgroup_half = OpTypePointer Workgroup %half
7406 %main = OpFunction %void None %3
7407 %5 = OpLabel
7408 %15 = OpAccessChain %_ptr_Workgroup_short %_ %int_0
7409 OpStore %15 %short_3
7410 %19 = OpAccessChain %_ptr_Workgroup_half %_ %int_1
7411 OpStore %19 %half_0x1_898p_3
7412 OpReturn
7413 OpFunctionEnd
7414 )";
7415
7416 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7417 EXPECT_EQ(SPV_SUCCESS,
7418 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7419 }
7420
TEST_F(ValidateDecorations,WorkgroupBlockVariableScalarLayout)7421 TEST_F(ValidateDecorations, WorkgroupBlockVariableScalarLayout) {
7422 std::string spirv = R"(
7423 OpCapability Shader
7424 OpCapability WorkgroupMemoryExplicitLayoutKHR
7425 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7426 OpMemoryModel Logical GLSL450
7427 OpEntryPoint Vertex %main "main" %B
7428 OpSource GLSL 450
7429 OpMemberDecorate %S 0 Offset 0
7430 OpMemberDecorate %S 1 Offset 4
7431 OpMemberDecorate %S 2 Offset 16
7432 OpMemberDecorate %S 3 Offset 28
7433 OpDecorate %S Block
7434 OpDecorate %B Aliased
7435 %void = OpTypeVoid
7436 %3 = OpTypeFunction %void
7437 %float = OpTypeFloat 32
7438 %v3float = OpTypeVector %float 3
7439 %S = OpTypeStruct %float %v3float %v3float %v3float
7440 %_ptr_Workgroup_S = OpTypePointer Workgroup %S
7441 %B = OpVariable %_ptr_Workgroup_S Workgroup
7442 %main = OpFunction %void None %3
7443 %5 = OpLabel
7444 OpReturn
7445 OpFunctionEnd
7446 )";
7447
7448 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7449 spvValidatorOptionsSetWorkgroupScalarBlockLayout(getValidatorOptions(), true);
7450 EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4))
7451 << getDiagnosticString();
7452 }
7453
TEST_F(ValidateDecorations,WorkgroupMixBlockAndNonBlockBad)7454 TEST_F(ValidateDecorations, WorkgroupMixBlockAndNonBlockBad) {
7455 std::string spirv = R"(
7456 OpCapability Shader
7457 OpCapability WorkgroupMemoryExplicitLayoutKHR
7458 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7459 OpMemoryModel Logical GLSL450
7460 OpEntryPoint GLCompute %main "main" %_ %b
7461 OpExecutionMode %main LocalSize 8 1 1
7462 OpMemberDecorate %first 0 Offset 0
7463 OpDecorate %first Block
7464 OpDecorate %_ Aliased
7465 OpDecorate %b Aliased
7466 %void = OpTypeVoid
7467 %3 = OpTypeFunction %void
7468 %int = OpTypeInt 32 1
7469 %first = OpTypeStruct %int
7470 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7471 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7472 %int_0 = OpConstant %int 0
7473 %int_2 = OpConstant %int 2
7474 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7475 %b = OpVariable %_ptr_Workgroup_int Workgroup
7476 %int_3 = OpConstant %int 3
7477 %main = OpFunction %void None %3
7478 %5 = OpLabel
7479 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7480 OpStore %13 %int_2
7481 OpStore %b %int_3
7482 OpReturn
7483 OpFunctionEnd
7484 )";
7485
7486 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7487 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7488 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7489 EXPECT_THAT(
7490 getDiagnosticString(),
7491 HasSubstr("either all or none of the Workgroup Storage Class variables "
7492 "in the entry point interface must point to struct types "
7493 "decorated with Block"));
7494 }
7495
TEST_F(ValidateDecorations,WorkgroupMultiBlockVariableMissingAliased)7496 TEST_F(ValidateDecorations, WorkgroupMultiBlockVariableMissingAliased) {
7497 std::string spirv = R"(
7498 OpCapability Shader
7499 OpCapability WorkgroupMemoryExplicitLayoutKHR
7500 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7501 OpMemoryModel Logical GLSL450
7502 OpEntryPoint GLCompute %main "main" %_ %__0
7503 OpExecutionMode %main LocalSize 8 1 1
7504 OpMemberDecorate %first 0 Offset 0
7505 OpDecorate %first Block
7506 OpMemberDecorate %second 0 Offset 0
7507 OpDecorate %second Block
7508 OpDecorate %_ Aliased
7509 %void = OpTypeVoid
7510 %3 = OpTypeFunction %void
7511 %int = OpTypeInt 32 1
7512 %first = OpTypeStruct %int
7513 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7514 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7515 %int_0 = OpConstant %int 0
7516 %int_2 = OpConstant %int 2
7517 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7518 %second = OpTypeStruct %int
7519 %_ptr_Workgroup_second = OpTypePointer Workgroup %second
7520 %__0 = OpVariable %_ptr_Workgroup_second Workgroup
7521 %int_3 = OpConstant %int 3
7522 %main = OpFunction %void None %3
7523 %5 = OpLabel
7524 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7525 OpStore %13 %int_2
7526 %18 = OpAccessChain %_ptr_Workgroup_int %__0 %int_0
7527 OpStore %18 %int_3
7528 OpReturn
7529 OpFunctionEnd
7530 )";
7531
7532 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7533 EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
7534 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7535 EXPECT_THAT(
7536 getDiagnosticString(),
7537 HasSubstr("more than one Workgroup Storage Class variable in the "
7538 "entry point interface point to a type decorated with Block, "
7539 "all of them must be decorated with Aliased"));
7540 }
7541
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableNotAStruct)7542 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableNotAStruct) {
7543 std::string spirv = R"(
7544 OpCapability Shader
7545 OpCapability WorkgroupMemoryExplicitLayoutKHR
7546 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7547 OpMemoryModel Logical GLSL450
7548 OpEntryPoint GLCompute %main "main" %_
7549 OpExecutionMode %main LocalSize 8 1 1
7550 OpDecorate %first Block
7551 %void = OpTypeVoid
7552 %3 = OpTypeFunction %void
7553 %int = OpTypeInt 32 1
7554 %int_3 = OpConstant %int 3
7555 %first = OpTypeArray %int %int_3
7556 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7557 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7558 %int_0 = OpConstant %int 0
7559 %int_2 = OpConstant %int 2
7560 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7561 %main = OpFunction %void None %3
7562 %5 = OpLabel
7563 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7564 OpStore %13 %int_2
7565 OpReturn
7566 OpFunctionEnd
7567 )";
7568
7569 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7570 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7571 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7572 EXPECT_THAT(
7573 getDiagnosticString(),
7574 HasSubstr("Block decoration on a non-struct type"));
7575 }
7576
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableMissingLayout)7577 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableMissingLayout) {
7578 std::string spirv = R"(
7579 OpCapability Shader
7580 OpCapability WorkgroupMemoryExplicitLayoutKHR
7581 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7582 OpMemoryModel Logical GLSL450
7583 OpEntryPoint GLCompute %main "main" %_
7584 OpExecutionMode %main LocalSize 8 1 1
7585 OpDecorate %first Block
7586 %void = OpTypeVoid
7587 %3 = OpTypeFunction %void
7588 %int = OpTypeInt 32 1
7589 %first = OpTypeStruct %int
7590 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7591 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7592 %int_0 = OpConstant %int 0
7593 %int_2 = OpConstant %int 2
7594 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7595 %main = OpFunction %void None %3
7596 %5 = OpLabel
7597 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7598 OpStore %13 %int_2
7599 OpReturn
7600 OpFunctionEnd
7601 )";
7602
7603 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7604 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7605 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7606 EXPECT_THAT(
7607 getDiagnosticString(),
7608 HasSubstr("Block must be explicitly laid out with Offset decorations"));
7609 }
7610
TEST_F(ValidateDecorations,WorkgroupSingleBlockVariableBadLayout)7611 TEST_F(ValidateDecorations, WorkgroupSingleBlockVariableBadLayout) {
7612 std::string spirv = R"(
7613 OpCapability Shader
7614 OpCapability WorkgroupMemoryExplicitLayoutKHR
7615 OpExtension "SPV_KHR_workgroup_memory_explicit_layout"
7616 OpMemoryModel Logical GLSL450
7617 OpEntryPoint GLCompute %main "main" %_
7618 OpExecutionMode %main LocalSize 8 1 1
7619 OpMemberDecorate %first 0 Offset 1
7620 OpDecorate %first Block
7621 %void = OpTypeVoid
7622 %3 = OpTypeFunction %void
7623 %int = OpTypeInt 32 1
7624 %first = OpTypeStruct %int
7625 %_ptr_Workgroup_first = OpTypePointer Workgroup %first
7626 %_ = OpVariable %_ptr_Workgroup_first Workgroup
7627 %int_0 = OpConstant %int 0
7628 %int_2 = OpConstant %int 2
7629 %_ptr_Workgroup_int = OpTypePointer Workgroup %int
7630 %main = OpFunction %void None %3
7631 %5 = OpLabel
7632 %13 = OpAccessChain %_ptr_Workgroup_int %_ %int_0
7633 OpStore %13 %int_2
7634 OpReturn
7635 OpFunctionEnd
7636 )";
7637
7638 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
7639 EXPECT_EQ(SPV_ERROR_INVALID_ID,
7640 ValidateAndRetrieveValidationState(SPV_ENV_UNIVERSAL_1_4));
7641 EXPECT_THAT(
7642 getDiagnosticString(),
7643 HasSubstr(
7644 "Block for variable in Workgroup storage class must follow "
7645 "standard storage buffer layout rules: "
7646 "member 0 at offset 1 is not aligned to 4"));
7647 }
7648
7649 } // namespace
7650 } // namespace val
7651 } // namespace spvtools
7652