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