• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2022 The Khronos Group Inc.
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 // Tests instructions from SPV_EXT_mesh_shader
16 
17 #include <sstream>
18 #include <string>
19 
20 #include "gmock/gmock.h"
21 #include "test/val/val_fixtures.h"
22 
23 namespace spvtools {
24 namespace val {
25 namespace {
26 
27 using ::testing::HasSubstr;
28 using ::testing::Values;
29 
30 using ValidateMeshShading = spvtest::ValidateBase<bool>;
31 
TEST_F(ValidateMeshShading,EmitMeshTasksEXTNotLastInstructionUniversal)32 TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionUniversal) {
33   const std::string body = R"(
34                OpCapability MeshShadingEXT
35                OpExtension "SPV_EXT_mesh_shader"
36                OpMemoryModel Logical GLSL450
37                OpEntryPoint TaskEXT %main "main" %p
38                OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1
39        %void = OpTypeVoid
40        %func = OpTypeFunction %void
41        %uint = OpTypeInt 32 0
42      %uint_1 = OpConstant %uint 1
43       %float = OpTypeFloat 32
44   %arr_float = OpTypeArray %float %uint_1
45     %Payload = OpTypeStruct %arr_float
46 %ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload
47           %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT
48        %main = OpFunction %void None %func
49      %label1 = OpLabel
50                OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p
51                OpBranch %label2
52      %label2 = OpLabel
53                OpReturn
54                OpFunctionEnd
55 )";
56 
57   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_4);
58   EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT,
59             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
60   EXPECT_THAT(getDiagnosticString(),
61               HasSubstr("Branch must appear in a block"));
62 }
63 
TEST_F(ValidateMeshShading,EmitMeshTasksEXTNotLastInstructionVulkan)64 TEST_F(ValidateMeshShading, EmitMeshTasksEXTNotLastInstructionVulkan) {
65   const std::string body = R"(
66                OpCapability MeshShadingEXT
67                OpExtension "SPV_EXT_mesh_shader"
68                OpMemoryModel Logical GLSL450
69                OpEntryPoint TaskEXT %main "main" %p
70                OpExecutionModeId %main LocalSizeId %uint_1 %uint_1 %uint_1
71        %void = OpTypeVoid
72        %func = OpTypeFunction %void
73        %uint = OpTypeInt 32 0
74      %uint_1 = OpConstant %uint 1
75       %float = OpTypeFloat 32
76   %arr_float = OpTypeArray %float %uint_1
77     %Payload = OpTypeStruct %arr_float
78 %ptr_Payload = OpTypePointer TaskPayloadWorkgroupEXT %Payload
79           %p = OpVariable %ptr_Payload TaskPayloadWorkgroupEXT
80        %main = OpFunction %void None %func
81      %label1 = OpLabel
82                OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %p
83                OpReturn
84                OpFunctionEnd
85 )";
86 
87   CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
88   EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2));
89   EXPECT_THAT(getDiagnosticString(),
90               HasSubstr("Return must appear in a block"));
91 }
92 
TEST_F(ValidateMeshShading,BasicTaskSuccess)93 TEST_F(ValidateMeshShading, BasicTaskSuccess) {
94   const std::string body = R"(
95                OpCapability MeshShadingEXT
96                OpExtension "SPV_EXT_mesh_shader"
97                OpMemoryModel Logical GLSL450
98                OpEntryPoint TaskEXT %main "main"
99        %void = OpTypeVoid
100        %func = OpTypeFunction %void
101        %main = OpFunction %void None %func
102       %label = OpLabel
103                OpReturn
104                OpFunctionEnd
105 )";
106 
107   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
108   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
109 }
110 
TEST_F(ValidateMeshShading,BasicMeshSuccess)111 TEST_F(ValidateMeshShading, BasicMeshSuccess) {
112   const std::string body = R"(
113                OpCapability MeshShadingEXT
114                OpExtension "SPV_EXT_mesh_shader"
115                OpMemoryModel Logical GLSL450
116                OpEntryPoint MeshEXT %main "main"
117                OpExecutionMode %main OutputVertices 1
118                OpExecutionMode %main OutputPrimitivesEXT 1
119                OpExecutionMode %main OutputTrianglesEXT
120        %void = OpTypeVoid
121        %func = OpTypeFunction %void
122        %main = OpFunction %void None %func
123       %label = OpLabel
124                OpReturn
125                OpFunctionEnd
126 )";
127 
128   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
129   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
130 }
131 
TEST_F(ValidateMeshShading,VulkanBasicMeshAndTaskSuccess)132 TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskSuccess) {
133   const std::string body = R"(
134                OpCapability MeshShadingEXT
135                OpExtension "SPV_EXT_mesh_shader"
136                OpExtension "SPV_NV_mesh_shader"
137                OpMemoryModel Logical GLSL450
138                OpEntryPoint MeshEXT %mainMesh "mainMesh"
139                OpEntryPoint TaskEXT %mainTask "mainTask"
140                OpExecutionMode %mainMesh OutputVertices 1
141                OpExecutionMode %mainMesh OutputPrimitivesEXT 1
142                OpExecutionMode %mainMesh OutputTrianglesEXT
143        %void = OpTypeVoid
144        %func = OpTypeFunction %void
145    %mainMesh = OpFunction %void None %func
146   %labelMesh = OpLabel
147                OpReturn
148                OpFunctionEnd
149    %mainTask = OpFunction %void None %func
150   %labelTask = OpLabel
151                OpReturn
152                OpFunctionEnd
153 )";
154 
155   CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
156   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
157 }
158 
TEST_F(ValidateMeshShading,VulkanBasicMeshAndTaskBad)159 TEST_F(ValidateMeshShading, VulkanBasicMeshAndTaskBad) {
160   const std::string body = R"(
161                OpCapability MeshShadingEXT
162                OpCapability MeshShadingNV
163                OpExtension "SPV_EXT_mesh_shader"
164                OpExtension "SPV_NV_mesh_shader"
165                OpMemoryModel Logical GLSL450
166                OpEntryPoint MeshEXT %mainMesh "mainMesh"
167                OpEntryPoint TaskNV %mainTask "mainTask"
168                OpExecutionMode %mainMesh OutputVertices 1
169                OpExecutionMode %mainMesh OutputPrimitivesEXT 1
170                OpExecutionMode %mainMesh OutputTrianglesEXT
171        %void = OpTypeVoid
172        %func = OpTypeFunction %void
173    %mainMesh = OpFunction %void None %func
174   %labelMesh = OpLabel
175                OpReturn
176                OpFunctionEnd
177    %mainTask = OpFunction %void None %func
178   %labelTask = OpLabel
179                OpReturn
180                OpFunctionEnd
181 )";
182 
183   CompileSuccessfully(body, SPV_ENV_VULKAN_1_2);
184   EXPECT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions(SPV_ENV_VULKAN_1_2));
185   EXPECT_THAT(getDiagnosticString(),
186               AnyVUID("VUID-StandaloneSpirv-MeshEXT-07102"));
187   EXPECT_THAT(getDiagnosticString(),
188               HasSubstr("Module can't mix MeshEXT/TaskEXT with MeshNV/TaskNV "
189                         "Execution Model."));
190 }
191 
TEST_F(ValidateMeshShading,MeshMissingOutputVertices)192 TEST_F(ValidateMeshShading, MeshMissingOutputVertices) {
193   const std::string body = R"(
194                OpCapability MeshShadingEXT
195                OpExtension "SPV_EXT_mesh_shader"
196                OpMemoryModel Logical GLSL450
197                OpEntryPoint MeshEXT %main "main"
198                OpExecutionMode %main OutputPrimitivesEXT 1
199                OpExecutionMode %main OutputTrianglesEXT
200        %void = OpTypeVoid
201        %func = OpTypeFunction %void
202        %main = OpFunction %void None %func
203       %label = OpLabel
204                OpReturn
205                OpFunctionEnd
206 )";
207 
208   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
209   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
210             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
211   EXPECT_THAT(
212       getDiagnosticString(),
213       HasSubstr("MeshEXT execution model entry points must specify both "
214                 "OutputPrimitivesEXT and OutputVertices Execution Modes."));
215 }
216 
TEST_F(ValidateMeshShading,MeshMissingOutputPrimitivesEXT)217 TEST_F(ValidateMeshShading, MeshMissingOutputPrimitivesEXT) {
218   const std::string body = R"(
219                OpCapability MeshShadingEXT
220                OpExtension "SPV_EXT_mesh_shader"
221                OpMemoryModel Logical GLSL450
222                OpEntryPoint MeshEXT %main "main"
223                OpExecutionMode %main OutputVertices 1
224                OpExecutionMode %main OutputTrianglesEXT
225        %void = OpTypeVoid
226        %func = OpTypeFunction %void
227        %main = OpFunction %void None %func
228       %label = OpLabel
229                OpReturn
230                OpFunctionEnd
231 )";
232 
233   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
234   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
235             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
236   EXPECT_THAT(
237       getDiagnosticString(),
238       HasSubstr("MeshEXT execution model entry points must specify both "
239                 "OutputPrimitivesEXT and OutputVertices Execution Modes."));
240 }
241 
TEST_F(ValidateMeshShading,MeshMissingOutputType)242 TEST_F(ValidateMeshShading, MeshMissingOutputType) {
243   const std::string body = R"(
244                OpCapability MeshShadingEXT
245                OpExtension "SPV_EXT_mesh_shader"
246                OpMemoryModel Logical GLSL450
247                OpEntryPoint MeshEXT %main "main"
248                OpExecutionMode %main OutputVertices 1
249                OpExecutionMode %main OutputPrimitivesEXT 1
250        %void = OpTypeVoid
251        %func = OpTypeFunction %void
252        %main = OpFunction %void None %func
253       %label = OpLabel
254                OpReturn
255                OpFunctionEnd
256 )";
257 
258   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
259   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
260             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
261   EXPECT_THAT(getDiagnosticString(),
262               HasSubstr("MeshEXT execution model entry points must specify "
263                         "exactly one of OutputPoints, OutputLinesEXT, or "
264                         "OutputTrianglesEXT Execution Modes."));
265 }
266 
TEST_F(ValidateMeshShading,MeshMultipleOutputType)267 TEST_F(ValidateMeshShading, MeshMultipleOutputType) {
268   const std::string body = R"(
269                OpCapability MeshShadingEXT
270                OpExtension "SPV_EXT_mesh_shader"
271                OpMemoryModel Logical GLSL450
272                OpEntryPoint MeshEXT %main "main"
273                OpExecutionMode %main OutputVertices 1
274                OpExecutionMode %main OutputPrimitivesEXT 1
275                OpExecutionMode %main OutputLinesEXT
276                OpExecutionMode %main OutputTrianglesEXT
277        %void = OpTypeVoid
278        %func = OpTypeFunction %void
279        %main = OpFunction %void None %func
280       %label = OpLabel
281                OpReturn
282                OpFunctionEnd
283 )";
284 
285   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
286   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
287             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
288   EXPECT_THAT(getDiagnosticString(),
289               HasSubstr("MeshEXT execution model entry points must specify "
290                         "exactly one of OutputPoints, OutputLinesEXT, or "
291                         "OutputTrianglesEXT Execution Modes."));
292 }
293 
TEST_F(ValidateMeshShading,BadExecutionModelOutputLinesEXT)294 TEST_F(ValidateMeshShading, BadExecutionModelOutputLinesEXT) {
295   const std::string body = R"(
296                OpCapability MeshShadingEXT
297                OpExtension "SPV_EXT_mesh_shader"
298                OpMemoryModel Logical GLSL450
299                OpEntryPoint GLCompute %main "main"
300                OpExecutionMode %main OutputLinesEXT
301        %void = OpTypeVoid
302        %func = OpTypeFunction %void
303        %main = OpFunction %void None %func
304       %label = OpLabel
305                OpReturn
306                OpFunctionEnd
307 )";
308 
309   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
310   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
311             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
312   EXPECT_THAT(getDiagnosticString(),
313               HasSubstr("Execution mode can only be used with the MeshEXT or "
314                         "MeshNV execution model."));
315 }
316 
TEST_F(ValidateMeshShading,BadExecutionModelOutputTrianglesEXT)317 TEST_F(ValidateMeshShading, BadExecutionModelOutputTrianglesEXT) {
318   const std::string body = R"(
319                OpCapability MeshShadingEXT
320                OpExtension "SPV_EXT_mesh_shader"
321                OpMemoryModel Logical GLSL450
322                OpEntryPoint GLCompute %main "main"
323                OpExecutionMode %main OutputTrianglesEXT
324        %void = OpTypeVoid
325        %func = OpTypeFunction %void
326        %main = OpFunction %void None %func
327       %label = OpLabel
328                OpReturn
329                OpFunctionEnd
330 )";
331 
332   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
333   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
334             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
335   EXPECT_THAT(getDiagnosticString(),
336               HasSubstr("Execution mode can only be used with the MeshEXT or "
337                         "MeshNV execution model."));
338 }
339 
TEST_F(ValidateMeshShading,BadExecutionModelOutputPrimitivesEXT)340 TEST_F(ValidateMeshShading, BadExecutionModelOutputPrimitivesEXT) {
341   const std::string body = R"(
342                OpCapability MeshShadingEXT
343                OpExtension "SPV_EXT_mesh_shader"
344                OpMemoryModel Logical GLSL450
345                OpEntryPoint GLCompute %main "main"
346                OpExecutionMode %main OutputPrimitivesEXT 1
347        %void = OpTypeVoid
348        %func = OpTypeFunction %void
349        %main = OpFunction %void None %func
350       %label = OpLabel
351                OpReturn
352                OpFunctionEnd
353 )";
354 
355   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
356   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
357             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
358   EXPECT_THAT(getDiagnosticString(),
359               HasSubstr("Execution mode can only be used with the MeshEXT or "
360                         "MeshNV execution model."));
361 }
362 
TEST_F(ValidateMeshShading,OpEmitMeshTasksBadGroupCountSignedInt)363 TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountSignedInt) {
364   const std::string body = R"(
365                OpCapability MeshShadingEXT
366                OpExtension "SPV_EXT_mesh_shader"
367                OpMemoryModel Logical GLSL450
368                OpEntryPoint TaskEXT %main "main"
369        %void = OpTypeVoid
370        %func = OpTypeFunction %void
371         %int = OpTypeInt 32 1
372        %uint = OpTypeInt 32 0
373       %int_1 = OpConstant %int 1
374      %uint_1 = OpConstant %uint 1
375        %main = OpFunction %void None %func
376        %label = OpLabel
377                OpEmitMeshTasksEXT %int_1 %uint_1 %uint_1
378                OpFunctionEnd
379 )";
380 
381   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
382   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
383             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
384   EXPECT_THAT(getDiagnosticString(),
385               HasSubstr("Group Count X must be a 32-bit unsigned int scalar"));
386 }
387 
TEST_F(ValidateMeshShading,OpEmitMeshTasksBadGroupCountVector)388 TEST_F(ValidateMeshShading, OpEmitMeshTasksBadGroupCountVector) {
389   const std::string body = R"(
390                OpCapability MeshShadingEXT
391                OpExtension "SPV_EXT_mesh_shader"
392                OpMemoryModel Logical GLSL450
393                OpEntryPoint TaskEXT %main "main"
394        %void = OpTypeVoid
395        %func = OpTypeFunction %void
396        %uint = OpTypeInt 32 0
397      %v2uint = OpTypeVector %uint 2
398 %_ptr_v2uint = OpTypePointer Function %v2uint
399      %uint_1 = OpConstant %uint 1
400   %composite = OpConstantComposite %v2uint %uint_1 %uint_1
401   %_ptr_uint = OpTypePointer Function %uint
402        %main = OpFunction %void None %func
403       %label = OpLabel
404           %x = OpVariable %_ptr_v2uint Function
405                OpStore %x %composite
406          %13 = OpAccessChain %_ptr_uint %x %uint_1
407          %14 = OpLoad %uint %13
408                OpEmitMeshTasksEXT %14 %composite %uint_1
409                OpFunctionEnd
410 )";
411 
412   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
413   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
414             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
415   EXPECT_THAT(getDiagnosticString(),
416               HasSubstr("Group Count Y must be a 32-bit unsigned int scalar"));
417 }
418 
TEST_F(ValidateMeshShading,OpEmitMeshTasksBadPayload)419 TEST_F(ValidateMeshShading, OpEmitMeshTasksBadPayload) {
420   const std::string body = R"(
421                OpCapability MeshShadingEXT
422                OpExtension "SPV_EXT_mesh_shader"
423                OpMemoryModel Logical GLSL450
424                OpEntryPoint TaskEXT %main "main" %payload
425        %void = OpTypeVoid
426        %func = OpTypeFunction %void
427        %uint = OpTypeInt 32 0
428        %task = OpTypeStruct %uint
429 %_ptr_Uniform = OpTypePointer Uniform %task
430     %payload = OpVariable %_ptr_Uniform Uniform
431      %uint_1 = OpConstant %uint 1
432        %main = OpFunction %void None %func
433       %label = OpLabel
434                OpEmitMeshTasksEXT %uint_1 %uint_1 %uint_1 %payload
435                OpFunctionEnd
436 )";
437 
438   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
439   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
440             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
441   EXPECT_THAT(getDiagnosticString(),
442               HasSubstr("Payload OpVariable must have a storage class of "
443                         "TaskPayloadWorkgroupEXT"));
444 }
445 
TEST_F(ValidateMeshShading,TaskPayloadWorkgroupBadExecutionModel)446 TEST_F(ValidateMeshShading, TaskPayloadWorkgroupBadExecutionModel) {
447   const std::string body = R"(
448                OpCapability MeshShadingEXT
449                OpExtension "SPV_EXT_mesh_shader"
450                OpMemoryModel Logical GLSL450
451                OpEntryPoint GLCompute %main "main" %payload
452        %void = OpTypeVoid
453        %func = OpTypeFunction %void
454        %uint = OpTypeInt 32 0
455 %_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
456     %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT
457        %main = OpFunction %void None %func
458       %label = OpLabel
459        %load = OpLoad %uint %payload
460                OpReturn
461                OpFunctionEnd
462 )";
463 
464   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
465   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
466   EXPECT_THAT(getDiagnosticString(),
467               HasSubstr("TaskPayloadWorkgroupEXT Storage Class is limited to "
468                         "TaskEXT and MeshKHR execution model"));
469 }
470 
TEST_F(ValidateMeshShading,OpSetMeshOutputsBadVertexCount)471 TEST_F(ValidateMeshShading, OpSetMeshOutputsBadVertexCount) {
472   const std::string body = R"(
473                OpCapability MeshShadingEXT
474                OpExtension "SPV_EXT_mesh_shader"
475                OpMemoryModel Logical GLSL450
476                OpEntryPoint MeshEXT %main "main"
477                OpExecutionMode %main OutputVertices 1
478                OpExecutionMode %main OutputPrimitivesNV 1
479                OpExecutionMode %main OutputTrianglesNV
480        %void = OpTypeVoid
481           %3 = OpTypeFunction %void
482         %int = OpTypeInt 32 1
483        %uint = OpTypeInt 32 0
484   %_ptr_int = OpTypePointer Function %int
485       %int_1 = OpConstant %int 1
486      %uint_1 = OpConstant %uint 1
487        %main = OpFunction %void None %3
488           %5 = OpLabel
489           %x = OpVariable %_ptr_int Function
490                OpStore %x %int_1
491        %load = OpLoad %int %x
492                OpSetMeshOutputsEXT %load %uint_1
493                OpReturn
494                OpFunctionEnd
495 )";
496 
497   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
498   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
499             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
500   EXPECT_THAT(getDiagnosticString(),
501               HasSubstr("Vertex Count must be a 32-bit unsigned int scalar"));
502 }
503 
TEST_F(ValidateMeshShading,OpSetMeshOutputsBadPrimitiveCount)504 TEST_F(ValidateMeshShading, OpSetMeshOutputsBadPrimitiveCount) {
505   const std::string body = R"(
506                OpCapability MeshShadingEXT
507                OpExtension "SPV_EXT_mesh_shader"
508                OpMemoryModel Logical GLSL450
509                OpEntryPoint MeshEXT %main "main"
510                OpExecutionMode %main OutputVertices 1
511                OpExecutionMode %main OutputPrimitivesNV 1
512                OpExecutionMode %main OutputTrianglesNV
513        %void = OpTypeVoid
514           %3 = OpTypeFunction %void
515         %int = OpTypeInt 32 1
516        %uint = OpTypeInt 32 0
517       %int_1 = OpConstant %int 1
518      %uint_1 = OpConstant %uint 1
519        %main = OpFunction %void None %3
520           %5 = OpLabel
521                OpSetMeshOutputsEXT %uint_1 %int_1
522                OpReturn
523                OpFunctionEnd
524 )";
525 
526   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
527   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
528             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
529   EXPECT_THAT(
530       getDiagnosticString(),
531       HasSubstr("Primitive Count must be a 32-bit unsigned int scalar"));
532 }
533 
TEST_F(ValidateMeshShading,OpSetMeshOutputsBadExecutionModel)534 TEST_F(ValidateMeshShading, OpSetMeshOutputsBadExecutionModel) {
535   const std::string body = R"(
536                OpCapability MeshShadingEXT
537                OpExtension "SPV_EXT_mesh_shader"
538                OpMemoryModel Logical GLSL450
539                OpEntryPoint TaskEXT %main "main"
540        %void = OpTypeVoid
541           %3 = OpTypeFunction %void
542        %uint = OpTypeInt 32 0
543      %uint_1 = OpConstant %uint 1
544        %main = OpFunction %void None %3
545           %5 = OpLabel
546                OpSetMeshOutputsEXT %uint_1 %uint_1
547                OpReturn
548                OpFunctionEnd
549 )";
550 
551   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
552   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
553   EXPECT_THAT(
554       getDiagnosticString(),
555       HasSubstr("OpSetMeshOutputsEXT requires MeshEXT execution model"));
556 }
557 
TEST_F(ValidateMeshShading,OpSetMeshOutputsZeroSuccess)558 TEST_F(ValidateMeshShading, OpSetMeshOutputsZeroSuccess) {
559   const std::string body = R"(
560                OpCapability MeshShadingEXT
561                OpExtension "SPV_EXT_mesh_shader"
562                OpMemoryModel Logical GLSL450
563                OpEntryPoint MeshEXT %main "main"
564                OpExecutionMode %main OutputVertices 1
565                OpExecutionMode %main OutputPrimitivesNV 1
566                OpExecutionMode %main OutputTrianglesNV
567        %void = OpTypeVoid
568           %3 = OpTypeFunction %void
569        %uint = OpTypeInt 32 0
570      %uint_0 = OpConstant %uint 0
571        %main = OpFunction %void None %3
572           %5 = OpLabel
573                OpSetMeshOutputsEXT %uint_0 %uint_0
574                OpReturn
575                OpFunctionEnd
576 )";
577 
578   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
579   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
580 }
581 
TEST_F(ValidateMeshShading,OpEmitMeshTasksZeroSuccess)582 TEST_F(ValidateMeshShading, OpEmitMeshTasksZeroSuccess) {
583   const std::string body = R"(
584                OpCapability MeshShadingEXT
585                OpExtension "SPV_EXT_mesh_shader"
586                OpMemoryModel Logical GLSL450
587                OpEntryPoint TaskEXT %main "main"
588        %void = OpTypeVoid
589        %func = OpTypeFunction %void
590        %uint = OpTypeInt 32 0
591      %uint_0 = OpConstant %uint 1
592        %main = OpFunction %void None %func
593       %label = OpLabel
594                OpEmitMeshTasksEXT %uint_0 %uint_0 %uint_0
595                OpFunctionEnd
596 )";
597 
598   CompileSuccessfully(body, SPV_ENV_UNIVERSAL_1_5);
599   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
600 }
601 
602 }  // namespace
603 }  // namespace val
604 }  // namespace spvtools
605