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