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