1 // Copyright (c) 2018 Google LLC.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <string>
16
17 #include "gmock/gmock.h"
18 #include "test/unit_spirv.h"
19 #include "test/val/val_fixtures.h"
20
21 namespace spvtools {
22 namespace val {
23 namespace {
24
25 using ::testing::HasSubstr;
26
27 using ValidateInterfacesTest = spvtest::ValidateBase<bool>;
28
TEST_F(ValidateInterfacesTest,EntryPointMissingInput)29 TEST_F(ValidateInterfacesTest, EntryPointMissingInput) {
30 std::string text = R"(
31 OpCapability Shader
32 OpMemoryModel Logical GLSL450
33 OpEntryPoint Fragment %1 "func"
34 OpExecutionMode %1 OriginUpperLeft
35 %2 = OpTypeVoid
36 %3 = OpTypeInt 32 0
37 %4 = OpTypePointer Input %3
38 %5 = OpVariable %4 Input
39 %6 = OpTypeFunction %2
40 %1 = OpFunction %2 None %6
41 %7 = OpLabel
42 %8 = OpLoad %3 %5
43 OpReturn
44 OpFunctionEnd
45 )";
46
47 CompileSuccessfully(text);
48 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
49 EXPECT_THAT(
50 getDiagnosticString(),
51 HasSubstr(
52 "Interface variable id <5> is used by entry point 'func' id <1>, "
53 "but is not listed as an interface"));
54 }
55
TEST_F(ValidateInterfacesTest,EntryPointMissingOutput)56 TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) {
57 std::string text = R"(
58 OpCapability Shader
59 OpMemoryModel Logical GLSL450
60 OpEntryPoint Fragment %1 "func"
61 OpExecutionMode %1 OriginUpperLeft
62 %2 = OpTypeVoid
63 %3 = OpTypeInt 32 0
64 %4 = OpTypePointer Output %3
65 %5 = OpVariable %4 Output
66 %6 = OpTypeFunction %2
67 %1 = OpFunction %2 None %6
68 %7 = OpLabel
69 %8 = OpLoad %3 %5
70 OpReturn
71 OpFunctionEnd
72 )";
73
74 CompileSuccessfully(text);
75 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
76 EXPECT_THAT(
77 getDiagnosticString(),
78 HasSubstr(
79 "Interface variable id <5> is used by entry point 'func' id <1>, "
80 "but is not listed as an interface"));
81 }
82
TEST_F(ValidateInterfacesTest,InterfaceMissingUseInSubfunction)83 TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) {
84 std::string text = R"(
85 OpCapability Shader
86 OpMemoryModel Logical GLSL450
87 OpEntryPoint Fragment %1 "func"
88 OpExecutionMode %1 OriginUpperLeft
89 %2 = OpTypeVoid
90 %3 = OpTypeInt 32 0
91 %4 = OpTypePointer Input %3
92 %5 = OpVariable %4 Input
93 %6 = OpTypeFunction %2
94 %1 = OpFunction %2 None %6
95 %7 = OpLabel
96 %8 = OpFunctionCall %2 %9
97 OpReturn
98 OpFunctionEnd
99 %9 = OpFunction %2 None %6
100 %10 = OpLabel
101 %11 = OpLoad %3 %5
102 OpReturn
103 OpFunctionEnd
104 )";
105
106 CompileSuccessfully(text);
107 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
108 EXPECT_THAT(
109 getDiagnosticString(),
110 HasSubstr(
111 "Interface variable id <5> is used by entry point 'func' id <1>, "
112 "but is not listed as an interface"));
113 }
114
TEST_F(ValidateInterfacesTest,TwoEntryPointsOneFunction)115 TEST_F(ValidateInterfacesTest, TwoEntryPointsOneFunction) {
116 std::string text = R"(
117 OpCapability Shader
118 OpMemoryModel Logical GLSL450
119 OpEntryPoint Fragment %1 "func" %2
120 OpEntryPoint Fragment %1 "func2"
121 OpExecutionMode %1 OriginUpperLeft
122 %3 = OpTypeVoid
123 %4 = OpTypeInt 32 0
124 %5 = OpTypePointer Input %4
125 %2 = OpVariable %5 Input
126 %6 = OpTypeFunction %3
127 %1 = OpFunction %3 None %6
128 %7 = OpLabel
129 %8 = OpLoad %4 %2
130 OpReturn
131 OpFunctionEnd
132 )";
133
134 CompileSuccessfully(text);
135 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
136 EXPECT_THAT(
137 getDiagnosticString(),
138 HasSubstr(
139 "Interface variable id <2> is used by entry point 'func2' id <1>, "
140 "but is not listed as an interface"));
141 }
142
TEST_F(ValidateInterfacesTest,MissingInterfaceThroughInitializer)143 TEST_F(ValidateInterfacesTest, MissingInterfaceThroughInitializer) {
144 const std::string text = R"(
145 OpCapability Shader
146 OpCapability VariablePointers
147 OpMemoryModel Logical GLSL450
148 OpEntryPoint Fragment %1 "func"
149 OpExecutionMode %1 OriginUpperLeft
150 %2 = OpTypeVoid
151 %3 = OpTypeInt 32 0
152 %4 = OpTypePointer Input %3
153 %5 = OpTypePointer Function %4
154 %6 = OpVariable %4 Input
155 %7 = OpTypeFunction %2
156 %1 = OpFunction %2 None %7
157 %8 = OpLabel
158 %9 = OpVariable %5 Function %6
159 OpReturn
160 OpFunctionEnd
161 )";
162
163 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
164 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
165 EXPECT_THAT(
166 getDiagnosticString(),
167 HasSubstr(
168 "Interface variable id <6> is used by entry point 'func' id <1>, "
169 "but is not listed as an interface"));
170 }
171
TEST_F(ValidateInterfacesTest,NonUniqueInterfacesSPV1p3)172 TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p3) {
173 const std::string text = R"(
174 OpCapability Shader
175 OpMemoryModel Logical GLSL450
176 OpEntryPoint GLCompute %main "main" %var %var
177 OpExecutionMode %main LocalSize 1 1 1
178 %void = OpTypeVoid
179 %uint = OpTypeInt 32 0
180 %uint3 = OpTypeVector %uint 3
181 %struct = OpTypeStruct %uint3
182 %ptr_struct = OpTypePointer Input %struct
183 %var = OpVariable %ptr_struct Input
184 %func_ty = OpTypeFunction %void
185 %main = OpFunction %void None %func_ty
186 %1 = OpLabel
187 OpReturn
188 OpFunctionEnd
189 )";
190
191 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
192 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
193 }
194
TEST_F(ValidateInterfacesTest,NonUniqueInterfacesSPV1p4)195 TEST_F(ValidateInterfacesTest, NonUniqueInterfacesSPV1p4) {
196 const std::string text = R"(
197 OpCapability Shader
198 OpMemoryModel Logical GLSL450
199 OpEntryPoint GLCompute %main "main" %var %var
200 OpExecutionMode %main LocalSize 1 1 1
201 OpName %main "main"
202 OpName %var "var"
203 %void = OpTypeVoid
204 %uint = OpTypeInt 32 0
205 %uint3 = OpTypeVector %uint 3
206 %struct = OpTypeStruct %uint3
207 %ptr_struct = OpTypePointer Input %struct
208 %var = OpVariable %ptr_struct Input
209 %func_ty = OpTypeFunction %void
210 %main = OpFunction %void None %func_ty
211 %1 = OpLabel
212 OpReturn
213 OpFunctionEnd
214 )";
215
216 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
217 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
218 EXPECT_THAT(
219 getDiagnosticString(),
220 HasSubstr("Non-unique OpEntryPoint interface 2[%var] is disallowed"));
221 }
222
TEST_F(ValidateInterfacesTest,MissingGlobalVarSPV1p3)223 TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p3) {
224 const std::string text = R"(
225 OpCapability Shader
226 OpMemoryModel Logical GLSL450
227 OpEntryPoint GLCompute %main "main"
228 OpExecutionMode %main LocalSize 1 1 1
229 %void = OpTypeVoid
230 %uint = OpTypeInt 32 0
231 %uint3 = OpTypeVector %uint 3
232 %struct = OpTypeStruct %uint3
233 %ptr_struct = OpTypePointer StorageBuffer %struct
234 %var = OpVariable %ptr_struct StorageBuffer
235 %func_ty = OpTypeFunction %void
236 %main = OpFunction %void None %func_ty
237 %1 = OpLabel
238 %ld = OpLoad %struct %var
239 OpReturn
240 OpFunctionEnd
241 )";
242
243 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
244 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
245 }
246
TEST_F(ValidateInterfacesTest,MissingGlobalVarSPV1p4)247 TEST_F(ValidateInterfacesTest, MissingGlobalVarSPV1p4) {
248 const std::string text = R"(
249 OpCapability Shader
250 OpMemoryModel Logical GLSL450
251 OpEntryPoint GLCompute %main "main"
252 OpExecutionMode %main LocalSize 1 1 1
253 OpName %var "var"
254 %void = OpTypeVoid
255 %uint = OpTypeInt 32 0
256 %uint3 = OpTypeVector %uint 3
257 %struct = OpTypeStruct %uint3
258 %ptr_struct = OpTypePointer StorageBuffer %struct
259 %var = OpVariable %ptr_struct StorageBuffer
260 %func_ty = OpTypeFunction %void
261 %main = OpFunction %void None %func_ty
262 %1 = OpLabel
263 %ld = OpLoad %struct %var
264 OpReturn
265 OpFunctionEnd
266 )";
267
268 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
269 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
270 EXPECT_THAT(getDiagnosticString(),
271 HasSubstr("Interface variable id <2> is used by entry point "
272 "'main' id <1>, but is not listed as an interface"));
273 }
274
TEST_F(ValidateInterfacesTest,FunctionInterfaceVarSPV1p3)275 TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p3) {
276 const std::string text = R"(
277 OpCapability Shader
278 OpMemoryModel Logical GLSL450
279 OpEntryPoint GLCompute %main "main" %var
280 OpExecutionMode %main LocalSize 1 1 1
281 OpName %var "var"
282 %void = OpTypeVoid
283 %uint = OpTypeInt 32 0
284 %uint3 = OpTypeVector %uint 3
285 %struct = OpTypeStruct %uint3
286 %ptr_struct = OpTypePointer Function %struct
287 %func_ty = OpTypeFunction %void
288 %main = OpFunction %void None %func_ty
289 %1 = OpLabel
290 %var = OpVariable %ptr_struct Function
291 OpReturn
292 OpFunctionEnd
293 )";
294
295 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
296 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
297 EXPECT_THAT(getDiagnosticString(),
298 HasSubstr("OpEntryPoint interfaces must be OpVariables with "
299 "Storage Class of Input(1) or Output(3). Found Storage "
300 "Class 7 for Entry Point id 1."));
301 }
302
TEST_F(ValidateInterfacesTest,FunctionInterfaceVarSPV1p4)303 TEST_F(ValidateInterfacesTest, FunctionInterfaceVarSPV1p4) {
304 const std::string text = R"(
305 OpCapability Shader
306 OpMemoryModel Logical GLSL450
307 OpEntryPoint GLCompute %main "main" %var
308 OpExecutionMode %main LocalSize 1 1 1
309 OpName %var "var"
310 %void = OpTypeVoid
311 %uint = OpTypeInt 32 0
312 %uint3 = OpTypeVector %uint 3
313 %struct = OpTypeStruct %uint3
314 %ptr_struct = OpTypePointer Function %struct
315 %func_ty = OpTypeFunction %void
316 %main = OpFunction %void None %func_ty
317 %1 = OpLabel
318 %var = OpVariable %ptr_struct Function
319 OpReturn
320 OpFunctionEnd
321 )";
322
323 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
324 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
325 EXPECT_THAT(
326 getDiagnosticString(),
327 HasSubstr("OpEntryPoint interfaces should only list global variables"));
328 }
329
TEST_F(ValidateInterfacesTest,ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals)330 TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_NotAllUsedGlobals) {
331 const std::string text = R"(
332 OpCapability Shader
333 OpMemoryModel Logical GLSL450
334 OpEntryPoint GLCompute %main "main"
335 OpExecutionMode %main LocalSize 1 1 1
336 OpName %var "var"
337 %void = OpTypeVoid
338 %uint = OpTypeInt 32 0
339 %uint3 = OpTypeVector %uint 3
340 %struct = OpTypeStruct %uint3
341 %ptr_struct = OpTypePointer StorageBuffer %struct
342 %var = OpVariable %ptr_struct StorageBuffer
343 %func_ty = OpTypeFunction %void
344 %main = OpFunction %void None %func_ty
345 %1 = OpLabel
346 %ld = OpLoad %struct %var
347 OpReturn
348 OpFunctionEnd
349 )";
350
351 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
352 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
353 }
354
TEST_F(ValidateInterfacesTest,ModuleSPV1p3ValidateSPV1p4_DuplicateInterface)355 TEST_F(ValidateInterfacesTest, ModuleSPV1p3ValidateSPV1p4_DuplicateInterface) {
356 const std::string text = R"(
357 OpCapability Shader
358 OpMemoryModel Logical GLSL450
359 OpEntryPoint GLCompute %main "main" %gid %gid
360 OpExecutionMode %main LocalSize 1 1 1
361 OpDecorate %gid BuiltIn GlobalInvocationId
362 %void = OpTypeVoid
363 %int = OpTypeInt 32 0
364 %int3 = OpTypeVector %int 3
365 %ptr_input_int3 = OpTypePointer Input %int3
366 %gid = OpVariable %ptr_input_int3 Input
367 %void_fn = OpTypeFunction %void
368 %main = OpFunction %void None %void_fn
369 %entry = OpLabel
370 OpReturn
371 OpFunctionEnd
372 )";
373
374 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
375 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
376 }
377
TEST_F(ValidateInterfacesTest,SPV14MultipleEntryPointsSameFunction)378 TEST_F(ValidateInterfacesTest, SPV14MultipleEntryPointsSameFunction) {
379 const std::string text = R"(
380 OpCapability Shader
381 OpMemoryModel Logical GLSL450
382 OpEntryPoint GLCompute %main "main1" %gid
383 OpEntryPoint GLCompute %main "main2" %gid
384 OpExecutionMode %main LocalSize 1 1 1
385 OpDecorate %gid BuiltIn GlobalInvocationId
386 %void = OpTypeVoid
387 %int = OpTypeInt 32 0
388 %int3 = OpTypeVector %int 3
389 %ptr_input_int3 = OpTypePointer Input %int3
390 %gid = OpVariable %ptr_input_int3 Input
391 %void_fn = OpTypeFunction %void
392 %main = OpFunction %void None %void_fn
393 %entry = OpLabel
394 OpReturn
395 OpFunctionEnd
396 )";
397
398 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_4);
399 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
400 }
401
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentVariable)402 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentVariable) {
403 const std::string text = R"(
404 OpCapability Shader
405 OpMemoryModel Logical GLSL450
406 OpEntryPoint Fragment %main "main" %var
407 OpExecutionMode %main OriginUpperLeft
408 OpDecorate %var Location 0
409 OpDecorate %var Location 1
410 %void = OpTypeVoid
411 %void_fn = OpTypeFunction %void
412 %float = OpTypeFloat 32
413 %ptr_input_float = OpTypePointer Input %float
414 %var = OpVariable %ptr_input_float Input
415 %main = OpFunction %void None %void_fn
416 %entry = OpLabel
417 OpReturn
418 OpFunctionEnd
419 )";
420
421 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
422 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
423 EXPECT_THAT(getDiagnosticString(),
424 HasSubstr("Variable has conflicting location decorations"));
425 }
426
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableAndMemberAssigned)427 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableAndMemberAssigned) {
428 const std::string text = R"(
429 OpCapability Shader
430 OpMemoryModel Logical GLSL450
431 OpEntryPoint Fragment %main "main" %var
432 OpExecutionMode %main OriginUpperLeft
433 OpDecorate %var Location 0
434 OpDecorate %struct Block
435 OpMemberDecorate %struct 0 Location 0
436 %void = OpTypeVoid
437 %void_fn = OpTypeFunction %void
438 %float = OpTypeFloat 32
439 %struct = OpTypeStruct %float
440 %ptr_input_struct = OpTypePointer Input %struct
441 %var = OpVariable %ptr_input_struct Input
442 %main = OpFunction %void None %void_fn
443 %entry = OpLabel
444 OpReturn
445 OpFunctionEnd
446 )";
447
448 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
449 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
450 EXPECT_THAT(getDiagnosticString(),
451 HasSubstr("Members cannot be assigned a location"));
452 }
453
TEST_F(ValidateInterfacesTest,VulkanLocationsMemberAndSubMemberAssigned)454 TEST_F(ValidateInterfacesTest, VulkanLocationsMemberAndSubMemberAssigned) {
455 const std::string text = R"(
456 OpCapability Shader
457 OpMemoryModel Logical GLSL450
458 OpEntryPoint Fragment %main "main" %var
459 OpExecutionMode %main OriginUpperLeft
460 OpDecorate %outer Block
461 OpMemberDecorate %outer 0 Location 0
462 OpMemberDecorate %struct 0 Location 0
463 %void = OpTypeVoid
464 %void_fn = OpTypeFunction %void
465 %float = OpTypeFloat 32
466 %struct = OpTypeStruct %float
467 %outer = OpTypeStruct %struct
468 %ptr_input_outer = OpTypePointer Input %outer
469 %var = OpVariable %ptr_input_outer Input
470 %main = OpFunction %void None %void_fn
471 %entry = OpLabel
472 OpReturn
473 OpFunctionEnd
474 )";
475
476 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
477 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
478 EXPECT_THAT(getDiagnosticString(),
479 HasSubstr("Members cannot be assigned a location"));
480 }
481
TEST_F(ValidateInterfacesTest,VulkanLocationsDoubleAssignmentStructMember)482 TEST_F(ValidateInterfacesTest, VulkanLocationsDoubleAssignmentStructMember) {
483 const std::string text = R"(
484 OpCapability Shader
485 OpMemoryModel Logical GLSL450
486 OpEntryPoint Fragment %main "main" %var
487 OpExecutionMode %main OriginUpperLeft
488 OpDecorate %struct Block
489 OpMemberDecorate %struct 1 Location 0
490 OpMemberDecorate %struct 1 Location 1
491 %void = OpTypeVoid
492 %void_fn = OpTypeFunction %void
493 %float = OpTypeFloat 32
494 %struct = OpTypeStruct %float %float
495 %ptr_input_struct = OpTypePointer Input %struct
496 %var = OpVariable %ptr_input_struct Input
497 %main = OpFunction %void None %void_fn
498 %entry = OpLabel
499 OpReturn
500 OpFunctionEnd
501 )";
502
503 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
504 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
505 EXPECT_THAT(getDiagnosticString(),
506 HasSubstr("Member index 1 has conflicting location assignments"));
507 }
508
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentStructMember)509 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentStructMember) {
510 const std::string text = R"(
511 OpCapability Shader
512 OpMemoryModel Logical GLSL450
513 OpEntryPoint Fragment %main "main" %var
514 OpExecutionMode %main OriginUpperLeft
515 OpDecorate %struct Block
516 OpMemberDecorate %struct 1 Location 1
517 %void = OpTypeVoid
518 %void_fn = OpTypeFunction %void
519 %float = OpTypeFloat 32
520 %struct = OpTypeStruct %float %float
521 %ptr_input_struct = OpTypePointer Input %struct
522 %var = OpVariable %ptr_input_struct Input
523 %main = OpFunction %void None %void_fn
524 %entry = OpLabel
525 OpReturn
526 OpFunctionEnd
527 )";
528
529 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
530 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
531 EXPECT_THAT(getDiagnosticString(),
532 HasSubstr("Member index 0 is missing a location assignment"));
533 }
534
TEST_F(ValidateInterfacesTest,VulkanLocationsMissingAssignmentNonBlockStruct)535 TEST_F(ValidateInterfacesTest, VulkanLocationsMissingAssignmentNonBlockStruct) {
536 const std::string text = R"(
537 OpCapability Shader
538 OpMemoryModel Logical GLSL450
539 OpEntryPoint Fragment %main "main" %var
540 OpExecutionMode %main OriginUpperLeft
541 %void = OpTypeVoid
542 %void_fn = OpTypeFunction %void
543 %float = OpTypeFloat 32
544 %struct = OpTypeStruct %float %float
545 %ptr_input_struct = OpTypePointer Input %struct
546 %var = OpVariable %ptr_input_struct Input
547 %main = OpFunction %void None %void_fn
548 %entry = OpLabel
549 OpReturn
550 OpFunctionEnd
551 )";
552
553 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
554 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
555 EXPECT_THAT(getDiagnosticString(),
556 HasSubstr("Variable must be decorated with a location"));
557 }
558
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictInput)559 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictInput) {
560 const std::string text = R"(
561 OpCapability Shader
562 OpMemoryModel Logical GLSL450
563 OpEntryPoint Fragment %main "main" %var1 %var2
564 OpExecutionMode %main OriginUpperLeft
565 OpDecorate %var1 Location 0
566 OpDecorate %var2 Location 0
567 %void = OpTypeVoid
568 %void_fn = OpTypeFunction %void
569 %float = OpTypeFloat 32
570 %struct = OpTypeStruct %float %float
571 %ptr_input_struct = OpTypePointer Input %struct
572 %var1 = OpVariable %ptr_input_struct Input
573 %var2 = OpVariable %ptr_input_struct Input
574 %main = OpFunction %void None %void_fn
575 %entry = OpLabel
576 OpReturn
577 OpFunctionEnd
578 )";
579
580 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
581 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
582 EXPECT_THAT(getDiagnosticString(),
583 HasSubstr("Entry-point has conflicting input location assignment "
584 "at location 0"));
585 }
586
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutput)587 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutput) {
588 const std::string text = R"(
589 OpCapability Shader
590 OpMemoryModel Logical GLSL450
591 OpEntryPoint Fragment %main "main" %var1 %var2
592 OpExecutionMode %main OriginUpperLeft
593 OpDecorate %var1 Location 1
594 OpDecorate %var2 Location 1
595 %void = OpTypeVoid
596 %void_fn = OpTypeFunction %void
597 %float = OpTypeFloat 32
598 %struct = OpTypeStruct %float %float
599 %ptr_output_struct = OpTypePointer Output %struct
600 %var1 = OpVariable %ptr_output_struct Output
601 %var2 = OpVariable %ptr_output_struct Output
602 %main = OpFunction %void None %void_fn
603 %entry = OpLabel
604 OpReturn
605 OpFunctionEnd
606 )";
607
608 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
609 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
610 EXPECT_THAT(
611 getDiagnosticString(),
612 HasSubstr("Entry-point has conflicting output location assignment "
613 "at location 1"));
614 }
615
TEST_F(ValidateInterfacesTest,VulkanLocationsSameLocationInputAndOutputNoConflict)616 TEST_F(ValidateInterfacesTest,
617 VulkanLocationsSameLocationInputAndOutputNoConflict) {
618 const std::string text = R"(
619 OpCapability Shader
620 OpMemoryModel Logical GLSL450
621 OpEntryPoint Fragment %main "main" %var1 %var2
622 OpExecutionMode %main OriginUpperLeft
623 OpDecorate %var1 Location 1
624 OpDecorate %var2 Location 1
625 %void = OpTypeVoid
626 %void_fn = OpTypeFunction %void
627 %float = OpTypeFloat 32
628 %struct = OpTypeStruct %float %float
629 %ptr_input_struct = OpTypePointer Input %struct
630 %ptr_output_struct = OpTypePointer Output %struct
631 %var1 = OpVariable %ptr_input_struct Input
632 %var2 = OpVariable %ptr_output_struct Output
633 %main = OpFunction %void None %void_fn
634 %entry = OpLabel
635 OpReturn
636 OpFunctionEnd
637 )";
638
639 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
640 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
641 }
642
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableInGap)643 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableInGap) {
644 const std::string text = R"(
645 OpCapability Shader
646 OpMemoryModel Logical GLSL450
647 OpEntryPoint Fragment %main "main" %var1 %var2
648 OpExecutionMode %main OriginUpperLeft
649 OpDecorate %struct Block
650 OpMemberDecorate %struct 0 Location 0
651 OpMemberDecorate %struct 1 Location 2
652 OpDecorate %var2 Location 1
653 %void = OpTypeVoid
654 %void_fn = OpTypeFunction %void
655 %float = OpTypeFloat 32
656 %struct = OpTypeStruct %float %float
657 %ptr_input_struct = OpTypePointer Input %struct
658 %ptr_input_float = OpTypePointer Input %float
659 %var1 = OpVariable %ptr_input_struct Input
660 %var2 = OpVariable %ptr_input_float Input
661 %main = OpFunction %void None %void_fn
662 %entry = OpLabel
663 OpReturn
664 OpFunctionEnd
665 )";
666
667 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
668 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
669 }
670
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeFloatVectorConflict)671 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeFloatVectorConflict) {
672 const std::string text = R"(
673 OpCapability Shader
674 OpCapability Float64
675 OpMemoryModel Logical GLSL450
676 OpEntryPoint Fragment %main "main" %var1 %var2
677 OpExecutionMode %main OriginUpperLeft
678 OpDecorate %var1 Location 0
679 OpDecorate %var2 Location 1
680 %void = OpTypeVoid
681 %void_fn = OpTypeFunction %void
682 %float = OpTypeFloat 32
683 %double = OpTypeFloat 64
684 %vector = OpTypeVector %double 3
685 %ptr_input_float = OpTypePointer Input %float
686 %ptr_input_vector = OpTypePointer Input %vector
687 %var1 = OpVariable %ptr_input_vector Input
688 %var2 = OpVariable %ptr_input_float Input
689 %main = OpFunction %void None %void_fn
690 %entry = OpLabel
691 OpReturn
692 OpFunctionEnd
693 )";
694
695 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
696 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
697 EXPECT_THAT(getDiagnosticString(),
698 HasSubstr("Entry-point has conflicting input location assignment "
699 "at location 1"));
700 }
701
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeIntVectorConflict)702 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeIntVectorConflict) {
703 const std::string text = R"(
704 OpCapability Shader
705 OpCapability Int64
706 OpMemoryModel Logical GLSL450
707 OpEntryPoint Fragment %main "main" %var1 %var2
708 OpExecutionMode %main OriginUpperLeft
709 OpDecorate %var1 Location 0
710 OpDecorate %var2 Location 1
711 %void = OpTypeVoid
712 %void_fn = OpTypeFunction %void
713 %float = OpTypeFloat 32
714 %long = OpTypeInt 64 0
715 %vector = OpTypeVector %long 4
716 %ptr_input_float = OpTypePointer Input %float
717 %ptr_input_vector = OpTypePointer Input %vector
718 %var1 = OpVariable %ptr_input_vector Input
719 %var2 = OpVariable %ptr_input_float Input
720 %main = OpFunction %void None %void_fn
721 %entry = OpLabel
722 OpReturn
723 OpFunctionEnd
724 )";
725
726 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
727 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
728 EXPECT_THAT(getDiagnosticString(),
729 HasSubstr("Entry-point has conflicting input location assignment "
730 "at location 1"));
731 }
732
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix2x2Conflict)733 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix2x2Conflict) {
734 const std::string text = R"(
735 OpCapability Shader
736 OpMemoryModel Logical GLSL450
737 OpEntryPoint Fragment %main "main" %var1 %var2
738 OpExecutionMode %main OriginUpperLeft
739 OpDecorate %var1 Location 0
740 OpDecorate %var2 Location 1
741 %void = OpTypeVoid
742 %void_fn = OpTypeFunction %void
743 %float = OpTypeFloat 32
744 %vector = OpTypeVector %float 2
745 %matrix = OpTypeMatrix %vector 2
746 %ptr_input_float = OpTypePointer Input %float
747 %ptr_input_matrix = OpTypePointer Input %matrix
748 %var1 = OpVariable %ptr_input_matrix Input
749 %var2 = OpVariable %ptr_input_float Input
750 %main = OpFunction %void None %void_fn
751 %entry = OpLabel
752 OpReturn
753 OpFunctionEnd
754 )";
755
756 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
757 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
758 EXPECT_THAT(getDiagnosticString(),
759 HasSubstr("Entry-point has conflicting input location assignment "
760 "at location 1"));
761 }
762
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix3x3Conflict)763 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix3x3Conflict) {
764 const std::string text = R"(
765 OpCapability Shader
766 OpMemoryModel Logical GLSL450
767 OpEntryPoint Fragment %main "main" %var1 %var2
768 OpExecutionMode %main OriginUpperLeft
769 OpDecorate %var1 Location 0
770 OpDecorate %var2 Location 2
771 %void = OpTypeVoid
772 %void_fn = OpTypeFunction %void
773 %float = OpTypeFloat 32
774 %vector = OpTypeVector %float 3
775 %matrix = OpTypeMatrix %vector 3
776 %ptr_input_float = OpTypePointer Input %float
777 %ptr_input_matrix = OpTypePointer Input %matrix
778 %var1 = OpVariable %ptr_input_matrix Input
779 %var2 = OpVariable %ptr_input_float Input
780 %main = OpFunction %void None %void_fn
781 %entry = OpLabel
782 OpReturn
783 OpFunctionEnd
784 )";
785
786 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
787 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
788 EXPECT_THAT(getDiagnosticString(),
789 HasSubstr("Entry-point has conflicting input location assignment "
790 "at location 2"));
791 }
792
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Conflict)793 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Conflict) {
794 const std::string text = R"(
795 OpCapability Shader
796 OpMemoryModel Logical GLSL450
797 OpEntryPoint Fragment %main "main" %var1 %var2
798 OpExecutionMode %main OriginUpperLeft
799 OpDecorate %var1 Location 0
800 OpDecorate %var2 Location 3
801 %void = OpTypeVoid
802 %void_fn = OpTypeFunction %void
803 %float = OpTypeFloat 32
804 %vector = OpTypeVector %float 4
805 %matrix = OpTypeMatrix %vector 4
806 %ptr_input_float = OpTypePointer Input %float
807 %ptr_input_matrix = OpTypePointer Input %matrix
808 %var1 = OpVariable %ptr_input_matrix Input
809 %var2 = OpVariable %ptr_input_float Input
810 %main = OpFunction %void None %void_fn
811 %entry = OpLabel
812 OpReturn
813 OpFunctionEnd
814 )";
815
816 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
817 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
818 EXPECT_THAT(getDiagnosticString(),
819 HasSubstr("Entry-point has conflicting input location assignment "
820 "at location 3"));
821 }
822
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix2x2Conflict)823 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix2x2Conflict) {
824 const std::string text = R"(
825 OpCapability Shader
826 OpCapability Float64
827 OpMemoryModel Logical GLSL450
828 OpEntryPoint Fragment %main "main" %var1 %var2
829 OpExecutionMode %main OriginUpperLeft
830 OpDecorate %var1 Location 0
831 OpDecorate %var2 Location 1
832 %void = OpTypeVoid
833 %void_fn = OpTypeFunction %void
834 %float = OpTypeFloat 32
835 %double = OpTypeFloat 64
836 %vector = OpTypeVector %double 2
837 %matrix = OpTypeMatrix %vector 2
838 %ptr_input_float = OpTypePointer Input %float
839 %ptr_input_matrix = OpTypePointer Input %matrix
840 %var1 = OpVariable %ptr_input_matrix Input
841 %var2 = OpVariable %ptr_input_float Input
842 %main = OpFunction %void None %void_fn
843 %entry = OpLabel
844 OpReturn
845 OpFunctionEnd
846 )";
847
848 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
849 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
850 EXPECT_THAT(getDiagnosticString(),
851 HasSubstr("Entry-point has conflicting input location assignment "
852 "at location 1"));
853 }
854
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix3x3Conflict)855 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix3x3Conflict) {
856 const std::string text = R"(
857 OpCapability Shader
858 OpCapability Float64
859 OpMemoryModel Logical GLSL450
860 OpEntryPoint Fragment %main "main" %var1 %var2
861 OpExecutionMode %main OriginUpperLeft
862 OpDecorate %var1 Location 0
863 OpDecorate %var2 Location 5
864 %void = OpTypeVoid
865 %void_fn = OpTypeFunction %void
866 %float = OpTypeFloat 32
867 %double = OpTypeFloat 64
868 %vector = OpTypeVector %double 3
869 %matrix = OpTypeMatrix %vector 3
870 %ptr_input_float = OpTypePointer Input %float
871 %ptr_input_matrix = OpTypePointer Input %matrix
872 %var1 = OpVariable %ptr_input_matrix Input
873 %var2 = OpVariable %ptr_input_float Input
874 %main = OpFunction %void None %void_fn
875 %entry = OpLabel
876 OpReturn
877 OpFunctionEnd
878 )";
879
880 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
881 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
882 EXPECT_THAT(getDiagnosticString(),
883 HasSubstr("Entry-point has conflicting input location assignment "
884 "at location 5"));
885 }
886
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeMatrix4x4Conflict)887 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeMatrix4x4Conflict) {
888 const std::string text = R"(
889 OpCapability Shader
890 OpCapability Float64
891 OpMemoryModel Logical GLSL450
892 OpEntryPoint Fragment %main "main" %var1 %var2
893 OpExecutionMode %main OriginUpperLeft
894 OpDecorate %var1 Location 0
895 OpDecorate %var2 Location 7
896 %void = OpTypeVoid
897 %void_fn = OpTypeFunction %void
898 %float = OpTypeFloat 32
899 %double = OpTypeFloat 64
900 %vector = OpTypeVector %double 4
901 %matrix = OpTypeMatrix %vector 4
902 %ptr_input_float = OpTypePointer Input %float
903 %ptr_input_matrix = OpTypePointer Input %matrix
904 %var1 = OpVariable %ptr_input_matrix Input
905 %var2 = OpVariable %ptr_input_float Input
906 %main = OpFunction %void None %void_fn
907 %entry = OpLabel
908 OpReturn
909 OpFunctionEnd
910 )";
911
912 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
913 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
914 EXPECT_THAT(getDiagnosticString(),
915 HasSubstr("Entry-point has conflicting input location assignment "
916 "at location 7"));
917 }
918
TEST_F(ValidateInterfacesTest,VulkanLocationsArray2Conflict)919 TEST_F(ValidateInterfacesTest, VulkanLocationsArray2Conflict) {
920 const std::string text = R"(
921 OpCapability Shader
922 OpMemoryModel Logical GLSL450
923 OpEntryPoint Fragment %main "main" %var1 %var2
924 OpExecutionMode %main OriginUpperLeft
925 OpDecorate %var1 Location 0
926 OpDecorate %var2 Location 1
927 %void = OpTypeVoid
928 %void_fn = OpTypeFunction %void
929 %float = OpTypeFloat 32
930 %int = OpTypeInt 32 0
931 %int_2 = OpConstant %int 2
932 %array = OpTypeArray %int %int_2
933 %struct = OpTypeStruct %array
934 %ptr_input_float = OpTypePointer Input %float
935 %ptr_input_struct = OpTypePointer Input %struct
936 %var1 = OpVariable %ptr_input_struct Input
937 %var2 = OpVariable %ptr_input_float Input
938 %main = OpFunction %void None %void_fn
939 %entry = OpLabel
940 OpReturn
941 OpFunctionEnd
942 )";
943
944 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
945 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
946 EXPECT_THAT(getDiagnosticString(),
947 HasSubstr("Entry-point has conflicting input location assignment "
948 "at location 1"));
949 }
950
TEST_F(ValidateInterfacesTest,VulkanLocationsArray4Conflict)951 TEST_F(ValidateInterfacesTest, VulkanLocationsArray4Conflict) {
952 const std::string text = R"(
953 OpCapability Shader
954 OpMemoryModel Logical GLSL450
955 OpEntryPoint Fragment %main "main" %var1 %var2
956 OpExecutionMode %main OriginUpperLeft
957 OpDecorate %var1 Location 0
958 OpDecorate %var2 Location 3
959 %void = OpTypeVoid
960 %void_fn = OpTypeFunction %void
961 %float = OpTypeFloat 32
962 %int = OpTypeInt 32 0
963 %int_4 = OpConstant %int 4
964 %array = OpTypeArray %int %int_4
965 %struct = OpTypeStruct %array
966 %ptr_input_float = OpTypePointer Input %float
967 %ptr_input_struct = OpTypePointer Input %struct
968 %var1 = OpVariable %ptr_input_struct Input
969 %var2 = OpVariable %ptr_input_float Input
970 %main = OpFunction %void None %void_fn
971 %entry = OpLabel
972 OpReturn
973 OpFunctionEnd
974 )";
975
976 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
977 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
978 EXPECT_THAT(getDiagnosticString(),
979 HasSubstr("Entry-point has conflicting input location assignment "
980 "at location 3"));
981 }
982
TEST_F(ValidateInterfacesTest,VulkanLocationsMatrix4x4Array4Conflict)983 TEST_F(ValidateInterfacesTest, VulkanLocationsMatrix4x4Array4Conflict) {
984 const std::string text = R"(
985 OpCapability Shader
986 OpMemoryModel Logical GLSL450
987 OpEntryPoint Fragment %main "main" %var1 %var2
988 OpExecutionMode %main OriginUpperLeft
989 OpDecorate %var1 Location 0
990 OpDecorate %var2 Location 15
991 %void = OpTypeVoid
992 %void_fn = OpTypeFunction %void
993 %float = OpTypeFloat 32
994 %int = OpTypeInt 32 0
995 %int_4 = OpConstant %int 4
996 %vector = OpTypeVector %float 4
997 %matrix = OpTypeMatrix %vector 4
998 %array = OpTypeArray %matrix %int_4
999 %struct = OpTypeStruct %array
1000 %ptr_input_float = OpTypePointer Input %float
1001 %ptr_input_struct = OpTypePointer Input %struct
1002 %var1 = OpVariable %ptr_input_struct Input
1003 %var2 = OpVariable %ptr_input_float Input
1004 %main = OpFunction %void None %void_fn
1005 %entry = OpLabel
1006 OpReturn
1007 OpFunctionEnd
1008 )";
1009
1010 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1011 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1012 EXPECT_THAT(getDiagnosticString(),
1013 HasSubstr("Entry-point has conflicting input location assignment "
1014 "at location 15"));
1015 }
1016
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentDisambiguates)1017 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentDisambiguates) {
1018 const std::string text = R"(
1019 OpCapability Shader
1020 OpMemoryModel Logical GLSL450
1021 OpEntryPoint Fragment %main "main" %var1
1022 OpExecutionMode %main OriginUpperLeft
1023 OpDecorate %struct Block
1024 OpMemberDecorate %struct 0 Location 0
1025 OpMemberDecorate %struct 0 Component 0
1026 OpMemberDecorate %struct 1 Location 0
1027 OpMemberDecorate %struct 1 Component 1
1028 %void = OpTypeVoid
1029 %void_fn = OpTypeFunction %void
1030 %float = OpTypeFloat 32
1031 %struct = OpTypeStruct %float %float
1032 %ptr_input_struct = OpTypePointer Input %struct
1033 %var1 = OpVariable %ptr_input_struct Input
1034 %main = OpFunction %void None %void_fn
1035 %entry = OpLabel
1036 OpReturn
1037 OpFunctionEnd
1038 )";
1039
1040 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1041 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1042 }
1043
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentIn64BitVec3)1044 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentIn64BitVec3) {
1045 const std::string text = R"(
1046 OpCapability Shader
1047 OpCapability Float64
1048 OpMemoryModel Logical GLSL450
1049 OpEntryPoint Fragment %main "main" %var
1050 OpExecutionMode %main OriginUpperLeft
1051 OpDecorate %struct Block
1052 OpMemberDecorate %struct 0 Location 0
1053 OpMemberDecorate %struct 1 Location 1
1054 OpMemberDecorate %struct 1 Component 1
1055 %void = OpTypeVoid
1056 %void_fn = OpTypeFunction %void
1057 %float = OpTypeFloat 32
1058 %double = OpTypeFloat 64
1059 %double3 = OpTypeVector %double 3
1060 %struct = OpTypeStruct %double3 %float
1061 %ptr_input_struct = OpTypePointer Input %struct
1062 %var = OpVariable %ptr_input_struct Input
1063 %main = OpFunction %void None %void_fn
1064 %entry = OpLabel
1065 OpReturn
1066 OpFunctionEnd
1067 )";
1068
1069 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1070 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1071 EXPECT_THAT(getDiagnosticString(),
1072 HasSubstr("Entry-point has conflicting input location assignment "
1073 "at location 1, component 1"));
1074 }
1075
TEST_F(ValidateInterfacesTest,VulkanLocationsComponentAfter64BitVec3)1076 TEST_F(ValidateInterfacesTest, VulkanLocationsComponentAfter64BitVec3) {
1077 const std::string text = R"(
1078 OpCapability Shader
1079 OpCapability Float64
1080 OpMemoryModel Logical GLSL450
1081 OpEntryPoint Fragment %main "main" %var
1082 OpExecutionMode %main OriginUpperLeft
1083 OpDecorate %struct Block
1084 OpMemberDecorate %struct 0 Location 0
1085 OpMemberDecorate %struct 1 Location 1
1086 OpMemberDecorate %struct 1 Component 2
1087 %void = OpTypeVoid
1088 %void_fn = OpTypeFunction %void
1089 %float = OpTypeFloat 32
1090 %double = OpTypeFloat 64
1091 %double3 = OpTypeVector %double 3
1092 %struct = OpTypeStruct %double3 %float
1093 %ptr_input_struct = OpTypePointer Input %struct
1094 %var = OpVariable %ptr_input_struct Input
1095 %main = OpFunction %void None %void_fn
1096 %entry = OpLabel
1097 OpReturn
1098 OpFunctionEnd
1099 )";
1100
1101 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1102 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1103 }
1104
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentVariable)1105 TEST_F(ValidateInterfacesTest, VulkanLocationsConflictingComponentVariable) {
1106 const std::string text = R"(
1107 OpCapability Shader
1108 OpMemoryModel Logical GLSL450
1109 OpEntryPoint Fragment %main "main" %var
1110 OpExecutionMode %main OriginUpperLeft
1111 OpDecorate %var Location 0
1112 OpDecorate %var Component 0
1113 OpDecorate %var Component 1
1114 %void = OpTypeVoid
1115 %void_fn = OpTypeFunction %void
1116 %float = OpTypeFloat 32
1117 %ptr_input_float = OpTypePointer Input %float
1118 %var = OpVariable %ptr_input_float Input
1119 %main = OpFunction %void None %void_fn
1120 %entry = OpLabel
1121 OpReturn
1122 OpFunctionEnd
1123 )";
1124
1125 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1126 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1127 EXPECT_THAT(getDiagnosticString(),
1128 HasSubstr("Variable has conflicting component decorations"));
1129 }
1130
TEST_F(ValidateInterfacesTest,VulkanLocationsConflictingComponentStructMember)1131 TEST_F(ValidateInterfacesTest,
1132 VulkanLocationsConflictingComponentStructMember) {
1133 const std::string text = R"(
1134 OpCapability Shader
1135 OpMemoryModel Logical GLSL450
1136 OpEntryPoint Fragment %main "main" %var
1137 OpExecutionMode %main OriginUpperLeft
1138 OpDecorate %struct Block
1139 OpMemberDecorate %struct 0 Location 0
1140 OpMemberDecorate %struct 0 Component 0
1141 OpMemberDecorate %struct 0 Component 1
1142 %void = OpTypeVoid
1143 %void_fn = OpTypeFunction %void
1144 %float = OpTypeFloat 32
1145 %struct = OpTypeStruct %float
1146 %ptr_input_struct = OpTypePointer Input %struct
1147 %var = OpVariable %ptr_input_struct Input
1148 %main = OpFunction %void None %void_fn
1149 %entry = OpLabel
1150 OpReturn
1151 OpFunctionEnd
1152 )";
1153
1154 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1155 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1156 EXPECT_THAT(
1157 getDiagnosticString(),
1158 HasSubstr("Member index 0 has conflicting component assignments"));
1159 }
1160
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableConflictOutputIndex1)1161 TEST_F(ValidateInterfacesTest, VulkanLocationsVariableConflictOutputIndex1) {
1162 const std::string text = R"(
1163 OpCapability Shader
1164 OpMemoryModel Logical GLSL450
1165 OpEntryPoint Fragment %main "main" %var1 %var2
1166 OpExecutionMode %main OriginUpperLeft
1167 OpDecorate %var1 Location 1
1168 OpDecorate %var1 Index 1
1169 OpDecorate %var2 Location 1
1170 OpDecorate %var2 Index 1
1171 %void = OpTypeVoid
1172 %void_fn = OpTypeFunction %void
1173 %float = OpTypeFloat 32
1174 %struct = OpTypeStruct %float %float
1175 %ptr_output_struct = OpTypePointer Output %struct
1176 %var1 = OpVariable %ptr_output_struct Output
1177 %var2 = OpVariable %ptr_output_struct Output
1178 %main = OpFunction %void None %void_fn
1179 %entry = OpLabel
1180 OpReturn
1181 OpFunctionEnd
1182 )";
1183
1184 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1185 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1186 EXPECT_THAT(
1187 getDiagnosticString(),
1188 HasSubstr("Entry-point has conflicting output location assignment "
1189 "at location 1"));
1190 }
1191
TEST_F(ValidateInterfacesTest,VulkanLocationsVariableNoConflictDifferentIndex)1192 TEST_F(ValidateInterfacesTest,
1193 VulkanLocationsVariableNoConflictDifferentIndex) {
1194 const std::string text = R"(
1195 OpCapability Shader
1196 OpMemoryModel Logical GLSL450
1197 OpEntryPoint Fragment %main "main" %var1 %var2
1198 OpExecutionMode %main OriginUpperLeft
1199 OpDecorate %var1 Location 1
1200 OpDecorate %var1 Index 0
1201 OpDecorate %var2 Location 1
1202 OpDecorate %var2 Index 1
1203 %void = OpTypeVoid
1204 %void_fn = OpTypeFunction %void
1205 %float = OpTypeFloat 32
1206 %struct = OpTypeStruct %float %float
1207 %ptr_output_struct = OpTypePointer Output %struct
1208 %var1 = OpVariable %ptr_output_struct Output
1209 %var2 = OpVariable %ptr_output_struct Output
1210 %main = OpFunction %void None %void_fn
1211 %entry = OpLabel
1212 OpReturn
1213 OpFunctionEnd
1214 )";
1215
1216 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1217 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1218 }
1219
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexGLCompute)1220 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexGLCompute) {
1221 const std::string text = R"(
1222 OpCapability Shader
1223 OpCapability Geometry
1224 OpMemoryModel Logical GLSL450
1225 OpEntryPoint Geometry %main "main" %var1
1226 OpExecutionMode %main Triangles
1227 OpExecutionMode %main OutputPoints
1228 OpDecorate %var1 Location 1
1229 OpDecorate %var1 Index 1
1230 %void = OpTypeVoid
1231 %void_fn = OpTypeFunction %void
1232 %float = OpTypeFloat 32
1233 %struct = OpTypeStruct %float %float
1234 %ptr_output_struct = OpTypePointer Output %struct
1235 %var1 = OpVariable %ptr_output_struct Output
1236 %main = OpFunction %void None %void_fn
1237 %entry = OpLabel
1238 OpReturn
1239 OpFunctionEnd
1240 )";
1241
1242 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1243 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1244 EXPECT_THAT(
1245 getDiagnosticString(),
1246 HasSubstr("Index can only be applied to Fragment output variables"));
1247 }
1248
TEST_F(ValidateInterfacesTest,VulkanLocationsIndexInput)1249 TEST_F(ValidateInterfacesTest, VulkanLocationsIndexInput) {
1250 const std::string text = R"(
1251 OpCapability Shader
1252 OpMemoryModel Logical GLSL450
1253 OpEntryPoint Fragment %main "main" %var1
1254 OpExecutionMode %main OriginUpperLeft
1255 OpDecorate %var1 Location 1
1256 OpDecorate %var1 Index 1
1257 %void = OpTypeVoid
1258 %void_fn = OpTypeFunction %void
1259 %float = OpTypeFloat 32
1260 %struct = OpTypeStruct %float %float
1261 %ptr_input_struct = OpTypePointer Input %struct
1262 %var1 = OpVariable %ptr_input_struct Input
1263 %main = OpFunction %void None %void_fn
1264 %entry = OpLabel
1265 OpReturn
1266 OpFunctionEnd
1267 )";
1268
1269 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1270 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1271 EXPECT_THAT(
1272 getDiagnosticString(),
1273 HasSubstr("Index can only be applied to Fragment output variables"));
1274 }
1275
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponent)1276 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponent) {
1277 const std::string text = R"(
1278 OpCapability Shader
1279 OpMemoryModel Logical GLSL450
1280 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1281 OpExecutionMode %4 OriginUpperLeft
1282 OpDecorate %11 Location 0
1283 OpDecorate %18 Component 0
1284 OpDecorate %18 Location 0
1285 OpDecorate %28 Component 1
1286 OpDecorate %28 Location 0
1287 OpDecorate %36 Location 1
1288 OpDecorate %40 Component 0
1289 OpDecorate %40 Location 1
1290 %void = OpTypeVoid
1291 %3 = OpTypeFunction %void
1292 %float = OpTypeFloat 32
1293 %v4float = OpTypeVector %float 4
1294 %_ptr_Input_v4float = OpTypePointer Input %v4float
1295 %11 = OpVariable %_ptr_Input_v4float Input
1296 %_ptr_Output_float = OpTypePointer Output %float
1297 %18 = OpVariable %_ptr_Output_float Output
1298 %uint = OpTypeInt 32 0
1299 %v3float = OpTypeVector %float 3
1300 %uint_2 = OpConstant %uint 2
1301 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1302 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1303 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1304 %_ptr_Output_v3float = OpTypePointer Output %v3float
1305 %36 = OpVariable %_ptr_Input_v4float Input
1306 %40 = OpVariable %_ptr_Output_float Output
1307 %4 = OpFunction %void None %3
1308 %5 = OpLabel
1309 OpReturn
1310 OpFunctionEnd
1311 )";
1312
1313 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1314 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1315 }
1316
TEST_F(ValidateInterfacesTest,VulkanLocationsArrayWithComponentBad)1317 TEST_F(ValidateInterfacesTest, VulkanLocationsArrayWithComponentBad) {
1318 const std::string text = R"(
1319 OpCapability Shader
1320 OpMemoryModel Logical GLSL450
1321 OpEntryPoint Fragment %4 "main" %11 %18 %28 %36 %40
1322 OpExecutionMode %4 OriginUpperLeft
1323 OpDecorate %11 Location 0
1324 OpDecorate %18 Component 0
1325 OpDecorate %18 Location 0
1326 OpDecorate %28 Component 1
1327 OpDecorate %28 Location 0
1328 OpDecorate %36 Location 1
1329 OpDecorate %40 Component 1
1330 OpDecorate %40 Location 1
1331 %void = OpTypeVoid
1332 %3 = OpTypeFunction %void
1333 %float = OpTypeFloat 32
1334 %v4float = OpTypeVector %float 4
1335 %_ptr_Input_v4float = OpTypePointer Input %v4float
1336 %11 = OpVariable %_ptr_Input_v4float Input
1337 %_ptr_Output_float = OpTypePointer Output %float
1338 %18 = OpVariable %_ptr_Output_float Output
1339 %uint = OpTypeInt 32 0
1340 %v3float = OpTypeVector %float 3
1341 %uint_2 = OpConstant %uint 2
1342 %_arr_v3float_uint_2 = OpTypeArray %v3float %uint_2
1343 %_ptr_Output__arr_v3float_uint_2 = OpTypePointer Output %_arr_v3float_uint_2
1344 %28 = OpVariable %_ptr_Output__arr_v3float_uint_2 Output
1345 %_ptr_Output_v3float = OpTypePointer Output %v3float
1346 %36 = OpVariable %_ptr_Input_v4float Input
1347 %40 = OpVariable %_ptr_Output_float Output
1348 %4 = OpFunction %void None %3
1349 %5 = OpLabel
1350 OpReturn
1351 OpFunctionEnd
1352 )";
1353
1354 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1355 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1356 EXPECT_THAT(getDiagnosticString(),
1357 HasSubstr("Entry-point has conflicting output location "
1358 "assignment at location 1, component 1"));
1359 }
1360
TEST_F(ValidateInterfacesTest,VulkanLocationsLargeLocation)1361 TEST_F(ValidateInterfacesTest, VulkanLocationsLargeLocation) {
1362 const std::string text = R"(
1363 OpCapability Shader
1364 OpMemoryModel Logical GLSL450
1365 OpEntryPoint Fragment %4 "????????" %17
1366 OpExecutionMode %4 OriginUpperLeft
1367 OpDecorate %17 Location 4227868160
1368 %void = OpTypeVoid
1369 %3 = OpTypeFunction %void
1370 %float = OpTypeFloat 32
1371 %v3float = OpTypeVector %float 3
1372 %_ptr_Input_v3float = OpTypePointer Input %v3float
1373 %17 = OpVariable %_ptr_Input_v3float Input
1374 %4 = OpFunction %void None %3
1375 %5 = OpLabel
1376 OpUnreachable
1377 OpFunctionEnd
1378 )";
1379
1380 CompileSuccessfully(text, SPV_ENV_VULKAN_1_0);
1381 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1382 }
1383
TEST_F(ValidateInterfacesTest,VulkanLocationMeshShader)1384 TEST_F(ValidateInterfacesTest, VulkanLocationMeshShader) {
1385 const std::string text = R"(
1386 OpCapability Shader
1387 OpCapability MeshShadingNV
1388 OpExtension "SPV_NV_mesh_shader"
1389 OpMemoryModel Logical GLSL450
1390 OpEntryPoint MeshNV %foo "foo" %in
1391 OpExecutionMode %foo LocalSize 1 1 1
1392 OpDecorate %block Block
1393 OpMemberDecorate %block 0 PerTaskNV
1394 OpMemberDecorate %block 0 Offset 0
1395 %void = OpTypeVoid
1396 %int = OpTypeInt 32 0
1397 %int_32 = OpConstant %int 32
1398 %array = OpTypeArray %int %int_32
1399 %block = OpTypeStruct %array
1400 %ptr_input_block = OpTypePointer Input %block
1401 %in = OpVariable %ptr_input_block Input
1402 %void_fn = OpTypeFunction %void
1403 %foo = OpFunction %void None %void_fn
1404 %entry = OpLabel
1405 OpReturn
1406 OpFunctionEnd
1407 )";
1408
1409 CompileSuccessfully(text, SPV_ENV_VULKAN_1_2);
1410 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1411 }
1412
1413 } // namespace
1414 } // namespace val
1415 } // namespace spvtools
1416