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