• 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_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
423   EXPECT_THAT(getDiagnosticString(),
424               HasSubstr("Variable has conflicting location decorations"));
425 }
426 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableAndMemberAssigned)427 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableAndMemberAssigned) {
428   const std::string text = R"(
429 OpCapability Shader
430 OpMemoryModel Logical GLSL450
431 OpEntryPoint Fragment %main "main" %var
432 OpExecutionMode %main OriginUpperLeft
433 OpDecorate %var Location 0
434 OpDecorate %struct Block
435 OpMemberDecorate %struct 0 Location 0
436 %void = OpTypeVoid
437 %void_fn = OpTypeFunction %void
438 %float = OpTypeFloat 32
439 %struct = OpTypeStruct %float
440 %ptr_input_struct = OpTypePointer Input %struct
441 %var = OpVariable %ptr_input_struct Input
442 %main = OpFunction %void None %void_fn
443 %entry = OpLabel
444 OpReturn
445 OpFunctionEnd
446 )";
447 
448   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
449   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
450   EXPECT_THAT(getDiagnosticString(),
451               HasSubstr("Members cannot be assigned a location"));
452 }
453 
TEST_F(ValidateInterfacesTest,VulkanLocationsMemberAndSubMemberAssigned)454 TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
455   const std::string text = R"(
456 OpCapability Shader
457 OpMemoryModel Logical GLSL450
458 OpEntryPoint Fragment %main "main" %var
459 OpExecutionMode %main OriginUpperLeft
460 OpDecorate %outer Block
461 OpMemberDecorate %outer 0 Location 0
462 OpMemberDecorate %struct 0 Location 0
463 %void = OpTypeVoid
464 %void_fn = OpTypeFunction %void
465 %float = OpTypeFloat 32
466 %struct = OpTypeStruct %float
467 %outer = OpTypeStruct %struct
468 %ptr_input_outer = OpTypePointer Input %outer
469 %var = OpVariable %ptr_input_outer Input
470 %main = OpFunction %void None %void_fn
471 %entry = OpLabel
472 OpReturn
473 OpFunctionEnd
474 )";
475 
476   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
477   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
478   EXPECT_THAT(getDiagnosticString(),
479               HasSubstr("Members cannot be assigned a location"));
480 }
481 
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentStructMember)482 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
483   const std::string text = R"(
484 OpCapability Shader
485 OpMemoryModel Logical GLSL450
486 OpEntryPoint Fragment %main "main" %var
487 OpExecutionMode %main OriginUpperLeft
488 OpDecorate %struct Block
489 OpMemberDecorate %struct 1 Location 0
490 OpMemberDecorate %struct 1 Location 1
491 %void = OpTypeVoid
492 %void_fn = OpTypeFunction %void
493 %float = OpTypeFloat 32
494 %struct = OpTypeStruct %float %float
495 %ptr_input_struct = OpTypePointer Input %struct
496 %var = OpVariable %ptr_input_struct Input
497 %main = OpFunction %void None %void_fn
498 %entry = OpLabel
499 OpReturn
500 OpFunctionEnd
501 )";
502 
503   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
504   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
505   EXPECT_THAT(getDiagnosticString(),
506               HasSubstr("Member index 1 has conflicting location assignments"));
507 }
508 
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentStructMember)509 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
510   const std::string text = R"(
511 OpCapability Shader
512 OpMemoryModel Logical GLSL450
513 OpEntryPoint Fragment %main "main" %var
514 OpExecutionMode %main OriginUpperLeft
515 OpDecorate %struct Block
516 OpMemberDecorate %struct 1 Location 1
517 %void = OpTypeVoid
518 %void_fn = OpTypeFunction %void
519 %float = OpTypeFloat 32
520 %struct = OpTypeStruct %float %float
521 %ptr_input_struct = OpTypePointer Input %struct
522 %var = OpVariable %ptr_input_struct Input
523 %main = OpFunction %void None %void_fn
524 %entry = OpLabel
525 OpReturn
526 OpFunctionEnd
527 )";
528 
529   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
530   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
531   EXPECT_THAT(getDiagnosticString(),
532               HasSubstr("Member index 0 is missing a location assignment"));
533 }
534 
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentNonBlockStruct)535 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
536   const std::string text = R"(
537 OpCapability Shader
538 OpMemoryModel Logical GLSL450
539 OpEntryPoint Fragment %main "main" %var
540 OpExecutionMode %main OriginUpperLeft
541 %void = OpTypeVoid
542 %void_fn = OpTypeFunction %void
543 %float = OpTypeFloat 32
544 %struct = OpTypeStruct %float %float
545 %ptr_input_struct = OpTypePointer Input %struct
546 %var = OpVariable %ptr_input_struct Input
547 %main = OpFunction %void None %void_fn
548 %entry = OpLabel
549 OpReturn
550 OpFunctionEnd
551 )";
552 
553   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
554   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
555   EXPECT_THAT(getDiagnosticString(),
556               HasSubstr("Variable must be decorated with a location"));
557 }
558 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictInput)559 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
560   const std::string text = R"(
561 OpCapability Shader
562 OpMemoryModel Logical GLSL450
563 OpEntryPoint Fragment %main "main" %var1 %var2
564 OpExecutionMode %main OriginUpperLeft
565 OpDecorate %var1 Location 0
566 OpDecorate %var2 Location 0
567 %void = OpTypeVoid
568 %void_fn = OpTypeFunction %void
569 %float = OpTypeFloat 32
570 %struct = OpTypeStruct %float %float
571 %ptr_input_struct = OpTypePointer Input %struct
572 %var1 = OpVariable %ptr_input_struct Input
573 %var2 = OpVariable %ptr_input_struct Input
574 %main = OpFunction %void None %void_fn
575 %entry = OpLabel
576 OpReturn
577 OpFunctionEnd
578 )";
579 
580   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
581   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
582   EXPECT_THAT(getDiagnosticString(),
583               HasSubstr("Entry-point has conflicting input location assignment "
584                         "at location 0"));
585 }
586 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutput)587 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
588   const std::string text = R"(
589 OpCapability Shader
590 OpMemoryModel Logical GLSL450
591 OpEntryPoint Fragment %main "main" %var1 %var2
592 OpExecutionMode %main OriginUpperLeft
593 OpDecorate %var1 Location 1
594 OpDecorate %var2 Location 1
595 %void = OpTypeVoid
596 %void_fn = OpTypeFunction %void
597 %float = OpTypeFloat 32
598 %struct = OpTypeStruct %float %float
599 %ptr_output_struct = OpTypePointer Output %struct
600 %var1 = OpVariable %ptr_output_struct Output
601 %var2 = OpVariable %ptr_output_struct Output
602 %main = OpFunction %void None %void_fn
603 %entry = OpLabel
604 OpReturn
605 OpFunctionEnd
606 )";
607 
608   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
609   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
610   EXPECT_THAT(
611       getDiagnosticString(),
612       HasSubstr("Entry-point has conflicting output location assignment "
613                 "at location 1"));
614 }
615 
TEST_F(ValidateInterfacesTest,VulkanLocationsSameLocationInputAndOutputNoConflict)616 TEST_F(ValidateInterfacesTest,
617        VulkanLocationsSameLocationInputAndOutputNoConflict) {
618   const std::string text = R"(
619 OpCapability Shader
620 OpMemoryModel Logical GLSL450
621 OpEntryPoint Fragment %main "main" %var1 %var2
622 OpExecutionMode %main OriginUpperLeft
623 OpDecorate %var1 Location 1
624 OpDecorate %var2 Location 1
625 %void = OpTypeVoid
626 %void_fn = OpTypeFunction %void
627 %float = OpTypeFloat 32
628 %struct = OpTypeStruct %float %float
629 %ptr_input_struct = OpTypePointer Input %struct
630 %ptr_output_struct = OpTypePointer Output %struct
631 %var1 = OpVariable %ptr_input_struct Input
632 %var2 = OpVariable %ptr_output_struct Output
633 %main = OpFunction %void None %void_fn
634 %entry = OpLabel
635 OpReturn
636 OpFunctionEnd
637 )";
638 
639   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
640   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
641 }
642 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableInGap)643 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
644   const std::string text = R"(
645 OpCapability Shader
646 OpMemoryModel Logical GLSL450
647 OpEntryPoint Fragment %main "main" %var1 %var2
648 OpExecutionMode %main OriginUpperLeft
649 OpDecorate %struct Block
650 OpMemberDecorate %struct 0 Location 0
651 OpMemberDecorate %struct 1 Location 2
652 OpDecorate %var2 Location 1
653 %void = OpTypeVoid
654 %void_fn = OpTypeFunction %void
655 %float = OpTypeFloat 32
656 %struct = OpTypeStruct %float %float
657 %ptr_input_struct = OpTypePointer Input %struct
658 %ptr_input_float = OpTypePointer Input %float
659 %var1 = OpVariable %ptr_input_struct Input
660 %var2 = OpVariable %ptr_input_float Input
661 %main = OpFunction %void None %void_fn
662 %entry = OpLabel
663 OpReturn
664 OpFunctionEnd
665 )";
666 
667   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
668   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
669 }
670 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeFloatVectorConflict)671 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
672   const std::string text = R"(
673 OpCapability Shader
674 OpCapability Float64
675 OpMemoryModel Logical GLSL450
676 OpEntryPoint Fragment %main "main" %var1 %var2
677 OpExecutionMode %main OriginUpperLeft
678 OpDecorate %var1 Location 0
679 OpDecorate %var2 Location 1
680 %void = OpTypeVoid
681 %void_fn = OpTypeFunction %void
682 %float = OpTypeFloat 32
683 %double = OpTypeFloat 64
684 %vector = OpTypeVector %double 3
685 %ptr_input_float = OpTypePointer Input %float
686 %ptr_input_vector = OpTypePointer Input %vector
687 %var1 = OpVariable %ptr_input_vector Input
688 %var2 = OpVariable %ptr_input_float Input
689 %main = OpFunction %void None %void_fn
690 %entry = OpLabel
691 OpReturn
692 OpFunctionEnd
693 )";
694 
695   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
696   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
697   EXPECT_THAT(getDiagnosticString(),
698               HasSubstr("Entry-point has conflicting input location assignment "
699                         "at location 1"));
700 }
701 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeIntVectorConflict)702 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
703   const std::string text = R"(
704 OpCapability Shader
705 OpCapability Int64
706 OpMemoryModel Logical GLSL450
707 OpEntryPoint Fragment %main "main" %var1 %var2
708 OpExecutionMode %main OriginUpperLeft
709 OpDecorate %var1 Location 0
710 OpDecorate %var2 Location 1
711 %void = OpTypeVoid
712 %void_fn = OpTypeFunction %void
713 %float = OpTypeFloat 32
714 %long = OpTypeInt 64 0
715 %vector = OpTypeVector %long 4
716 %ptr_input_float = OpTypePointer Input %float
717 %ptr_input_vector = OpTypePointer Input %vector
718 %var1 = OpVariable %ptr_input_vector Input
719 %var2 = OpVariable %ptr_input_float Input
720 %main = OpFunction %void None %void_fn
721 %entry = OpLabel
722 OpReturn
723 OpFunctionEnd
724 )";
725 
726   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
727   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
728   EXPECT_THAT(getDiagnosticString(),
729               HasSubstr("Entry-point has conflicting input location assignment "
730                         "at location 1"));
731 }
732 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix2x2Conflict)733 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
734   const std::string text = R"(
735 OpCapability Shader
736 OpMemoryModel Logical GLSL450
737 OpEntryPoint Fragment %main "main" %var1 %var2
738 OpExecutionMode %main OriginUpperLeft
739 OpDecorate %var1 Location 0
740 OpDecorate %var2 Location 1
741 %void = OpTypeVoid
742 %void_fn = OpTypeFunction %void
743 %float = OpTypeFloat 32
744 %vector = OpTypeVector %float 2
745 %matrix = OpTypeMatrix %vector 2
746 %ptr_input_float = OpTypePointer Input %float
747 %ptr_input_matrix = OpTypePointer Input %matrix
748 %var1 = OpVariable %ptr_input_matrix Input
749 %var2 = OpVariable %ptr_input_float Input
750 %main = OpFunction %void None %void_fn
751 %entry = OpLabel
752 OpReturn
753 OpFunctionEnd
754 )";
755 
756   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
757   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
758   EXPECT_THAT(getDiagnosticString(),
759               HasSubstr("Entry-point has conflicting input location assignment "
760                         "at location 1"));
761 }
762 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix3x3Conflict)763 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
764   const std::string text = R"(
765 OpCapability Shader
766 OpMemoryModel Logical GLSL450
767 OpEntryPoint Fragment %main "main" %var1 %var2
768 OpExecutionMode %main OriginUpperLeft
769 OpDecorate %var1 Location 0
770 OpDecorate %var2 Location 2
771 %void = OpTypeVoid
772 %void_fn = OpTypeFunction %void
773 %float = OpTypeFloat 32
774 %vector = OpTypeVector %float 3
775 %matrix = OpTypeMatrix %vector 3
776 %ptr_input_float = OpTypePointer Input %float
777 %ptr_input_matrix = OpTypePointer Input %matrix
778 %var1 = OpVariable %ptr_input_matrix Input
779 %var2 = OpVariable %ptr_input_float Input
780 %main = OpFunction %void None %void_fn
781 %entry = OpLabel
782 OpReturn
783 OpFunctionEnd
784 )";
785 
786   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
787   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
788   EXPECT_THAT(getDiagnosticString(),
789               HasSubstr("Entry-point has conflicting input location assignment "
790                         "at location 2"));
791 }
792 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Conflict)793 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
794   const std::string text = R"(
795 OpCapability Shader
796 OpMemoryModel Logical GLSL450
797 OpEntryPoint Fragment %main "main" %var1 %var2
798 OpExecutionMode %main OriginUpperLeft
799 OpDecorate %var1 Location 0
800 OpDecorate %var2 Location 3
801 %void = OpTypeVoid
802 %void_fn = OpTypeFunction %void
803 %float = OpTypeFloat 32
804 %vector = OpTypeVector %float 4
805 %matrix = OpTypeMatrix %vector 4
806 %ptr_input_float = OpTypePointer Input %float
807 %ptr_input_matrix = OpTypePointer Input %matrix
808 %var1 = OpVariable %ptr_input_matrix Input
809 %var2 = OpVariable %ptr_input_float Input
810 %main = OpFunction %void None %void_fn
811 %entry = OpLabel
812 OpReturn
813 OpFunctionEnd
814 )";
815 
816   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
817   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
818   EXPECT_THAT(getDiagnosticString(),
819               HasSubstr("Entry-point has conflicting input location assignment "
820                         "at location 3"));
821 }
822 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix2x2Conflict)823 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
824   const std::string text = R"(
825 OpCapability Shader
826 OpCapability Float64
827 OpMemoryModel Logical GLSL450
828 OpEntryPoint Fragment %main "main" %var1 %var2
829 OpExecutionMode %main OriginUpperLeft
830 OpDecorate %var1 Location 0
831 OpDecorate %var2 Location 1
832 %void = OpTypeVoid
833 %void_fn = OpTypeFunction %void
834 %float = OpTypeFloat 32
835 %double = OpTypeFloat 64
836 %vector = OpTypeVector %double 2
837 %matrix = OpTypeMatrix %vector 2
838 %ptr_input_float = OpTypePointer Input %float
839 %ptr_input_matrix = OpTypePointer Input %matrix
840 %var1 = OpVariable %ptr_input_matrix Input
841 %var2 = OpVariable %ptr_input_float Input
842 %main = OpFunction %void None %void_fn
843 %entry = OpLabel
844 OpReturn
845 OpFunctionEnd
846 )";
847 
848   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
849   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
850   EXPECT_THAT(getDiagnosticString(),
851               HasSubstr("Entry-point has conflicting input location assignment "
852                         "at location 1"));
853 }
854 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix3x3Conflict)855 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
856   const std::string text = R"(
857 OpCapability Shader
858 OpCapability Float64
859 OpMemoryModel Logical GLSL450
860 OpEntryPoint Fragment %main "main" %var1 %var2
861 OpExecutionMode %main OriginUpperLeft
862 OpDecorate %var1 Location 0
863 OpDecorate %var2 Location 5
864 %void = OpTypeVoid
865 %void_fn = OpTypeFunction %void
866 %float = OpTypeFloat 32
867 %double = OpTypeFloat 64
868 %vector = OpTypeVector %double 3
869 %matrix = OpTypeMatrix %vector 3
870 %ptr_input_float = OpTypePointer Input %float
871 %ptr_input_matrix = OpTypePointer Input %matrix
872 %var1 = OpVariable %ptr_input_matrix Input
873 %var2 = OpVariable %ptr_input_float Input
874 %main = OpFunction %void None %void_fn
875 %entry = OpLabel
876 OpReturn
877 OpFunctionEnd
878 )";
879 
880   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
881   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
882   EXPECT_THAT(getDiagnosticString(),
883               HasSubstr("Entry-point has conflicting input location assignment "
884                         "at location 5"));
885 }
886 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix4x4Conflict)887 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
888   const std::string text = R"(
889 OpCapability Shader
890 OpCapability Float64
891 OpMemoryModel Logical GLSL450
892 OpEntryPoint Fragment %main "main" %var1 %var2
893 OpExecutionMode %main OriginUpperLeft
894 OpDecorate %var1 Location 0
895 OpDecorate %var2 Location 7
896 %void = OpTypeVoid
897 %void_fn = OpTypeFunction %void
898 %float = OpTypeFloat 32
899 %double = OpTypeFloat 64
900 %vector = OpTypeVector %double 4
901 %matrix = OpTypeMatrix %vector 4
902 %ptr_input_float = OpTypePointer Input %float
903 %ptr_input_matrix = OpTypePointer Input %matrix
904 %var1 = OpVariable %ptr_input_matrix Input
905 %var2 = OpVariable %ptr_input_float Input
906 %main = OpFunction %void None %void_fn
907 %entry = OpLabel
908 OpReturn
909 OpFunctionEnd
910 )";
911 
912   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
913   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
914   EXPECT_THAT(getDiagnosticString(),
915               HasSubstr("Entry-point has conflicting input location assignment "
916                         "at location 7"));
917 }
918 
TEST_F(ValidateInterfacesTest,VulkanLocationsArray2Conflict)919 TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
920   const std::string text = R"(
921 OpCapability Shader
922 OpMemoryModel Logical GLSL450
923 OpEntryPoint Fragment %main "main" %var1 %var2
924 OpExecutionMode %main OriginUpperLeft
925 OpDecorate %var1 Location 0
926 OpDecorate %var2 Location 1
927 %void = OpTypeVoid
928 %void_fn = OpTypeFunction %void
929 %float = OpTypeFloat 32
930 %int = OpTypeInt 32 0
931 %int_2 = OpConstant %int 2
932 %array = OpTypeArray %int %int_2
933 %struct = OpTypeStruct %array
934 %ptr_input_float = OpTypePointer Input %float
935 %ptr_input_struct = OpTypePointer Input %struct
936 %var1 = OpVariable %ptr_input_struct Input
937 %var2 = OpVariable %ptr_input_float Input
938 %main = OpFunction %void None %void_fn
939 %entry = OpLabel
940 OpReturn
941 OpFunctionEnd
942 )";
943 
944   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
945   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
946   EXPECT_THAT(getDiagnosticString(),
947               HasSubstr("Entry-point has conflicting input location assignment "
948                         "at location 1"));
949 }
950 
TEST_F(ValidateInterfacesTest,VulkanLocationsArray4Conflict)951 TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
952   const std::string text = R"(
953 OpCapability Shader
954 OpMemoryModel Logical GLSL450
955 OpEntryPoint Fragment %main "main" %var1 %var2
956 OpExecutionMode %main OriginUpperLeft
957 OpDecorate %var1 Location 0
958 OpDecorate %var2 Location 3
959 %void = OpTypeVoid
960 %void_fn = OpTypeFunction %void
961 %float = OpTypeFloat 32
962 %int = OpTypeInt 32 0
963 %int_4 = OpConstant %int 4
964 %array = OpTypeArray %int %int_4
965 %struct = OpTypeStruct %array
966 %ptr_input_float = OpTypePointer Input %float
967 %ptr_input_struct = OpTypePointer Input %struct
968 %var1 = OpVariable %ptr_input_struct Input
969 %var2 = OpVariable %ptr_input_float Input
970 %main = OpFunction %void None %void_fn
971 %entry = OpLabel
972 OpReturn
973 OpFunctionEnd
974 )";
975 
976   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
977   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
978   EXPECT_THAT(getDiagnosticString(),
979               HasSubstr("Entry-point has conflicting input location assignment "
980                         "at location 3"));
981 }
982 
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Array4Conflict)983 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
984   const std::string text = R"(
985 OpCapability Shader
986 OpMemoryModel Logical GLSL450
987 OpEntryPoint Fragment %main "main" %var1 %var2
988 OpExecutionMode %main OriginUpperLeft
989 OpDecorate %var1 Location 0
990 OpDecorate %var2 Location 15
991 %void = OpTypeVoid
992 %void_fn = OpTypeFunction %void
993 %float = OpTypeFloat 32
994 %int = OpTypeInt 32 0
995 %int_4 = OpConstant %int 4
996 %vector = OpTypeVector %float 4
997 %matrix = OpTypeMatrix %vector 4
998 %array = OpTypeArray %matrix %int_4
999 %struct = OpTypeStruct %array
1000 %ptr_input_float = OpTypePointer Input %float
1001 %ptr_input_struct = OpTypePointer Input %struct
1002 %var1 = OpVariable %ptr_input_struct Input
1003 %var2 = OpVariable %ptr_input_float Input
1004 %main = OpFunction %void None %void_fn
1005 %entry = OpLabel
1006 OpReturn
1007 OpFunctionEnd
1008 )";
1009 
1010   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1011   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1012   EXPECT_THAT(getDiagnosticString(),
1013               HasSubstr("Entry-point has conflicting input location assignment "
1014                         "at location 15"));
1015 }
1016 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentDisambiguates)1017 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
1018   const std::string text = R"(
1019 OpCapability Shader
1020 OpMemoryModel Logical GLSL450
1021 OpEntryPoint Fragment %main "main" %var1
1022 OpExecutionMode %main OriginUpperLeft
1023 OpDecorate %struct Block
1024 OpMemberDecorate %struct 0 Location 0
1025 OpMemberDecorate %struct 0 Component 0
1026 OpMemberDecorate %struct 1 Location 0
1027 OpMemberDecorate %struct 1 Component 1
1028 %void = OpTypeVoid
1029 %void_fn = OpTypeFunction %void
1030 %float = OpTypeFloat 32
1031 %struct = OpTypeStruct %float %float
1032 %ptr_input_struct = OpTypePointer Input %struct
1033 %var1 = OpVariable %ptr_input_struct Input
1034 %main = OpFunction %void None %void_fn
1035 %entry = OpLabel
1036 OpReturn
1037 OpFunctionEnd
1038 )";
1039 
1040   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1041   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1042 }
1043 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentIn64BitVec3)1044 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
1045   const std::string text = R"(
1046 OpCapability Shader
1047 OpCapability Float64
1048 OpMemoryModel Logical GLSL450
1049 OpEntryPoint Fragment %main "main" %var
1050 OpExecutionMode %main OriginUpperLeft
1051 OpDecorate %struct Block
1052 OpMemberDecorate %struct 0 Location 0
1053 OpMemberDecorate %struct 1 Location 1
1054 OpMemberDecorate %struct 1 Component 1
1055 %void = OpTypeVoid
1056 %void_fn = OpTypeFunction %void
1057 %float = OpTypeFloat 32
1058 %double = OpTypeFloat 64
1059 %double3 = OpTypeVector %double 3
1060 %struct = OpTypeStruct %double3 %float
1061 %ptr_input_struct = OpTypePointer Input %struct
1062 %var = OpVariable %ptr_input_struct Input
1063 %main = OpFunction %void None %void_fn
1064 %entry = OpLabel
1065 OpReturn
1066 OpFunctionEnd
1067 )";
1068 
1069   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1070   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1071   EXPECT_THAT(getDiagnosticString(),
1072               HasSubstr("Entry-point has conflicting input location assignment "
1073                         "at location 1, component 1"));
1074 }
1075 
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentAfter64BitVec3)1076 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
1077   const std::string text = R"(
1078 OpCapability Shader
1079 OpCapability Float64
1080 OpMemoryModel Logical GLSL450
1081 OpEntryPoint Fragment %main "main" %var
1082 OpExecutionMode %main OriginUpperLeft
1083 OpDecorate %struct Block
1084 OpMemberDecorate %struct 0 Location 0
1085 OpMemberDecorate %struct 1 Location 1
1086 OpMemberDecorate %struct 1 Component 2
1087 %void = OpTypeVoid
1088 %void_fn = OpTypeFunction %void
1089 %float = OpTypeFloat 32
1090 %double = OpTypeFloat 64
1091 %double3 = OpTypeVector %double 3
1092 %struct = OpTypeStruct %double3 %float
1093 %ptr_input_struct = OpTypePointer Input %struct
1094 %var = OpVariable %ptr_input_struct Input
1095 %main = OpFunction %void None %void_fn
1096 %entry = OpLabel
1097 OpReturn
1098 OpFunctionEnd
1099 )";
1100 
1101   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1102   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1103 }
1104 
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentVariable)1105 TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
1106   const std::string text = R"(
1107 OpCapability Shader
1108 OpMemoryModel Logical GLSL450
1109 OpEntryPoint Fragment %main "main" %var
1110 OpExecutionMode %main OriginUpperLeft
1111 OpDecorate %var Location 0
1112 OpDecorate %var Component 0
1113 OpDecorate %var Component 1
1114 %void = OpTypeVoid
1115 %void_fn = OpTypeFunction %void
1116 %float = OpTypeFloat 32
1117 %ptr_input_float = OpTypePointer Input %float
1118 %var = OpVariable %ptr_input_float Input
1119 %main = OpFunction %void None %void_fn
1120 %entry = OpLabel
1121 OpReturn
1122 OpFunctionEnd
1123 )";
1124 
1125   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1126   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1127   EXPECT_THAT(getDiagnosticString(),
1128               HasSubstr("Variable has conflicting component decorations"));
1129 }
1130 
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentStructMember)1131 TEST_F(ValidateInterfacesTest,
1132        VulkanLocationsConflictingComponentStructMember) {
1133   const std::string text = R"(
1134 OpCapability Shader
1135 OpMemoryModel Logical GLSL450
1136 OpEntryPoint Fragment %main "main" %var
1137 OpExecutionMode %main OriginUpperLeft
1138 OpDecorate %struct Block
1139 OpMemberDecorate %struct 0 Location 0
1140 OpMemberDecorate %struct 0 Component 0
1141 OpMemberDecorate %struct 0 Component 1
1142 %void = OpTypeVoid
1143 %void_fn = OpTypeFunction %void
1144 %float = OpTypeFloat 32
1145 %struct = OpTypeStruct %float
1146 %ptr_input_struct = OpTypePointer Input %struct
1147 %var = OpVariable %ptr_input_struct Input
1148 %main = OpFunction %void None %void_fn
1149 %entry = OpLabel
1150 OpReturn
1151 OpFunctionEnd
1152 )";
1153 
1154   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1155   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1156   EXPECT_THAT(
1157       getDiagnosticString(),
1158       HasSubstr("Member index 0 has conflicting component assignments"));
1159 }
1160 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutputIndex1)1161 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
1162   const std::string text = R"(
1163 OpCapability Shader
1164 OpMemoryModel Logical GLSL450
1165 OpEntryPoint Fragment %main "main" %var1 %var2
1166 OpExecutionMode %main OriginUpperLeft
1167 OpDecorate %var1 Location 1
1168 OpDecorate %var1 Index 1
1169 OpDecorate %var2 Location 1
1170 OpDecorate %var2 Index 1
1171 %void = OpTypeVoid
1172 %void_fn = OpTypeFunction %void
1173 %float = OpTypeFloat 32
1174 %struct = OpTypeStruct %float %float
1175 %ptr_output_struct = OpTypePointer Output %struct
1176 %var1 = OpVariable %ptr_output_struct Output
1177 %var2 = OpVariable %ptr_output_struct Output
1178 %main = OpFunction %void None %void_fn
1179 %entry = OpLabel
1180 OpReturn
1181 OpFunctionEnd
1182 )";
1183 
1184   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1185   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1186   EXPECT_THAT(
1187       getDiagnosticString(),
1188       HasSubstr("Entry-point has conflicting output location assignment "
1189                 "at location 1"));
1190 }
1191 
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableNoConflictDifferentIndex)1192 TEST_F(ValidateInterfacesTest,
1193        VulkanLocationsVariableNoConflictDifferentIndex) {
1194   const std::string text = R"(
1195 OpCapability Shader
1196 OpMemoryModel Logical GLSL450
1197 OpEntryPoint Fragment %main "main" %var1 %var2
1198 OpExecutionMode %main OriginUpperLeft
1199 OpDecorate %var1 Location 1
1200 OpDecorate %var1 Index 0
1201 OpDecorate %var2 Location 1
1202 OpDecorate %var2 Index 1
1203 %void = OpTypeVoid
1204 %void_fn = OpTypeFunction %void
1205 %float = OpTypeFloat 32
1206 %struct = OpTypeStruct %float %float
1207 %ptr_output_struct = OpTypePointer Output %struct
1208 %var1 = OpVariable %ptr_output_struct Output
1209 %var2 = OpVariable %ptr_output_struct Output
1210 %main = OpFunction %void None %void_fn
1211 %entry = OpLabel
1212 OpReturn
1213 OpFunctionEnd
1214 )";
1215 
1216   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1217   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1218 }
1219 
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexGLCompute)1220 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
1221   const std::string text = R"(
1222 OpCapability Shader
1223 OpCapability Geometry
1224 OpMemoryModel Logical GLSL450
1225 OpEntryPoint Geometry %main "main" %var1
1226 OpExecutionMode %main Triangles
1227 OpExecutionMode %main OutputPoints
1228 OpDecorate %var1 Location 1
1229 OpDecorate %var1 Index 1
1230 %void = OpTypeVoid
1231 %void_fn = OpTypeFunction %void
1232 %float = OpTypeFloat 32
1233 %struct = OpTypeStruct %float %float
1234 %ptr_output_struct = OpTypePointer Output %struct
1235 %var1 = OpVariable %ptr_output_struct Output
1236 %main = OpFunction %void None %void_fn
1237 %entry = OpLabel
1238 OpReturn
1239 OpFunctionEnd
1240 )";
1241 
1242   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1243   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1244   EXPECT_THAT(
1245       getDiagnosticString(),
1246       HasSubstr("Index can only be applied to Fragment output variables"));
1247 }
1248 
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexInput)1249 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
1250   const std::string text = R"(
1251 OpCapability Shader
1252 OpMemoryModel Logical GLSL450
1253 OpEntryPoint Fragment %main "main" %var1
1254 OpExecutionMode %main OriginUpperLeft
1255 OpDecorate %var1 Location 1
1256 OpDecorate %var1 Index 1
1257 %void = OpTypeVoid
1258 %void_fn = OpTypeFunction %void
1259 %float = OpTypeFloat 32
1260 %struct = OpTypeStruct %float %float
1261 %ptr_input_struct = OpTypePointer Input %struct
1262 %var1 = OpVariable %ptr_input_struct Input
1263 %main = OpFunction %void None %void_fn
1264 %entry = OpLabel
1265 OpReturn
1266 OpFunctionEnd
1267 )";
1268 
1269   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1270   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1271   EXPECT_THAT(
1272       getDiagnosticString(),
1273       HasSubstr("Index can only be applied to Fragment output variables"));
1274 }
1275 
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponent)1276 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
1277   const std::string text = R"(
1278 OpCapability Shader
1279 OpMemoryModel Logical GLSL450
1280 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1281 OpExecutionMode %4 OriginUpperLeft
1282 OpDecorate %11 Location 0
1283 OpDecorate %18 Component 0
1284 OpDecorate %18 Location 0
1285 OpDecorate %28 Component 1
1286 OpDecorate %28 Location 0
1287 OpDecorate %36 Location 1
1288 OpDecorate %40 Component 0
1289 OpDecorate %40 Location 1
1290 %void = OpTypeVoid
1291 %3 = OpTypeFunction %void
1292 %float = OpTypeFloat 32
1293 %v4float = OpTypeVector %float 4
1294 %_ptr_Input_v4float = OpTypePointer Input %v4float
1295 %11 = OpVariable %_ptr_Input_v4float Input
1296 %_ptr_Output_float = OpTypePointer Output %float
1297 %18 = OpVariable %_ptr_Output_float Output
1298 %uint = OpTypeInt 32 0
1299 %v3float = OpTypeVector %float 3
1300 %uint_2 = OpConstant %uint 2
1301 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1302 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1303 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1304 %_ptr_Output_v3float = OpTypePointer Output %v3float
1305 %36 = OpVariable %_ptr_Input_v4float Input
1306 %40 = OpVariable %_ptr_Output_float Output
1307 %4 = OpFunction %void None %3
1308 %5 = OpLabel
1309 OpReturn
1310 OpFunctionEnd
1311 )";
1312 
1313   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1314   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1315 }
1316 
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponentBad)1317 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
1318   const std::string text = R"(
1319 OpCapability Shader
1320 OpMemoryModel Logical GLSL450
1321 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1322 OpExecutionMode %4 OriginUpperLeft
1323 OpDecorate %11 Location 0
1324 OpDecorate %18 Component 0
1325 OpDecorate %18 Location 0
1326 OpDecorate %28 Component 1
1327 OpDecorate %28 Location 0
1328 OpDecorate %36 Location 1
1329 OpDecorate %40 Component 1
1330 OpDecorate %40 Location 1
1331 %void = OpTypeVoid
1332 %3 = OpTypeFunction %void
1333 %float = OpTypeFloat 32
1334 %v4float = OpTypeVector %float 4
1335 %_ptr_Input_v4float = OpTypePointer Input %v4float
1336 %11 = OpVariable %_ptr_Input_v4float Input
1337 %_ptr_Output_float = OpTypePointer Output %float
1338 %18 = OpVariable %_ptr_Output_float Output
1339 %uint = OpTypeInt 32 0
1340 %v3float = OpTypeVector %float 3
1341 %uint_2 = OpConstant %uint 2
1342 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1343 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1344 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1345 %_ptr_Output_v3float = OpTypePointer Output %v3float
1346 %36 = OpVariable %_ptr_Input_v4float Input
1347 %40 = OpVariable %_ptr_Output_float Output
1348 %4 = OpFunction %void None %3
1349 %5 = OpLabel
1350 OpReturn
1351 OpFunctionEnd
1352 )";
1353 
1354   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1355   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1356   EXPECT_THAT(getDiagnosticString(),
1357               HasSubstr("Entry-point has conflicting output location "
1358                         "assignment at location 1, component 1"));
1359 }
1360 
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeLocation)1361 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
1362   const std::string text = R"(
1363                OpCapability Shader
1364                OpMemoryModel Logical GLSL450
1365                OpEntryPoint Fragment %4 "????????" %17
1366                OpExecutionMode %4 OriginUpperLeft
1367                OpDecorate %17 Location 4227868160
1368        %void = OpTypeVoid
1369           %3 = OpTypeFunction %void
1370       %float = OpTypeFloat 32
1371     %v3float = OpTypeVector %float 3
1372 %_ptr_Input_v3float = OpTypePointer Input %v3float
1373          %17 = OpVariable %_ptr_Input_v3float Input
1374           %4 = OpFunction %void None %3
1375           %5 = OpLabel
1376                OpUnreachable
1377                OpFunctionEnd
1378 )";
1379 
1380   CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1381   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1382 }
1383 
TEST_F(ValidateInterfacesTest,VulkanLocationMeshShader)1384 TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
1385   const std::string text = R"(
1386 OpCapability Shader
1387 OpCapability MeshShadingNV
1388 OpExtension "SPV_NV_mesh_shader"
1389 OpMemoryModel Logical GLSL450
1390 OpEntryPoint MeshNV %foo "foo" %in
1391 OpExecutionMode %foo LocalSize 1 1 1
1392 OpDecorate %block Block
1393 OpMemberDecorate %block 0 PerTaskNV
1394 OpMemberDecorate %block 0 Offset 0
1395 %void = OpTypeVoid
1396 %int = OpTypeInt 32 0
1397 %int_32 = OpConstant %int 32
1398 %array = OpTypeArray %int %int_32
1399 %block = OpTypeStruct %array
1400 %ptr_input_block = OpTypePointer Input %block
1401 %in = OpVariable %ptr_input_block Input
1402 %void_fn = OpTypeFunction %void
1403 %foo = OpFunction %void None %void_fn
1404 %entry = OpLabel
1405 OpReturn
1406 OpFunctionEnd
1407 )";
1408 
1409   CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
1410   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1411 }
1412 
1413 }  // namespace
1414 }  // namespace val
1415 }  // namespace spvtools
1416