• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google LLC.
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 #include <string>
16 
17 #include "gmock/gmock.h"
18 #include "test/unit_spirv.h"
19 #include "test/val/val_fixtures.h"
20 
21 namespace spvtools {
22 namespace val {
23 namespace {
24 
25 using ::testing::HasSubstr;
26 
27 using ValidateInterfacesTest = spvtest::ValidateBase<bool>;
28 
TEST_F(ValidateInterfacesTest,EntryPointMissingInput)29 TEST_F(ValidateInterfacesTest, EntryPointMissingInput) {
30   std::string text = R"(
31 OpCapability Shader
32 OpMemoryModel Logical GLSL450
33 OpEntryPoint Fragment %1 "func"
34 OpExecutionMode %1 OriginUpperLeft
35 %2 = OpTypeVoid
36 %3 = OpTypeInt 32 0
37 %4 = OpTypePointer Input %3
38 %5 = OpVariable %4 Input
39 %6 = OpTypeFunction %2
40 %1 = OpFunction %2 None %6
41 %7 = OpLabel
42 %8 = OpLoad %3 %5
43 OpReturn
44 OpFunctionEnd
45 )";
46 
47   CompileSuccessfully(text);
48   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
49   EXPECT_THAT(
50       getDiagnosticString(),
51       HasSubstr(
52           "Interface variable id <5> is used by entry point 'func' id <1>, "
53           "but is not listed as an interface"));
54 }
55 
TEST_F(ValidateInterfacesTest,EntryPointMissingOutput)56 TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) {
57   std::string text = R"(
58 OpCapability Shader
59 OpMemoryModel Logical GLSL450
60 OpEntryPoint Fragment %1 "func"
61 OpExecutionMode %1 OriginUpperLeft
62 %2 = OpTypeVoid
63 %3 = OpTypeInt 32 0
64 %4 = OpTypePointer Output %3
65 %5 = OpVariable %4 Output
66 %6 = OpTypeFunction %2
67 %1 = OpFunction %2 None %6
68 %7 = OpLabel
69 %8 = OpLoad %3 %5
70 OpReturn
71 OpFunctionEnd
72 )";
73 
74   CompileSuccessfully(text);
75   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
76   EXPECT_THAT(
77       getDiagnosticString(),
78       HasSubstr(
79           "Interface variable id <5> is used by entry point 'func' id <1>, "
80           "but is not listed as an interface"));
81 }
82 
TEST_F(ValidateInterfacesTest,InterfaceMissingUseInSubfunction)83 TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) {
84   std::string text = R"(
85 OpCapability Shader
86 OpMemoryModel Logical GLSL450
87 OpEntryPoint Fragment %1 "func"
88 OpExecutionMode %1 OriginUpperLeft
89 %2 = OpTypeVoid
90 %3 = OpTypeInt 32 0
91 %4 = OpTypePointer Input %3
92 %5 = OpVariable %4 Input
93 %6 = OpTypeFunction %2
94 %1 = OpFunction %2 None %6
95 %7 = OpLabel
96 %8 = OpFunctionCall %2 %9
97 OpReturn
98 OpFunctionEnd
99 %9 = OpFunction %2 None %6
100 %10 = OpLabel
101 %11 = OpLoad %3 %5
102 OpReturn
103 OpFunctionEnd
104 )";
105 
106   CompileSuccessfully(text);
107   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
108   EXPECT_THAT(
109       getDiagnosticString(),
110       HasSubstr(
111           "Interface variable id <5> is used by entry point 'func' id <1>, "
112           "but is not listed as an interface"));
113 }
114 
TEST_F(ValidateInterfacesTest,TwoEntryPointsOneFunction)115 TEST_F(ValidateInterfacesTest, TwoEntryPointsOneFunction) {
116   std::string text = R"(
117 OpCapability Shader
118 OpMemoryModel Logical GLSL450
119 OpEntryPoint Fragment %1 "func" %2
120 OpEntryPoint Fragment %1 "func2"
121 OpExecutionMode %1 OriginUpperLeft
122 %3 = OpTypeVoid
123 %4 = OpTypeInt 32 0
124 %5 = OpTypePointer Input %4
125 %2 = OpVariable %5 Input
126 %6 = OpTypeFunction %3
127 %1 = OpFunction %3 None %6
128 %7 = OpLabel
129 %8 = OpLoad %4 %2
130 OpReturn
131 OpFunctionEnd
132 )";
133 
134   CompileSuccessfully(text);
135   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
136   EXPECT_THAT(
137       getDiagnosticString(),
138       HasSubstr(
139           "Interface variable id <2> is used by entry point 'func2' id <1>, "
140           "but is not listed as an interface"));
141 }
142 
TEST_F(ValidateInterfacesTest,MissingInterfaceThroughInitializer)143 TEST_F(ValidateInterfacesTest, MissingInterfaceThroughInitializer) {
144   const std::string text = R"(
145 OpCapability Shader
146 OpCapability VariablePointers
147 OpMemoryModel Logical GLSL450
148 OpEntryPoint Fragment %1 "func"
149 OpExecutionMode %1 OriginUpperLeft
150 %2 = OpTypeVoid
151 %3 = OpTypeInt 32 0
152 %4 = OpTypePointer Input %3
153 %5 = OpTypePointer Function %4
154 %6 = OpVariable %4 Input
155 %7 = OpTypeFunction %2
156 %1 = OpFunction %2 None %7
157 %8 = OpLabel
158 %9 = OpVariable %5 Function %6
159 OpReturn
160 OpFunctionEnd
161 )";
162 
163   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
164   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
165   EXPECT_THAT(
166       getDiagnosticString(),
167       HasSubstr(
168           "Interface variable id <6> is used by entry point 'func' id <1>, "
169           "but is not listed as an interface"));
170 }
171 
TEST_F(ValidateInterfacesTest,NonUniqueInterfacesSPV1p3)172 TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p3) {
173   const std::string text = R"(
174 OpCapability Shader
175 OpMemoryModel Logical GLSL450
176 OpEntryPoint GLCompute %main "main" %var %var
177 OpExecutionMode %main LocalSize 1 1 1
178 %void = OpTypeVoid
179 %uint = OpTypeInt 32 0
180 %uint3 = OpTypeVector %uint 3
181 %struct = OpTypeStruct %uint3
182 %ptr_struct = OpTypePointer Input %struct
183 %var = OpVariable %ptr_struct Input
184 %func_ty = OpTypeFunction %void
185 %main = OpFunction %void None %func_ty
186 %1 = OpLabel
187 OpReturn
188 OpFunctionEnd
189 )";
190 
191   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
192   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
193 }
194 
TEST_F(ValidateInterfacesTest,NonUniqueInterfacesSPV1p4)195 TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p4) {
196   const std::string text = R"(
197 OpCapability Shader
198 OpMemoryModel Logical GLSL450
199 OpEntryPoint GLCompute %main "main" %var %var
200 OpExecutionMode %main LocalSize 1 1 1
201 OpName %main "main"
202 OpName %var "var"
203 %void = OpTypeVoid
204 %uint = OpTypeInt 32 0
205 %uint3 = OpTypeVector %uint 3
206 %struct = OpTypeStruct %uint3
207 %ptr_struct = OpTypePointer Input %struct
208 %var = OpVariable %ptr_struct Input
209 %func_ty = OpTypeFunction %void
210 %main = OpFunction %void None %func_ty
211 %1 = OpLabel
212 OpReturn
213 OpFunctionEnd
214 )";
215 
216   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
217   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
218   EXPECT_THAT(
219       getDiagnosticString(),
220       HasSubstr("Non-unique OpEntryPoint interface '2[%var]' is disallowed"));
221 }
222 
TEST_F(ValidateInterfacesTest,MissingGlobalVarSPV1p3)223 TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p3) {
224   const std::string text = R"(
225 OpCapability Shader
226 OpMemoryModel Logical GLSL450
227 OpEntryPoint GLCompute %main "main"
228 OpExecutionMode %main LocalSize 1 1 1
229 %void = OpTypeVoid
230 %uint = OpTypeInt 32 0
231 %uint3 = OpTypeVector %uint 3
232 %struct = OpTypeStruct %uint3
233 %ptr_struct = OpTypePointer StorageBuffer %struct
234 %var = OpVariable %ptr_struct StorageBuffer
235 %func_ty = OpTypeFunction %void
236 %main = OpFunction %void None %func_ty
237 %1 = OpLabel
238 %ld = OpLoad %struct %var
239 OpReturn
240 OpFunctionEnd
241 )";
242 
243   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
244   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
245 }
246 
TEST_F(ValidateInterfacesTest,MissingGlobalVarSPV1p4)247 TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p4) {
248   const std::string text = R"(
249 OpCapability Shader
250 OpMemoryModel Logical GLSL450
251 OpEntryPoint GLCompute %main "main"
252 OpExecutionMode %main LocalSize 1 1 1
253 OpName %var "var"
254 %void = OpTypeVoid
255 %uint = OpTypeInt 32 0
256 %uint3 = OpTypeVector %uint 3
257 %struct = OpTypeStruct %uint3
258 %ptr_struct = OpTypePointer StorageBuffer %struct
259 %var = OpVariable %ptr_struct StorageBuffer
260 %func_ty = OpTypeFunction %void
261 %main = OpFunction %void None %func_ty
262 %1 = OpLabel
263 %ld = OpLoad %struct %var
264 OpReturn
265 OpFunctionEnd
266 )";
267 
268   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
269   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
270   EXPECT_THAT(getDiagnosticString(),
271               HasSubstr("Interface variable id <2> is used by entry point "
272                         "'main' id <1>, but is not listed as an interface"));
273 }
274 
TEST_F(ValidateInterfacesTest,FunctionInterfaceVarSPV1p3)275 TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p3) {
276   const std::string text = R"(
277 OpCapability Shader
278 OpMemoryModel Logical GLSL450
279 OpEntryPoint GLCompute %main "main" %var
280 OpExecutionMode %main LocalSize 1 1 1
281 OpName %var "var"
282 %void = OpTypeVoid
283 %uint = OpTypeInt 32 0
284 %uint3 = OpTypeVector %uint 3
285 %struct = OpTypeStruct %uint3
286 %ptr_struct = OpTypePointer Function %struct
287 %func_ty = OpTypeFunction %void
288 %main = OpFunction %void None %func_ty
289 %1 = OpLabel
290 %var = OpVariable %ptr_struct Function
291 OpReturn
292 OpFunctionEnd
293 )";
294 
295   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
296   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
297   EXPECT_THAT(getDiagnosticString(),
298               HasSubstr("OpEntryPoint interfaces must be OpVariables with "
299                         "Storage Class of Input(1) or Output(3). Found Storage "
300                         "Class 7 for Entry Point id 1."));
301 }
302 
TEST_F(ValidateInterfacesTest,FunctionInterfaceVarSPV1p4)303 TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p4) {
304   const std::string text = R"(
305 OpCapability Shader
306 OpMemoryModel Logical GLSL450
307 OpEntryPoint GLCompute %main "main" %var
308 OpExecutionMode %main LocalSize 1 1 1
309 OpName %var "var"
310 %void = OpTypeVoid
311 %uint = OpTypeInt 32 0
312 %uint3 = OpTypeVector %uint 3
313 %struct = OpTypeStruct %uint3
314 %ptr_struct = OpTypePointer Function %struct
315 %func_ty = OpTypeFunction %void
316 %main = OpFunction %void None %func_ty
317 %1 = OpLabel
318 %var = OpVariable %ptr_struct Function
319 OpReturn
320 OpFunctionEnd
321 )";
322 
323   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
324   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
325   EXPECT_THAT(
326       getDiagnosticString(),
327       HasSubstr("OpEntryPoint interfaces should only list global variables"));
328 }
329 
TEST_F(ValidateInterfacesTest,ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals)330 TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals) {
331   const std::string text = R"(
332 OpCapability Shader
333 OpMemoryModel Logical GLSL450
334 OpEntryPoint GLCompute %main "main"
335 OpExecutionMode %main LocalSize 1 1 1
336 OpName %var "var"
337 %void = OpTypeVoid
338 %uint = OpTypeInt 32 0
339 %uint3 = OpTypeVector %uint 3
340 %struct = OpTypeStruct %uint3
341 %ptr_struct = OpTypePointer StorageBuffer %struct
342 %var = OpVariable %ptr_struct StorageBuffer
343 %func_ty = OpTypeFunction %void
344 %main = OpFunction %void None %func_ty
345 %1 = OpLabel
346 %ld = OpLoad %struct %var
347 OpReturn
348 OpFunctionEnd
349 )";
350 
351   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
352   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
353 }
354 
TEST_F(ValidateInterfacesTest,ModuleSPV1p3ValidateSPV1p4_DuplicateInterface)355 TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_DuplicateInterface) {
356   const std::string text = R"(
357 OpCapability Shader
358 OpMemoryModel Logical GLSL450
359 OpEntryPoint GLCompute %main "main" %gid %gid
360 OpExecutionMode %main LocalSize 1 1 1
361 OpDecorate %gid BuiltIn GlobalInvocationId
362 %void = OpTypeVoid
363 %int = OpTypeInt 32 0
364 %int3 = OpTypeVector %int 3
365 %ptr_input_int3 = OpTypePointer Input %int3
366 %gid = OpVariable %ptr_input_int3 Input
367 %void_fn = OpTypeFunction %void
368 %main = OpFunction %void None %void_fn
369 %entry = OpLabel
370 OpReturn
371 OpFunctionEnd
372 )";
373 
374   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
375   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
376 }
377 
TEST_F(ValidateInterfacesTest,SPV14MultipleEntryPointsSameFunction)378 TEST_F(ValidateInterfacesTest, SPV14MultipleEntryPointsSameFunction) {
379   const std::string text = R"(
380 OpCapability Shader
381 OpMemoryModel Logical GLSL450
382 OpEntryPoint GLCompute %main "main1" %gid
383 OpEntryPoint GLCompute %main "main2" %gid
384 OpExecutionMode %main LocalSize 1 1 1
385 OpDecorate %gid BuiltIn GlobalInvocationId
386 %void = OpTypeVoid
387 %int = OpTypeInt 32 0
388 %int3 = OpTypeVector %int 3
389 %ptr_input_int3 = OpTypePointer Input %int3
390 %gid = OpVariable %ptr_input_int3 Input
391 %void_fn = OpTypeFunction %void
392 %main = OpFunction %void None %void_fn
393 %entry = OpLabel
394 OpReturn
395 OpFunctionEnd
396 )";
397 
398   CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
399   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
400 }
401 
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentVariable)402 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentVariable) {
403   const std::string text = R"(
404 OpCapability Shader
405 OpMemoryModel Logical GLSL450
406 OpEntryPoint Fragment %main "main" %var
407 OpExecutionMode %main OriginUpperLeft
408 OpDecorate %var Location 0
409 OpDecorate %var Location 1
410 %void = OpTypeVoid
411 %void_fn = OpTypeFunction %void
412 %float = OpTypeFloat 32
413 %ptr_input_float = OpTypePointer Input %float
414 %var = OpVariable %ptr_input_float Input
415 %main = OpFunction %void None %void_fn
416 %entry = OpLabel
417 OpReturn
418 OpFunctionEnd
419 )";
420 
421   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
422   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
423   EXPECT_THAT(
424       getDiagnosticString(),
425       HasSubstr("decorated with Location multiple times is not allowed"));
426 }
427 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableAndMemberAssigned)428 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableAndMemberAssigned) {
429   const std::string text = R"(
430 OpCapability Shader
431 OpMemoryModel Logical GLSL450
432 OpEntryPoint Fragment %main "main" %var
433 OpExecutionMode %main OriginUpperLeft
434 OpDecorate %var Location 0
435 OpDecorate %struct Block
436 OpMemberDecorate %struct 0 Location 0
437 %void = OpTypeVoid
438 %void_fn = OpTypeFunction %void
439 %float = OpTypeFloat 32
440 %struct = OpTypeStruct %float
441 %ptr_input_struct = OpTypePointer Input %struct
442 %var = OpVariable %ptr_input_struct Input
443 %main = OpFunction %void None %void_fn
444 %entry = OpLabel
445 OpReturn
446 OpFunctionEnd
447 )";
448 
449   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
450   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
451   EXPECT_THAT(getDiagnosticString(),
452               AnyVUID("VUID-StandaloneSpirv-Location-04918"));
453   EXPECT_THAT(getDiagnosticString(),
454               HasSubstr("Members cannot be assigned a location"));
455 }
456 
TEST_F(ValidateInterfacesTest,VulkanLocationsMemberAndSubMemberAssigned)457 TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
458   const std::string text = R"(
459 OpCapability Shader
460 OpMemoryModel Logical GLSL450
461 OpEntryPoint Fragment %main "main" %var
462 OpExecutionMode %main OriginUpperLeft
463 OpDecorate %outer Block
464 OpMemberDecorate %outer 0 Location 0
465 OpMemberDecorate %struct 0 Location 0
466 %void = OpTypeVoid
467 %void_fn = OpTypeFunction %void
468 %float = OpTypeFloat 32
469 %struct = OpTypeStruct %float
470 %outer = OpTypeStruct %struct
471 %ptr_input_outer = OpTypePointer Input %outer
472 %var = OpVariable %ptr_input_outer Input
473 %main = OpFunction %void None %void_fn
474 %entry = OpLabel
475 OpReturn
476 OpFunctionEnd
477 )";
478 
479   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
480   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
481   EXPECT_THAT(getDiagnosticString(),
482               AnyVUID("VUID-StandaloneSpirv-Location-04918"));
483   EXPECT_THAT(getDiagnosticString(),
484               HasSubstr("Members cannot be assigned a location"));
485 }
486 
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentStructMember)487 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
488   const std::string text = R"(
489 OpCapability Shader
490 OpMemoryModel Logical GLSL450
491 OpEntryPoint Fragment %main "main" %var
492 OpExecutionMode %main OriginUpperLeft
493 OpDecorate %struct Block
494 OpMemberDecorate %struct 1 Location 0
495 OpMemberDecorate %struct 1 Location 1
496 %void = OpTypeVoid
497 %void_fn = OpTypeFunction %void
498 %float = OpTypeFloat 32
499 %struct = OpTypeStruct %float %float
500 %ptr_input_struct = OpTypePointer Input %struct
501 %var = OpVariable %ptr_input_struct Input
502 %main = OpFunction %void None %void_fn
503 %entry = OpLabel
504 OpReturn
505 OpFunctionEnd
506 )";
507 
508   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
509   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
510   EXPECT_THAT(
511       getDiagnosticString(),
512       HasSubstr("decorated with Location multiple times is not allowed"));
513 }
514 
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentStructMember)515 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
516   const std::string text = R"(
517 OpCapability Shader
518 OpMemoryModel Logical GLSL450
519 OpEntryPoint Fragment %main "main" %var
520 OpExecutionMode %main OriginUpperLeft
521 OpDecorate %struct Block
522 OpMemberDecorate %struct 1 Location 1
523 %void = OpTypeVoid
524 %void_fn = OpTypeFunction %void
525 %float = OpTypeFloat 32
526 %struct = OpTypeStruct %float %float
527 %ptr_input_struct = OpTypePointer Input %struct
528 %var = OpVariable %ptr_input_struct Input
529 %main = OpFunction %void None %void_fn
530 %entry = OpLabel
531 OpReturn
532 OpFunctionEnd
533 )";
534 
535   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
536   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
537   EXPECT_THAT(getDiagnosticString(),
538               HasSubstr("Member index 0 is missing a location assignment"));
539 }
540 
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentNonBlockStruct)541 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
542   const std::string text = R"(
543 OpCapability Shader
544 OpMemoryModel Logical GLSL450
545 OpEntryPoint Fragment %main "main" %var
546 OpExecutionMode %main OriginUpperLeft
547 %void = OpTypeVoid
548 %void_fn = OpTypeFunction %void
549 %float = OpTypeFloat 32
550 %struct = OpTypeStruct %float %float
551 %ptr_input_struct = OpTypePointer Input %struct
552 %var = OpVariable %ptr_input_struct Input
553 %main = OpFunction %void None %void_fn
554 %entry = OpLabel
555 OpReturn
556 OpFunctionEnd
557 )";
558 
559   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
560   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
561   EXPECT_THAT(getDiagnosticString(),
562               HasSubstr("Variable must be decorated with a location"));
563 }
564 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictInput)565 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
566   const std::string text = R"(
567 OpCapability Shader
568 OpMemoryModel Logical GLSL450
569 OpEntryPoint Fragment %main "main" %var1 %var2
570 OpExecutionMode %main OriginUpperLeft
571 OpDecorate %var1 Location 0
572 OpDecorate %var2 Location 0
573 %void = OpTypeVoid
574 %void_fn = OpTypeFunction %void
575 %float = OpTypeFloat 32
576 %struct = OpTypeStruct %float %float
577 %ptr_input_struct = OpTypePointer Input %struct
578 %var1 = OpVariable %ptr_input_struct Input
579 %var2 = OpVariable %ptr_input_struct Input
580 %main = OpFunction %void None %void_fn
581 %entry = OpLabel
582 OpReturn
583 OpFunctionEnd
584 )";
585 
586   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
587   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
588   EXPECT_THAT(getDiagnosticString(),
589               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
590   EXPECT_THAT(getDiagnosticString(),
591               HasSubstr("Entry-point has conflicting input location assignment "
592                         "at location 0"));
593 }
594 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutput)595 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
596   const std::string text = R"(
597 OpCapability Shader
598 OpMemoryModel Logical GLSL450
599 OpEntryPoint Fragment %main "main" %var1 %var2
600 OpExecutionMode %main OriginUpperLeft
601 OpDecorate %var1 Location 1
602 OpDecorate %var2 Location 1
603 %void = OpTypeVoid
604 %void_fn = OpTypeFunction %void
605 %float = OpTypeFloat 32
606 %struct = OpTypeStruct %float %float
607 %ptr_output_struct = OpTypePointer Output %struct
608 %var1 = OpVariable %ptr_output_struct Output
609 %var2 = OpVariable %ptr_output_struct Output
610 %main = OpFunction %void None %void_fn
611 %entry = OpLabel
612 OpReturn
613 OpFunctionEnd
614 )";
615 
616   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
617   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
618   EXPECT_THAT(getDiagnosticString(),
619               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
620   EXPECT_THAT(
621       getDiagnosticString(),
622       HasSubstr("Entry-point has conflicting output location assignment "
623                 "at location 1"));
624 }
625 
TEST_F(ValidateInterfacesTest,VulkanPatchAndNonPatchOverlap)626 TEST_F(ValidateInterfacesTest, VulkanPatchAndNonPatchOverlap) {
627   const std::string text = R"(
628                OpCapability Tessellation
629                OpMemoryModel Logical GLSL450
630                OpEntryPoint TessellationControl %main "main" %a %b
631                OpExecutionMode %main OutputVertices 4
632                OpDecorate %a Location 0
633                OpDecorate %b Patch
634                OpDecorate %b Location 0
635        %void = OpTypeVoid
636           %3 = OpTypeFunction %void
637       %float = OpTypeFloat 32
638        %uint = OpTypeInt 32 0
639      %uint_4 = OpConstant %uint 4
640 %_arr_float_uint_4 = OpTypeArray %float %uint_4
641 %_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
642           %a = OpVariable %_ptr_Output__arr_float_uint_4 Output
643 %_ptr_Output_float = OpTypePointer Output %float
644           %b = OpVariable %_ptr_Output_float Output
645        %main = OpFunction %void None %3
646           %5 = OpLabel
647                OpReturn
648                OpFunctionEnd
649     )";
650 
651   CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
652   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
653 }
654 
TEST_F(ValidateInterfacesTest,VulkanPatchOverlap)655 TEST_F(ValidateInterfacesTest, VulkanPatchOverlap) {
656   const std::string text = R"(
657                OpCapability Tessellation
658                OpMemoryModel Logical GLSL450
659                OpEntryPoint TessellationControl %main "main" %a %b %c
660                OpExecutionMode %main OutputVertices 4
661                OpDecorate %a Location 0
662                OpDecorate %b Patch
663                OpDecorate %b Location 6
664                OpDecorate %c Patch
665                OpDecorate %c Location 6
666        %void = OpTypeVoid
667           %3 = OpTypeFunction %void
668       %float = OpTypeFloat 32
669        %uint = OpTypeInt 32 0
670      %uint_4 = OpConstant %uint 4
671 %_arr_float_uint_4 = OpTypeArray %float %uint_4
672 %_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
673           %a = OpVariable %_ptr_Output__arr_float_uint_4 Output
674 %_ptr_Output_float = OpTypePointer Output %float
675           %b = OpVariable %_ptr_Output_float Output
676           %c = OpVariable %_ptr_Output_float Output
677        %main = OpFunction %void None %3
678           %5 = OpLabel
679                OpReturn
680                OpFunctionEnd
681     )";
682 
683   CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
684   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
685   EXPECT_THAT(getDiagnosticString(),
686               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
687   EXPECT_THAT(getDiagnosticString(),
688               HasSubstr("Entry-point has conflicting output location "
689                         "assignment at location 6, component 0"));
690 }
691 
TEST_F(ValidateInterfacesTest,VulkanLocationsSameLocationInputAndOutputNoConflict)692 TEST_F(ValidateInterfacesTest,
693        VulkanLocationsSameLocationInputAndOutputNoConflict) {
694   const std::string text = R"(
695 OpCapability Shader
696 OpMemoryModel Logical GLSL450
697 OpEntryPoint Fragment %main "main" %var1 %var2
698 OpExecutionMode %main OriginUpperLeft
699 OpDecorate %var1 Location 1
700 OpDecorate %var2 Location 1
701 %void = OpTypeVoid
702 %void_fn = OpTypeFunction %void
703 %float = OpTypeFloat 32
704 %struct = OpTypeStruct %float %float
705 %ptr_input_struct = OpTypePointer Input %struct
706 %ptr_output_struct = OpTypePointer Output %struct
707 %var1 = OpVariable %ptr_input_struct Input
708 %var2 = OpVariable %ptr_output_struct Output
709 %main = OpFunction %void None %void_fn
710 %entry = OpLabel
711 OpReturn
712 OpFunctionEnd
713 )";
714 
715   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
716   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
717 }
718 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableInGap)719 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
720   const std::string text = R"(
721 OpCapability Shader
722 OpMemoryModel Logical GLSL450
723 OpEntryPoint Fragment %main "main" %var1 %var2
724 OpExecutionMode %main OriginUpperLeft
725 OpDecorate %struct Block
726 OpMemberDecorate %struct 0 Location 0
727 OpMemberDecorate %struct 1 Location 2
728 OpDecorate %var2 Location 1
729 %void = OpTypeVoid
730 %void_fn = OpTypeFunction %void
731 %float = OpTypeFloat 32
732 %struct = OpTypeStruct %float %float
733 %ptr_input_struct = OpTypePointer Input %struct
734 %ptr_input_float = OpTypePointer Input %float
735 %var1 = OpVariable %ptr_input_struct Input
736 %var2 = OpVariable %ptr_input_float Input
737 %main = OpFunction %void None %void_fn
738 %entry = OpLabel
739 OpReturn
740 OpFunctionEnd
741 )";
742 
743   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
744   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
745 }
746 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeFloatVectorConflict)747 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
748   const std::string text = R"(
749 OpCapability Shader
750 OpCapability Float64
751 OpMemoryModel Logical GLSL450
752 OpEntryPoint Fragment %main "main" %var1 %var2
753 OpExecutionMode %main OriginUpperLeft
754 OpDecorate %var1 Location 0
755 OpDecorate %var2 Location 1
756 %void = OpTypeVoid
757 %void_fn = OpTypeFunction %void
758 %float = OpTypeFloat 32
759 %double = OpTypeFloat 64
760 %vector = OpTypeVector %double 3
761 %ptr_input_float = OpTypePointer Input %float
762 %ptr_input_vector = OpTypePointer Input %vector
763 %var1 = OpVariable %ptr_input_vector Input
764 %var2 = OpVariable %ptr_input_float Input
765 %main = OpFunction %void None %void_fn
766 %entry = OpLabel
767 OpReturn
768 OpFunctionEnd
769 )";
770 
771   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
772   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
773   EXPECT_THAT(getDiagnosticString(),
774               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
775   EXPECT_THAT(getDiagnosticString(),
776               HasSubstr("Entry-point has conflicting input location assignment "
777                         "at location 1"));
778 }
779 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeIntVectorConflict)780 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
781   const std::string text = R"(
782 OpCapability Shader
783 OpCapability Int64
784 OpMemoryModel Logical GLSL450
785 OpEntryPoint Fragment %main "main" %var1 %var2
786 OpExecutionMode %main OriginUpperLeft
787 OpDecorate %var1 Location 0
788 OpDecorate %var1 Flat
789 OpDecorate %var2 Location 1
790 OpDecorate %var2 Flat
791 %void = OpTypeVoid
792 %void_fn = OpTypeFunction %void
793 %float = OpTypeFloat 32
794 %long = OpTypeInt 64 0
795 %vector = OpTypeVector %long 4
796 %ptr_input_float = OpTypePointer Input %float
797 %ptr_input_vector = OpTypePointer Input %vector
798 %var1 = OpVariable %ptr_input_vector Input
799 %var2 = OpVariable %ptr_input_float Input
800 %main = OpFunction %void None %void_fn
801 %entry = OpLabel
802 OpReturn
803 OpFunctionEnd
804 )";
805 
806   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
807   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
808   EXPECT_THAT(getDiagnosticString(),
809               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
810   EXPECT_THAT(getDiagnosticString(),
811               HasSubstr("Entry-point has conflicting input location assignment "
812                         "at location 1"));
813 }
814 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix2x2Conflict)815 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
816   const std::string text = R"(
817 OpCapability Shader
818 OpMemoryModel Logical GLSL450
819 OpEntryPoint Fragment %main "main" %var1 %var2
820 OpExecutionMode %main OriginUpperLeft
821 OpDecorate %var1 Location 0
822 OpDecorate %var2 Location 1
823 %void = OpTypeVoid
824 %void_fn = OpTypeFunction %void
825 %float = OpTypeFloat 32
826 %vector = OpTypeVector %float 2
827 %matrix = OpTypeMatrix %vector 2
828 %ptr_input_float = OpTypePointer Input %float
829 %ptr_input_matrix = OpTypePointer Input %matrix
830 %var1 = OpVariable %ptr_input_matrix Input
831 %var2 = OpVariable %ptr_input_float Input
832 %main = OpFunction %void None %void_fn
833 %entry = OpLabel
834 OpReturn
835 OpFunctionEnd
836 )";
837 
838   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
839   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
840   EXPECT_THAT(getDiagnosticString(),
841               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
842   EXPECT_THAT(getDiagnosticString(),
843               HasSubstr("Entry-point has conflicting input location assignment "
844                         "at location 1"));
845 }
846 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix3x3Conflict)847 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
848   const std::string text = R"(
849 OpCapability Shader
850 OpMemoryModel Logical GLSL450
851 OpEntryPoint Fragment %main "main" %var1 %var2
852 OpExecutionMode %main OriginUpperLeft
853 OpDecorate %var1 Location 0
854 OpDecorate %var2 Location 2
855 %void = OpTypeVoid
856 %void_fn = OpTypeFunction %void
857 %float = OpTypeFloat 32
858 %vector = OpTypeVector %float 3
859 %matrix = OpTypeMatrix %vector 3
860 %ptr_input_float = OpTypePointer Input %float
861 %ptr_input_matrix = OpTypePointer Input %matrix
862 %var1 = OpVariable %ptr_input_matrix Input
863 %var2 = OpVariable %ptr_input_float Input
864 %main = OpFunction %void None %void_fn
865 %entry = OpLabel
866 OpReturn
867 OpFunctionEnd
868 )";
869 
870   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
871   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
872   EXPECT_THAT(getDiagnosticString(),
873               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
874   EXPECT_THAT(getDiagnosticString(),
875               HasSubstr("Entry-point has conflicting input location assignment "
876                         "at location 2"));
877 }
878 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Conflict)879 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
880   const std::string text = R"(
881 OpCapability Shader
882 OpMemoryModel Logical GLSL450
883 OpEntryPoint Fragment %main "main" %var1 %var2
884 OpExecutionMode %main OriginUpperLeft
885 OpDecorate %var1 Location 0
886 OpDecorate %var2 Location 3
887 %void = OpTypeVoid
888 %void_fn = OpTypeFunction %void
889 %float = OpTypeFloat 32
890 %vector = OpTypeVector %float 4
891 %matrix = OpTypeMatrix %vector 4
892 %ptr_input_float = OpTypePointer Input %float
893 %ptr_input_matrix = OpTypePointer Input %matrix
894 %var1 = OpVariable %ptr_input_matrix Input
895 %var2 = OpVariable %ptr_input_float Input
896 %main = OpFunction %void None %void_fn
897 %entry = OpLabel
898 OpReturn
899 OpFunctionEnd
900 )";
901 
902   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
903   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
904   EXPECT_THAT(getDiagnosticString(),
905               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
906   EXPECT_THAT(getDiagnosticString(),
907               HasSubstr("Entry-point has conflicting input location assignment "
908                         "at location 3"));
909 }
910 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix2x2Conflict)911 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
912   const std::string text = R"(
913 OpCapability Shader
914 OpCapability Float64
915 OpMemoryModel Logical GLSL450
916 OpEntryPoint Fragment %main "main" %var1 %var2
917 OpExecutionMode %main OriginUpperLeft
918 OpDecorate %var1 Location 0
919 OpDecorate %var2 Location 1
920 %void = OpTypeVoid
921 %void_fn = OpTypeFunction %void
922 %float = OpTypeFloat 32
923 %double = OpTypeFloat 64
924 %vector = OpTypeVector %double 2
925 %matrix = OpTypeMatrix %vector 2
926 %ptr_input_float = OpTypePointer Input %float
927 %ptr_input_matrix = OpTypePointer Input %matrix
928 %var1 = OpVariable %ptr_input_matrix Input
929 %var2 = OpVariable %ptr_input_float Input
930 %main = OpFunction %void None %void_fn
931 %entry = OpLabel
932 OpReturn
933 OpFunctionEnd
934 )";
935 
936   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
937   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
938   EXPECT_THAT(getDiagnosticString(),
939               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
940   EXPECT_THAT(getDiagnosticString(),
941               HasSubstr("Entry-point has conflicting input location assignment "
942                         "at location 1"));
943 }
944 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix3x3Conflict)945 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
946   const std::string text = R"(
947 OpCapability Shader
948 OpCapability Float64
949 OpMemoryModel Logical GLSL450
950 OpEntryPoint Fragment %main "main" %var1 %var2
951 OpExecutionMode %main OriginUpperLeft
952 OpDecorate %var1 Location 0
953 OpDecorate %var2 Location 5
954 %void = OpTypeVoid
955 %void_fn = OpTypeFunction %void
956 %float = OpTypeFloat 32
957 %double = OpTypeFloat 64
958 %vector = OpTypeVector %double 3
959 %matrix = OpTypeMatrix %vector 3
960 %ptr_input_float = OpTypePointer Input %float
961 %ptr_input_matrix = OpTypePointer Input %matrix
962 %var1 = OpVariable %ptr_input_matrix Input
963 %var2 = OpVariable %ptr_input_float Input
964 %main = OpFunction %void None %void_fn
965 %entry = OpLabel
966 OpReturn
967 OpFunctionEnd
968 )";
969 
970   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
971   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
972   EXPECT_THAT(getDiagnosticString(),
973               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
974   EXPECT_THAT(getDiagnosticString(),
975               HasSubstr("Entry-point has conflicting input location assignment "
976                         "at location 5"));
977 }
978 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix4x4Conflict)979 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
980   const std::string text = R"(
981 OpCapability Shader
982 OpCapability Float64
983 OpMemoryModel Logical GLSL450
984 OpEntryPoint Fragment %main "main" %var1 %var2
985 OpExecutionMode %main OriginUpperLeft
986 OpDecorate %var1 Location 0
987 OpDecorate %var2 Location 7
988 %void = OpTypeVoid
989 %void_fn = OpTypeFunction %void
990 %float = OpTypeFloat 32
991 %double = OpTypeFloat 64
992 %vector = OpTypeVector %double 4
993 %matrix = OpTypeMatrix %vector 4
994 %ptr_input_float = OpTypePointer Input %float
995 %ptr_input_matrix = OpTypePointer Input %matrix
996 %var1 = OpVariable %ptr_input_matrix Input
997 %var2 = OpVariable %ptr_input_float Input
998 %main = OpFunction %void None %void_fn
999 %entry = OpLabel
1000 OpReturn
1001 OpFunctionEnd
1002 )";
1003 
1004   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1005   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1006   EXPECT_THAT(getDiagnosticString(),
1007               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1008   EXPECT_THAT(getDiagnosticString(),
1009               HasSubstr("Entry-point has conflicting input location assignment "
1010                         "at location 7"));
1011 }
1012 
TEST_F(ValidateInterfacesTest,VulkanLocationsArray2Conflict)1013 TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
1014   const std::string text = R"(
1015 OpCapability Shader
1016 OpMemoryModel Logical GLSL450
1017 OpEntryPoint Fragment %main "main" %var1 %var2
1018 OpExecutionMode %main OriginUpperLeft
1019 OpDecorate %var1 Location 0
1020 OpDecorate %var2 Location 1
1021 %void = OpTypeVoid
1022 %void_fn = OpTypeFunction %void
1023 %float = OpTypeFloat 32
1024 %int = OpTypeInt 32 0
1025 %int_2 = OpConstant %int 2
1026 %array = OpTypeArray %int %int_2
1027 %struct = OpTypeStruct %array
1028 %ptr_input_float = OpTypePointer Input %float
1029 %ptr_input_struct = OpTypePointer Input %struct
1030 %var1 = OpVariable %ptr_input_struct Input
1031 %var2 = OpVariable %ptr_input_float Input
1032 %main = OpFunction %void None %void_fn
1033 %entry = OpLabel
1034 OpReturn
1035 OpFunctionEnd
1036 )";
1037 
1038   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1039   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1040   EXPECT_THAT(getDiagnosticString(),
1041               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1042   EXPECT_THAT(getDiagnosticString(),
1043               HasSubstr("Entry-point has conflicting input location assignment "
1044                         "at location 1"));
1045 }
1046 
TEST_F(ValidateInterfacesTest,VulkanLocationsArray4Conflict)1047 TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
1048   const std::string text = R"(
1049 OpCapability Shader
1050 OpMemoryModel Logical GLSL450
1051 OpEntryPoint Fragment %main "main" %var1 %var2
1052 OpExecutionMode %main OriginUpperLeft
1053 OpDecorate %var1 Location 0
1054 OpDecorate %var2 Location 3
1055 %void = OpTypeVoid
1056 %void_fn = OpTypeFunction %void
1057 %float = OpTypeFloat 32
1058 %int = OpTypeInt 32 0
1059 %int_4 = OpConstant %int 4
1060 %array = OpTypeArray %int %int_4
1061 %struct = OpTypeStruct %array
1062 %ptr_input_float = OpTypePointer Input %float
1063 %ptr_input_struct = OpTypePointer Input %struct
1064 %var1 = OpVariable %ptr_input_struct Input
1065 %var2 = OpVariable %ptr_input_float Input
1066 %main = OpFunction %void None %void_fn
1067 %entry = OpLabel
1068 OpReturn
1069 OpFunctionEnd
1070 )";
1071 
1072   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1073   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1074   EXPECT_THAT(getDiagnosticString(),
1075               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1076   EXPECT_THAT(getDiagnosticString(),
1077               HasSubstr("Entry-point has conflicting input location assignment "
1078                         "at location 3"));
1079 }
1080 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Array4Conflict)1081 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
1082   const std::string text = R"(
1083 OpCapability Shader
1084 OpMemoryModel Logical GLSL450
1085 OpEntryPoint Fragment %main "main" %var1 %var2
1086 OpExecutionMode %main OriginUpperLeft
1087 OpDecorate %var1 Location 0
1088 OpDecorate %var2 Location 15
1089 %void = OpTypeVoid
1090 %void_fn = OpTypeFunction %void
1091 %float = OpTypeFloat 32
1092 %int = OpTypeInt 32 0
1093 %int_4 = OpConstant %int 4
1094 %vector = OpTypeVector %float 4
1095 %matrix = OpTypeMatrix %vector 4
1096 %array = OpTypeArray %matrix %int_4
1097 %struct = OpTypeStruct %array
1098 %ptr_input_float = OpTypePointer Input %float
1099 %ptr_input_struct = OpTypePointer Input %struct
1100 %var1 = OpVariable %ptr_input_struct Input
1101 %var2 = OpVariable %ptr_input_float Input
1102 %main = OpFunction %void None %void_fn
1103 %entry = OpLabel
1104 OpReturn
1105 OpFunctionEnd
1106 )";
1107 
1108   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1109   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1110   EXPECT_THAT(getDiagnosticString(),
1111               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1112   EXPECT_THAT(getDiagnosticString(),
1113               HasSubstr("Entry-point has conflicting input location assignment "
1114                         "at location 15"));
1115 }
1116 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentDisambiguates)1117 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
1118   const std::string text = R"(
1119 OpCapability Shader
1120 OpMemoryModel Logical GLSL450
1121 OpEntryPoint Fragment %main "main" %var1
1122 OpExecutionMode %main OriginUpperLeft
1123 OpDecorate %struct Block
1124 OpMemberDecorate %struct 0 Location 0
1125 OpMemberDecorate %struct 0 Component 0
1126 OpMemberDecorate %struct 1 Location 0
1127 OpMemberDecorate %struct 1 Component 1
1128 %void = OpTypeVoid
1129 %void_fn = OpTypeFunction %void
1130 %float = OpTypeFloat 32
1131 %struct = OpTypeStruct %float %float
1132 %ptr_input_struct = OpTypePointer Input %struct
1133 %var1 = OpVariable %ptr_input_struct Input
1134 %main = OpFunction %void None %void_fn
1135 %entry = OpLabel
1136 OpReturn
1137 OpFunctionEnd
1138 )";
1139 
1140   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1141   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1142 }
1143 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentIn64BitVec3)1144 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
1145   const std::string text = R"(
1146 OpCapability Shader
1147 OpCapability Float64
1148 OpMemoryModel Logical GLSL450
1149 OpEntryPoint Fragment %main "main" %var
1150 OpExecutionMode %main OriginUpperLeft
1151 OpDecorate %struct Block
1152 OpMemberDecorate %struct 0 Location 0
1153 OpMemberDecorate %struct 1 Location 1
1154 OpMemberDecorate %struct 1 Component 1
1155 %void = OpTypeVoid
1156 %void_fn = OpTypeFunction %void
1157 %float = OpTypeFloat 32
1158 %double = OpTypeFloat 64
1159 %double3 = OpTypeVector %double 3
1160 %struct = OpTypeStruct %double3 %float
1161 %ptr_input_struct = OpTypePointer Input %struct
1162 %var = OpVariable %ptr_input_struct Input
1163 %main = OpFunction %void None %void_fn
1164 %entry = OpLabel
1165 OpReturn
1166 OpFunctionEnd
1167 )";
1168 
1169   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1170   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1171   EXPECT_THAT(getDiagnosticString(),
1172               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1173   EXPECT_THAT(getDiagnosticString(),
1174               HasSubstr("Entry-point has conflicting input location assignment "
1175                         "at location 1, component 1"));
1176 }
1177 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentAfter64BitVec3)1178 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
1179   const std::string text = R"(
1180 OpCapability Shader
1181 OpCapability Float64
1182 OpMemoryModel Logical GLSL450
1183 OpEntryPoint Fragment %main "main" %var
1184 OpExecutionMode %main OriginUpperLeft
1185 OpDecorate %struct Block
1186 OpMemberDecorate %struct 0 Location 0
1187 OpMemberDecorate %struct 1 Location 1
1188 OpMemberDecorate %struct 1 Component 2
1189 %void = OpTypeVoid
1190 %void_fn = OpTypeFunction %void
1191 %float = OpTypeFloat 32
1192 %double = OpTypeFloat 64
1193 %double3 = OpTypeVector %double 3
1194 %struct = OpTypeStruct %double3 %float
1195 %ptr_input_struct = OpTypePointer Input %struct
1196 %var = OpVariable %ptr_input_struct Input
1197 %main = OpFunction %void None %void_fn
1198 %entry = OpLabel
1199 OpReturn
1200 OpFunctionEnd
1201 )";
1202 
1203   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1204   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1205 }
1206 
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentVariable)1207 TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
1208   const std::string text = R"(
1209 OpCapability Shader
1210 OpMemoryModel Logical GLSL450
1211 OpEntryPoint Fragment %main "main" %var
1212 OpExecutionMode %main OriginUpperLeft
1213 OpDecorate %var Location 0
1214 OpDecorate %var Component 0
1215 OpDecorate %var Component 1
1216 %void = OpTypeVoid
1217 %void_fn = OpTypeFunction %void
1218 %float = OpTypeFloat 32
1219 %ptr_input_float = OpTypePointer Input %float
1220 %var = OpVariable %ptr_input_float Input
1221 %main = OpFunction %void None %void_fn
1222 %entry = OpLabel
1223 OpReturn
1224 OpFunctionEnd
1225 )";
1226 
1227   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1228   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1229   EXPECT_THAT(
1230       getDiagnosticString(),
1231       HasSubstr("decorated with Component multiple times is not allowed"));
1232 }
1233 
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentStructMember)1234 TEST_F(ValidateInterfacesTest,
1235        VulkanLocationsConflictingComponentStructMember) {
1236   const std::string text = R"(
1237 OpCapability Shader
1238 OpMemoryModel Logical GLSL450
1239 OpEntryPoint Fragment %main "main" %var
1240 OpExecutionMode %main OriginUpperLeft
1241 OpDecorate %struct Block
1242 OpMemberDecorate %struct 0 Location 0
1243 OpMemberDecorate %struct 0 Component 0
1244 OpMemberDecorate %struct 0 Component 1
1245 %void = OpTypeVoid
1246 %void_fn = OpTypeFunction %void
1247 %float = OpTypeFloat 32
1248 %struct = OpTypeStruct %float
1249 %ptr_input_struct = OpTypePointer Input %struct
1250 %var = OpVariable %ptr_input_struct Input
1251 %main = OpFunction %void None %void_fn
1252 %entry = OpLabel
1253 OpReturn
1254 OpFunctionEnd
1255 )";
1256 
1257   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1258   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1259   EXPECT_THAT(
1260       getDiagnosticString(),
1261       HasSubstr("decorated with Component multiple times is not allowed"));
1262 }
1263 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutputIndex1)1264 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
1265   const std::string text = R"(
1266 OpCapability Shader
1267 OpMemoryModel Logical GLSL450
1268 OpEntryPoint Fragment %main "main" %var1 %var2
1269 OpExecutionMode %main OriginUpperLeft
1270 OpDecorate %var1 Location 1
1271 OpDecorate %var1 Index 1
1272 OpDecorate %var2 Location 1
1273 OpDecorate %var2 Index 1
1274 %void = OpTypeVoid
1275 %void_fn = OpTypeFunction %void
1276 %float = OpTypeFloat 32
1277 %struct = OpTypeStruct %float %float
1278 %ptr_output_struct = OpTypePointer Output %struct
1279 %var1 = OpVariable %ptr_output_struct Output
1280 %var2 = OpVariable %ptr_output_struct Output
1281 %main = OpFunction %void None %void_fn
1282 %entry = OpLabel
1283 OpReturn
1284 OpFunctionEnd
1285 )";
1286 
1287   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1288   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1289   EXPECT_THAT(getDiagnosticString(),
1290               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
1291   EXPECT_THAT(
1292       getDiagnosticString(),
1293       HasSubstr("Entry-point has conflicting output location assignment "
1294                 "at location 1"));
1295 }
1296 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableNoConflictDifferentIndex)1297 TEST_F(ValidateInterfacesTest,
1298        VulkanLocationsVariableNoConflictDifferentIndex) {
1299   const std::string text = R"(
1300 OpCapability Shader
1301 OpMemoryModel Logical GLSL450
1302 OpEntryPoint Fragment %main "main" %var1 %var2
1303 OpExecutionMode %main OriginUpperLeft
1304 OpDecorate %var1 Location 1
1305 OpDecorate %var1 Index 0
1306 OpDecorate %var2 Location 1
1307 OpDecorate %var2 Index 1
1308 %void = OpTypeVoid
1309 %void_fn = OpTypeFunction %void
1310 %float = OpTypeFloat 32
1311 %struct = OpTypeStruct %float %float
1312 %ptr_output_struct = OpTypePointer Output %struct
1313 %var1 = OpVariable %ptr_output_struct Output
1314 %var2 = OpVariable %ptr_output_struct Output
1315 %main = OpFunction %void None %void_fn
1316 %entry = OpLabel
1317 OpReturn
1318 OpFunctionEnd
1319 )";
1320 
1321   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1322   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1323 }
1324 
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexGLCompute)1325 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
1326   const std::string text = R"(
1327 OpCapability Shader
1328 OpCapability Geometry
1329 OpMemoryModel Logical GLSL450
1330 OpEntryPoint Geometry %main "main" %var1
1331 OpExecutionMode %main Triangles
1332 OpExecutionMode %main OutputPoints
1333 OpDecorate %var1 Location 1
1334 OpDecorate %var1 Index 1
1335 %void = OpTypeVoid
1336 %void_fn = OpTypeFunction %void
1337 %float = OpTypeFloat 32
1338 %struct = OpTypeStruct %float %float
1339 %ptr_output_struct = OpTypePointer Output %struct
1340 %var1 = OpVariable %ptr_output_struct Output
1341 %main = OpFunction %void None %void_fn
1342 %entry = OpLabel
1343 OpReturn
1344 OpFunctionEnd
1345 )";
1346 
1347   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1348   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1349   EXPECT_THAT(
1350       getDiagnosticString(),
1351       HasSubstr("Index can only be applied to Fragment output variables"));
1352 }
1353 
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexInput)1354 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
1355   const std::string text = R"(
1356 OpCapability Shader
1357 OpMemoryModel Logical GLSL450
1358 OpEntryPoint Fragment %main "main" %var1
1359 OpExecutionMode %main OriginUpperLeft
1360 OpDecorate %var1 Location 1
1361 OpDecorate %var1 Index 1
1362 %void = OpTypeVoid
1363 %void_fn = OpTypeFunction %void
1364 %float = OpTypeFloat 32
1365 %struct = OpTypeStruct %float %float
1366 %ptr_input_struct = OpTypePointer Input %struct
1367 %var1 = OpVariable %ptr_input_struct Input
1368 %main = OpFunction %void None %void_fn
1369 %entry = OpLabel
1370 OpReturn
1371 OpFunctionEnd
1372 )";
1373 
1374   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1375   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1376   EXPECT_THAT(getDiagnosticString(),
1377               HasSubstr("must be in the Output storage class"));
1378 }
1379 
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponent)1380 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
1381   const std::string text = R"(
1382 OpCapability Shader
1383 OpMemoryModel Logical GLSL450
1384 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1385 OpExecutionMode %4 OriginUpperLeft
1386 OpDecorate %11 Location 0
1387 OpDecorate %18 Component 0
1388 OpDecorate %18 Location 0
1389 OpDecorate %28 Component 1
1390 OpDecorate %28 Location 0
1391 OpDecorate %36 Location 1
1392 OpDecorate %40 Component 0
1393 OpDecorate %40 Location 1
1394 %void = OpTypeVoid
1395 %3 = OpTypeFunction %void
1396 %float = OpTypeFloat 32
1397 %v4float = OpTypeVector %float 4
1398 %_ptr_Input_v4float = OpTypePointer Input %v4float
1399 %11 = OpVariable %_ptr_Input_v4float Input
1400 %_ptr_Output_float = OpTypePointer Output %float
1401 %18 = OpVariable %_ptr_Output_float Output
1402 %uint = OpTypeInt 32 0
1403 %v3float = OpTypeVector %float 3
1404 %uint_2 = OpConstant %uint 2
1405 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1406 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1407 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1408 %_ptr_Output_v3float = OpTypePointer Output %v3float
1409 %36 = OpVariable %_ptr_Input_v4float Input
1410 %40 = OpVariable %_ptr_Output_float Output
1411 %4 = OpFunction %void None %3
1412 %5 = OpLabel
1413 OpReturn
1414 OpFunctionEnd
1415 )";
1416 
1417   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1418   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1419 }
1420 
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponentBad)1421 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
1422   const std::string text = R"(
1423 OpCapability Shader
1424 OpMemoryModel Logical GLSL450
1425 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1426 OpExecutionMode %4 OriginUpperLeft
1427 OpDecorate %11 Location 0
1428 OpDecorate %18 Component 0
1429 OpDecorate %18 Location 0
1430 OpDecorate %28 Component 1
1431 OpDecorate %28 Location 0
1432 OpDecorate %36 Location 1
1433 OpDecorate %40 Component 1
1434 OpDecorate %40 Location 1
1435 %void = OpTypeVoid
1436 %3 = OpTypeFunction %void
1437 %float = OpTypeFloat 32
1438 %v4float = OpTypeVector %float 4
1439 %_ptr_Input_v4float = OpTypePointer Input %v4float
1440 %11 = OpVariable %_ptr_Input_v4float Input
1441 %_ptr_Output_float = OpTypePointer Output %float
1442 %18 = OpVariable %_ptr_Output_float Output
1443 %uint = OpTypeInt 32 0
1444 %v3float = OpTypeVector %float 3
1445 %uint_2 = OpConstant %uint 2
1446 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1447 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1448 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1449 %_ptr_Output_v3float = OpTypePointer Output %v3float
1450 %36 = OpVariable %_ptr_Input_v4float Input
1451 %40 = OpVariable %_ptr_Output_float Output
1452 %4 = OpFunction %void None %3
1453 %5 = OpLabel
1454 OpReturn
1455 OpFunctionEnd
1456 )";
1457 
1458   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1459   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1460   EXPECT_THAT(getDiagnosticString(),
1461               AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
1462   EXPECT_THAT(getDiagnosticString(),
1463               HasSubstr("Entry-point has conflicting output location "
1464                         "assignment at location 1, component 1"));
1465 }
1466 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeLocation)1467 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
1468   const std::string text = R"(
1469                OpCapability Shader
1470                OpMemoryModel Logical GLSL450
1471                OpEntryPoint Fragment %4 "????????" %17
1472                OpExecutionMode %4 OriginUpperLeft
1473                OpDecorate %17 Location 4227868160
1474        %void = OpTypeVoid
1475           %3 = OpTypeFunction %void
1476       %float = OpTypeFloat 32
1477     %v3float = OpTypeVector %float 3
1478 %_ptr_Input_v3float = OpTypePointer Input %v3float
1479          %17 = OpVariable %_ptr_Input_v3float Input
1480           %4 = OpFunction %void None %3
1481           %5 = OpLabel
1482                OpUnreachable
1483                OpFunctionEnd
1484 )";
1485 
1486   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1487   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1488 }
1489 
TEST_F(ValidateInterfacesTest,VulkanLocationMeshShader)1490 TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
1491   const std::string text = R"(
1492 OpCapability Shader
1493 OpCapability MeshShadingNV
1494 OpExtension "SPV_NV_mesh_shader"
1495 OpMemoryModel Logical GLSL450
1496 OpEntryPoint MeshNV %foo "foo" %in
1497 OpExecutionMode %foo LocalSize 1 1 1
1498 OpDecorate %block Block
1499 OpMemberDecorate %block 0 PerTaskNV
1500 OpMemberDecorate %block 0 Offset 0
1501 %void = OpTypeVoid
1502 %int = OpTypeInt 32 0
1503 %int_32 = OpConstant %int 32
1504 %array = OpTypeArray %int %int_32
1505 %block = OpTypeStruct %array
1506 %ptr_input_block = OpTypePointer Input %block
1507 %in = OpVariable %ptr_input_block Input
1508 %void_fn = OpTypeFunction %void
1509 %foo = OpFunction %void None %void_fn
1510 %entry = OpLabel
1511 OpReturn
1512 OpFunctionEnd
1513 )";
1514 
1515   CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
1516   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1517 }
1518 
TEST_F(ValidateInterfacesTest,VulkanLocationArrayWithComponent1)1519 TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent1) {
1520   const std::string text = R"(
1521 OpCapability Shader
1522 OpMemoryModel Logical GLSL450
1523 OpEntryPoint Fragment %main "main" %in
1524 OpExecutionMode %main OriginUpperLeft
1525 OpDecorate %struct Block
1526 OpMemberDecorate %struct 0 Location 0
1527 OpMemberDecorate %struct 0 Component 0
1528 OpMemberDecorate %struct 1 Location 0
1529 OpMemberDecorate %struct 1 Component 1
1530 %void = OpTypeVoid
1531 %void_fn = OpTypeFunction %void
1532 %float = OpTypeFloat 32
1533 %int = OpTypeInt 32 0
1534 %int_2 = OpConstant %int 2
1535 %float_arr = OpTypeArray %float %int_2
1536 %struct = OpTypeStruct %float_arr %float_arr
1537 %ptr = OpTypePointer Input %struct
1538 %in = OpVariable %ptr Input
1539 %main = OpFunction %void None %void_fn
1540 %entry = OpLabel
1541 OpReturn
1542 OpFunctionEnd
1543 )";
1544 
1545   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1546   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1547 }
1548 
TEST_F(ValidateInterfacesTest,VulkanLocationArrayWithComponent2)1549 TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent2) {
1550   const std::string text = R"(
1551 OpCapability Shader
1552 OpCapability Float64
1553 OpMemoryModel Logical GLSL450
1554 OpEntryPoint Fragment %main "main" %in
1555 OpExecutionMode %main OriginUpperLeft
1556 OpDecorate %struct Block
1557 OpMemberDecorate %struct 0 Location 0
1558 OpMemberDecorate %struct 0 Component 0
1559 OpMemberDecorate %struct 1 Location 0
1560 OpMemberDecorate %struct 1 Component 2
1561 %void = OpTypeVoid
1562 %void_fn = OpTypeFunction %void
1563 %float = OpTypeFloat 32
1564 %double = OpTypeFloat 64
1565 %int = OpTypeInt 32 0
1566 %int_2 = OpConstant %int 2
1567 %double_arr = OpTypeArray %double %int_2
1568 %struct = OpTypeStruct %float %double_arr
1569 %ptr = OpTypePointer Input %struct
1570 %in = OpVariable %ptr Input
1571 %main = OpFunction %void None %void_fn
1572 %entry = OpLabel
1573 OpReturn
1574 OpFunctionEnd
1575 )";
1576 
1577   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1578   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1579 }
1580 
TEST_F(ValidateInterfacesTest,DuplicateInterfaceVariableSuccess)1581 TEST_F(ValidateInterfacesTest, DuplicateInterfaceVariableSuccess) {
1582   const std::string text = R"(
1583 OpCapability Shader
1584 OpMemoryModel Logical GLSL450
1585 OpEntryPoint Fragment %main "main" %in %out %in
1586 OpExecutionMode %main OriginUpperLeft
1587 OpDecorate %in Location 0
1588 OpDecorate %out Location 0
1589 %void = OpTypeVoid
1590 %float = OpTypeFloat 32
1591 %in_ptr = OpTypePointer Input %float
1592 %out_ptr = OpTypePointer Output %float
1593 %in = OpVariable %in_ptr Input
1594 %out = OpVariable %out_ptr Output
1595 %void_fn = OpTypeFunction %void
1596 %main = OpFunction %void None %void_fn
1597 %entry = OpLabel
1598 OpReturn
1599 OpFunctionEnd
1600 )";
1601 
1602   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1603   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1604 }
1605 
TEST_F(ValidateInterfacesTest,StructWithBuiltinsMissingBlock_Bad)1606 TEST_F(ValidateInterfacesTest, StructWithBuiltinsMissingBlock_Bad) {
1607   // See https://github.com/KhronosGroup/SPIRV-Registry/issues/134
1608   //
1609   // When a shader input or output is a struct that does not have Block,
1610   // then it must have a Location.
1611   // But BuiltIns must not have locations.
1612   const std::string text = R"(
1613 OpCapability Shader
1614 OpMemoryModel Logical GLSL450
1615 OpEntryPoint Fragment %main "main" %in
1616 OpExecutionMode %main OriginUpperLeft
1617 ; %struct needs a Block decoration
1618 OpMemberDecorate %struct 0 BuiltIn Position
1619 %void = OpTypeVoid
1620 %float = OpTypeFloat 32
1621 %v4float = OpTypeVector %float 4
1622 %struct = OpTypeStruct %v4float
1623 %in_ptr = OpTypePointer Input %struct
1624 %in = OpVariable %in_ptr Input
1625 %void_fn = OpTypeFunction %void
1626 %main = OpFunction %void None %void_fn
1627 %entry = OpLabel
1628 OpReturn
1629 OpFunctionEnd
1630 )";
1631 
1632   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1633   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1634   EXPECT_THAT(getDiagnosticString(),
1635               AnyVUID("VUID-StandaloneSpirv-Location-04919"));
1636   EXPECT_THAT(
1637       getDiagnosticString(),
1638       HasSubstr(
1639           "Interface struct has no Block decoration but has BuiltIn members."));
1640 }
1641 
TEST_F(ValidateInterfacesTest,InvalidLocationTypePointer)1642 TEST_F(ValidateInterfacesTest, InvalidLocationTypePointer) {
1643   const std::string text = R"(
1644                OpCapability Shader
1645                OpMemoryModel Logical Simple
1646                OpEntryPoint Vertex %1 "Aiqn0" %2 %3
1647                OpDecorate %2 Location 0
1648        %void = OpTypeVoid
1649           %5 = OpTypeFunction %void
1650       %float = OpTypeFloat 32
1651 %_ptr_Private_void = OpTypePointer Private %void
1652        %uint = OpTypeInt 32 0
1653 %uint_4278132784 = OpConstant %uint 4278132784
1654 %_arr__ptr_Private_void_uint_4278132784 = OpTypeArray %_ptr_Private_void %uint_4278132784
1655 %_ptr_Output__arr__ptr_Private_void_uint_4278132784 = OpTypePointer Output %_arr__ptr_Private_void_uint_4278132784
1656           %2 = OpVariable %_ptr_Output__arr__ptr_Private_void_uint_4278132784 Output
1657 %_ptr_Output__ptr_Private_void = OpTypePointer Output %_ptr_Private_void
1658           %3 = OpVariable %_ptr_Output__arr__ptr_Private_void_uint_4278132784 Output
1659           %1 = OpFunction %void None %5
1660          %15 = OpLabel
1661                OpReturn
1662                OpFunctionEnd
1663 )";
1664 
1665   CompileSuccessfully(text, SPV_ENV_VULKAN_1_1);
1666   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1667   EXPECT_THAT(getDiagnosticString(),
1668               HasSubstr("Invalid type to assign a location"));
1669 }
1670 
TEST_F(ValidateInterfacesTest,ValidLocationTypePhysicalStorageBufferPointer)1671 TEST_F(ValidateInterfacesTest, ValidLocationTypePhysicalStorageBufferPointer) {
1672   const std::string text = R"(
1673 OpCapability Shader
1674 OpCapability PhysicalStorageBufferAddresses
1675 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1676 OpEntryPoint Vertex %main "main" %var
1677 OpDecorate %var Location 0
1678 OpDecorate %var RestrictPointer
1679 %void = OpTypeVoid
1680 %int = OpTypeInt 32 0
1681 %ptr = OpTypePointer PhysicalStorageBuffer %int
1682 %ptr2 = OpTypePointer Input %ptr
1683 %var = OpVariable %ptr2 Input
1684 %void_fn = OpTypeFunction %void
1685 %main = OpFunction %void None %void_fn
1686 %entry = OpLabel
1687 OpReturn
1688 OpFunctionEnd
1689 )";
1690   CompileSuccessfully(text, SPV_ENV_VULKAN_1_3);
1691   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1692 }
1693 
1694 }  // namespace
1695 }  // namespace val
1696 }  // namespace spvtools
1697