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 AnyVUID("VUID-StandaloneSpirv-Location-04918"));
452 EXPECT_THAT(getDiagnosticString(),
453 HasSubstr("Members cannot be assigned a location"));
454 }
455
TEST_F(ValidateInterfacesTest,VulkanLocationsMemberAndSubMemberAssigned)456 TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
457 const std::string text = R"(
458 OpCapability Shader
459 OpMemoryModel Logical GLSL450
460 OpEntryPoint Fragment %main "main" %var
461 OpExecutionMode %main OriginUpperLeft
462 OpDecorate %outer Block
463 OpMemberDecorate %outer 0 Location 0
464 OpMemberDecorate %struct 0 Location 0
465 %void = OpTypeVoid
466 %void_fn = OpTypeFunction %void
467 %float = OpTypeFloat 32
468 %struct = OpTypeStruct %float
469 %outer = OpTypeStruct %struct
470 %ptr_input_outer = OpTypePointer Input %outer
471 %var = OpVariable %ptr_input_outer Input
472 %main = OpFunction %void None %void_fn
473 %entry = OpLabel
474 OpReturn
475 OpFunctionEnd
476 )";
477
478 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
479 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
480 EXPECT_THAT(getDiagnosticString(),
481 AnyVUID("VUID-StandaloneSpirv-Location-04918"));
482 EXPECT_THAT(getDiagnosticString(),
483 HasSubstr("Members cannot be assigned a location"));
484 }
485
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentStructMember)486 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
487 const std::string text = R"(
488 OpCapability Shader
489 OpMemoryModel Logical GLSL450
490 OpEntryPoint Fragment %main "main" %var
491 OpExecutionMode %main OriginUpperLeft
492 OpDecorate %struct Block
493 OpMemberDecorate %struct 1 Location 0
494 OpMemberDecorate %struct 1 Location 1
495 %void = OpTypeVoid
496 %void_fn = OpTypeFunction %void
497 %float = OpTypeFloat 32
498 %struct = OpTypeStruct %float %float
499 %ptr_input_struct = OpTypePointer Input %struct
500 %var = OpVariable %ptr_input_struct Input
501 %main = OpFunction %void None %void_fn
502 %entry = OpLabel
503 OpReturn
504 OpFunctionEnd
505 )";
506
507 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
508 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
509 EXPECT_THAT(getDiagnosticString(),
510 HasSubstr("Member index 1 has conflicting location assignments"));
511 }
512
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentStructMember)513 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
514 const std::string text = R"(
515 OpCapability Shader
516 OpMemoryModel Logical GLSL450
517 OpEntryPoint Fragment %main "main" %var
518 OpExecutionMode %main OriginUpperLeft
519 OpDecorate %struct Block
520 OpMemberDecorate %struct 1 Location 1
521 %void = OpTypeVoid
522 %void_fn = OpTypeFunction %void
523 %float = OpTypeFloat 32
524 %struct = OpTypeStruct %float %float
525 %ptr_input_struct = OpTypePointer Input %struct
526 %var = OpVariable %ptr_input_struct Input
527 %main = OpFunction %void None %void_fn
528 %entry = OpLabel
529 OpReturn
530 OpFunctionEnd
531 )";
532
533 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
534 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
535 EXPECT_THAT(getDiagnosticString(),
536 HasSubstr("Member index 0 is missing a location assignment"));
537 }
538
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentNonBlockStruct)539 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
540 const std::string text = R"(
541 OpCapability Shader
542 OpMemoryModel Logical GLSL450
543 OpEntryPoint Fragment %main "main" %var
544 OpExecutionMode %main OriginUpperLeft
545 %void = OpTypeVoid
546 %void_fn = OpTypeFunction %void
547 %float = OpTypeFloat 32
548 %struct = OpTypeStruct %float %float
549 %ptr_input_struct = OpTypePointer Input %struct
550 %var = OpVariable %ptr_input_struct Input
551 %main = OpFunction %void None %void_fn
552 %entry = OpLabel
553 OpReturn
554 OpFunctionEnd
555 )";
556
557 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
558 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
559 EXPECT_THAT(getDiagnosticString(),
560 HasSubstr("Variable must be decorated with a location"));
561 }
562
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictInput)563 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
564 const std::string text = R"(
565 OpCapability Shader
566 OpMemoryModel Logical GLSL450
567 OpEntryPoint Fragment %main "main" %var1 %var2
568 OpExecutionMode %main OriginUpperLeft
569 OpDecorate %var1 Location 0
570 OpDecorate %var2 Location 0
571 %void = OpTypeVoid
572 %void_fn = OpTypeFunction %void
573 %float = OpTypeFloat 32
574 %struct = OpTypeStruct %float %float
575 %ptr_input_struct = OpTypePointer Input %struct
576 %var1 = OpVariable %ptr_input_struct Input
577 %var2 = OpVariable %ptr_input_struct Input
578 %main = OpFunction %void None %void_fn
579 %entry = OpLabel
580 OpReturn
581 OpFunctionEnd
582 )";
583
584 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
585 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
586 EXPECT_THAT(getDiagnosticString(),
587 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
588 EXPECT_THAT(getDiagnosticString(),
589 HasSubstr("Entry-point has conflicting input location assignment "
590 "at location 0"));
591 }
592
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutput)593 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
594 const std::string text = R"(
595 OpCapability Shader
596 OpMemoryModel Logical GLSL450
597 OpEntryPoint Fragment %main "main" %var1 %var2
598 OpExecutionMode %main OriginUpperLeft
599 OpDecorate %var1 Location 1
600 OpDecorate %var2 Location 1
601 %void = OpTypeVoid
602 %void_fn = OpTypeFunction %void
603 %float = OpTypeFloat 32
604 %struct = OpTypeStruct %float %float
605 %ptr_output_struct = OpTypePointer Output %struct
606 %var1 = OpVariable %ptr_output_struct Output
607 %var2 = OpVariable %ptr_output_struct Output
608 %main = OpFunction %void None %void_fn
609 %entry = OpLabel
610 OpReturn
611 OpFunctionEnd
612 )";
613
614 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
615 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
616 EXPECT_THAT(getDiagnosticString(),
617 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
618 EXPECT_THAT(
619 getDiagnosticString(),
620 HasSubstr("Entry-point has conflicting output location assignment "
621 "at location 1"));
622 }
623
TEST_F(ValidateInterfacesTest,VulkanLocationsSameLocationInputAndOutputNoConflict)624 TEST_F(ValidateInterfacesTest,
625 VulkanLocationsSameLocationInputAndOutputNoConflict) {
626 const std::string text = R"(
627 OpCapability Shader
628 OpMemoryModel Logical GLSL450
629 OpEntryPoint Fragment %main "main" %var1 %var2
630 OpExecutionMode %main OriginUpperLeft
631 OpDecorate %var1 Location 1
632 OpDecorate %var2 Location 1
633 %void = OpTypeVoid
634 %void_fn = OpTypeFunction %void
635 %float = OpTypeFloat 32
636 %struct = OpTypeStruct %float %float
637 %ptr_input_struct = OpTypePointer Input %struct
638 %ptr_output_struct = OpTypePointer Output %struct
639 %var1 = OpVariable %ptr_input_struct Input
640 %var2 = OpVariable %ptr_output_struct Output
641 %main = OpFunction %void None %void_fn
642 %entry = OpLabel
643 OpReturn
644 OpFunctionEnd
645 )";
646
647 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
648 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
649 }
650
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableInGap)651 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
652 const std::string text = R"(
653 OpCapability Shader
654 OpMemoryModel Logical GLSL450
655 OpEntryPoint Fragment %main "main" %var1 %var2
656 OpExecutionMode %main OriginUpperLeft
657 OpDecorate %struct Block
658 OpMemberDecorate %struct 0 Location 0
659 OpMemberDecorate %struct 1 Location 2
660 OpDecorate %var2 Location 1
661 %void = OpTypeVoid
662 %void_fn = OpTypeFunction %void
663 %float = OpTypeFloat 32
664 %struct = OpTypeStruct %float %float
665 %ptr_input_struct = OpTypePointer Input %struct
666 %ptr_input_float = OpTypePointer Input %float
667 %var1 = OpVariable %ptr_input_struct Input
668 %var2 = OpVariable %ptr_input_float Input
669 %main = OpFunction %void None %void_fn
670 %entry = OpLabel
671 OpReturn
672 OpFunctionEnd
673 )";
674
675 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
676 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
677 }
678
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeFloatVectorConflict)679 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
680 const std::string text = R"(
681 OpCapability Shader
682 OpCapability Float64
683 OpMemoryModel Logical GLSL450
684 OpEntryPoint Fragment %main "main" %var1 %var2
685 OpExecutionMode %main OriginUpperLeft
686 OpDecorate %var1 Location 0
687 OpDecorate %var2 Location 1
688 %void = OpTypeVoid
689 %void_fn = OpTypeFunction %void
690 %float = OpTypeFloat 32
691 %double = OpTypeFloat 64
692 %vector = OpTypeVector %double 3
693 %ptr_input_float = OpTypePointer Input %float
694 %ptr_input_vector = OpTypePointer Input %vector
695 %var1 = OpVariable %ptr_input_vector Input
696 %var2 = OpVariable %ptr_input_float Input
697 %main = OpFunction %void None %void_fn
698 %entry = OpLabel
699 OpReturn
700 OpFunctionEnd
701 )";
702
703 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
704 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
705 EXPECT_THAT(getDiagnosticString(),
706 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
707 EXPECT_THAT(getDiagnosticString(),
708 HasSubstr("Entry-point has conflicting input location assignment "
709 "at location 1"));
710 }
711
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeIntVectorConflict)712 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
713 const std::string text = R"(
714 OpCapability Shader
715 OpCapability Int64
716 OpMemoryModel Logical GLSL450
717 OpEntryPoint Fragment %main "main" %var1 %var2
718 OpExecutionMode %main OriginUpperLeft
719 OpDecorate %var1 Location 0
720 OpDecorate %var1 Flat
721 OpDecorate %var2 Location 1
722 OpDecorate %var2 Flat
723 %void = OpTypeVoid
724 %void_fn = OpTypeFunction %void
725 %float = OpTypeFloat 32
726 %long = OpTypeInt 64 0
727 %vector = OpTypeVector %long 4
728 %ptr_input_float = OpTypePointer Input %float
729 %ptr_input_vector = OpTypePointer Input %vector
730 %var1 = OpVariable %ptr_input_vector Input
731 %var2 = OpVariable %ptr_input_float Input
732 %main = OpFunction %void None %void_fn
733 %entry = OpLabel
734 OpReturn
735 OpFunctionEnd
736 )";
737
738 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
739 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
740 EXPECT_THAT(getDiagnosticString(),
741 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
742 EXPECT_THAT(getDiagnosticString(),
743 HasSubstr("Entry-point has conflicting input location assignment "
744 "at location 1"));
745 }
746
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix2x2Conflict)747 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
748 const std::string text = R"(
749 OpCapability Shader
750 OpMemoryModel Logical GLSL450
751 OpEntryPoint Fragment %main "main" %var1 %var2
752 OpExecutionMode %main OriginUpperLeft
753 OpDecorate %var1 Location 0
754 OpDecorate %var2 Location 1
755 %void = OpTypeVoid
756 %void_fn = OpTypeFunction %void
757 %float = OpTypeFloat 32
758 %vector = OpTypeVector %float 2
759 %matrix = OpTypeMatrix %vector 2
760 %ptr_input_float = OpTypePointer Input %float
761 %ptr_input_matrix = OpTypePointer Input %matrix
762 %var1 = OpVariable %ptr_input_matrix Input
763 %var2 = OpVariable %ptr_input_float Input
764 %main = OpFunction %void None %void_fn
765 %entry = OpLabel
766 OpReturn
767 OpFunctionEnd
768 )";
769
770 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
771 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
772 EXPECT_THAT(getDiagnosticString(),
773 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
774 EXPECT_THAT(getDiagnosticString(),
775 HasSubstr("Entry-point has conflicting input location assignment "
776 "at location 1"));
777 }
778
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix3x3Conflict)779 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
780 const std::string text = R"(
781 OpCapability Shader
782 OpMemoryModel Logical GLSL450
783 OpEntryPoint Fragment %main "main" %var1 %var2
784 OpExecutionMode %main OriginUpperLeft
785 OpDecorate %var1 Location 0
786 OpDecorate %var2 Location 2
787 %void = OpTypeVoid
788 %void_fn = OpTypeFunction %void
789 %float = OpTypeFloat 32
790 %vector = OpTypeVector %float 3
791 %matrix = OpTypeMatrix %vector 3
792 %ptr_input_float = OpTypePointer Input %float
793 %ptr_input_matrix = OpTypePointer Input %matrix
794 %var1 = OpVariable %ptr_input_matrix Input
795 %var2 = OpVariable %ptr_input_float Input
796 %main = OpFunction %void None %void_fn
797 %entry = OpLabel
798 OpReturn
799 OpFunctionEnd
800 )";
801
802 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
803 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
804 EXPECT_THAT(getDiagnosticString(),
805 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
806 EXPECT_THAT(getDiagnosticString(),
807 HasSubstr("Entry-point has conflicting input location assignment "
808 "at location 2"));
809 }
810
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Conflict)811 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
812 const std::string text = R"(
813 OpCapability Shader
814 OpMemoryModel Logical GLSL450
815 OpEntryPoint Fragment %main "main" %var1 %var2
816 OpExecutionMode %main OriginUpperLeft
817 OpDecorate %var1 Location 0
818 OpDecorate %var2 Location 3
819 %void = OpTypeVoid
820 %void_fn = OpTypeFunction %void
821 %float = OpTypeFloat 32
822 %vector = OpTypeVector %float 4
823 %matrix = OpTypeMatrix %vector 4
824 %ptr_input_float = OpTypePointer Input %float
825 %ptr_input_matrix = OpTypePointer Input %matrix
826 %var1 = OpVariable %ptr_input_matrix Input
827 %var2 = OpVariable %ptr_input_float Input
828 %main = OpFunction %void None %void_fn
829 %entry = OpLabel
830 OpReturn
831 OpFunctionEnd
832 )";
833
834 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
835 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
836 EXPECT_THAT(getDiagnosticString(),
837 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
838 EXPECT_THAT(getDiagnosticString(),
839 HasSubstr("Entry-point has conflicting input location assignment "
840 "at location 3"));
841 }
842
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix2x2Conflict)843 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
844 const std::string text = R"(
845 OpCapability Shader
846 OpCapability Float64
847 OpMemoryModel Logical GLSL450
848 OpEntryPoint Fragment %main "main" %var1 %var2
849 OpExecutionMode %main OriginUpperLeft
850 OpDecorate %var1 Location 0
851 OpDecorate %var2 Location 1
852 %void = OpTypeVoid
853 %void_fn = OpTypeFunction %void
854 %float = OpTypeFloat 32
855 %double = OpTypeFloat 64
856 %vector = OpTypeVector %double 2
857 %matrix = OpTypeMatrix %vector 2
858 %ptr_input_float = OpTypePointer Input %float
859 %ptr_input_matrix = OpTypePointer Input %matrix
860 %var1 = OpVariable %ptr_input_matrix Input
861 %var2 = OpVariable %ptr_input_float Input
862 %main = OpFunction %void None %void_fn
863 %entry = OpLabel
864 OpReturn
865 OpFunctionEnd
866 )";
867
868 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
869 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
870 EXPECT_THAT(getDiagnosticString(),
871 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
872 EXPECT_THAT(getDiagnosticString(),
873 HasSubstr("Entry-point has conflicting input location assignment "
874 "at location 1"));
875 }
876
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix3x3Conflict)877 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
878 const std::string text = R"(
879 OpCapability Shader
880 OpCapability Float64
881 OpMemoryModel Logical GLSL450
882 OpEntryPoint Fragment %main "main" %var1 %var2
883 OpExecutionMode %main OriginUpperLeft
884 OpDecorate %var1 Location 0
885 OpDecorate %var2 Location 5
886 %void = OpTypeVoid
887 %void_fn = OpTypeFunction %void
888 %float = OpTypeFloat 32
889 %double = OpTypeFloat 64
890 %vector = OpTypeVector %double 3
891 %matrix = OpTypeMatrix %vector 3
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 5"));
909 }
910
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix4x4Conflict)911 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
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 7
920 %void = OpTypeVoid
921 %void_fn = OpTypeFunction %void
922 %float = OpTypeFloat 32
923 %double = OpTypeFloat 64
924 %vector = OpTypeVector %double 4
925 %matrix = OpTypeMatrix %vector 4
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 7"));
943 }
944
TEST_F(ValidateInterfacesTest,VulkanLocationsArray2Conflict)945 TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
946 const std::string text = R"(
947 OpCapability Shader
948 OpMemoryModel Logical GLSL450
949 OpEntryPoint Fragment %main "main" %var1 %var2
950 OpExecutionMode %main OriginUpperLeft
951 OpDecorate %var1 Location 0
952 OpDecorate %var2 Location 1
953 %void = OpTypeVoid
954 %void_fn = OpTypeFunction %void
955 %float = OpTypeFloat 32
956 %int = OpTypeInt 32 0
957 %int_2 = OpConstant %int 2
958 %array = OpTypeArray %int %int_2
959 %struct = OpTypeStruct %array
960 %ptr_input_float = OpTypePointer Input %float
961 %ptr_input_struct = OpTypePointer Input %struct
962 %var1 = OpVariable %ptr_input_struct 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 1"));
977 }
978
TEST_F(ValidateInterfacesTest,VulkanLocationsArray4Conflict)979 TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
980 const std::string text = R"(
981 OpCapability Shader
982 OpMemoryModel Logical GLSL450
983 OpEntryPoint Fragment %main "main" %var1 %var2
984 OpExecutionMode %main OriginUpperLeft
985 OpDecorate %var1 Location 0
986 OpDecorate %var2 Location 3
987 %void = OpTypeVoid
988 %void_fn = OpTypeFunction %void
989 %float = OpTypeFloat 32
990 %int = OpTypeInt 32 0
991 %int_4 = OpConstant %int 4
992 %array = OpTypeArray %int %int_4
993 %struct = OpTypeStruct %array
994 %ptr_input_float = OpTypePointer Input %float
995 %ptr_input_struct = OpTypePointer Input %struct
996 %var1 = OpVariable %ptr_input_struct 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 3"));
1011 }
1012
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Array4Conflict)1013 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
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 15
1021 %void = OpTypeVoid
1022 %void_fn = OpTypeFunction %void
1023 %float = OpTypeFloat 32
1024 %int = OpTypeInt 32 0
1025 %int_4 = OpConstant %int 4
1026 %vector = OpTypeVector %float 4
1027 %matrix = OpTypeMatrix %vector 4
1028 %array = OpTypeArray %matrix %int_4
1029 %struct = OpTypeStruct %array
1030 %ptr_input_float = OpTypePointer Input %float
1031 %ptr_input_struct = OpTypePointer Input %struct
1032 %var1 = OpVariable %ptr_input_struct Input
1033 %var2 = OpVariable %ptr_input_float 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_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1042 EXPECT_THAT(getDiagnosticString(),
1043 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1044 EXPECT_THAT(getDiagnosticString(),
1045 HasSubstr("Entry-point has conflicting input location assignment "
1046 "at location 15"));
1047 }
1048
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentDisambiguates)1049 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
1050 const std::string text = R"(
1051 OpCapability Shader
1052 OpMemoryModel Logical GLSL450
1053 OpEntryPoint Fragment %main "main" %var1
1054 OpExecutionMode %main OriginUpperLeft
1055 OpDecorate %struct Block
1056 OpMemberDecorate %struct 0 Location 0
1057 OpMemberDecorate %struct 0 Component 0
1058 OpMemberDecorate %struct 1 Location 0
1059 OpMemberDecorate %struct 1 Component 1
1060 %void = OpTypeVoid
1061 %void_fn = OpTypeFunction %void
1062 %float = OpTypeFloat 32
1063 %struct = OpTypeStruct %float %float
1064 %ptr_input_struct = OpTypePointer Input %struct
1065 %var1 = OpVariable %ptr_input_struct 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_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1074 }
1075
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentIn64BitVec3)1076 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
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 1
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_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1103 EXPECT_THAT(getDiagnosticString(),
1104 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08721"));
1105 EXPECT_THAT(getDiagnosticString(),
1106 HasSubstr("Entry-point has conflicting input location assignment "
1107 "at location 1, component 1"));
1108 }
1109
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentAfter64BitVec3)1110 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
1111 const std::string text = R"(
1112 OpCapability Shader
1113 OpCapability Float64
1114 OpMemoryModel Logical GLSL450
1115 OpEntryPoint Fragment %main "main" %var
1116 OpExecutionMode %main OriginUpperLeft
1117 OpDecorate %struct Block
1118 OpMemberDecorate %struct 0 Location 0
1119 OpMemberDecorate %struct 1 Location 1
1120 OpMemberDecorate %struct 1 Component 2
1121 %void = OpTypeVoid
1122 %void_fn = OpTypeFunction %void
1123 %float = OpTypeFloat 32
1124 %double = OpTypeFloat 64
1125 %double3 = OpTypeVector %double 3
1126 %struct = OpTypeStruct %double3 %float
1127 %ptr_input_struct = OpTypePointer Input %struct
1128 %var = OpVariable %ptr_input_struct Input
1129 %main = OpFunction %void None %void_fn
1130 %entry = OpLabel
1131 OpReturn
1132 OpFunctionEnd
1133 )";
1134
1135 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1136 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1137 }
1138
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentVariable)1139 TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
1140 const std::string text = R"(
1141 OpCapability Shader
1142 OpMemoryModel Logical GLSL450
1143 OpEntryPoint Fragment %main "main" %var
1144 OpExecutionMode %main OriginUpperLeft
1145 OpDecorate %var Location 0
1146 OpDecorate %var Component 0
1147 OpDecorate %var Component 1
1148 %void = OpTypeVoid
1149 %void_fn = OpTypeFunction %void
1150 %float = OpTypeFloat 32
1151 %ptr_input_float = OpTypePointer Input %float
1152 %var = OpVariable %ptr_input_float Input
1153 %main = OpFunction %void None %void_fn
1154 %entry = OpLabel
1155 OpReturn
1156 OpFunctionEnd
1157 )";
1158
1159 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1160 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1161 EXPECT_THAT(getDiagnosticString(),
1162 HasSubstr("Variable has conflicting component decorations"));
1163 }
1164
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentStructMember)1165 TEST_F(ValidateInterfacesTest,
1166 VulkanLocationsConflictingComponentStructMember) {
1167 const std::string text = R"(
1168 OpCapability Shader
1169 OpMemoryModel Logical GLSL450
1170 OpEntryPoint Fragment %main "main" %var
1171 OpExecutionMode %main OriginUpperLeft
1172 OpDecorate %struct Block
1173 OpMemberDecorate %struct 0 Location 0
1174 OpMemberDecorate %struct 0 Component 0
1175 OpMemberDecorate %struct 0 Component 1
1176 %void = OpTypeVoid
1177 %void_fn = OpTypeFunction %void
1178 %float = OpTypeFloat 32
1179 %struct = OpTypeStruct %float
1180 %ptr_input_struct = OpTypePointer Input %struct
1181 %var = OpVariable %ptr_input_struct Input
1182 %main = OpFunction %void None %void_fn
1183 %entry = OpLabel
1184 OpReturn
1185 OpFunctionEnd
1186 )";
1187
1188 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1189 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1190 EXPECT_THAT(
1191 getDiagnosticString(),
1192 HasSubstr("Member index 0 has conflicting component assignments"));
1193 }
1194
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutputIndex1)1195 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
1196 const std::string text = R"(
1197 OpCapability Shader
1198 OpMemoryModel Logical GLSL450
1199 OpEntryPoint Fragment %main "main" %var1 %var2
1200 OpExecutionMode %main OriginUpperLeft
1201 OpDecorate %var1 Location 1
1202 OpDecorate %var1 Index 1
1203 OpDecorate %var2 Location 1
1204 OpDecorate %var2 Index 1
1205 %void = OpTypeVoid
1206 %void_fn = OpTypeFunction %void
1207 %float = OpTypeFloat 32
1208 %struct = OpTypeStruct %float %float
1209 %ptr_output_struct = OpTypePointer Output %struct
1210 %var1 = OpVariable %ptr_output_struct Output
1211 %var2 = OpVariable %ptr_output_struct Output
1212 %main = OpFunction %void None %void_fn
1213 %entry = OpLabel
1214 OpReturn
1215 OpFunctionEnd
1216 )";
1217
1218 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1219 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1220 EXPECT_THAT(getDiagnosticString(),
1221 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
1222 EXPECT_THAT(
1223 getDiagnosticString(),
1224 HasSubstr("Entry-point has conflicting output location assignment "
1225 "at location 1"));
1226 }
1227
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableNoConflictDifferentIndex)1228 TEST_F(ValidateInterfacesTest,
1229 VulkanLocationsVariableNoConflictDifferentIndex) {
1230 const std::string text = R"(
1231 OpCapability Shader
1232 OpMemoryModel Logical GLSL450
1233 OpEntryPoint Fragment %main "main" %var1 %var2
1234 OpExecutionMode %main OriginUpperLeft
1235 OpDecorate %var1 Location 1
1236 OpDecorate %var1 Index 0
1237 OpDecorate %var2 Location 1
1238 OpDecorate %var2 Index 1
1239 %void = OpTypeVoid
1240 %void_fn = OpTypeFunction %void
1241 %float = OpTypeFloat 32
1242 %struct = OpTypeStruct %float %float
1243 %ptr_output_struct = OpTypePointer Output %struct
1244 %var1 = OpVariable %ptr_output_struct Output
1245 %var2 = OpVariable %ptr_output_struct Output
1246 %main = OpFunction %void None %void_fn
1247 %entry = OpLabel
1248 OpReturn
1249 OpFunctionEnd
1250 )";
1251
1252 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1253 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1254 }
1255
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexGLCompute)1256 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
1257 const std::string text = R"(
1258 OpCapability Shader
1259 OpCapability Geometry
1260 OpMemoryModel Logical GLSL450
1261 OpEntryPoint Geometry %main "main" %var1
1262 OpExecutionMode %main Triangles
1263 OpExecutionMode %main OutputPoints
1264 OpDecorate %var1 Location 1
1265 OpDecorate %var1 Index 1
1266 %void = OpTypeVoid
1267 %void_fn = OpTypeFunction %void
1268 %float = OpTypeFloat 32
1269 %struct = OpTypeStruct %float %float
1270 %ptr_output_struct = OpTypePointer Output %struct
1271 %var1 = OpVariable %ptr_output_struct Output
1272 %main = OpFunction %void None %void_fn
1273 %entry = OpLabel
1274 OpReturn
1275 OpFunctionEnd
1276 )";
1277
1278 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1279 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1280 EXPECT_THAT(
1281 getDiagnosticString(),
1282 HasSubstr("Index can only be applied to Fragment output variables"));
1283 }
1284
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexInput)1285 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
1286 const std::string text = R"(
1287 OpCapability Shader
1288 OpMemoryModel Logical GLSL450
1289 OpEntryPoint Fragment %main "main" %var1
1290 OpExecutionMode %main OriginUpperLeft
1291 OpDecorate %var1 Location 1
1292 OpDecorate %var1 Index 1
1293 %void = OpTypeVoid
1294 %void_fn = OpTypeFunction %void
1295 %float = OpTypeFloat 32
1296 %struct = OpTypeStruct %float %float
1297 %ptr_input_struct = OpTypePointer Input %struct
1298 %var1 = OpVariable %ptr_input_struct Input
1299 %main = OpFunction %void None %void_fn
1300 %entry = OpLabel
1301 OpReturn
1302 OpFunctionEnd
1303 )";
1304
1305 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1306 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1307 EXPECT_THAT(getDiagnosticString(),
1308 HasSubstr("must be in the Output storage class"));
1309 }
1310
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponent)1311 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
1312 const std::string text = R"(
1313 OpCapability Shader
1314 OpMemoryModel Logical GLSL450
1315 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1316 OpExecutionMode %4 OriginUpperLeft
1317 OpDecorate %11 Location 0
1318 OpDecorate %18 Component 0
1319 OpDecorate %18 Location 0
1320 OpDecorate %28 Component 1
1321 OpDecorate %28 Location 0
1322 OpDecorate %36 Location 1
1323 OpDecorate %40 Component 0
1324 OpDecorate %40 Location 1
1325 %void = OpTypeVoid
1326 %3 = OpTypeFunction %void
1327 %float = OpTypeFloat 32
1328 %v4float = OpTypeVector %float 4
1329 %_ptr_Input_v4float = OpTypePointer Input %v4float
1330 %11 = OpVariable %_ptr_Input_v4float Input
1331 %_ptr_Output_float = OpTypePointer Output %float
1332 %18 = OpVariable %_ptr_Output_float Output
1333 %uint = OpTypeInt 32 0
1334 %v3float = OpTypeVector %float 3
1335 %uint_2 = OpConstant %uint 2
1336 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1337 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1338 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1339 %_ptr_Output_v3float = OpTypePointer Output %v3float
1340 %36 = OpVariable %_ptr_Input_v4float Input
1341 %40 = OpVariable %_ptr_Output_float Output
1342 %4 = OpFunction %void None %3
1343 %5 = OpLabel
1344 OpReturn
1345 OpFunctionEnd
1346 )";
1347
1348 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1349 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1350 }
1351
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponentBad)1352 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
1353 const std::string text = R"(
1354 OpCapability Shader
1355 OpMemoryModel Logical GLSL450
1356 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1357 OpExecutionMode %4 OriginUpperLeft
1358 OpDecorate %11 Location 0
1359 OpDecorate %18 Component 0
1360 OpDecorate %18 Location 0
1361 OpDecorate %28 Component 1
1362 OpDecorate %28 Location 0
1363 OpDecorate %36 Location 1
1364 OpDecorate %40 Component 1
1365 OpDecorate %40 Location 1
1366 %void = OpTypeVoid
1367 %3 = OpTypeFunction %void
1368 %float = OpTypeFloat 32
1369 %v4float = OpTypeVector %float 4
1370 %_ptr_Input_v4float = OpTypePointer Input %v4float
1371 %11 = OpVariable %_ptr_Input_v4float Input
1372 %_ptr_Output_float = OpTypePointer Output %float
1373 %18 = OpVariable %_ptr_Output_float Output
1374 %uint = OpTypeInt 32 0
1375 %v3float = OpTypeVector %float 3
1376 %uint_2 = OpConstant %uint 2
1377 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1378 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1379 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1380 %_ptr_Output_v3float = OpTypePointer Output %v3float
1381 %36 = OpVariable %_ptr_Input_v4float Input
1382 %40 = OpVariable %_ptr_Output_float Output
1383 %4 = OpFunction %void None %3
1384 %5 = OpLabel
1385 OpReturn
1386 OpFunctionEnd
1387 )";
1388
1389 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1390 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1391 EXPECT_THAT(getDiagnosticString(),
1392 AnyVUID("VUID-StandaloneSpirv-OpEntryPoint-08722"));
1393 EXPECT_THAT(getDiagnosticString(),
1394 HasSubstr("Entry-point has conflicting output location "
1395 "assignment at location 1, component 1"));
1396 }
1397
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeLocation)1398 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
1399 const std::string text = R"(
1400 OpCapability Shader
1401 OpMemoryModel Logical GLSL450
1402 OpEntryPoint Fragment %4 "????????" %17
1403 OpExecutionMode %4 OriginUpperLeft
1404 OpDecorate %17 Location 4227868160
1405 %void = OpTypeVoid
1406 %3 = OpTypeFunction %void
1407 %float = OpTypeFloat 32
1408 %v3float = OpTypeVector %float 3
1409 %_ptr_Input_v3float = OpTypePointer Input %v3float
1410 %17 = OpVariable %_ptr_Input_v3float Input
1411 %4 = OpFunction %void None %3
1412 %5 = OpLabel
1413 OpUnreachable
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,VulkanLocationMeshShader)1421 TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
1422 const std::string text = R"(
1423 OpCapability Shader
1424 OpCapability MeshShadingNV
1425 OpExtension "SPV_NV_mesh_shader"
1426 OpMemoryModel Logical GLSL450
1427 OpEntryPoint MeshNV %foo "foo" %in
1428 OpExecutionMode %foo LocalSize 1 1 1
1429 OpDecorate %block Block
1430 OpMemberDecorate %block 0 PerTaskNV
1431 OpMemberDecorate %block 0 Offset 0
1432 %void = OpTypeVoid
1433 %int = OpTypeInt 32 0
1434 %int_32 = OpConstant %int 32
1435 %array = OpTypeArray %int %int_32
1436 %block = OpTypeStruct %array
1437 %ptr_input_block = OpTypePointer Input %block
1438 %in = OpVariable %ptr_input_block Input
1439 %void_fn = OpTypeFunction %void
1440 %foo = OpFunction %void None %void_fn
1441 %entry = OpLabel
1442 OpReturn
1443 OpFunctionEnd
1444 )";
1445
1446 CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
1447 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1448 }
1449
TEST_F(ValidateInterfacesTest,VulkanLocationArrayWithComponent1)1450 TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent1) {
1451 const std::string text = R"(
1452 OpCapability Shader
1453 OpMemoryModel Logical GLSL450
1454 OpEntryPoint Fragment %main "main" %in
1455 OpExecutionMode %main OriginUpperLeft
1456 OpDecorate %struct Block
1457 OpMemberDecorate %struct 0 Location 0
1458 OpMemberDecorate %struct 0 Component 0
1459 OpMemberDecorate %struct 1 Location 0
1460 OpMemberDecorate %struct 1 Component 1
1461 %void = OpTypeVoid
1462 %void_fn = OpTypeFunction %void
1463 %float = OpTypeFloat 32
1464 %int = OpTypeInt 32 0
1465 %int_2 = OpConstant %int 2
1466 %float_arr = OpTypeArray %float %int_2
1467 %struct = OpTypeStruct %float_arr %float_arr
1468 %ptr = OpTypePointer Input %struct
1469 %in = OpVariable %ptr Input
1470 %main = OpFunction %void None %void_fn
1471 %entry = OpLabel
1472 OpReturn
1473 OpFunctionEnd
1474 )";
1475
1476 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1477 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1478 }
1479
TEST_F(ValidateInterfacesTest,VulkanLocationArrayWithComponent2)1480 TEST_F(ValidateInterfacesTest, VulkanLocationArrayWithComponent2) {
1481 const std::string text = R"(
1482 OpCapability Shader
1483 OpCapability Float64
1484 OpMemoryModel Logical GLSL450
1485 OpEntryPoint Fragment %main "main" %in
1486 OpExecutionMode %main OriginUpperLeft
1487 OpDecorate %struct Block
1488 OpMemberDecorate %struct 0 Location 0
1489 OpMemberDecorate %struct 0 Component 0
1490 OpMemberDecorate %struct 1 Location 0
1491 OpMemberDecorate %struct 1 Component 2
1492 %void = OpTypeVoid
1493 %void_fn = OpTypeFunction %void
1494 %float = OpTypeFloat 32
1495 %double = OpTypeFloat 64
1496 %int = OpTypeInt 32 0
1497 %int_2 = OpConstant %int 2
1498 %double_arr = OpTypeArray %double %int_2
1499 %struct = OpTypeStruct %float %double_arr
1500 %ptr = OpTypePointer Input %struct
1501 %in = OpVariable %ptr Input
1502 %main = OpFunction %void None %void_fn
1503 %entry = OpLabel
1504 OpReturn
1505 OpFunctionEnd
1506 )";
1507
1508 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1509 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1510 }
1511
TEST_F(ValidateInterfacesTest,DuplicateInterfaceVariableSuccess)1512 TEST_F(ValidateInterfacesTest, DuplicateInterfaceVariableSuccess) {
1513 const std::string text = R"(
1514 OpCapability Shader
1515 OpMemoryModel Logical GLSL450
1516 OpEntryPoint Fragment %main "main" %in %out %in
1517 OpExecutionMode %main OriginUpperLeft
1518 OpDecorate %in Location 0
1519 OpDecorate %out Location 0
1520 %void = OpTypeVoid
1521 %float = OpTypeFloat 32
1522 %in_ptr = OpTypePointer Input %float
1523 %out_ptr = OpTypePointer Output %float
1524 %in = OpVariable %in_ptr Input
1525 %out = OpVariable %out_ptr Output
1526 %void_fn = OpTypeFunction %void
1527 %main = OpFunction %void None %void_fn
1528 %entry = OpLabel
1529 OpReturn
1530 OpFunctionEnd
1531 )";
1532
1533 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1534 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1535 }
1536
TEST_F(ValidateInterfacesTest,StructWithBuiltinsMissingBlock_Bad)1537 TEST_F(ValidateInterfacesTest, StructWithBuiltinsMissingBlock_Bad) {
1538 // See https://github.com/KhronosGroup/SPIRV-Registry/issues/134
1539 //
1540 // When a shader input or output is a struct that does not have Block,
1541 // then it must have a Location.
1542 // But BuiltIns must not have locations.
1543 const std::string text = R"(
1544 OpCapability Shader
1545 OpMemoryModel Logical GLSL450
1546 OpEntryPoint Fragment %main "main" %in
1547 OpExecutionMode %main OriginUpperLeft
1548 ; %struct needs a Block decoration
1549 OpMemberDecorate %struct 0 BuiltIn Position
1550 %void = OpTypeVoid
1551 %float = OpTypeFloat 32
1552 %v4float = OpTypeVector %float 4
1553 %struct = OpTypeStruct %v4float
1554 %in_ptr = OpTypePointer Input %struct
1555 %in = OpVariable %in_ptr Input
1556 %void_fn = OpTypeFunction %void
1557 %main = OpFunction %void None %void_fn
1558 %entry = OpLabel
1559 OpReturn
1560 OpFunctionEnd
1561 )";
1562
1563 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1564 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1565 EXPECT_THAT(getDiagnosticString(),
1566 AnyVUID("VUID-StandaloneSpirv-Location-04919"));
1567 EXPECT_THAT(
1568 getDiagnosticString(),
1569 HasSubstr(
1570 "Interface struct has no Block decoration but has BuiltIn members."));
1571 }
1572
TEST_F(ValidateInterfacesTest,InvalidLocationTypePointer)1573 TEST_F(ValidateInterfacesTest, InvalidLocationTypePointer) {
1574 const std::string text = R"(
1575 OpCapability Shader
1576 OpMemoryModel Logical Simple
1577 OpEntryPoint Vertex %1 "Aiqn0" %2 %3
1578 OpDecorate %2 Location 0
1579 %void = OpTypeVoid
1580 %5 = OpTypeFunction %void
1581 %float = OpTypeFloat 32
1582 %_ptr_Private_void = OpTypePointer Private %void
1583 %uint = OpTypeInt 32 0
1584 %uint_4278132784 = OpConstant %uint 4278132784
1585 %_arr__ptr_Private_void_uint_4278132784 = OpTypeArray %_ptr_Private_void %uint_4278132784
1586 %_ptr_Output__arr__ptr_Private_void_uint_4278132784 = OpTypePointer Output %_arr__ptr_Private_void_uint_4278132784
1587 %2 = OpVariable %_ptr_Output__arr__ptr_Private_void_uint_4278132784 Output
1588 %_ptr_Output__ptr_Private_void = OpTypePointer Output %_ptr_Private_void
1589 %3 = OpVariable %_ptr_Output__arr__ptr_Private_void_uint_4278132784 Output
1590 %1 = OpFunction %void None %5
1591 %15 = OpLabel
1592 OpReturn
1593 OpFunctionEnd
1594 )";
1595
1596 CompileSuccessfully(text, SPV_ENV_VULKAN_1_1);
1597 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_1));
1598 EXPECT_THAT(getDiagnosticString(),
1599 HasSubstr("Invalid type to assign a location"));
1600 }
1601
TEST_F(ValidateInterfacesTest,ValidLocationTypePhysicalStorageBufferPointer)1602 TEST_F(ValidateInterfacesTest, ValidLocationTypePhysicalStorageBufferPointer) {
1603 const std::string text = R"(
1604 OpCapability Shader
1605 OpCapability PhysicalStorageBufferAddresses
1606 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1607 OpEntryPoint Vertex %main "main" %var
1608 OpDecorate %var Location 0
1609 OpDecorate %var RestrictPointer
1610 %void = OpTypeVoid
1611 %int = OpTypeInt 32 0
1612 %ptr = OpTypePointer PhysicalStorageBuffer %int
1613 %ptr2 = OpTypePointer Input %ptr
1614 %var = OpVariable %ptr2 Input
1615 %void_fn = OpTypeFunction %void
1616 %main = OpFunction %void None %void_fn
1617 %entry = OpLabel
1618 OpReturn
1619 OpFunctionEnd
1620 )";
1621 CompileSuccessfully(text, SPV_ENV_VULKAN_1_3);
1622 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1623 }
1624
1625 } // namespace
1626 } // namespace val
1627 } // namespace spvtools
1628