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 <sstream>
16 #include <string>
17 #include <vector>
18
19 #include "gmock/gmock.h"
20 #include "source/spirv_target_env.h"
21 #include "test/unit_spirv.h"
22 #include "test/val/val_fixtures.h"
23
24 namespace spvtools {
25 namespace val {
26 namespace {
27
28 using ::testing::Combine;
29 using ::testing::HasSubstr;
30 using ::testing::Values;
31 using ::testing::ValuesIn;
32
33 using ValidateMode = spvtest::ValidateBase<bool>;
34
35 const std::string kVoidFunction = R"(%void = OpTypeVoid
36 %void_fn = OpTypeFunction %void
37 %main = OpFunction %void None %void_fn
38 %entry = OpLabel
39 OpReturn
40 OpFunctionEnd
41 )";
42
TEST_F(ValidateMode,GLComputeNoMode)43 TEST_F(ValidateMode, GLComputeNoMode) {
44 const std::string spirv = R"(
45 OpCapability Shader
46 OpMemoryModel Logical GLSL450
47 OpEntryPoint GLCompute %main "main"
48 )" + kVoidFunction;
49
50 CompileSuccessfully(spirv);
51 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
52 }
53
TEST_F(ValidateMode,GLComputeNoModeVulkan)54 TEST_F(ValidateMode, GLComputeNoModeVulkan) {
55 const std::string spirv = R"(
56 OpCapability Shader
57 OpMemoryModel Logical GLSL450
58 OpEntryPoint GLCompute %main "main"
59 )" + kVoidFunction;
60
61 spv_target_env env = SPV_ENV_VULKAN_1_0;
62 CompileSuccessfully(spirv, env);
63 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
64 EXPECT_THAT(getDiagnosticString(),
65 AnyVUID("VUID-StandaloneSpirv-LocalSize-06426"));
66 EXPECT_THAT(
67 getDiagnosticString(),
68 HasSubstr(
69 "In the Vulkan environment, GLCompute execution model entry "
70 "points require either the LocalSize or LocalSizeId execution mode "
71 "or an object decorated with WorkgroupSize must be specified."));
72 }
73
TEST_F(ValidateMode,GLComputeNoModeVulkanWorkgroupSize)74 TEST_F(ValidateMode, GLComputeNoModeVulkanWorkgroupSize) {
75 const std::string spirv = R"(
76 OpCapability Shader
77 OpMemoryModel Logical GLSL450
78 OpEntryPoint GLCompute %main "main"
79 OpDecorate %int3_1 BuiltIn WorkgroupSize
80 %int = OpTypeInt 32 0
81 %int3 = OpTypeVector %int 3
82 %int_1 = OpConstant %int 1
83 %int3_1 = OpConstantComposite %int3 %int_1 %int_1 %int_1
84 )" + kVoidFunction;
85
86 spv_target_env env = SPV_ENV_VULKAN_1_0;
87 CompileSuccessfully(spirv, env);
88 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
89 }
90
TEST_F(ValidateMode,GLComputeVulkanLocalSize)91 TEST_F(ValidateMode, GLComputeVulkanLocalSize) {
92 const std::string spirv = R"(
93 OpCapability Shader
94 OpMemoryModel Logical GLSL450
95 OpEntryPoint GLCompute %main "main"
96 OpExecutionMode %main LocalSize 1 1 1
97 )" + kVoidFunction;
98
99 spv_target_env env = SPV_ENV_VULKAN_1_0;
100 CompileSuccessfully(spirv, env);
101 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
102 }
103
TEST_F(ValidateMode,GLComputeVulkanLocalSizeIdBad)104 TEST_F(ValidateMode, GLComputeVulkanLocalSizeIdBad) {
105 const std::string spirv = R"(
106 OpCapability Shader
107 OpMemoryModel Logical GLSL450
108 OpEntryPoint GLCompute %main "main"
109 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
110 %int = OpTypeInt 32 0
111 %int_1 = OpConstant %int 1
112 )" + kVoidFunction;
113
114 spv_target_env env = SPV_ENV_VULKAN_1_1; // need SPIR-V 1.2
115 CompileSuccessfully(spirv, env);
116 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
117 EXPECT_THAT(
118 getDiagnosticString(),
119 HasSubstr("LocalSizeId mode is not allowed by the current environment."));
120 }
121
TEST_F(ValidateMode,GLComputeVulkanLocalSizeIdGood)122 TEST_F(ValidateMode, GLComputeVulkanLocalSizeIdGood) {
123 const std::string spirv = R"(
124 OpCapability Shader
125 OpMemoryModel Logical GLSL450
126 OpEntryPoint GLCompute %main "main"
127 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
128 %int = OpTypeInt 32 0
129 %int_1 = OpConstant %int 1
130 )" + kVoidFunction;
131
132 spv_target_env env = SPV_ENV_VULKAN_1_1; // need SPIR-V 1.2
133 CompileSuccessfully(spirv, env);
134 spvValidatorOptionsSetAllowLocalSizeId(getValidatorOptions(), true);
135 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
136 }
137
TEST_F(ValidateMode,FragmentOriginLowerLeftVulkan)138 TEST_F(ValidateMode, FragmentOriginLowerLeftVulkan) {
139 const std::string spirv = R"(
140 OpCapability Shader
141 OpMemoryModel Logical GLSL450
142 OpEntryPoint Fragment %main "main"
143 OpExecutionMode %main OriginLowerLeft
144 )" + kVoidFunction;
145
146 spv_target_env env = SPV_ENV_VULKAN_1_0;
147 CompileSuccessfully(spirv, env);
148 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
149 EXPECT_THAT(getDiagnosticString(),
150 AnyVUID("VUID-StandaloneSpirv-OriginLowerLeft-04653"));
151 EXPECT_THAT(getDiagnosticString(),
152 HasSubstr("In the Vulkan environment, the OriginLowerLeft "
153 "execution mode must not be used."));
154 }
155
TEST_F(ValidateMode,FragmentPixelCenterIntegerVulkan)156 TEST_F(ValidateMode, FragmentPixelCenterIntegerVulkan) {
157 const std::string spirv = R"(
158 OpCapability Shader
159 OpMemoryModel Logical GLSL450
160 OpEntryPoint Fragment %main "main"
161 OpExecutionMode %main OriginUpperLeft
162 OpExecutionMode %main PixelCenterInteger
163 )" + kVoidFunction;
164
165 spv_target_env env = SPV_ENV_VULKAN_1_0;
166 CompileSuccessfully(spirv, env);
167 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
168 EXPECT_THAT(getDiagnosticString(),
169 AnyVUID("VUID-StandaloneSpirv-PixelCenterInteger-04654"));
170 EXPECT_THAT(getDiagnosticString(),
171 HasSubstr("In the Vulkan environment, the PixelCenterInteger "
172 "execution mode must not be used."));
173 }
174
TEST_F(ValidateMode,GeometryNoOutputMode)175 TEST_F(ValidateMode, GeometryNoOutputMode) {
176 const std::string spirv = R"(
177 OpCapability Geometry
178 OpMemoryModel Logical GLSL450
179 OpEntryPoint Geometry %main "main"
180 OpExecutionMode %main InputPoints
181 )" + kVoidFunction;
182
183 CompileSuccessfully(spirv);
184 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
185 EXPECT_THAT(getDiagnosticString(),
186 HasSubstr("Geometry execution model entry points must specify "
187 "exactly one of OutputPoints, OutputLineStrip or "
188 "OutputTriangleStrip execution modes."));
189 }
190
TEST_F(ValidateMode,GeometryNoInputMode)191 TEST_F(ValidateMode, GeometryNoInputMode) {
192 const std::string spirv = R"(
193 OpCapability Geometry
194 OpMemoryModel Logical GLSL450
195 OpEntryPoint Geometry %main "main"
196 OpExecutionMode %main OutputPoints
197 )" + kVoidFunction;
198
199 CompileSuccessfully(spirv);
200 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
201 EXPECT_THAT(
202 getDiagnosticString(),
203 HasSubstr("Geometry execution model entry points must specify exactly "
204 "one of InputPoints, InputLines, InputLinesAdjacency, "
205 "Triangles or InputTrianglesAdjacency execution modes."));
206 }
207
TEST_F(ValidateMode,FragmentNoOrigin)208 TEST_F(ValidateMode, FragmentNoOrigin) {
209 const std::string spirv = R"(
210 OpCapability Shader
211 OpMemoryModel Logical GLSL450
212 OpEntryPoint Fragment %main "main"
213 )" + kVoidFunction;
214
215 CompileSuccessfully(spirv);
216 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
217 EXPECT_THAT(
218 getDiagnosticString(),
219 HasSubstr("Fragment execution model entry points require either an "
220 "OriginUpperLeft or OriginLowerLeft execution mode."));
221 }
222
TEST_F(ValidateMode,FragmentBothOrigins)223 TEST_F(ValidateMode, FragmentBothOrigins) {
224 const std::string spirv = R"(
225 OpCapability Shader
226 OpMemoryModel Logical GLSL450
227 OpEntryPoint Fragment %main "main"
228 OpExecutionMode %main OriginUpperLeft
229 OpExecutionMode %main OriginLowerLeft
230 )" + kVoidFunction;
231
232 CompileSuccessfully(spirv);
233 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
234 EXPECT_THAT(
235 getDiagnosticString(),
236 HasSubstr("Fragment execution model entry points can only specify one of "
237 "OriginUpperLeft or OriginLowerLeft execution modes."));
238 }
239
TEST_F(ValidateMode,FragmentDepthGreaterAndLess)240 TEST_F(ValidateMode, FragmentDepthGreaterAndLess) {
241 const std::string spirv = R"(
242 OpCapability Shader
243 OpMemoryModel Logical GLSL450
244 OpEntryPoint Fragment %main "main"
245 OpExecutionMode %main OriginUpperLeft
246 OpExecutionMode %main DepthGreater
247 OpExecutionMode %main DepthLess
248 )" + kVoidFunction;
249
250 CompileSuccessfully(spirv);
251 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
252 EXPECT_THAT(getDiagnosticString(),
253 HasSubstr("Fragment execution model entry points can specify at "
254 "most one of DepthGreater, DepthLess or DepthUnchanged "
255 "execution modes."));
256 }
257
TEST_F(ValidateMode,FragmentDepthGreaterAndUnchanged)258 TEST_F(ValidateMode, FragmentDepthGreaterAndUnchanged) {
259 const std::string spirv = R"(
260 OpCapability Shader
261 OpMemoryModel Logical GLSL450
262 OpEntryPoint Fragment %main "main"
263 OpExecutionMode %main OriginUpperLeft
264 OpExecutionMode %main DepthGreater
265 OpExecutionMode %main DepthUnchanged
266 )" + kVoidFunction;
267
268 CompileSuccessfully(spirv);
269 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
270 EXPECT_THAT(getDiagnosticString(),
271 HasSubstr("Fragment execution model entry points can specify at "
272 "most one of DepthGreater, DepthLess or DepthUnchanged "
273 "execution modes."));
274 }
275
TEST_F(ValidateMode,FragmentDepthLessAndUnchanged)276 TEST_F(ValidateMode, FragmentDepthLessAndUnchanged) {
277 const std::string spirv = R"(
278 OpCapability Shader
279 OpMemoryModel Logical GLSL450
280 OpEntryPoint Fragment %main "main"
281 OpExecutionMode %main OriginUpperLeft
282 OpExecutionMode %main DepthLess
283 OpExecutionMode %main DepthUnchanged
284 )" + kVoidFunction;
285
286 CompileSuccessfully(spirv);
287 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
288 EXPECT_THAT(getDiagnosticString(),
289 HasSubstr("Fragment execution model entry points can specify at "
290 "most one of DepthGreater, DepthLess or DepthUnchanged "
291 "execution modes."));
292 }
293
TEST_F(ValidateMode,FragmentAllDepths)294 TEST_F(ValidateMode, FragmentAllDepths) {
295 const std::string spirv = R"(
296 OpCapability Shader
297 OpMemoryModel Logical GLSL450
298 OpEntryPoint Fragment %main "main"
299 OpExecutionMode %main OriginUpperLeft
300 OpExecutionMode %main DepthGreater
301 OpExecutionMode %main DepthLess
302 OpExecutionMode %main DepthUnchanged
303 )" + kVoidFunction;
304
305 CompileSuccessfully(spirv);
306 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
307 EXPECT_THAT(getDiagnosticString(),
308 HasSubstr("Fragment execution model entry points can specify at "
309 "most one of DepthGreater, DepthLess or DepthUnchanged "
310 "execution modes."));
311 }
312
TEST_F(ValidateMode,TessellationControlSpacingEqualAndFractionalOdd)313 TEST_F(ValidateMode, TessellationControlSpacingEqualAndFractionalOdd) {
314 const std::string spirv = R"(
315 OpCapability Tessellation
316 OpMemoryModel Logical GLSL450
317 OpEntryPoint TessellationControl %main "main"
318 OpExecutionMode %main SpacingEqual
319 OpExecutionMode %main SpacingFractionalOdd
320 )" + kVoidFunction;
321
322 CompileSuccessfully(spirv);
323 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
324 EXPECT_THAT(getDiagnosticString(),
325 HasSubstr("Tessellation execution model entry points can specify "
326 "at most one of SpacingEqual, SpacingFractionalOdd or "
327 "SpacingFractionalEven execution modes."));
328 }
329
TEST_F(ValidateMode,TessellationControlSpacingEqualAndSpacingFractionalEven)330 TEST_F(ValidateMode, TessellationControlSpacingEqualAndSpacingFractionalEven) {
331 const std::string spirv = R"(
332 OpCapability Tessellation
333 OpMemoryModel Logical GLSL450
334 OpEntryPoint TessellationControl %main "main"
335 OpExecutionMode %main SpacingEqual
336 OpExecutionMode %main SpacingFractionalEven
337 )" + kVoidFunction;
338
339 CompileSuccessfully(spirv);
340 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
341 EXPECT_THAT(getDiagnosticString(),
342 HasSubstr("Tessellation execution model entry points can specify "
343 "at most one of SpacingEqual, SpacingFractionalOdd or "
344 "SpacingFractionalEven execution modes."));
345 }
346
TEST_F(ValidateMode,TessellationControlSpacingFractionalOddAndSpacingFractionalEven)347 TEST_F(ValidateMode,
348 TessellationControlSpacingFractionalOddAndSpacingFractionalEven) {
349 const std::string spirv = R"(
350 OpCapability Tessellation
351 OpMemoryModel Logical GLSL450
352 OpEntryPoint TessellationControl %main "main"
353 OpExecutionMode %main SpacingFractionalOdd
354 OpExecutionMode %main SpacingFractionalEven
355 )" + kVoidFunction;
356
357 CompileSuccessfully(spirv);
358 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
359 EXPECT_THAT(getDiagnosticString(),
360 HasSubstr("Tessellation execution model entry points can specify "
361 "at most one of SpacingEqual, SpacingFractionalOdd or "
362 "SpacingFractionalEven execution modes."));
363 }
364
TEST_F(ValidateMode,TessellationControlAllSpacing)365 TEST_F(ValidateMode, TessellationControlAllSpacing) {
366 const std::string spirv = R"(
367 OpCapability Tessellation
368 OpMemoryModel Logical GLSL450
369 OpEntryPoint TessellationControl %main "main"
370 OpExecutionMode %main SpacingEqual
371 OpExecutionMode %main SpacingFractionalOdd
372 OpExecutionMode %main SpacingFractionalEven
373 )" + kVoidFunction;
374
375 CompileSuccessfully(spirv);
376 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
377 EXPECT_THAT(getDiagnosticString(),
378 HasSubstr("Tessellation execution model entry points can specify "
379 "at most one of SpacingEqual, SpacingFractionalOdd or "
380 "SpacingFractionalEven execution modes."));
381 }
382
TEST_F(ValidateMode,TessellationEvaluationSpacingEqualAndSpacingFractionalOdd)383 TEST_F(ValidateMode,
384 TessellationEvaluationSpacingEqualAndSpacingFractionalOdd) {
385 const std::string spirv = R"(
386 OpCapability Tessellation
387 OpMemoryModel Logical GLSL450
388 OpEntryPoint TessellationEvaluation %main "main"
389 OpExecutionMode %main SpacingEqual
390 OpExecutionMode %main SpacingFractionalOdd
391 )" + kVoidFunction;
392
393 CompileSuccessfully(spirv);
394 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
395 EXPECT_THAT(getDiagnosticString(),
396 HasSubstr("Tessellation execution model entry points can specify "
397 "at most one of SpacingEqual, SpacingFractionalOdd or "
398 "SpacingFractionalEven execution modes."));
399 }
400
TEST_F(ValidateMode,TessellationEvaluationSpacingEqualAndSpacingFractionalEven)401 TEST_F(ValidateMode,
402 TessellationEvaluationSpacingEqualAndSpacingFractionalEven) {
403 const std::string spirv = R"(
404 OpCapability Tessellation
405 OpMemoryModel Logical GLSL450
406 OpEntryPoint TessellationEvaluation %main "main"
407 OpExecutionMode %main SpacingEqual
408 OpExecutionMode %main SpacingFractionalEven
409 )" + kVoidFunction;
410
411 CompileSuccessfully(spirv);
412 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
413 EXPECT_THAT(getDiagnosticString(),
414 HasSubstr("Tessellation execution model entry points can specify "
415 "at most one of SpacingEqual, SpacingFractionalOdd or "
416 "SpacingFractionalEven execution modes."));
417 }
418
TEST_F(ValidateMode,TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven)419 TEST_F(ValidateMode,
420 TessellationEvaluationSpacingFractionalOddAndSpacingFractionalEven) {
421 const std::string spirv = R"(
422 OpCapability Tessellation
423 OpMemoryModel Logical GLSL450
424 OpEntryPoint TessellationEvaluation %main "main"
425 OpExecutionMode %main SpacingFractionalOdd
426 OpExecutionMode %main SpacingFractionalEven
427 )" + kVoidFunction;
428
429 CompileSuccessfully(spirv);
430 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
431 EXPECT_THAT(getDiagnosticString(),
432 HasSubstr("Tessellation execution model entry points can specify "
433 "at most one of SpacingEqual, SpacingFractionalOdd or "
434 "SpacingFractionalEven execution modes."));
435 }
436
TEST_F(ValidateMode,TessellationEvaluationAllSpacing)437 TEST_F(ValidateMode, TessellationEvaluationAllSpacing) {
438 const std::string spirv = R"(
439 OpCapability Tessellation
440 OpMemoryModel Logical GLSL450
441 OpEntryPoint TessellationEvaluation %main "main"
442 OpExecutionMode %main SpacingEqual
443 OpExecutionMode %main SpacingFractionalOdd
444 OpExecutionMode %main SpacingFractionalEven
445 )" + kVoidFunction;
446
447 CompileSuccessfully(spirv);
448 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
449 EXPECT_THAT(getDiagnosticString(),
450 HasSubstr("Tessellation execution model entry points can specify "
451 "at most one of SpacingEqual, SpacingFractionalOdd or "
452 "SpacingFractionalEven execution modes."));
453 }
454
TEST_F(ValidateMode,TessellationControlBothVertex)455 TEST_F(ValidateMode, TessellationControlBothVertex) {
456 const std::string spirv = R"(
457 OpCapability Tessellation
458 OpMemoryModel Logical GLSL450
459 OpEntryPoint TessellationControl %main "main"
460 OpExecutionMode %main VertexOrderCw
461 OpExecutionMode %main VertexOrderCcw
462 )" + kVoidFunction;
463
464 CompileSuccessfully(spirv);
465 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
466 EXPECT_THAT(
467 getDiagnosticString(),
468 HasSubstr("Tessellation execution model entry points can specify at most "
469 "one of VertexOrderCw or VertexOrderCcw execution modes."));
470 }
471
TEST_F(ValidateMode,TessellationEvaluationBothVertex)472 TEST_F(ValidateMode, TessellationEvaluationBothVertex) {
473 const std::string spirv = R"(
474 OpCapability Tessellation
475 OpMemoryModel Logical GLSL450
476 OpEntryPoint TessellationEvaluation %main "main"
477 OpExecutionMode %main VertexOrderCw
478 OpExecutionMode %main VertexOrderCcw
479 )" + kVoidFunction;
480
481 CompileSuccessfully(spirv);
482 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
483 EXPECT_THAT(
484 getDiagnosticString(),
485 HasSubstr("Tessellation execution model entry points can specify at most "
486 "one of VertexOrderCw or VertexOrderCcw execution modes."));
487 }
488
489 using ValidateModeGeometry = spvtest::ValidateBase<std::tuple<
490 std::tuple<std::string, std::string, std::string, std::string, std::string>,
491 std::tuple<std::string, std::string, std::string>>>;
492
TEST_P(ValidateModeGeometry,ExecutionMode)493 TEST_P(ValidateModeGeometry, ExecutionMode) {
494 std::vector<std::string> input_modes;
495 std::vector<std::string> output_modes;
496 input_modes.push_back(std::get<0>(std::get<0>(GetParam())));
497 input_modes.push_back(std::get<1>(std::get<0>(GetParam())));
498 input_modes.push_back(std::get<2>(std::get<0>(GetParam())));
499 input_modes.push_back(std::get<3>(std::get<0>(GetParam())));
500 input_modes.push_back(std::get<4>(std::get<0>(GetParam())));
501 output_modes.push_back(std::get<0>(std::get<1>(GetParam())));
502 output_modes.push_back(std::get<1>(std::get<1>(GetParam())));
503 output_modes.push_back(std::get<2>(std::get<1>(GetParam())));
504
505 std::ostringstream sstr;
506 sstr << "OpCapability Geometry\n";
507 sstr << "OpMemoryModel Logical GLSL450\n";
508 sstr << "OpEntryPoint Geometry %main \"main\"\n";
509 size_t num_input_modes = 0;
510 for (auto input : input_modes) {
511 if (!input.empty()) {
512 num_input_modes++;
513 sstr << "OpExecutionMode %main " << input << "\n";
514 }
515 }
516 size_t num_output_modes = 0;
517 for (auto output : output_modes) {
518 if (!output.empty()) {
519 num_output_modes++;
520 sstr << "OpExecutionMode %main " << output << "\n";
521 }
522 }
523 sstr << "%void = OpTypeVoid\n";
524 sstr << "%void_fn = OpTypeFunction %void\n";
525 sstr << "%int = OpTypeInt 32 0\n";
526 sstr << "%int1 = OpConstant %int 1\n";
527 sstr << "%main = OpFunction %void None %void_fn\n";
528 sstr << "%entry = OpLabel\n";
529 sstr << "OpReturn\n";
530 sstr << "OpFunctionEnd\n";
531
532 CompileSuccessfully(sstr.str());
533 if (num_input_modes == 1 && num_output_modes == 1) {
534 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
535 } else {
536 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
537 if (num_input_modes != 1) {
538 EXPECT_THAT(getDiagnosticString(),
539 HasSubstr("Geometry execution model entry points must "
540 "specify exactly one of InputPoints, InputLines, "
541 "InputLinesAdjacency, Triangles or "
542 "InputTrianglesAdjacency execution modes."));
543 } else {
544 EXPECT_THAT(
545 getDiagnosticString(),
546 HasSubstr("Geometry execution model entry points must specify "
547 "exactly one of OutputPoints, OutputLineStrip or "
548 "OutputTriangleStrip execution modes."));
549 }
550 }
551 }
552
553 INSTANTIATE_TEST_SUITE_P(
554 GeometryRequiredModes, ValidateModeGeometry,
555 Combine(Combine(Values("InputPoints", ""), Values("InputLines", ""),
556 Values("InputLinesAdjacency", ""), Values("Triangles", ""),
557 Values("InputTrianglesAdjacency", "")),
558 Combine(Values("OutputPoints", ""), Values("OutputLineStrip", ""),
559 Values("OutputTriangleStrip", ""))));
560
561 using ValidateModeExecution =
562 spvtest::ValidateBase<std::tuple<spv_result_t, std::string, std::string,
563 std::string, spv_target_env>>;
564
TEST_P(ValidateModeExecution,ExecutionMode)565 TEST_P(ValidateModeExecution, ExecutionMode) {
566 const spv_result_t expectation = std::get<0>(GetParam());
567 const std::string error = std::get<1>(GetParam());
568 const std::string model = std::get<2>(GetParam());
569 const std::string mode = std::get<3>(GetParam());
570 const spv_target_env env = std::get<4>(GetParam());
571
572 std::ostringstream sstr;
573 sstr << "OpCapability Shader\n";
574 sstr << "OpCapability Geometry\n";
575 sstr << "OpCapability Tessellation\n";
576 sstr << "OpCapability TransformFeedback\n";
577 if (!spvIsVulkanEnv(env)) {
578 sstr << "OpCapability Kernel\n";
579 if (env == SPV_ENV_UNIVERSAL_1_3) {
580 sstr << "OpCapability SubgroupDispatch\n";
581 } else if (env == SPV_ENV_UNIVERSAL_1_5) {
582 sstr << "OpCapability TileImageColorReadAccessEXT\n";
583 sstr << "OpCapability TileImageDepthReadAccessEXT\n";
584 sstr << "OpCapability TileImageStencilReadAccessEXT\n";
585 sstr << "OpExtension \"SPV_EXT_shader_tile_image\"\n";
586 }
587 }
588 sstr << "OpMemoryModel Logical GLSL450\n";
589 sstr << "OpEntryPoint " << model << " %main \"main\"\n";
590 if (mode.find("LocalSizeId") == 0 || mode.find("LocalSizeHintId") == 0 ||
591 mode.find("SubgroupsPerWorkgroupId") == 0) {
592 sstr << "OpExecutionModeId %main " << mode << "\n";
593 } else {
594 sstr << "OpExecutionMode %main " << mode << "\n";
595 }
596 if (model == "Geometry") {
597 if (!(mode.find("InputPoints") == 0 || mode.find("InputLines") == 0 ||
598 mode.find("InputLinesAdjacency") == 0 ||
599 mode.find("Triangles") == 0 ||
600 mode.find("InputTrianglesAdjacency") == 0)) {
601 // Exactly one of the above modes is required for Geometry shaders.
602 sstr << "OpExecutionMode %main InputPoints\n";
603 }
604 if (!(mode.find("OutputPoints") == 0 || mode.find("OutputLineStrip") == 0 ||
605 mode.find("OutputTriangleStrip") == 0)) {
606 // Exactly one of the above modes is required for Geometry shaders.
607 sstr << "OpExecutionMode %main OutputPoints\n";
608 }
609 } else if (model == "Fragment") {
610 if (!(mode.find("OriginUpperLeft") == 0 ||
611 mode.find("OriginLowerLeft") == 0)) {
612 // Exactly one of the above modes is required for Fragment shaders.
613 sstr << "OpExecutionMode %main OriginUpperLeft\n";
614 }
615 }
616 sstr << "%void = OpTypeVoid\n";
617 sstr << "%void_fn = OpTypeFunction %void\n";
618 sstr << "%int = OpTypeInt 32 0\n";
619 sstr << "%int1 = OpConstant %int 1\n";
620 sstr << "%main = OpFunction %void None %void_fn\n";
621 sstr << "%entry = OpLabel\n";
622 sstr << "OpReturn\n";
623 sstr << "OpFunctionEnd\n";
624
625 CompileSuccessfully(sstr.str(), env);
626 EXPECT_THAT(expectation, ValidateInstructions(env));
627 if (expectation != SPV_SUCCESS) {
628 EXPECT_THAT(getDiagnosticString(), HasSubstr(error));
629 }
630 }
631
632 INSTANTIATE_TEST_SUITE_P(
633 ValidateModeGeometryOnlyGoodSpv10, ValidateModeExecution,
634 Combine(Values(SPV_SUCCESS), Values(""), Values("Geometry"),
635 Values("Invocations 3", "InputPoints", "InputLines",
636 "InputLinesAdjacency", "InputTrianglesAdjacency",
637 "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
638 Values(SPV_ENV_UNIVERSAL_1_0)));
639
640 INSTANTIATE_TEST_SUITE_P(
641 ValidateModeGeometryOnlyBadSpv10, ValidateModeExecution,
642 Combine(Values(SPV_ERROR_INVALID_DATA),
643 Values("Execution mode can only be used with the Geometry "
644 "execution model."),
645 Values("Fragment", "TessellationEvaluation", "TessellationControl",
646 "GLCompute", "Vertex", "Kernel"),
647 Values("Invocations 3", "InputPoints", "InputLines",
648 "InputLinesAdjacency", "InputTrianglesAdjacency",
649 "OutputPoints", "OutputLineStrip", "OutputTriangleStrip"),
650 Values(SPV_ENV_UNIVERSAL_1_0)));
651
652 INSTANTIATE_TEST_SUITE_P(
653 ValidateModeTessellationOnlyGoodSpv10, ValidateModeExecution,
654 Combine(Values(SPV_SUCCESS), Values(""),
655 Values("TessellationControl", "TessellationEvaluation"),
656 Values("SpacingEqual", "SpacingFractionalEven",
657 "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
658 "PointMode", "Quads", "Isolines"),
659 Values(SPV_ENV_UNIVERSAL_1_0)));
660
661 INSTANTIATE_TEST_SUITE_P(
662 ValidateModeTessellationOnlyBadSpv10, ValidateModeExecution,
663 Combine(Values(SPV_ERROR_INVALID_DATA),
664 Values("Execution mode can only be used with a tessellation "
665 "execution model."),
666 Values("Fragment", "Geometry", "GLCompute", "Vertex", "Kernel"),
667 Values("SpacingEqual", "SpacingFractionalEven",
668 "SpacingFractionalOdd", "VertexOrderCw", "VertexOrderCcw",
669 "PointMode", "Quads", "Isolines"),
670 Values(SPV_ENV_UNIVERSAL_1_0)));
671
672 INSTANTIATE_TEST_SUITE_P(ValidateModeGeometryAndTessellationGoodSpv10,
673 ValidateModeExecution,
674 Combine(Values(SPV_SUCCESS), Values(""),
675 Values("TessellationControl",
676 "TessellationEvaluation", "Geometry"),
677 Values("Triangles", "OutputVertices 3"),
678 Values(SPV_ENV_UNIVERSAL_1_0)));
679
680 INSTANTIATE_TEST_SUITE_P(
681 ValidateModeGeometryAndTessellationBadSpv10, ValidateModeExecution,
682 Combine(Values(SPV_ERROR_INVALID_DATA),
683 Values("Execution mode can only be used with a Geometry or "
684 "tessellation execution model."),
685 Values("Fragment", "GLCompute", "Vertex", "Kernel"),
686 Values("Triangles", "OutputVertices 3"),
687 Values(SPV_ENV_UNIVERSAL_1_0)));
688
689 INSTANTIATE_TEST_SUITE_P(
690 ValidateModeFragmentOnlyGoodSpv10, ValidateModeExecution,
691 Combine(Values(SPV_SUCCESS), Values(""), Values("Fragment"),
692 Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
693 "EarlyFragmentTests", "DepthReplacing", "DepthLess",
694 "DepthUnchanged"),
695 Values(SPV_ENV_UNIVERSAL_1_0)));
696
697 INSTANTIATE_TEST_SUITE_P(
698 ValidateModeFragmentOnlyBadSpv10, ValidateModeExecution,
699 Combine(Values(SPV_ERROR_INVALID_DATA),
700 Values("Execution mode can only be used with the Fragment "
701 "execution model."),
702 Values("Geometry", "TessellationControl", "TessellationEvaluation",
703 "GLCompute", "Vertex", "Kernel"),
704 Values("PixelCenterInteger", "OriginUpperLeft", "OriginLowerLeft",
705 "EarlyFragmentTests", "DepthReplacing", "DepthGreater",
706 "DepthLess", "DepthUnchanged"),
707 Values(SPV_ENV_UNIVERSAL_1_0)));
708
709 INSTANTIATE_TEST_SUITE_P(ValidateModeFragmentOnlyGoodSpv15,
710 ValidateModeExecution,
711 Combine(Values(SPV_SUCCESS), Values(""),
712 Values("Fragment"),
713 Values("NonCoherentColorAttachmentReadEXT",
714 "NonCoherentDepthAttachmentReadEXT",
715 "NonCoherentStencilAttachmentReadEXT"),
716 Values(SPV_ENV_UNIVERSAL_1_5)));
717
718 INSTANTIATE_TEST_SUITE_P(
719 ValidateModeFragmentOnlyBadSpv15, ValidateModeExecution,
720 Combine(Values(SPV_ERROR_INVALID_DATA),
721 Values("Execution mode can only be used with the Fragment "
722 "execution model."),
723 Values("Geometry", "TessellationControl", "TessellationEvaluation",
724 "GLCompute", "Vertex", "Kernel"),
725 Values("NonCoherentColorAttachmentReadEXT",
726 "NonCoherentDepthAttachmentReadEXT",
727 "NonCoherentStencilAttachmentReadEXT"),
728 Values(SPV_ENV_UNIVERSAL_1_5)));
729
730 INSTANTIATE_TEST_SUITE_P(ValidateModeKernelOnlyGoodSpv13, ValidateModeExecution,
731 Combine(Values(SPV_SUCCESS), Values(""),
732 Values("Kernel"),
733 Values("LocalSizeHint 1 1 1", "VecTypeHint 4",
734 "ContractionOff",
735 "LocalSizeHintId %int1 %int1 %int1"),
736 Values(SPV_ENV_UNIVERSAL_1_3)));
737
738 INSTANTIATE_TEST_SUITE_P(
739 ValidateModeKernelOnlyBadSpv13, ValidateModeExecution,
740 Combine(
741 Values(SPV_ERROR_INVALID_DATA),
742 Values(
743 "Execution mode can only be used with the Kernel execution model."),
744 Values("Geometry", "TessellationControl", "TessellationEvaluation",
745 "GLCompute", "Vertex", "Fragment"),
746 Values("LocalSizeHint 1 1 1", "VecTypeHint 4", "ContractionOff",
747 "LocalSizeHintId %int1 %int1 %int1"),
748 Values(SPV_ENV_UNIVERSAL_1_3)));
749
750 INSTANTIATE_TEST_SUITE_P(
751 ValidateModeGLComputeAndKernelGoodSpv13, ValidateModeExecution,
752 Combine(Values(SPV_SUCCESS), Values(""), Values("Kernel", "GLCompute"),
753 Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
754 Values(SPV_ENV_UNIVERSAL_1_3)));
755
756 INSTANTIATE_TEST_SUITE_P(
757 ValidateModeGLComputeAndKernelBadSpv13, ValidateModeExecution,
758 Combine(Values(SPV_ERROR_INVALID_DATA),
759 Values("Execution mode can only be used with a Kernel or GLCompute "
760 "execution model."),
761 Values("Geometry", "TessellationControl", "TessellationEvaluation",
762 "Fragment", "Vertex"),
763 Values("LocalSize 1 1 1", "LocalSizeId %int1 %int1 %int1"),
764 Values(SPV_ENV_UNIVERSAL_1_3)));
765
766 INSTANTIATE_TEST_SUITE_P(
767 ValidateModeAllGoodSpv13, ValidateModeExecution,
768 Combine(Values(SPV_SUCCESS), Values(""),
769 Values("Kernel", "GLCompute", "Geometry", "TessellationControl",
770 "TessellationEvaluation", "Fragment", "Vertex"),
771 Values("Xfb", "Initializer", "Finalizer", "SubgroupSize 1",
772 "SubgroupsPerWorkgroup 1", "SubgroupsPerWorkgroupId %int1"),
773 Values(SPV_ENV_UNIVERSAL_1_3)));
774
TEST_F(ValidateModeExecution,MeshNVLocalSize)775 TEST_F(ValidateModeExecution, MeshNVLocalSize) {
776 const std::string spirv = R"(
777 OpCapability Shader
778 OpCapability MeshShadingNV
779 OpExtension "SPV_NV_mesh_shader"
780 OpMemoryModel Logical GLSL450
781 OpEntryPoint MeshNV %main "main"
782 OpExecutionMode %main LocalSize 1 1 1
783 )" + kVoidFunction;
784
785 CompileSuccessfully(spirv);
786 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
787 }
788
TEST_F(ValidateModeExecution,TaskNVLocalSize)789 TEST_F(ValidateModeExecution, TaskNVLocalSize) {
790 const std::string spirv = R"(
791 OpCapability Shader
792 OpCapability MeshShadingNV
793 OpExtension "SPV_NV_mesh_shader"
794 OpMemoryModel Logical GLSL450
795 OpEntryPoint TaskNV %main "main"
796 OpExecutionMode %main LocalSize 1 1 1
797 )" + kVoidFunction;
798
799 CompileSuccessfully(spirv);
800 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
801 }
802
TEST_F(ValidateModeExecution,MeshNVOutputPoints)803 TEST_F(ValidateModeExecution, MeshNVOutputPoints) {
804 const std::string spirv = R"(
805 OpCapability Shader
806 OpCapability MeshShadingNV
807 OpExtension "SPV_NV_mesh_shader"
808 OpMemoryModel Logical GLSL450
809 OpEntryPoint MeshNV %main "main"
810 OpExecutionMode %main OutputPoints
811 )" + kVoidFunction;
812
813 CompileSuccessfully(spirv);
814 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
815 }
816
TEST_F(ValidateModeExecution,MeshNVOutputVertices)817 TEST_F(ValidateModeExecution, MeshNVOutputVertices) {
818 const std::string spirv = R"(
819 OpCapability Shader
820 OpCapability MeshShadingNV
821 OpExtension "SPV_NV_mesh_shader"
822 OpMemoryModel Logical GLSL450
823 OpEntryPoint MeshNV %main "main"
824 OpExecutionMode %main OutputVertices 42
825 )" + kVoidFunction;
826
827 CompileSuccessfully(spirv);
828 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
829 }
830
TEST_F(ValidateModeExecution,MeshNVLocalSizeId)831 TEST_F(ValidateModeExecution, MeshNVLocalSizeId) {
832 const std::string spirv = R"(
833 OpCapability Shader
834 OpCapability MeshShadingNV
835 OpExtension "SPV_NV_mesh_shader"
836 OpMemoryModel Logical GLSL450
837 OpEntryPoint MeshNV %main "main"
838 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
839 %int = OpTypeInt 32 0
840 %int_1 = OpConstant %int 1
841 )" + kVoidFunction;
842
843 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
844 CompileSuccessfully(spirv, env);
845 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
846 }
847
TEST_F(ValidateModeExecution,TaskNVLocalSizeId)848 TEST_F(ValidateModeExecution, TaskNVLocalSizeId) {
849 const std::string spirv = R"(
850 OpCapability Shader
851 OpCapability MeshShadingNV
852 OpExtension "SPV_NV_mesh_shader"
853 OpMemoryModel Logical GLSL450
854 OpEntryPoint TaskNV %main "main"
855 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
856 %int = OpTypeInt 32 0
857 %int_1 = OpConstant %int 1
858 )" + kVoidFunction;
859
860 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
861 CompileSuccessfully(spirv, env);
862 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
863 }
864
TEST_F(ValidateModeExecution,ExecModeSubgroupsPerWorkgroupIdBad)865 TEST_F(ValidateModeExecution, ExecModeSubgroupsPerWorkgroupIdBad) {
866 const std::string spirv = R"(
867 OpCapability Shader
868 OpCapability SubgroupDispatch
869 OpMemoryModel Logical GLSL450
870 OpEntryPoint Vertex %main "main"
871 OpExecutionMode %main SubgroupsPerWorkgroupId %int_1
872 %int = OpTypeInt 32 0
873 %int_1 = OpConstant %int 1
874 )" + kVoidFunction;
875
876 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
877 CompileSuccessfully(spirv, env);
878 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
879 EXPECT_THAT(getDiagnosticString(),
880 HasSubstr("OpExecutionMode is only valid when the Mode operand "
881 "is an execution mode that takes no Extra Operands"));
882 }
883
TEST_F(ValidateModeExecution,ExecModeIdSubgroupsPerWorkgroupIdGood)884 TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdGood) {
885 const std::string spirv = R"(
886 OpCapability Shader
887 OpCapability SubgroupDispatch
888 OpMemoryModel Logical GLSL450
889 OpEntryPoint Vertex %main "main"
890 OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
891 %int = OpTypeInt 32 0
892 %int_1 = OpConstant %int 1
893 )" + kVoidFunction;
894
895 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
896 CompileSuccessfully(spirv, env);
897 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
898 }
899
TEST_F(ValidateModeExecution,ExecModeIdSubgroupsPerWorkgroupIdNonConstantBad)900 TEST_F(ValidateModeExecution, ExecModeIdSubgroupsPerWorkgroupIdNonConstantBad) {
901 const std::string spirv = R"(
902 OpCapability Shader
903 OpCapability SubgroupDispatch
904 OpMemoryModel Logical GLSL450
905 OpEntryPoint Vertex %main "main"
906 OpExecutionModeId %main SubgroupsPerWorkgroupId %int_1
907 %int = OpTypeInt 32 0
908 %int_ptr = OpTypePointer Private %int
909 %int_1 = OpVariable %int_ptr Private
910 )" + kVoidFunction;
911
912 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
913 CompileSuccessfully(spirv, env);
914 EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
915 EXPECT_THAT(getDiagnosticString(),
916 HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
917 "constant instructions."));
918 }
919
TEST_F(ValidateModeExecution,ExecModeLocalSizeHintIdBad)920 TEST_F(ValidateModeExecution, ExecModeLocalSizeHintIdBad) {
921 const std::string spirv = R"(
922 OpCapability Kernel
923 OpCapability Shader
924 OpMemoryModel Logical GLSL450
925 OpEntryPoint Kernel %main "main"
926 OpExecutionMode %main LocalSizeHintId %int_1 %int_1 %int_1
927 %int = OpTypeInt 32 0
928 %int_1 = OpConstant %int 1
929 )" + kVoidFunction;
930
931 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
932 CompileSuccessfully(spirv, env);
933 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
934 EXPECT_THAT(getDiagnosticString(),
935 HasSubstr("OpExecutionMode is only valid when the Mode operand "
936 "is an execution mode that takes no Extra Operands"));
937 }
938
TEST_F(ValidateModeExecution,ExecModeIdLocalSizeHintIdGood)939 TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdGood) {
940 const std::string spirv = R"(
941 OpCapability Kernel
942 OpCapability Shader
943 OpMemoryModel Logical GLSL450
944 OpEntryPoint Kernel %main "main"
945 OpExecutionModeId %main LocalSizeHintId %int_1 %int_1 %int_1
946 %int = OpTypeInt 32 0
947 %int_1 = OpConstant %int 1
948 )" + kVoidFunction;
949
950 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
951 CompileSuccessfully(spirv, env);
952 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
953 }
954
TEST_F(ValidateModeExecution,ExecModeIdLocalSizeHintIdNonConstantBad)955 TEST_F(ValidateModeExecution, ExecModeIdLocalSizeHintIdNonConstantBad) {
956 const std::string spirv = R"(
957 OpCapability Kernel
958 OpCapability Shader
959 OpMemoryModel Logical GLSL450
960 OpEntryPoint Vertex %main "main"
961 OpExecutionModeId %main LocalSizeHintId %int_1 %int_1 %int_1
962 %int = OpTypeInt 32 0
963 %int_ptr = OpTypePointer Private %int
964 %int_1 = OpVariable %int_ptr Private
965 )" + kVoidFunction;
966
967 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
968 CompileSuccessfully(spirv, env);
969 EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
970 EXPECT_THAT(getDiagnosticString(),
971 HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
972 "constant instructions."));
973 }
974
TEST_F(ValidateModeExecution,ExecModeLocalSizeIdBad)975 TEST_F(ValidateModeExecution, ExecModeLocalSizeIdBad) {
976 const std::string spirv = R"(
977 OpCapability Kernel
978 OpCapability Shader
979 OpMemoryModel Logical GLSL450
980 OpEntryPoint Kernel %main "main"
981 OpExecutionMode %main LocalSizeId %int_1 %int_1 %int_1
982 %int = OpTypeInt 32 0
983 %int_1 = OpConstant %int 1
984 )" + kVoidFunction;
985
986 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
987 CompileSuccessfully(spirv, env);
988 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
989 EXPECT_THAT(getDiagnosticString(),
990 HasSubstr("OpExecutionMode is only valid when the Mode operand "
991 "is an execution mode that takes no Extra Operands"));
992 }
993
TEST_F(ValidateModeExecution,ExecModeIdLocalSizeIdGood)994 TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdGood) {
995 const std::string spirv = R"(
996 OpCapability Kernel
997 OpCapability Shader
998 OpMemoryModel Logical GLSL450
999 OpEntryPoint Kernel %main "main"
1000 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
1001 %int = OpTypeInt 32 0
1002 %int_1 = OpConstant %int 1
1003 )" + kVoidFunction;
1004
1005 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
1006 CompileSuccessfully(spirv, env);
1007 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions(env));
1008 }
1009
TEST_F(ValidateModeExecution,ExecModeIdLocalSizeIdNonConstantBad)1010 TEST_F(ValidateModeExecution, ExecModeIdLocalSizeIdNonConstantBad) {
1011 const std::string spirv = R"(
1012 OpCapability Kernel
1013 OpCapability Shader
1014 OpMemoryModel Logical GLSL450
1015 OpEntryPoint Vertex %main "main"
1016 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
1017 %int = OpTypeInt 32 0
1018 %int_ptr = OpTypePointer Private %int
1019 %int_1 = OpVariable %int_ptr Private
1020 )" + kVoidFunction;
1021
1022 spv_target_env env = SPV_ENV_UNIVERSAL_1_3;
1023 CompileSuccessfully(spirv, env);
1024 EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions(env));
1025 EXPECT_THAT(getDiagnosticString(),
1026 HasSubstr("For OpExecutionModeId all Extra Operand ids must be "
1027 "constant instructions."));
1028 }
1029
TEST_F(ValidateMode,FragmentShaderInterlockVertexBad)1030 TEST_F(ValidateMode, FragmentShaderInterlockVertexBad) {
1031 const std::string spirv = R"(
1032 OpCapability Shader
1033 OpCapability FragmentShaderPixelInterlockEXT
1034 OpExtension "SPV_EXT_fragment_shader_interlock"
1035 OpMemoryModel Logical GLSL450
1036 OpEntryPoint Vertex %main "main"
1037 OpExecutionMode %main PixelInterlockOrderedEXT
1038 )" + kVoidFunction;
1039
1040 CompileSuccessfully(spirv);
1041 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1042 EXPECT_THAT(
1043 getDiagnosticString(),
1044 HasSubstr(
1045 "Execution mode can only be used with the Fragment execution model"));
1046 }
1047
TEST_F(ValidateMode,FragmentShaderInterlockTooManyModesBad)1048 TEST_F(ValidateMode, FragmentShaderInterlockTooManyModesBad) {
1049 const std::string spirv = R"(
1050 OpCapability Shader
1051 OpCapability FragmentShaderPixelInterlockEXT
1052 OpCapability FragmentShaderSampleInterlockEXT
1053 OpExtension "SPV_EXT_fragment_shader_interlock"
1054 OpMemoryModel Logical GLSL450
1055 OpEntryPoint Fragment %main "main"
1056 OpExecutionMode %main OriginUpperLeft
1057 OpExecutionMode %main PixelInterlockOrderedEXT
1058 OpExecutionMode %main SampleInterlockOrderedEXT
1059 )" + kVoidFunction;
1060
1061 CompileSuccessfully(spirv);
1062 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1063 EXPECT_THAT(
1064 getDiagnosticString(),
1065 HasSubstr("Fragment execution model entry points can specify at most "
1066 "one fragment shader interlock execution mode"));
1067 }
1068
TEST_F(ValidateMode,FragmentShaderInterlockNoModeBad)1069 TEST_F(ValidateMode, FragmentShaderInterlockNoModeBad) {
1070 const std::string spirv = R"(
1071 OpCapability Shader
1072 OpCapability FragmentShaderPixelInterlockEXT
1073 OpExtension "SPV_EXT_fragment_shader_interlock"
1074 OpMemoryModel Logical GLSL450
1075 OpEntryPoint Fragment %main "main"
1076 OpExecutionMode %main OriginUpperLeft
1077 %void = OpTypeVoid
1078 %void_fn = OpTypeFunction %void
1079 %func = OpFunction %void None %void_fn
1080 %entryf = OpLabel
1081 OpBeginInvocationInterlockEXT
1082 OpEndInvocationInterlockEXT
1083 OpReturn
1084 OpFunctionEnd
1085 %main = OpFunction %void None %void_fn
1086 %entry = OpLabel
1087 %1 = OpFunctionCall %void %func
1088 OpReturn
1089 OpFunctionEnd
1090 )";
1091
1092 CompileSuccessfully(spirv);
1093 EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
1094 EXPECT_THAT(
1095 getDiagnosticString(),
1096 HasSubstr(
1097 "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT require a "
1098 "fragment shader interlock execution mode"));
1099 }
1100
TEST_F(ValidateMode,FragmentShaderInterlockGood)1101 TEST_F(ValidateMode, FragmentShaderInterlockGood) {
1102 const std::string spirv = R"(
1103 OpCapability Shader
1104 OpCapability FragmentShaderPixelInterlockEXT
1105 OpExtension "SPV_EXT_fragment_shader_interlock"
1106 OpMemoryModel Logical GLSL450
1107 OpEntryPoint Fragment %main "main"
1108 OpExecutionMode %main OriginUpperLeft
1109 OpExecutionMode %main PixelInterlockOrderedEXT
1110 %void = OpTypeVoid
1111 %void_fn = OpTypeFunction %void
1112 %func = OpFunction %void None %void_fn
1113 %entryf = OpLabel
1114 OpBeginInvocationInterlockEXT
1115 OpEndInvocationInterlockEXT
1116 OpReturn
1117 OpFunctionEnd
1118 %main = OpFunction %void None %void_fn
1119 %entry = OpLabel
1120 %1 = OpFunctionCall %void %func
1121 OpReturn
1122 OpFunctionEnd
1123 )";
1124
1125 CompileSuccessfully(spirv);
1126 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
1127 }
1128
1129
TEST_F(ValidateMode,FragmentShaderStencilRefFrontTooManyModesBad)1130 TEST_F(ValidateMode, FragmentShaderStencilRefFrontTooManyModesBad) {
1131 const std::string spirv = R"(
1132 OpCapability Shader
1133 OpCapability StencilExportEXT
1134 OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
1135 OpExtension "SPV_EXT_shader_stencil_export"
1136 OpMemoryModel Logical GLSL450
1137 OpEntryPoint Fragment %main "main"
1138 OpExecutionMode %main OriginUpperLeft
1139 OpExecutionMode %main EarlyAndLateFragmentTestsAMD
1140 OpExecutionMode %main StencilRefLessFrontAMD
1141 OpExecutionMode %main StencilRefGreaterFrontAMD
1142 )" + kVoidFunction;
1143
1144 CompileSuccessfully(spirv);
1145 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1146 EXPECT_THAT(
1147 getDiagnosticString(),
1148 HasSubstr("Fragment execution model entry points can specify at most "
1149 "one of StencilRefUnchangedFrontAMD, "
1150 "StencilRefLessFrontAMD or StencilRefGreaterFrontAMD "
1151 "execution modes."));
1152 }
1153
TEST_F(ValidateMode,FragmentShaderStencilRefBackTooManyModesBad)1154 TEST_F(ValidateMode, FragmentShaderStencilRefBackTooManyModesBad) {
1155 const std::string spirv = R"(
1156 OpCapability Shader
1157 OpCapability StencilExportEXT
1158 OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
1159 OpExtension "SPV_EXT_shader_stencil_export"
1160 OpMemoryModel Logical GLSL450
1161 OpEntryPoint Fragment %main "main"
1162 OpExecutionMode %main OriginUpperLeft
1163 OpExecutionMode %main EarlyAndLateFragmentTestsAMD
1164 OpExecutionMode %main StencilRefLessBackAMD
1165 OpExecutionMode %main StencilRefGreaterBackAMD
1166 )" + kVoidFunction;
1167
1168 CompileSuccessfully(spirv);
1169 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1170 EXPECT_THAT(
1171 getDiagnosticString(),
1172 HasSubstr("Fragment execution model entry points can specify at most "
1173 "one of StencilRefUnchangedBackAMD, "
1174 "StencilRefLessBackAMD or StencilRefGreaterBackAMD "
1175 "execution modes."));
1176 }
1177
TEST_F(ValidateMode,FragmentShaderStencilRefFrontGood)1178 TEST_F(ValidateMode, FragmentShaderStencilRefFrontGood) {
1179 const std::string spirv = R"(
1180 OpCapability Shader
1181 OpCapability StencilExportEXT
1182 OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
1183 OpExtension "SPV_EXT_shader_stencil_export"
1184 OpMemoryModel Logical GLSL450
1185 OpEntryPoint Fragment %main "main"
1186 OpExecutionMode %main OriginUpperLeft
1187 OpExecutionMode %main EarlyAndLateFragmentTestsAMD
1188 OpExecutionMode %main StencilRefLessFrontAMD
1189 )" + kVoidFunction;
1190
1191 CompileSuccessfully(spirv);
1192 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
1193 }
1194
TEST_F(ValidateMode,FragmentShaderStencilRefBackGood)1195 TEST_F(ValidateMode, FragmentShaderStencilRefBackGood) {
1196 const std::string spirv = R"(
1197 OpCapability Shader
1198 OpCapability StencilExportEXT
1199 OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
1200 OpExtension "SPV_EXT_shader_stencil_export"
1201 OpMemoryModel Logical GLSL450
1202 OpEntryPoint Fragment %main "main"
1203 OpExecutionMode %main OriginUpperLeft
1204 OpExecutionMode %main EarlyAndLateFragmentTestsAMD
1205 OpExecutionMode %main StencilRefLessBackAMD
1206 )" + kVoidFunction;
1207
1208 CompileSuccessfully(spirv);
1209 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
1210 }
1211
TEST_F(ValidateMode,FragmentShaderDemoteVertexBad)1212 TEST_F(ValidateMode, FragmentShaderDemoteVertexBad) {
1213 const std::string spirv = R"(
1214 OpCapability Shader
1215 OpCapability DemoteToHelperInvocationEXT
1216 OpExtension "SPV_EXT_demote_to_helper_invocation"
1217 OpMemoryModel Logical GLSL450
1218 OpEntryPoint Vertex %main "main"
1219 %bool = OpTypeBool
1220 %void = OpTypeVoid
1221 %void_fn = OpTypeFunction %void
1222 %main = OpFunction %void None %void_fn
1223 %entry = OpLabel
1224 OpDemoteToHelperInvocationEXT
1225 %1 = OpIsHelperInvocationEXT %bool
1226 OpReturn
1227 OpFunctionEnd
1228 )";
1229
1230 CompileSuccessfully(spirv);
1231 EXPECT_THAT(SPV_ERROR_INVALID_ID, ValidateInstructions());
1232 EXPECT_THAT(
1233 getDiagnosticString(),
1234 HasSubstr(
1235 "OpDemoteToHelperInvocationEXT requires Fragment execution model"));
1236 EXPECT_THAT(
1237 getDiagnosticString(),
1238 HasSubstr("OpIsHelperInvocationEXT requires Fragment execution model"));
1239 }
1240
TEST_F(ValidateMode,FragmentShaderDemoteGood)1241 TEST_F(ValidateMode, FragmentShaderDemoteGood) {
1242 const std::string spirv = R"(
1243 OpCapability Shader
1244 OpCapability DemoteToHelperInvocationEXT
1245 OpExtension "SPV_EXT_demote_to_helper_invocation"
1246 OpMemoryModel Logical GLSL450
1247 OpEntryPoint Fragment %main "main"
1248 OpExecutionMode %main OriginUpperLeft
1249 %bool = OpTypeBool
1250 %void = OpTypeVoid
1251 %void_fn = OpTypeFunction %void
1252 %main = OpFunction %void None %void_fn
1253 %entry = OpLabel
1254 OpDemoteToHelperInvocationEXT
1255 %1 = OpIsHelperInvocationEXT %bool
1256 OpReturn
1257 OpFunctionEnd
1258 )";
1259
1260 CompileSuccessfully(spirv);
1261 EXPECT_THAT(SPV_SUCCESS, ValidateInstructions());
1262 }
1263
TEST_F(ValidateMode,FragmentShaderDemoteBadType)1264 TEST_F(ValidateMode, FragmentShaderDemoteBadType) {
1265 const std::string spirv = R"(
1266 OpCapability Shader
1267 OpCapability DemoteToHelperInvocationEXT
1268 OpExtension "SPV_EXT_demote_to_helper_invocation"
1269 OpMemoryModel Logical GLSL450
1270 OpEntryPoint Fragment %main "main"
1271 OpExecutionMode %main OriginUpperLeft
1272 %u32 = OpTypeInt 32 0
1273 %void = OpTypeVoid
1274 %void_fn = OpTypeFunction %void
1275 %main = OpFunction %void None %void_fn
1276 %entry = OpLabel
1277 OpDemoteToHelperInvocationEXT
1278 %1 = OpIsHelperInvocationEXT %u32
1279 OpReturn
1280 OpFunctionEnd
1281 )";
1282
1283 CompileSuccessfully(spirv);
1284 EXPECT_THAT(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1285 EXPECT_THAT(getDiagnosticString(),
1286 HasSubstr("Expected bool scalar type as Result Type"));
1287 }
1288
TEST_F(ValidateMode,LocalSizeIdVulkan1p3DoesNotRequireOption)1289 TEST_F(ValidateMode, LocalSizeIdVulkan1p3DoesNotRequireOption) {
1290 const std::string spirv = R"(
1291 OpCapability Shader
1292 OpMemoryModel Logical GLSL450
1293 OpEntryPoint GLCompute %main "main"
1294 OpExecutionModeId %main LocalSizeId %int_1 %int_1 %int_1
1295 %void = OpTypeVoid
1296 %int = OpTypeInt 32 0
1297 %int_1 = OpConstant %int 1
1298 %void_fn = OpTypeFunction %void
1299 %main = OpFunction %void None %void_fn
1300 %entry = OpLabel
1301 OpReturn
1302 OpFunctionEnd
1303 )";
1304
1305 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_3);
1306 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_3));
1307 }
1308
TEST_F(ValidateMode,MaximalReconvergenceRequiresExtension)1309 TEST_F(ValidateMode, MaximalReconvergenceRequiresExtension) {
1310 const std::string spirv = R"(
1311 OpCapability Shader
1312 OpMemoryModel Logical GLSL450
1313 OpEntryPoint GLCompute %main "main"
1314 OpExecutionMode %main LocalSize 1 1 1
1315 OpExecutionMode %main MaximallyReconvergesKHR
1316 %void = OpTypeVoid
1317 %void_fn = OpTypeFunction %void
1318 %main = OpFunction %void None %void_fn
1319 %entry = OpLabel
1320 OpReturn
1321 OpFunctionEnd
1322 )";
1323
1324 CompileSuccessfully(spirv);
1325 EXPECT_EQ(SPV_ERROR_MISSING_EXTENSION, ValidateInstructions());
1326 EXPECT_THAT(getDiagnosticString(),
1327 HasSubstr("(6023) requires one of these extensions: "
1328 "SPV_KHR_maximal_reconvergence "));
1329 }
1330
TEST_F(ValidateMode,FPFastMathDefaultNotExecutionModeId)1331 TEST_F(ValidateMode, FPFastMathDefaultNotExecutionModeId) {
1332 const std::string spirv = R"(
1333 OpCapability Shader
1334 OpCapability FloatControls2
1335 OpExtension "SPV_KHR_float_controls2"
1336 OpMemoryModel Logical GLSL450
1337 OpEntryPoint GLCompute %main "main"
1338 OpExecutionMode %main LocalSize 1 1 1
1339 OpExecutionMode %main FPFastMathDefault %int_0 %int_0
1340 %void = OpTypeVoid
1341 %int = OpTypeInt 32 0
1342 %int_0 = OpConstant %int 0
1343 %void_fn = OpTypeFunction %void
1344 %main = OpFunction %void None %void_fn
1345 %entry = OpLabel
1346 OpReturn
1347 OpFunctionEnd
1348 )";
1349
1350 CompileSuccessfully(spirv);
1351 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1352 EXPECT_THAT(getDiagnosticString(),
1353 HasSubstr("OpExecutionMode is only valid when the Mode operand "
1354 "is an execution mode that takes no Extra Operands, or "
1355 "takes Extra Operands that are not id operands"));
1356 }
1357
TEST_F(ValidateMode,FPFastMathDefaultNotAType)1358 TEST_F(ValidateMode, FPFastMathDefaultNotAType) {
1359 const std::string spirv = R"(
1360 OpCapability Shader
1361 OpCapability FloatControls2
1362 OpExtension "SPV_KHR_float_controls2"
1363 OpMemoryModel Logical GLSL450
1364 OpEntryPoint GLCompute %main "main"
1365 OpExecutionMode %main LocalSize 1 1 1
1366 OpExecutionModeId %main FPFastMathDefault %int_0 %int_0
1367 %void = OpTypeVoid
1368 %int = OpTypeInt 32 0
1369 %int_0 = OpConstant %int 0
1370 %void_fn = OpTypeFunction %void
1371 %main = OpFunction %void None %void_fn
1372 %entry = OpLabel
1373 OpReturn
1374 OpFunctionEnd
1375 )";
1376
1377 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1378 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1379 EXPECT_THAT(
1380 getDiagnosticString(),
1381 HasSubstr(
1382 "The Target Type operand must be a floating-point scalar type"));
1383 }
1384
TEST_F(ValidateMode,FPFastMathDefaultNotAFloatType)1385 TEST_F(ValidateMode, FPFastMathDefaultNotAFloatType) {
1386 const std::string spirv = R"(
1387 OpCapability Shader
1388 OpCapability FloatControls2
1389 OpExtension "SPV_KHR_float_controls2"
1390 OpMemoryModel Logical GLSL450
1391 OpEntryPoint GLCompute %main "main"
1392 OpExecutionMode %main LocalSize 1 1 1
1393 OpExecutionModeId %main FPFastMathDefault %int %int_0
1394 %void = OpTypeVoid
1395 %int = OpTypeInt 32 0
1396 %int_0 = OpConstant %int 0
1397 %void_fn = OpTypeFunction %void
1398 %main = OpFunction %void None %void_fn
1399 %entry = OpLabel
1400 OpReturn
1401 OpFunctionEnd
1402 )";
1403
1404 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1405 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1406 EXPECT_THAT(
1407 getDiagnosticString(),
1408 HasSubstr(
1409 "The Target Type operand must be a floating-point scalar type"));
1410 }
1411
TEST_F(ValidateMode,FPFastMathDefaultNotAFloatScalarType)1412 TEST_F(ValidateMode, FPFastMathDefaultNotAFloatScalarType) {
1413 const std::string spirv = R"(
1414 OpCapability Shader
1415 OpCapability FloatControls2
1416 OpExtension "SPV_KHR_float_controls2"
1417 OpMemoryModel Logical GLSL450
1418 OpEntryPoint GLCompute %main "main"
1419 OpExecutionMode %main LocalSize 1 1 1
1420 OpExecutionModeId %main FPFastMathDefault %float2 %int_0
1421 %void = OpTypeVoid
1422 %int = OpTypeInt 32 0
1423 %int_0 = OpConstant %int 0
1424 %float = OpTypeFloat 32
1425 %float2 = OpTypeVector %float 2
1426 %void_fn = OpTypeFunction %void
1427 %main = OpFunction %void None %void_fn
1428 %entry = OpLabel
1429 OpReturn
1430 OpFunctionEnd
1431 )";
1432
1433 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1434 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1435 EXPECT_THAT(
1436 getDiagnosticString(),
1437 HasSubstr(
1438 "The Target Type operand must be a floating-point scalar type"));
1439 }
1440
TEST_F(ValidateMode,FPFastMathDefaultSpecConstant)1441 TEST_F(ValidateMode, FPFastMathDefaultSpecConstant) {
1442 const std::string spirv = R"(
1443 OpCapability Shader
1444 OpCapability FloatControls2
1445 OpExtension "SPV_KHR_float_controls2"
1446 OpMemoryModel Logical GLSL450
1447 OpEntryPoint GLCompute %main "main"
1448 OpExecutionMode %main LocalSize 1 1 1
1449 OpExecutionModeId %main FPFastMathDefault %float %int_0
1450 %void = OpTypeVoid
1451 %int = OpTypeInt 32 0
1452 %int_0 = OpSpecConstant %int 0
1453 %float = OpTypeFloat 32
1454 %void_fn = OpTypeFunction %void
1455 %main = OpFunction %void None %void_fn
1456 %entry = OpLabel
1457 OpReturn
1458 OpFunctionEnd
1459 )";
1460
1461 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1462 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1463 EXPECT_THAT(getDiagnosticString(),
1464 HasSubstr("The Fast Math Default operand must be a "
1465 "non-specialization constant"));
1466 }
1467
TEST_F(ValidateMode,FPFastMathDefaultInvalidMask)1468 TEST_F(ValidateMode, FPFastMathDefaultInvalidMask) {
1469 const std::string spirv = R"(
1470 OpCapability Shader
1471 OpCapability FloatControls2
1472 OpExtension "SPV_KHR_float_controls2"
1473 OpMemoryModel Logical GLSL450
1474 OpEntryPoint GLCompute %main "main"
1475 OpExecutionMode %main LocalSize 1 1 1
1476 OpExecutionModeId %main FPFastMathDefault %float %constant
1477 %void = OpTypeVoid
1478 %int = OpTypeInt 32 0
1479 %constant = OpConstant %int 524288
1480 %float = OpTypeFloat 32
1481 %void_fn = OpTypeFunction %void
1482 %main = OpFunction %void None %void_fn
1483 %entry = OpLabel
1484 OpReturn
1485 OpFunctionEnd
1486 )";
1487
1488 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1489 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1490 EXPECT_THAT(
1491 getDiagnosticString(),
1492 HasSubstr("The Fast Math Default operand is an invalid bitmask value"));
1493 }
1494
TEST_F(ValidateMode,FPFastMathDefaultContainsFast)1495 TEST_F(ValidateMode, FPFastMathDefaultContainsFast) {
1496 const std::string spirv = R"(
1497 OpCapability Shader
1498 OpCapability FloatControls2
1499 OpExtension "SPV_KHR_float_controls2"
1500 OpMemoryModel Logical GLSL450
1501 OpEntryPoint GLCompute %main "main"
1502 OpExecutionMode %main LocalSize 1 1 1
1503 OpExecutionModeId %main FPFastMathDefault %float %constant
1504 %void = OpTypeVoid
1505 %int = OpTypeInt 32 0
1506 %constant = OpConstant %int 16
1507 %float = OpTypeFloat 32
1508 %void_fn = OpTypeFunction %void
1509 %main = OpFunction %void None %void_fn
1510 %entry = OpLabel
1511 OpReturn
1512 OpFunctionEnd
1513 )";
1514
1515 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1516 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1517 EXPECT_THAT(getDiagnosticString(),
1518 HasSubstr("The Fast Math Default operand must not include Fast"));
1519 }
1520
TEST_F(ValidateMode,FPFastMathDefaultAllowTransformMissingAllowReassoc)1521 TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingAllowReassoc) {
1522 const std::string spirv = R"(
1523 OpCapability Shader
1524 OpCapability FloatControls2
1525 OpExtension "SPV_KHR_float_controls2"
1526 OpMemoryModel Logical GLSL450
1527 OpEntryPoint GLCompute %main "main"
1528 OpExecutionMode %main LocalSize 1 1 1
1529 OpExecutionModeId %main FPFastMathDefault %float %constant
1530 %void = OpTypeVoid
1531 %int = OpTypeInt 32 0
1532 %constant = OpConstant %int 327680
1533 %float = OpTypeFloat 32
1534 %void_fn = OpTypeFunction %void
1535 %main = OpFunction %void None %void_fn
1536 %entry = OpLabel
1537 OpReturn
1538 OpFunctionEnd
1539 )";
1540
1541 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1542 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1543 EXPECT_THAT(
1544 getDiagnosticString(),
1545 HasSubstr("The Fast Math Default operand must include AllowContract and "
1546 "AllowReassoc when AllowTransform is specified"));
1547 }
1548
TEST_F(ValidateMode,FPFastMathDefaultAllowTransformMissingAllowContract)1549 TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingAllowContract) {
1550 const std::string spirv = R"(
1551 OpCapability Shader
1552 OpCapability FloatControls2
1553 OpExtension "SPV_KHR_float_controls2"
1554 OpMemoryModel Logical GLSL450
1555 OpEntryPoint GLCompute %main "main"
1556 OpExecutionMode %main LocalSize 1 1 1
1557 OpExecutionModeId %main FPFastMathDefault %float %constant
1558 %void = OpTypeVoid
1559 %int = OpTypeInt 32 0
1560 %constant = OpConstant %int 393216
1561 %float = OpTypeFloat 32
1562 %void_fn = OpTypeFunction %void
1563 %main = OpFunction %void None %void_fn
1564 %entry = OpLabel
1565 OpReturn
1566 OpFunctionEnd
1567 )";
1568
1569 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1570 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1571 EXPECT_THAT(
1572 getDiagnosticString(),
1573 HasSubstr("The Fast Math Default operand must include AllowContract and "
1574 "AllowReassoc when AllowTransform is specified"));
1575 }
1576
TEST_F(ValidateMode,FPFastMathDefaultAllowTransformMissingContractAndReassoc)1577 TEST_F(ValidateMode, FPFastMathDefaultAllowTransformMissingContractAndReassoc) {
1578 const std::string spirv = R"(
1579 OpCapability Shader
1580 OpCapability FloatControls2
1581 OpExtension "SPV_KHR_float_controls2"
1582 OpMemoryModel Logical GLSL450
1583 OpEntryPoint GLCompute %main "main"
1584 OpExecutionMode %main LocalSize 1 1 1
1585 OpExecutionModeId %main FPFastMathDefault %float %constant
1586 %void = OpTypeVoid
1587 %int = OpTypeInt 32 0
1588 %constant = OpConstant %int 262144
1589 %float = OpTypeFloat 32
1590 %void_fn = OpTypeFunction %void
1591 %main = OpFunction %void None %void_fn
1592 %entry = OpLabel
1593 OpReturn
1594 OpFunctionEnd
1595 )";
1596
1597 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1598 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1599 EXPECT_THAT(
1600 getDiagnosticString(),
1601 HasSubstr("The Fast Math Default operand must include AllowContract and "
1602 "AllowReassoc when AllowTransform is specified"));
1603 }
1604
TEST_F(ValidateMode,FPFastMathDefaultSignedZeroInfNanPreserve)1605 TEST_F(ValidateMode, FPFastMathDefaultSignedZeroInfNanPreserve) {
1606 const std::string spirv = R"(
1607 OpCapability Shader
1608 OpCapability FloatControls2
1609 OpCapability SignedZeroInfNanPreserve
1610 OpExtension "SPV_KHR_float_controls2"
1611 OpExtension "SPV_KHR_float_controls"
1612 OpMemoryModel Logical GLSL450
1613 OpEntryPoint GLCompute %main "main"
1614 OpExecutionMode %main LocalSize 1 1 1
1615 OpExecutionModeId %main FPFastMathDefault %float %constant
1616 OpExecutionMode %main SignedZeroInfNanPreserve 32
1617 %void = OpTypeVoid
1618 %int = OpTypeInt 32 0
1619 %constant = OpConstant %int 0
1620 %float = OpTypeFloat 32
1621 %void_fn = OpTypeFunction %void
1622 %main = OpFunction %void None %void_fn
1623 %entry = OpLabel
1624 OpReturn
1625 OpFunctionEnd
1626 )";
1627
1628 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1629 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1630 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1631 EXPECT_THAT(
1632 getDiagnosticString(),
1633 HasSubstr("FPFastMathDefault and SignedZeroInfNanPreserve execution "
1634 "modes cannot be applied to the same entry point"));
1635 }
1636
TEST_F(ValidateMode,FPFastMathDefaultConractionOff)1637 TEST_F(ValidateMode, FPFastMathDefaultConractionOff) {
1638 const std::string spirv = R"(
1639 OpCapability Kernel
1640 OpCapability Addresses
1641 OpCapability FloatControls2
1642 OpCapability SignedZeroInfNanPreserve
1643 OpExtension "SPV_KHR_float_controls2"
1644 OpExtension "SPV_KHR_float_controls"
1645 OpMemoryModel Physical64 OpenCL
1646 OpEntryPoint Kernel %main "main"
1647 OpExecutionModeId %main FPFastMathDefault %float %constant
1648 OpExecutionMode %main ContractionOff
1649 %void = OpTypeVoid
1650 %int = OpTypeInt 32 0
1651 %constant = OpConstant %int 0
1652 %float = OpTypeFloat 32
1653 %void_fn = OpTypeFunction %void
1654 %main = OpFunction %void None %void_fn
1655 %entry = OpLabel
1656 OpReturn
1657 OpFunctionEnd
1658 )";
1659
1660 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1661 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1662 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1663 EXPECT_THAT(getDiagnosticString(),
1664 HasSubstr("FPFastMathDefault and ContractionOff execution modes "
1665 "cannot be applied to the same entry point"));
1666 }
1667
TEST_F(ValidateMode,FPFastMathDefaultNoContractionNotInCallTree)1668 TEST_F(ValidateMode, FPFastMathDefaultNoContractionNotInCallTree) {
1669 const std::string spirv = R"(
1670 OpCapability Shader
1671 OpCapability FloatControls2
1672 OpExtension "SPV_KHR_float_controls2"
1673 OpMemoryModel Logical GLSL450
1674 OpEntryPoint GLCompute %main "main"
1675 OpExecutionModeId %main FPFastMathDefault %float %constant
1676 OpExecutionMode %main LocalSize 1 1 1
1677 OpDecorate %add NoContraction
1678 %void = OpTypeVoid
1679 %int = OpTypeInt 32 0
1680 %constant = OpConstant %int 0
1681 %float = OpTypeFloat 32
1682 %zero = OpConstant %float 0
1683 %void_fn = OpTypeFunction %void
1684 %main = OpFunction %void None %void_fn
1685 %entry = OpLabel
1686 OpReturn
1687 OpFunctionEnd
1688 %func = OpFunction %void None %void_fn
1689 %func_entry = OpLabel
1690 %add = OpFAdd %float %zero %zero
1691 OpReturn
1692 OpFunctionEnd
1693 )";
1694
1695 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1696 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1697 }
1698
TEST_F(ValidateMode,FPFastMathDefaultNoContractionInCallTree)1699 TEST_F(ValidateMode, FPFastMathDefaultNoContractionInCallTree) {
1700 const std::string spirv = R"(
1701 OpCapability Shader
1702 OpCapability FloatControls2
1703 OpExtension "SPV_KHR_float_controls2"
1704 OpMemoryModel Logical GLSL450
1705 OpEntryPoint GLCompute %main "main"
1706 OpExecutionModeId %main FPFastMathDefault %float %constant
1707 OpExecutionMode %main LocalSize 1 1 1
1708 OpDecorate %add NoContraction
1709 %void = OpTypeVoid
1710 %int = OpTypeInt 32 0
1711 %constant = OpConstant %int 0
1712 %float = OpTypeFloat 32
1713 %zero = OpConstant %float 0
1714 %void_fn = OpTypeFunction %void
1715 %main = OpFunction %void None %void_fn
1716 %entry = OpLabel
1717 %call = OpFunctionCall %void %func
1718 OpReturn
1719 OpFunctionEnd
1720 %func = OpFunction %void None %void_fn
1721 %func_entry = OpLabel
1722 %add = OpFAdd %float %zero %zero
1723 OpReturn
1724 OpFunctionEnd
1725 )";
1726
1727 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1728 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1729 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1730 EXPECT_THAT(getDiagnosticString(),
1731 HasSubstr("NoContraction cannot be used by an entry point with "
1732 "the FPFastMathDefault execution mode"));
1733 }
1734
TEST_F(ValidateMode,FPFastMathDefaultNoContractionInCallTree2)1735 TEST_F(ValidateMode, FPFastMathDefaultNoContractionInCallTree2) {
1736 const std::string spirv = R"(
1737 OpCapability Shader
1738 OpCapability Kernel
1739 OpCapability Addresses
1740 OpCapability FloatControls2
1741 OpExtension "SPV_KHR_float_controls2"
1742 OpMemoryModel Physical64 OpenCL
1743 OpEntryPoint Kernel %main "main"
1744 OpExecutionModeId %main FPFastMathDefault %float %constant
1745 OpDecorate %const NoContraction
1746 %void = OpTypeVoid
1747 %int = OpTypeInt 32 0
1748 %constant = OpConstant %int 0
1749 %float = OpTypeFloat 32
1750 %zero = OpConstant %float 0
1751 %const = OpSpecConstantOp %float FAdd %zero %zero
1752 %void_fn = OpTypeFunction %void
1753 %main = OpFunction %void None %void_fn
1754 %entry = OpLabel
1755 %call = OpFunctionCall %void %func
1756 OpReturn
1757 OpFunctionEnd
1758 %func = OpFunction %void None %void_fn
1759 %func_entry = OpLabel
1760 %add = OpFAdd %float %const %zero
1761 OpReturn
1762 OpFunctionEnd
1763 )";
1764
1765 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1766 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1767 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1768 EXPECT_THAT(getDiagnosticString(),
1769 HasSubstr("NoContraction cannot be used by an entry point with "
1770 "the FPFastMathDefault execution mode"));
1771 }
1772
TEST_F(ValidateMode,FPFastMathDefaultFastMathFastNotInCallTree)1773 TEST_F(ValidateMode, FPFastMathDefaultFastMathFastNotInCallTree) {
1774 const std::string spirv = R"(
1775 OpCapability Shader
1776 OpCapability FloatControls2
1777 OpExtension "SPV_KHR_float_controls2"
1778 OpMemoryModel Logical GLSL450
1779 OpEntryPoint GLCompute %main "main"
1780 OpExecutionModeId %main FPFastMathDefault %float %constant
1781 OpExecutionMode %main LocalSize 1 1 1
1782 OpDecorate %add FPFastMathMode Fast
1783 %void = OpTypeVoid
1784 %int = OpTypeInt 32 0
1785 %constant = OpConstant %int 0
1786 %float = OpTypeFloat 32
1787 %zero = OpConstant %float 0
1788 %void_fn = OpTypeFunction %void
1789 %main = OpFunction %void None %void_fn
1790 %entry = OpLabel
1791 OpReturn
1792 OpFunctionEnd
1793 %func = OpFunction %void None %void_fn
1794 %func_entry = OpLabel
1795 %add = OpFAdd %float %zero %zero
1796 OpReturn
1797 OpFunctionEnd
1798 )";
1799
1800 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1801 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1802 }
1803
TEST_F(ValidateMode,FPFastMathDefaultFastMathFastInCallTree)1804 TEST_F(ValidateMode, FPFastMathDefaultFastMathFastInCallTree) {
1805 const std::string spirv = R"(
1806 OpCapability Shader
1807 OpCapability FloatControls2
1808 OpExtension "SPV_KHR_float_controls2"
1809 OpMemoryModel Logical GLSL450
1810 OpEntryPoint GLCompute %main "main"
1811 OpExecutionModeId %main FPFastMathDefault %float %constant
1812 OpExecutionMode %main LocalSize 1 1 1
1813 OpDecorate %add FPFastMathMode Fast
1814 %void = OpTypeVoid
1815 %int = OpTypeInt 32 0
1816 %constant = OpConstant %int 0
1817 %float = OpTypeFloat 32
1818 %zero = OpConstant %float 0
1819 %void_fn = OpTypeFunction %void
1820 %main = OpFunction %void None %void_fn
1821 %entry = OpLabel
1822 %call = OpFunctionCall %void %func
1823 OpReturn
1824 OpFunctionEnd
1825 %func = OpFunction %void None %void_fn
1826 %func_entry = OpLabel
1827 %add = OpFAdd %float %zero %zero
1828 OpReturn
1829 OpFunctionEnd
1830 )";
1831
1832 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1833 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1834 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1835 EXPECT_THAT(getDiagnosticString(),
1836 HasSubstr("FPFastMathMode Fast cannot be used by an entry point "
1837 "with the FPFastMathDefault execution mode"));
1838 }
1839
TEST_F(ValidateMode,FPFastMathDefaultFastMathFastInCallTree2)1840 TEST_F(ValidateMode, FPFastMathDefaultFastMathFastInCallTree2) {
1841 const std::string spirv = R"(
1842 OpCapability Kernel
1843 OpCapability Addresses
1844 OpCapability FloatControls2
1845 OpExtension "SPV_KHR_float_controls2"
1846 OpMemoryModel Physical64 OpenCL
1847 OpEntryPoint Kernel %main "main"
1848 OpExecutionModeId %main FPFastMathDefault %float %constant
1849 OpDecorate %const FPFastMathMode Fast
1850 %void = OpTypeVoid
1851 %int = OpTypeInt 32 0
1852 %constant = OpConstant %int 0
1853 %float = OpTypeFloat 32
1854 %zero = OpConstant %float 0
1855 %const = OpSpecConstantOp %float FAdd %zero %zero
1856 %void_fn = OpTypeFunction %void
1857 %main = OpFunction %void None %void_fn
1858 %entry = OpLabel
1859 %call = OpFunctionCall %void %func
1860 OpReturn
1861 OpFunctionEnd
1862 %func = OpFunction %void None %void_fn
1863 %func_entry = OpLabel
1864 %add = OpFAdd %float %const %zero
1865 OpReturn
1866 OpFunctionEnd
1867 )";
1868
1869 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1870 EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1871 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1872 EXPECT_THAT(getDiagnosticString(),
1873 HasSubstr("FPFastMathMode Fast cannot be used by an entry point "
1874 "with the FPFastMathDefault execution mode"));
1875 }
1876
TEST_F(ValidateMode,FragmentShaderRequireFullQuadsKHR)1877 TEST_F(ValidateMode, FragmentShaderRequireFullQuadsKHR) {
1878 const std::string spirv = R"(
1879 OpCapability Shader
1880 OpCapability GroupNonUniform
1881 OpCapability GroupNonUniformVote
1882 OpCapability GroupNonUniformBallot
1883 OpCapability QuadControlKHR
1884 OpExtension "SPV_KHR_quad_control"
1885 %1 = OpExtInstImport "GLSL.std.450"
1886 OpMemoryModel Logical GLSL450
1887 OpEntryPoint GLCompute %4 "main"
1888 OpExecutionMode %4 OriginUpperLeft
1889 OpExecutionMode %4 RequireFullQuadsKHR
1890 OpDecorate %17 Location 0
1891 OpDecorate %31 BuiltIn HelperInvocation
1892 OpDecorate %40 Location 0
1893 OpDecorate %44 DescriptorSet 0
1894 OpDecorate %44 Binding 0
1895 %2 = OpTypeVoid
1896 %3 = OpTypeFunction %2
1897 %6 = OpTypeInt 32 0
1898 %7 = OpTypeVector %6 4
1899 %8 = OpTypePointer Function %7
1900 %10 = OpTypeBool
1901 %11 = OpConstantTrue %10
1902 %12 = OpConstant %6 7
1903 %14 = OpTypeFloat 32
1904 %15 = OpTypeVector %14 4
1905 %16 = OpTypePointer Output %15
1906 %17 = OpVariable %16 Output
1907 %18 = OpConstant %14 1
1908 %19 = OpConstant %14 0
1909 %20 = OpConstantComposite %15 %18 %19 %19 %18
1910 %23 = OpConstant %6 4
1911 %27 = OpConstant %6 1
1912 %28 = OpTypePointer Output %14
1913 %30 = OpTypePointer Input %10
1914 %31 = OpVariable %30 Input
1915 %36 = OpConstant %6 2
1916 %38 = OpTypeVector %14 2
1917 %39 = OpTypePointer Input %38
1918 %40 = OpVariable %39 Input
1919 %41 = OpTypeImage %14 2D 0 0 0 1 Unknown
1920 %42 = OpTypeSampledImage %41
1921 %43 = OpTypePointer UniformConstant %42
1922 %44 = OpVariable %43 UniformConstant
1923 %4 = OpFunction %2 None %3
1924 %5 = OpLabel
1925 %9 = OpVariable %8 Function
1926 %13 = OpGroupNonUniformBallot %7 %12 %11
1927 OpStore %9 %13
1928 OpStore %17 %20
1929 %21 = OpLoad %7 %9
1930 %22 = OpGroupNonUniformBallotBitCount %6 %12 Reduce %21
1931 %24 = OpIEqual %10 %22 %23
1932 OpSelectionMerge %26 None
1933 OpBranchConditional %24 %25 %26
1934 %25 = OpLabel
1935 %29 = OpAccessChain %28 %17 %27
1936 OpStore %29 %18
1937 OpBranch %26
1938 %26 = OpLabel
1939 %32 = OpLoad %10 %31
1940 %33 = OpGroupNonUniformAny %10 %12 %32
1941 OpSelectionMerge %35 None
1942 OpBranchConditional %33 %34 %35
1943 %34 = OpLabel
1944 %37 = OpAccessChain %28 %17 %36
1945 OpStore %37 %18
1946 OpBranch %35
1947 %35 = OpLabel
1948 OpReturn
1949 OpFunctionEnd
1950 )";
1951
1952 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1953 EXPECT_THAT(SPV_ERROR_INVALID_DATA,
1954 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1955 EXPECT_THAT(
1956 getDiagnosticString(),
1957 HasSubstr(
1958 "Execution mode can only be used with the Fragment execution model"));
1959 }
1960
TEST_F(ValidateMode,FragmentShaderQuadDerivativesKHR)1961 TEST_F(ValidateMode, FragmentShaderQuadDerivativesKHR) {
1962 const std::string spirv = R"(
1963 OpCapability Shader
1964 OpCapability GroupNonUniform
1965 OpCapability GroupNonUniformVote
1966 OpCapability QuadControlKHR
1967 OpExtension "SPV_KHR_quad_control"
1968 %1 = OpExtInstImport "GLSL.std.450"
1969 OpMemoryModel Logical GLSL450
1970 OpEntryPoint GLCompute %4 "main"
1971 OpExecutionMode %4 OriginUpperLeft
1972 OpExecutionMode %4 QuadDerivativesKHR
1973 OpDecorate %12 BuiltIn FragCoord
1974 OpDecorate %41 Location 0
1975 OpDecorate %45 DescriptorSet 0
1976 OpDecorate %45 Binding 0
1977 OpDecorate %49 Location 0
1978 %2 = OpTypeVoid
1979 %3 = OpTypeFunction %2
1980 %6 = OpTypeBool
1981 %7 = OpTypePointer Function %6
1982 %9 = OpTypeFloat 32
1983 %10 = OpTypeVector %9 4
1984 %11 = OpTypePointer Input %10
1985 %12 = OpVariable %11 Input
1986 %13 = OpTypeInt 32 0
1987 %14 = OpConstant %13 1
1988 %15 = OpTypePointer Input %9
1989 %18 = OpConstant %9 8.5
1990 %21 = OpConstant %9 0.100000001
1991 %25 = OpConstant %13 0
1992 %28 = OpConstant %9 3.5
1993 %30 = OpConstant %9 6
1994 %36 = OpConstant %13 7
1995 %40 = OpTypePointer Output %10
1996 %41 = OpVariable %40 Output
1997 %42 = OpTypeImage %9 2D 0 0 0 1 Unknown
1998 %43 = OpTypeSampledImage %42
1999 %44 = OpTypePointer UniformConstant %43
2000 %45 = OpVariable %44 UniformConstant
2001 %47 = OpTypeVector %9 2
2002 %48 = OpTypePointer Input %47
2003 %49 = OpVariable %48 Input
2004 %53 = OpConstant %9 0.899999976
2005 %54 = OpConstant %9 0.200000003
2006 %55 = OpConstant %9 1
2007 %56 = OpConstantComposite %10 %53 %54 %54 %55
2008 %4 = OpFunction %2 None %3
2009 %5 = OpLabel
2010 %8 = OpVariable %7 Function
2011 %16 = OpAccessChain %15 %12 %14
2012 %17 = OpLoad %9 %16
2013 %19 = OpFSub %9 %17 %18
2014 %20 = OpExtInst %9 %1 FAbs %19
2015 %22 = OpFOrdLessThan %6 %20 %21
2016 OpSelectionMerge %24 None
2017 OpBranchConditional %22 %23 %24
2018 %23 = OpLabel
2019 %26 = OpAccessChain %15 %12 %25
2020 %27 = OpLoad %9 %26
2021 %29 = OpFSub %9 %27 %28
2022 %31 = OpFMod %9 %29 %30
2023 %33 = OpFOrdLessThan %6 %31 %21
2024 OpBranch %24
2025 %24 = OpLabel
2026 %34 = OpPhi %6 %22 %5 %33 %23
2027 OpStore %8 %34
2028 %35 = OpLoad %6 %8
2029 %37 = OpGroupNonUniformAny %6 %36 %35
2030 OpSelectionMerge %39 None
2031 OpBranchConditional %37 %38 %52
2032 %38 = OpLabel
2033 %46 = OpLoad %43 %45
2034 %50 = OpLoad %47 %49
2035 %51 = OpImageSampleImplicitLod %10 %46 %50
2036 OpStore %41 %51
2037 OpBranch %39
2038 %52 = OpLabel
2039 OpStore %41 %56
2040 OpBranch %39
2041 %39 = OpLabel
2042 OpReturn
2043 OpFunctionEnd
2044 )";
2045
2046 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2047 EXPECT_THAT(SPV_ERROR_INVALID_DATA,
2048 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2049 EXPECT_THAT(
2050 getDiagnosticString(),
2051 HasSubstr(
2052 "Execution mode can only be used with the Fragment execution model"));
2053 }
2054
2055 } // namespace
2056 } // namespace val
2057 } // namespace spvtools
2058