external/vulkancts/modules/vulkan/memory_model/vktMemoryModelPadding.cpp \
external/vulkancts/modules/vulkan/memory_model/vktMemoryModelSharedLayout.cpp \
external/vulkancts/modules/vulkan/memory_model/vktMemoryModelSharedLayoutCase.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderApiTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderBuiltinTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderMiscTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderPropertyTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSmokeTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSyncTests.cpp \
+ external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderTests.cpp \
external/vulkancts/modules/vulkan/modifiers/vktModifiersTests.cpp \
external/vulkancts/modules/vulkan/multiview/vktMultiViewRenderPassUtil.cpp \
external/vulkancts/modules/vulkan/multiview/vktMultiViewRenderTests.cpp \
$(deqp_dir)/external/vulkancts/modules/vulkan/imageless_framebuffer \
$(deqp_dir)/external/vulkancts/modules/vulkan/memory \
$(deqp_dir)/external/vulkancts/modules/vulkan/memory_model \
+ $(deqp_dir)/external/vulkancts/modules/vulkan/mesh_shader \
$(deqp_dir)/external/vulkancts/modules/vulkan/modifiers \
$(deqp_dir)/external/vulkancts/modules/vulkan/multiview \
$(deqp_dir)/external/vulkancts/modules/vulkan \
vk-master-2021-03-01/image.txt
vk-master-2021-03-01/memory-model.txt
vk-master-2021-03-01/memory.txt
+vk-master-2021-03-01/mesh-shader.txt
vk-master-2021-03-01/multiview.txt
vk-master-2021-03-01/pipeline.txt
vk-master-2021-03-01/protected-memory.txt
--- /dev/null
+dEQP-VK.mesh_shader.nv.smoke.mesh_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.task_only_shader_triangle
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_task
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_mesh
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_output_count
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_total_memory_size
+dEQP-VK.mesh_shader.nv.property.max_mesh_total_memory_size
+dEQP-VK.mesh_shader.nv.builtin.position
+dEQP-VK.mesh_shader.nv.builtin.point_size
+dEQP-VK.mesh_shader.nv.builtin.clip_distance
+dEQP-VK.mesh_shader.nv.builtin.cull_distance
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_glsl
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_spirv
+dEQP-VK.mesh_shader.nv.builtin.layer
+dEQP-VK.mesh_shader.nv.builtin.layer_shared
+dEQP-VK.mesh_shader.nv.builtin.viewport_index
+dEQP-VK.mesh_shader.nv.builtin.viewport_index_shared
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_task
+dEQP-VK.mesh_shader.nv.misc.complex_task_data
+dEQP-VK.mesh_shader.nv.misc.single_point
+dEQP-VK.mesh_shader.nv.misc.single_line
+dEQP-VK.mesh_shader.nv.misc.single_triangle
+dEQP-VK.mesh_shader.nv.misc.max_points
+dEQP-VK.mesh_shader.nv.misc.max_lines
+dEQP-VK.mesh_shader.nv.misc.max_triangles
+dEQP-VK.mesh_shader.nv.misc.many_task_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_task_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.no_points
+dEQP-VK.mesh_shader.nv.misc.no_lines
+dEQP-VK.mesh_shader.nv.misc.no_triangles
+dEQP-VK.mesh_shader.nv.misc.no_points_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_lines_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_triangles_extra_writes
+dEQP-VK.mesh_shader.nv.misc.barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_task
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_mesh
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.custom_attributes
+dEQP-VK.mesh_shader.nv.misc.custom_attributes_and_task_shader
+dEQP-VK.mesh_shader.nv.misc.push_constant
+dEQP-VK.mesh_shader.nv.misc.push_constant_and_task_shader
vk-master/info.txt
vk-master/memory-model.txt
vk-master/memory.txt
+vk-master/mesh-shader.txt
vk-master/multiview.txt
vk-master/pipeline.txt
vk-master/protected-memory.txt
--- /dev/null
+dEQP-VK.mesh_shader.nv.smoke.mesh_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.task_only_shader_triangle
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_task
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_mesh
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_output_count
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_total_memory_size
+dEQP-VK.mesh_shader.nv.property.max_mesh_total_memory_size
+dEQP-VK.mesh_shader.nv.builtin.position
+dEQP-VK.mesh_shader.nv.builtin.point_size
+dEQP-VK.mesh_shader.nv.builtin.clip_distance
+dEQP-VK.mesh_shader.nv.builtin.cull_distance
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_glsl
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_spirv
+dEQP-VK.mesh_shader.nv.builtin.layer
+dEQP-VK.mesh_shader.nv.builtin.layer_shared
+dEQP-VK.mesh_shader.nv.builtin.viewport_index
+dEQP-VK.mesh_shader.nv.builtin.viewport_index_shared
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_task
+dEQP-VK.mesh_shader.nv.misc.complex_task_data
+dEQP-VK.mesh_shader.nv.misc.single_point
+dEQP-VK.mesh_shader.nv.misc.single_line
+dEQP-VK.mesh_shader.nv.misc.single_triangle
+dEQP-VK.mesh_shader.nv.misc.max_points
+dEQP-VK.mesh_shader.nv.misc.max_lines
+dEQP-VK.mesh_shader.nv.misc.max_triangles
+dEQP-VK.mesh_shader.nv.misc.many_task_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_task_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.no_points
+dEQP-VK.mesh_shader.nv.misc.no_lines
+dEQP-VK.mesh_shader.nv.misc.no_triangles
+dEQP-VK.mesh_shader.nv.misc.no_points_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_lines_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_triangles_extra_writes
+dEQP-VK.mesh_shader.nv.misc.barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_task
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_mesh
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.custom_attributes
+dEQP-VK.mesh_shader.nv.misc.custom_attributes_and_task_shader
+dEQP-VK.mesh_shader.nv.misc.push_constant
+dEQP-VK.mesh_shader.nv.misc.push_constant_and_task_shader
case xe::ri::Shader::SHADERTYPE_MISS: return "miss";
case xe::ri::Shader::SHADERTYPE_INTERSECTION: return "sect";
case xe::ri::Shader::SHADERTYPE_CALLABLE: return "call";
+ case xe::ri::Shader::SHADERTYPE_TASK: return "task";
+ case xe::ri::Shader::SHADERTYPE_MESH: return "mesh";
default:
throw xe::Error("Invalid shader type");
SHADERTYPE_MISS,
SHADERTYPE_INTERSECTION,
SHADERTYPE_CALLABLE,
+ SHADERTYPE_TASK,
+ SHADERTYPE_MESH,
SHADERTYPE_LAST
};
case ri::Shader::SHADERTYPE_MISS: tagName = "MissShader"; break;
case ri::Shader::SHADERTYPE_INTERSECTION: tagName = "IntersectionShader"; break;
case ri::Shader::SHADERTYPE_CALLABLE: tagName = "CallableShader"; break;
+ case ri::Shader::SHADERTYPE_TASK: tagName = "TaskShader"; break;
+ case ri::Shader::SHADERTYPE_MESH: tagName = "MeshShader"; break;
default:
throw Error("Unknown shader type");
{ 0x8c64a6be, "ClosestHitShader", ri::Shader::SHADERTYPE_CLOSEST_HIT },
{ 0xb30ed398, "MissShader", ri::Shader::SHADERTYPE_MISS },
{ 0x26150e53, "IntersectionShader", ri::Shader::SHADERTYPE_INTERSECTION },
- { 0x7e50944c, "CallableShader", ri::Shader::SHADERTYPE_CALLABLE }
+ { 0x7e50944c, "CallableShader", ri::Shader::SHADERTYPE_CALLABLE },
+ { 0xc3a35d6f, "TaskShader", ri::Shader::SHADERTYPE_TASK },
+ { 0x925c7349, "MeshShader", ri::Shader::SHADERTYPE_MESH },
};
static const EnumMapEntry s_testTypeMap[] =
{
static const EShLanguage stageMap[] = {
EShLangVertex, EShLangFragment, EShLangGeometry, EShLangTessControl, EShLangTessEvaluation, EShLangCompute,
- EShLangRayGen, EShLangAnyHit, EShLangClosestHit, EShLangMiss, EShLangIntersect, EShLangCallable
+ EShLangRayGen, EShLangAnyHit, EShLangClosestHit, EShLangMiss, EShLangIntersect, EShLangCallable, EShLangTaskNV,
+ EShLangMeshNV
};
return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
"VK_KHR_format_feature_flags2",
"VK_KHR_maintenance4",
"VK_EXT_border_color_swizzle",
+ "VK_NV_mesh_shader",
};
#include "vkImageUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkTypeUtil.hpp"
+#include "vkQueryUtil.hpp"
#include "tcuVector.hpp"
return createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
}
+Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const VkShaderModule taskShaderModule,
+ const VkShaderModule meshShaderModule,
+ const VkShaderModule fragmentShaderModule,
+ const VkRenderPass renderPass,
+ const std::vector<VkViewport>& viewports,
+ const std::vector<VkRect2D>& scissors,
+ const deUint32 subpass,
+ const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo,
+ const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo,
+ const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo,
+ const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo,
+ const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo)
+{
+ const VkBool32 disableRasterization = (fragmentShaderModule == DE_NULL);
+
+ VkPipelineShaderStageCreateInfo stageCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType
+ nullptr, // const void* pNext
+ 0u, // VkPipelineShaderStageCreateFlags flags
+ VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage
+ DE_NULL, // VkShaderModule module
+ "main", // const char* pName
+ nullptr // const VkSpecializationInfo* pSpecializationInfo
+ };
+
+ std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStageParams;
+
+ if (taskShaderModule != DE_NULL)
+ {
+ stageCreateInfo.stage = VK_SHADER_STAGE_TASK_BIT_NV;
+ stageCreateInfo.module = taskShaderModule;
+ pipelineShaderStageParams.push_back(stageCreateInfo);
+ }
+
+ {
+ stageCreateInfo.stage = VK_SHADER_STAGE_MESH_BIT_NV;
+ stageCreateInfo.module = meshShaderModule;
+ pipelineShaderStageParams.push_back(stageCreateInfo);
+ }
+
+ if (fragmentShaderModule != DE_NULL)
+ {
+ stageCreateInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ stageCreateInfo.module = fragmentShaderModule;
+ pipelineShaderStageParams.push_back(stageCreateInfo);
+ }
+
+ VkPipelineViewportStateCreateInfo viewportStateCreateInfo = initVulkanStructure();
+ viewportStateCreateInfo.viewportCount = static_cast<uint32_t>(viewports.size());
+ viewportStateCreateInfo.pViewports = de::dataOrNull(viewports);
+ viewportStateCreateInfo.scissorCount = static_cast<uint32_t>(scissors.size());
+ viewportStateCreateInfo.pScissors = de::dataOrNull(scissors);
+
+ VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfoDefault = initVulkanStructure();
+ rasterizationStateCreateInfoDefault.rasterizerDiscardEnable = disableRasterization;
+ rasterizationStateCreateInfoDefault.lineWidth = 1.0f;
+
+ VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfoDefault = initVulkanStructure();
+ multisampleStateCreateInfoDefault.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ multisampleStateCreateInfoDefault.minSampleShading = 1.0f;
+
+ VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfoDefault = initVulkanStructure();
+ depthStencilStateCreateInfoDefault.maxDepthBounds = 1.0f;
+
+ VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {};
+ colorBlendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
+
+ VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoDefault = initVulkanStructure();
+ colorBlendStateCreateInfoDefault.attachmentCount = 1u;
+ colorBlendStateCreateInfoDefault.pAttachments = &colorBlendAttachmentState;
+
+ std::vector<VkDynamicState> dynamicStates;
+
+ if (viewports.empty())
+ dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
+ if (scissors.empty())
+ dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
+
+ VkPipelineDynamicStateCreateInfo dynamicStateCreateInfoDefault = initVulkanStructure();
+ dynamicStateCreateInfoDefault.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size());
+ dynamicStateCreateInfoDefault.pDynamicStates = de::dataOrNull(dynamicStates);
+
+ const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfoDefaultPtr = dynamicStates.empty() ? nullptr : &dynamicStateCreateInfoDefault;
+
+ const VkGraphicsPipelineCreateInfo pipelineCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType
+ nullptr, // const void* pNext
+ 0u, // VkPipelineCreateFlags flags
+ static_cast<uint32_t>(pipelineShaderStageParams.size()), // deUint32 stageCount
+ de::dataOrNull(pipelineShaderStageParams), // const VkPipelineShaderStageCreateInfo* pStages
+ nullptr, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState
+ nullptr, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState
+ nullptr, // const VkPipelineTessellationStateCreateInfo* pTessellationState
+ &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState
+ rasterizationStateCreateInfo ? rasterizationStateCreateInfo : &rasterizationStateCreateInfoDefault, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState
+ multisampleStateCreateInfo ? multisampleStateCreateInfo : &multisampleStateCreateInfoDefault, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState
+ depthStencilStateCreateInfo ? depthStencilStateCreateInfo : &depthStencilStateCreateInfoDefault, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState
+ colorBlendStateCreateInfo ? colorBlendStateCreateInfo : &colorBlendStateCreateInfoDefault, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState
+ dynamicStateCreateInfo ? dynamicStateCreateInfo : dynamicStateCreateInfoDefaultPtr, // const VkPipelineDynamicStateCreateInfo* pDynamicState
+ pipelineLayout, // VkPipelineLayout layout
+ renderPass, // VkRenderPass renderPass
+ subpass, // deUint32 subpass
+ DE_NULL, // VkPipeline basePipelineHandle
+ 0 // deInt32 basePipelineIndex;
+ };
+
+ return createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
+}
+
Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
const VkDevice device,
const VkFormat colorFormat,
const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo = DE_NULL,
const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo = DE_NULL);
+Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
+ const VkDevice device,
+ const VkPipelineLayout pipelineLayout,
+ const VkShaderModule taskShaderModule,
+ const VkShaderModule meshShaderModule,
+ const VkShaderModule fragmentShaderModule,
+ const VkRenderPass renderPass,
+ const std::vector<VkViewport>& viewports,
+ const std::vector<VkRect2D>& scissors,
+ const deUint32 subpass = 0u,
+ const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo = nullptr,
+ const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo = nullptr,
+ const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo = nullptr,
+ const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo = nullptr,
+ const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo = nullptr);
+
Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
const VkDevice device,
const VkFormat colorFormat = VK_FORMAT_UNDEFINED,
VK_SHADER_STAGE_MISS_BIT_NV,
VK_SHADER_STAGE_INTERSECTION_BIT_NV,
VK_SHADER_STAGE_CALLABLE_BIT_NV,
+ VK_SHADER_STAGE_TASK_BIT_NV,
+ VK_SHADER_STAGE_MESH_BIT_NV,
};
return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(s_shaderStages, shaderType);
void disassembleProgram (const ProgramBinary& program, std::ostream* dst);
bool validateProgram (const ProgramBinary& program, std::ostream* dst, const SpirvValidatorOptions&);
-Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags);
+Move<VkShaderModule> createShaderModule (const DeviceInterface& deviceInterface, VkDevice device, const ProgramBinary& binary, VkShaderModuleCreateFlags flags = 0u);
glu::ShaderType getGluShaderType (VkShaderStageFlagBits shaderStage);
VkShaderStageFlagBits getVkShaderStage (glu::ShaderType shaderType);
EShLangMiss,
EShLangIntersect,
EShLangCallable,
+ EShLangTaskNV,
+ EShLangMeshNV,
};
return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
}
add_subdirectory(postmortem)
add_subdirectory(fragment_shading_rate)
add_subdirectory(reconvergence)
+add_subdirectory(mesh_shader)
include_directories(
ray_query
postmortem
reconvergence
+ mesh_shader
)
set(DEQP_VK_SRCS
deqp-vk-postmortem
deqp-vk-fragment-shading-rate
deqp-vk-reconvergence
+ deqp-vk-mesh-shader
)
if (DE_COMPILER_IS_MSC AND (DE_PTR_SIZE EQUAL 4))
--- /dev/null
+include_directories(..)
+
+set(DEQP_VK_MESH_SHADER_SRCS
+ vktMeshShaderTests.cpp
+ vktMeshShaderTests.hpp
+ vktMeshShaderSyncTests.cpp
+ vktMeshShaderSyncTests.hpp
+ vktMeshShaderSmokeTests.cpp
+ vktMeshShaderSmokeTests.hpp
+ vktMeshShaderApiTests.cpp
+ vktMeshShaderApiTests.hpp
+ vktMeshShaderPropertyTests.cpp
+ vktMeshShaderPropertyTests.hpp
+ vktMeshShaderBuiltinTests.cpp
+ vktMeshShaderBuiltinTests.hpp
+ vktMeshShaderMiscTests.cpp
+ vktMeshShaderMiscTests.hpp
+ )
+
+set(DEQP_VK_MESH_SHADER_LIBS
+ tcutil
+ vkutil
+ )
+
+PCH(DEQP_VK_MESH_SHADER_SRCS ../pch.cpp)
+
+add_library(deqp-vk-mesh-shader STATIC ${DEQP_VK_MESH_SHADER_SRCS})
+target_link_libraries(deqp-vk-mesh-shader ${DEQP_VK_MESH_SHADER_LIBS})
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader API Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderApiTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkTypeUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkObjUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkImageUtil.hpp"
+
+#include "tcuMaybe.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuImageCompare.hpp"
+
+#include "deRandom.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using namespace vk;
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+using ImageWithMemoryPtr = de::MovePtr<ImageWithMemory>;
+using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
+
+enum class DrawType
+{
+ DRAW = 0,
+ DRAW_INDIRECT,
+ DRAW_INDIRECT_COUNT,
+};
+
+std::ostream& operator<< (std::ostream& stream, DrawType drawType)
+{
+ switch (drawType)
+ {
+ case DrawType::DRAW: stream << "draw"; break;
+ case DrawType::DRAW_INDIRECT: stream << "draw_indirect"; break;
+ case DrawType::DRAW_INDIRECT_COUNT: stream << "draw_indirect_count"; break;
+ default: DE_ASSERT(false); break;
+ }
+ return stream;
+}
+
+
+// This helps test the maxDrawCount rule for the DRAW_INDIRECT_COUNT case.
+enum class IndirectCountLimitType
+{
+ BUFFER_VALUE = 0, // The actual count will be given by the count buffer.
+ MAX_COUNT, // The actual count will be given by the maxDrawCount argument passed to the draw command.
+};
+
+struct IndirectArgs
+{
+ uint32_t offset;
+ uint32_t stride;
+};
+
+struct TestParams
+{
+ DrawType drawType;
+ uint32_t seed;
+ uint32_t drawCount; // Equivalent to taskCount or drawCount.
+ uint32_t firstTask; // Equivalent to firstTask in every call.
+ tcu::Maybe<IndirectArgs> indirectArgs; // Only used for DRAW_INDIRECT*.
+ tcu::Maybe<IndirectCountLimitType> indirectCountLimit; // Only used for DRAW_INDIRECT_COUNT.
+ tcu::Maybe<uint32_t> indirectCountOffset; // Only used for DRAW_INDIRECT_COUNT.
+ bool useTask;
+};
+
+// The framebuffer will have a number of rows and 32 columns. Each mesh shader workgroup will generate geometry to fill a single
+// framebuffer row, using a triangle list with 32 triangles of different colors, each covering a framebuffer pixel.
+//
+// Note: the total framebuffer rows is called "full" below (e.g. 64). When using a task shader to generate work, each workgroup will
+// generate a single mesh workgroup using a push constant instead of a compile-time constant.
+//
+// When using DRAW, the task count will tell us how many rows of pixels will be filled in the framebuffer.
+//
+// When using indirect draws, the full framebuffer will always be drawn into by using multiple draw command structures, except in
+// the case of drawCount==0. Each draw will spawn the needed number of tasks to fill the whole framebuffer. In addition, in order to
+// make all argument structures different, the number of tasks in each draw count will be slightly different and assigned
+// pseudorandomly.
+//
+// DRAW: taskCount=0, taskCount=1, taskCount=2, taskCount=half, taskCount=full
+//
+// DRAW_INDIRECT: drawCount=0, drawCount=1, drawCount=2, drawCount=half, drawCount=full.
+// * With offset 0 and pseudorandom (multiples of 4).
+// * With stride adding a padding of 0 and pseudorandom (multiples of 4).
+//
+// DRAW_INDIRECT_COUNT: same as indirect in two variants:
+// 1. Passing the count in a buffer with a large maximum.
+// 2. Passing a large value in the buffer and limiting it with the maximum.
+
+class MeshApiCase : public vkt::TestCase
+{
+public:
+ MeshApiCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
+ : vkt::TestCase (testCtx, name, description)
+ , m_params (params)
+ {}
+ virtual ~MeshApiCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ void checkSupport (Context& context) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ TestParams m_params;
+};
+
+class MeshApiInstance : public vkt::TestInstance
+{
+public:
+ MeshApiInstance (Context& context, const TestParams& params)
+ : vkt::TestInstance (context)
+ , m_params (params)
+ {}
+ virtual ~MeshApiInstance (void) {}
+
+ tcu::TestStatus iterate (void) override;
+
+protected:
+ TestParams m_params;
+};
+
+TestInstance* MeshApiCase::createInstance (Context& context) const
+{
+ return new MeshApiInstance(context, m_params);
+}
+
+struct PushConstantData
+{
+ uint32_t width;
+ uint32_t height;
+ uint32_t firstTaskMesh;
+ uint32_t one;
+ uint32_t firstTaskTask;
+
+ std::vector<VkPushConstantRange> getRanges (bool includeTask) const
+ {
+ constexpr uint32_t offsetMesh = 0u;
+ constexpr uint32_t offsetTask = static_cast<uint32_t>(offsetof(PushConstantData, one));
+ constexpr uint32_t sizeMesh = offsetTask;
+ constexpr uint32_t sizeTask = static_cast<uint32_t>(sizeof(PushConstantData)) - offsetTask;
+
+ const VkPushConstantRange meshRange =
+ {
+ VK_SHADER_STAGE_MESH_BIT_NV, // VkShaderStageFlags stageFlags;
+ offsetMesh, // uint32_t offset;
+ sizeMesh, // uint32_t size;
+ };
+ const VkPushConstantRange taskRange =
+ {
+ VK_SHADER_STAGE_TASK_BIT_NV, // VkShaderStageFlags stageFlags;
+ offsetTask, // uint32_t offset;
+ sizeTask, // uint32_t size;
+ };
+
+ std::vector<VkPushConstantRange> ranges (1u, meshRange);
+ if (includeTask)
+ ranges.push_back(taskRange);
+ return ranges;
+ }
+};
+
+void MeshApiCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const std::string taskDataDecl =
+ "taskNV TaskData {\n"
+ " uint blockNumber;\n"
+ " uint blockRow;\n"
+ "} td;\n"
+ ;
+
+ // Task shader if needed.
+ if (m_params.useTask)
+ {
+ std::ostringstream task;
+ task
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "\n"
+ << "layout (push_constant, std430) uniform TaskPushConstantBlock {\n"
+ << " layout (offset=12) uint one;\n"
+ << " layout (offset=16) uint firstTask;\n"
+ << "} pc;\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = pc.one;\n"
+ << " td.blockNumber = uint(gl_DrawID);\n"
+ << " td.blockRow = gl_WorkGroupID.x - pc.firstTask;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Mesh shader.
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=32) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=96, max_primitives=32) out;\n"
+ << "\n"
+ << "layout (push_constant, std430) uniform MeshPushConstantBlock {\n"
+ << " uint width;\n"
+ << " uint height;\n"
+ << " uint firstTask;\n"
+ << "} pc;\n"
+ << "\n"
+ << "layout (location=0) perprimitiveNV out vec4 primitiveColor[];\n"
+ << "\n"
+ << (m_params.useTask ? ("in " + taskDataDecl): "")
+ << "\n"
+ << "layout (set=0, binding=0, std430) readonly buffer BlockSizes {\n"
+ << " uint blockSize[];\n"
+ << "} bsz;\n"
+ << "\n"
+ << "uint startOfBlock (uint blockNumber)\n"
+ << "{\n"
+ << " uint start = 0;\n"
+ << " for (uint i = 0; i < blockNumber; i++)\n"
+ << " start += bsz.blockSize[i];\n"
+ << " return start;\n"
+ << "}\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " const uint blockNumber = " << (m_params.useTask ? "td.blockNumber" : "uint(gl_DrawID)") << ";\n"
+ << " const uint blockRow = " << (m_params.useTask ? "td.blockRow" : "(gl_WorkGroupID.x - pc.firstTask)") << ";\n"
+ << "\n"
+ << " // Each workgroup will fill one row, and each invocation will generate a\n"
+ << " // triangle around the pixel center in each column.\n"
+ << " const uint row = startOfBlock(blockNumber) + blockRow;\n"
+ << " const uint col = gl_LocalInvocationID.x;\n"
+ << "\n"
+ << " const float fHeight = float(pc.height);\n"
+ << " const float fWidth = float(pc.width);\n"
+ << "\n"
+ << " // Pixel coordinates, normalized.\n"
+ << " const float rowNorm = (float(row) + 0.5) / fHeight;\n"
+ << " const float colNorm = (float(col) + 0.5) / fWidth;\n"
+ << "\n"
+ << " // Framebuffer coordinates.\n"
+ << " const float coordX = (colNorm * 2.0) - 1.0;\n"
+ << " const float coordY = (rowNorm * 2.0) - 1.0;\n"
+ << "\n"
+ << " const float pixelWidth = 2.0 / fWidth;\n"
+ << " const float pixelHeight = 2.0 / fHeight;\n"
+ << "\n"
+ << " const float offsetX = pixelWidth / 2.0;\n"
+ << " const float offsetY = pixelHeight / 2.0;\n"
+ << "\n"
+ << " const uint baseIndex = col*3;\n"
+ << " const uvec3 indices = uvec3(baseIndex, baseIndex + 1, baseIndex + 2);\n"
+ << "\n"
+ << " gl_PrimitiveCountNV = 32u;\n"
+ << " primitiveColor[col] = vec4(rowNorm, colNorm, 0.0, 1.0);\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[indices.x] = indices.x;\n"
+ << " gl_PrimitiveIndicesNV[indices.y] = indices.y;\n"
+ << " gl_PrimitiveIndicesNV[indices.z] = indices.z;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[indices.x].gl_Position = vec4(coordX - offsetX, coordY + offsetY, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[indices.y].gl_Position = vec4(coordX + offsetX, coordY + offsetY, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[indices.z].gl_Position = vec4(coordX, coordY - offsetY, 0.0, 1.0);\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Frag shader.
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) perprimitiveNV in vec4 primitiveColor;\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " outColor = primitiveColor;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+void MeshApiCase::checkSupport (Context& context) const
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (!meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shaders not supported");
+
+ if (m_params.useTask && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shaders not supported");
+
+ // VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02718
+ if (m_params.drawType == DrawType::DRAW_INDIRECT && m_params.drawCount > 1u)
+ {
+ const auto& features = context.getDeviceFeatures();
+ if (!features.multiDrawIndirect)
+ TCU_THROW(NotSupportedError, "Indirect multi-draws not supported");
+ }
+
+ // VUID-vkCmdDrawMeshTasksIndirectCountNV-None-04445
+ if (m_params.drawType == DrawType::DRAW_INDIRECT_COUNT)
+ context.requireDeviceFunctionality("VK_KHR_draw_indirect_count");
+}
+
+template <typename T>
+BufferWithMemoryPtr makeStridedBuffer(const DeviceInterface& vkd, VkDevice device, Allocator& alloc, const std::vector<T>& elements, uint32_t offset, uint32_t stride, VkBufferUsageFlags usage, uint32_t endPadding)
+{
+ const auto elementSize = static_cast<uint32_t>(sizeof(T));
+ const auto actualStride = std::max(elementSize, stride);
+ const auto bufferSize = static_cast<size_t>(offset) + static_cast<size_t>(actualStride) * elements.size() + static_cast<size_t>(endPadding);
+ const auto bufferInfo = makeBufferCreateInfo(static_cast<VkDeviceSize>(bufferSize), usage);
+
+ BufferWithMemoryPtr buffer(new BufferWithMemory(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible));
+ auto& bufferAlloc = buffer->getAllocation();
+ char* bufferDataPtr = reinterpret_cast<char*>(bufferAlloc.getHostPtr());
+
+ char* itr = bufferDataPtr + offset;
+ for (const auto& elem : elements)
+ {
+ deMemcpy(itr, &elem, sizeof(elem));
+ itr += actualStride;
+ }
+ if (endPadding > 0u)
+ deMemset(itr, 0xFF, endPadding);
+
+ flushAlloc(vkd, device, bufferAlloc);
+
+ return buffer;
+}
+
+VkExtent3D getExtent ()
+{
+ return makeExtent3D(32u, 64u, 1u);
+}
+
+tcu::TestStatus MeshApiInstance::iterate (void)
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto extent = getExtent();
+ const auto iExtent3D = tcu::IVec3(static_cast<int>(extent.width), static_cast<int>(extent.height), static_cast<int>(extent.depth));
+ const auto iExtent2D = tcu::IVec2(iExtent3D.x(), iExtent3D.y());
+ const auto format = VK_FORMAT_R8G8B8A8_UNORM;
+ const auto tcuFormat = mapVkFormat(format);
+ const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
+ const float colorThres = 0.005f; // 1/255 < 0.005 < 2/255
+ const tcu::Vec4 threshold (colorThres, colorThres, 0.0f, 0.0f);
+
+ ImageWithMemoryPtr colorBuffer;
+ Move<VkImageView> colorBufferView;
+ {
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ format, // VkFormat format;
+ extent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ colorUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+ colorBuffer = ImageWithMemoryPtr(new ImageWithMemory(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any));
+ colorBufferView = makeImageView(vkd, device, colorBuffer->get(), VK_IMAGE_VIEW_TYPE_2D, format, colorSRR);
+ }
+
+ // Prepare buffer containing the array of block sizes.
+ de::Random rnd (m_params.seed);
+ std::vector<uint32_t> blockSizes;
+
+ const uint32_t vectorSize = std::max(1u, m_params.drawCount);
+ const uint32_t largeDrawCount = vectorSize + 1u; // The indirect buffer needs to have some padding at the end. See below.
+ const uint32_t evenBlockSize = extent.height / vectorSize;
+ uint32_t remainingRows = extent.height;
+
+ blockSizes.reserve(vectorSize);
+ for (uint32_t i = 0; i < vectorSize - 1u; ++i)
+ {
+ const auto blockSize = static_cast<uint32_t>(rnd.getInt(1, evenBlockSize));
+ remainingRows -= blockSize;
+ blockSizes.push_back(blockSize);
+ }
+ blockSizes.push_back(remainingRows);
+
+ const auto blockSizesBufferSize = static_cast<VkDeviceSize>(de::dataSize(blockSizes));
+ BufferWithMemoryPtr blockSizesBuffer = makeStridedBuffer(vkd, device, alloc, blockSizes, 0u, 0u, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 0u);
+
+ // Descriptor set layout, pool and set.
+ DescriptorSetLayoutBuilder layoutBuilder;
+ layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_NV);
+ const auto setLayout = layoutBuilder.build(vkd, device);
+
+ DescriptorPoolBuilder poolBuilder;
+ poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+ const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
+
+ // Update descriptor set.
+ {
+ DescriptorSetUpdateBuilder updateBuilder;
+
+ const auto location = DescriptorSetUpdateBuilder::Location::binding(0u);
+ const auto descriptorBufferInfo = makeDescriptorBufferInfo(blockSizesBuffer->get(), 0ull, blockSizesBufferSize);
+
+ updateBuilder.writeSingle(descriptorSet.get(), location, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
+ updateBuilder.update(vkd, device);
+ }
+
+ // Pipeline layout.
+ PushConstantData pcData;
+ const auto pcRanges = pcData.getRanges(m_params.useTask);
+ const auto pipelineLayout = makePipelineLayout(vkd, device, 1u, &setLayout.get(), static_cast<uint32_t>(pcRanges.size()), de::dataOrNull(pcRanges));
+
+ // Push constants.
+ pcData.width = extent.width;
+ pcData.height = extent.height;
+ pcData.firstTaskMesh = m_params.firstTask;
+ pcData.one = 1u;
+ pcData.firstTaskTask = m_params.firstTask;
+
+ // Render pass and framebuffer.
+ const auto renderPass = makeRenderPass(vkd, device, format);
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), extent.width, extent.height);
+
+ // Pipeline.
+ Move<VkShaderModule> taskModule;
+ Move<VkShaderModule> meshModule;
+ Move<VkShaderModule> fragModule;
+
+ const auto& binaries = m_context.getBinaryCollection();
+ if (m_params.useTask)
+ taskModule = createShaderModule(vkd, device, binaries.get("task"));
+ meshModule = createShaderModule(vkd, device, binaries.get("mesh"));
+ fragModule = createShaderModule(vkd, device, binaries.get("frag"));
+
+ const std::vector<VkViewport> viewports (1u, makeViewport(extent));
+ const std::vector<VkRect2D> scissors (1u, makeRect2D(extent));
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskModule.get(), meshModule.get(), fragModule.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ // Indirect and count buffers if needed.
+ BufferWithMemoryPtr indirectBuffer;
+ BufferWithMemoryPtr countBuffer;
+
+ if (m_params.drawType != DrawType::DRAW)
+ {
+ // Indirect draws.
+ DE_ASSERT(static_cast<bool>(m_params.indirectArgs));
+ const auto& indirectArgs = m_params.indirectArgs.get();
+
+ // Check stride and offset validity.
+ DE_ASSERT(indirectArgs.offset % 4u == 0u);
+ DE_ASSERT(indirectArgs.stride % 4u == 0u && (indirectArgs.stride == 0u || indirectArgs.stride >= static_cast<uint32_t>(sizeof(VkDrawMeshTasksIndirectCommandNV))));
+
+ // Prepare struct vector, which will be converted to a buffer with the proper stride and offset later.
+ std::vector<VkDrawMeshTasksIndirectCommandNV> commands;
+ commands.reserve(blockSizes.size());
+
+ std::transform(begin(blockSizes), end(blockSizes), std::back_inserter(commands),
+ [this](uint32_t blockSize) { return VkDrawMeshTasksIndirectCommandNV{blockSize, this->m_params.firstTask}; });
+
+ const auto padding = static_cast<uint32_t>(sizeof(VkDrawMeshTasksIndirectCommandNV));
+ indirectBuffer = makeStridedBuffer(vkd, device, alloc, commands, indirectArgs.offset, indirectArgs.stride, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, padding);
+
+ // Prepare count buffer if needed.
+ if (m_params.drawType == DrawType::DRAW_INDIRECT_COUNT)
+ {
+ DE_ASSERT(static_cast<bool>(m_params.indirectCountLimit));
+ DE_ASSERT(static_cast<bool>(m_params.indirectCountOffset));
+
+ const auto countBufferValue = ((m_params.indirectCountLimit.get() == IndirectCountLimitType::BUFFER_VALUE)
+ ? m_params.drawCount
+ : largeDrawCount);
+
+ const std::vector<uint32_t> singleCount (1u, countBufferValue);
+ countBuffer = makeStridedBuffer(vkd, device, alloc, singleCount, m_params.indirectCountOffset.get(), static_cast<uint32_t>(sizeof(uint32_t)), VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, 0u);
+ }
+ }
+
+ // Submit commands.
+ beginCommandBuffer(vkd, cmdBuffer);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
+
+ vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
+ {
+ const char* pcDataPtr = reinterpret_cast<const char*>(&pcData);
+ for (const auto& range : pcRanges)
+ vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), range.stageFlags, range.offset, range.size, pcDataPtr + range.offset);
+ }
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+
+ if (m_params.drawType == DrawType::DRAW)
+ {
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params.drawCount, m_params.firstTask);
+ }
+ else if (m_params.drawType == DrawType::DRAW_INDIRECT)
+ {
+ const auto& indirectArgs = m_params.indirectArgs.get();
+ vkd.cmdDrawMeshTasksIndirectNV(cmdBuffer, indirectBuffer->get(), indirectArgs.offset, m_params.drawCount, indirectArgs.stride);
+ }
+ else if (m_params.drawType == DrawType::DRAW_INDIRECT_COUNT)
+ {
+ const auto& indirectArgs = m_params.indirectArgs.get();
+ const auto& indirectCountOffset = m_params.indirectCountOffset.get();
+ const auto& indirectCountLimit = m_params.indirectCountLimit.get();
+
+ const auto maxCount = ((indirectCountLimit == IndirectCountLimitType::MAX_COUNT)
+ ? m_params.drawCount
+ : largeDrawCount);
+ vkd.cmdDrawMeshTasksIndirectCountNV(cmdBuffer, indirectBuffer->get(), indirectArgs.offset, countBuffer->get(), indirectCountOffset, maxCount, indirectArgs.stride);
+ }
+ else
+ DE_ASSERT(false);
+
+ endRenderPass(vkd, cmdBuffer);
+
+ // Output buffer to extract the color buffer.
+ BufferWithMemoryPtr outBuffer;
+ void* outBufferData = nullptr;
+ {
+ const auto outBufferSize = static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * extent.width * extent.height);
+ const auto outBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ const auto outBufferInfo = makeBufferCreateInfo(outBufferSize, outBufferUsage);
+
+ outBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible));
+ outBufferData = outBuffer->getAllocation().getHostPtr();
+ }
+
+ copyImageToBuffer(vkd, cmdBuffer, colorBuffer->get(), outBuffer->get(), iExtent2D);
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Generate reference image and compare.
+ {
+ auto& log = m_context.getTestContext().getLog();
+ auto& outBufferAlloc = outBuffer->getAllocation();
+ tcu::ConstPixelBufferAccess result (tcuFormat, iExtent3D, outBufferData);
+ tcu::TextureLevel referenceLevel (tcuFormat, iExtent3D.x(), iExtent3D.y());
+ const auto reference = referenceLevel.getAccess();
+ const auto setName = de::toString(m_params.drawType) + "_draw_count_" + de::toString(m_params.drawCount) + (m_params.useTask ? "_with_task" : "_no_task");
+ const auto fHeight = static_cast<float>(extent.height);
+ const auto fWidth = static_cast<float>(extent.width);
+
+ invalidateAlloc(vkd, device, outBufferAlloc);
+
+ for (int y = 0; y < iExtent3D.y(); ++y)
+ for (int x = 0; x < iExtent3D.x(); ++x)
+ {
+ const tcu::Vec4 refColor = ((m_params.drawCount == 0u || (m_params.drawType == DrawType::DRAW && y >= static_cast<int>(m_params.drawCount)))
+ ? clearColor
+ : tcu::Vec4(
+ // These match the per-primitive color set by the mesh shader.
+ (static_cast<float>(y) + 0.5f) / fHeight,
+ (static_cast<float>(x) + 0.5f) / fWidth,
+ 0.0f,
+ 1.0f));
+ reference.setPixel(refColor, x, y);
+ }
+
+ if (!tcu::floatThresholdCompare(log, setName.c_str(), "", reference, result, threshold, tcu::COMPARE_LOG_ON_ERROR))
+ return tcu::TestStatus::fail("Image comparison failed; check log for details");
+ }
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createMeshShaderApiTests (tcu::TestContext& testCtx)
+{
+ GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "api", "Mesh Shader API tests"));
+
+ const DrawType drawCases[] =
+ {
+ DrawType::DRAW,
+ DrawType::DRAW_INDIRECT,
+ DrawType::DRAW_INDIRECT_COUNT,
+ };
+
+ const auto extent = getExtent();
+ const uint32_t drawCountCases[] = { 0u, 1u, 2u, extent.height / 2u, extent.height };
+
+ const uint32_t normalStride = static_cast<uint32_t>(sizeof(VkDrawMeshTasksIndirectCommandNV));
+ const uint32_t largeStride = 2u * normalStride + 4u;
+ const uint32_t altOffset = 20u;
+
+ const struct
+ {
+ tcu::Maybe<IndirectArgs> indirectArgs;
+ const char* name;
+ } indirectArgsCases[] =
+ {
+ { tcu::nothing<IndirectArgs>(), "no_indirect_args" },
+
+ // Offset 0, varying strides.
+ { tcu::just(IndirectArgs{ 0u, 0u }), "offset_0_stride_0" },
+ { tcu::just(IndirectArgs{ 0u, normalStride }), "offset_0_stride_normal" },
+ { tcu::just(IndirectArgs{ 0u, largeStride }), "offset_0_stride_large" },
+
+ // Nonzero offset, varying strides.
+ { tcu::just(IndirectArgs{ altOffset, 0u }), "offset_alt_stride_0" },
+ { tcu::just(IndirectArgs{ altOffset, normalStride }), "offset_alt_stride_normal" },
+ { tcu::just(IndirectArgs{ altOffset, largeStride }), "offset_alt_stride_large" },
+ };
+
+ const struct
+ {
+ tcu::Maybe<IndirectCountLimitType> limitType;
+ const char* name;
+ } countLimitCases[] =
+ {
+ { tcu::nothing<IndirectCountLimitType>(), "no_count_limit" },
+ { tcu::just(IndirectCountLimitType::BUFFER_VALUE), "count_limit_buffer" },
+ { tcu::just(IndirectCountLimitType::MAX_COUNT), "count_limit_max_count" },
+ };
+
+ const struct
+ {
+ tcu::Maybe<uint32_t> countOffset;
+ const char* name;
+ } countOffsetCases[] =
+ {
+ { tcu::nothing<uint32_t>(), "no_count_offset" },
+ { tcu::just(uint32_t{0u}), "count_offset_0" },
+ { tcu::just(altOffset), "count_offset_alt" },
+ };
+
+ const struct
+ {
+ bool useTask;
+ const char* name;
+ } taskCases[] =
+ {
+ { false, "no_task_shader" },
+ { true, "with_task_shader" },
+ };
+
+ const struct
+ {
+ uint32_t firstTask;
+ const char* name;
+ } firstTaskCases[] =
+ {
+ { 0u, "first_task_zero" },
+ { 1001u, "first_task_nonzero" },
+ };
+
+ uint32_t seed = 1628678795u;
+
+ for (const auto& drawCase : drawCases)
+ {
+ const auto drawCaseName = de::toString(drawCase);
+ const bool isIndirect = (drawCase != DrawType::DRAW);
+ const bool isIndirectNoCount = (drawCase == DrawType::DRAW_INDIRECT);
+ const bool isIndirectCount = (drawCase == DrawType::DRAW_INDIRECT_COUNT);
+
+ GroupPtr drawGroup(new tcu::TestCaseGroup(testCtx, drawCaseName.c_str(), ""));
+
+ for (const auto& drawCountCase : drawCountCases)
+ {
+ const auto drawCountName = "draw_count_" + de::toString(drawCountCase);
+ GroupPtr drawCountGroup(new tcu::TestCaseGroup(testCtx, drawCountName.c_str(), ""));
+
+ for (const auto& indirectArgsCase : indirectArgsCases)
+ {
+ const bool hasIndirectArgs = static_cast<bool>(indirectArgsCase.indirectArgs);
+ const bool strideZero = (hasIndirectArgs && indirectArgsCase.indirectArgs.get().stride == 0u);
+
+ if (isIndirect != hasIndirectArgs)
+ continue;
+
+ // VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02146 and VUID-vkCmdDrawMeshTasksIndirectCountNV-stride-02182.
+ if (((isIndirectNoCount && drawCountCase > 1u) || isIndirectCount) && strideZero)
+ continue;
+
+ GroupPtr indirectArgsGroup(new tcu::TestCaseGroup(testCtx, indirectArgsCase.name, ""));
+
+ for (const auto& countLimitCase : countLimitCases)
+ {
+ const bool hasCountLimit = static_cast<bool>(countLimitCase.limitType);
+
+ if (isIndirectCount != hasCountLimit)
+ continue;
+
+ GroupPtr countLimitGroup(new tcu::TestCaseGroup(testCtx, countLimitCase.name, ""));
+
+ for (const auto& countOffsetCase : countOffsetCases)
+ {
+ const bool hasCountOffsetType = static_cast<bool>(countOffsetCase.countOffset);
+
+ if (isIndirectCount != hasCountOffsetType)
+ continue;
+
+ GroupPtr countOffsetGroup(new tcu::TestCaseGroup(testCtx, countOffsetCase.name, ""));
+
+ for (const auto& taskCase : taskCases)
+ {
+ GroupPtr taskCaseGrp(new tcu::TestCaseGroup(testCtx, taskCase.name, ""));
+
+ for (const auto& firstTaskCase : firstTaskCases)
+ {
+ const TestParams params =
+ {
+ drawCase, // DrawType drawType;
+ seed++, // uint32_t seed;
+ drawCountCase, // uint32_t drawCount;
+ firstTaskCase.firstTask, // uint32_t firstTask;
+ indirectArgsCase.indirectArgs, // tcu::Maybe<IndirectArgs> indirectArgs;
+ countLimitCase.limitType, // tcu::Maybe<IndirectCountLimitType> indirectCountLimit;
+ countOffsetCase.countOffset, // tcu::Maybe<uint32_t> indirectCountOffset;
+ taskCase.useTask, // bool useTask;
+ };
+
+ taskCaseGrp->addChild(new MeshApiCase(testCtx, firstTaskCase.name, "", params));
+ }
+
+ countOffsetGroup->addChild(taskCaseGrp.release());
+ }
+
+ countLimitGroup->addChild(countOffsetGroup.release());
+ }
+
+ indirectArgsGroup->addChild(countLimitGroup.release());
+ }
+
+ drawCountGroup->addChild(indirectArgsGroup.release());
+ }
+
+ drawGroup->addChild(drawCountGroup.release());
+ }
+
+ mainGroup->addChild(drawGroup.release());
+ }
+
+ return mainGroup.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERAPITESTS_HPP
+#define _VKTMESHSHADERAPITESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader API Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderApiTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERAPITESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Builtin Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderBuiltinTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkObjUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkBarrierUtil.hpp"
+
+#include "tcuTexture.hpp"
+#include "tcuTestLog.hpp"
+
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <map>
+#include <utility>
+#include <sstream>
+
+namespace tcu
+{
+// Needed for PixelMap below.
+bool operator<(const IVec2& a, const IVec2& b)
+{
+ return (a.x() < b.x() || (a.x() == b.x() && a.y() < b.y()));
+}
+}
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using namespace vk;
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+using DrawCommandVec = std::vector<VkDrawMeshTasksIndirectCommandNV>;
+using ImageWithMemoryPtr = de::MovePtr<ImageWithMemory>;
+using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
+using ViewportVec = std::vector<VkViewport>;
+using ColorVec = std::vector<tcu::Vec4>;
+using PixelMap = std::map<tcu::IVec2, tcu::Vec4>; // Coordinates to color.
+
+VkExtent2D getDefaultExtent ()
+{
+ return makeExtent2D(8u, 8u);
+}
+
+VkExtent2D getLinearExtent ()
+{
+ return makeExtent2D(8u, 1u);
+}
+
+struct JobSize
+{
+ uint32_t numTasks;
+ uint32_t localSize;
+};
+
+JobSize getLargeJobSize ()
+{
+ return JobSize{8u, 8u};
+}
+
+// Single draw command with the given number of tasks, 1 by default.
+DrawCommandVec getDefaultDrawCommands (uint32_t taskCount = 1u)
+{
+ return DrawCommandVec(1u, makeDrawMeshTasksIndirectCommandNV(taskCount, 0u));
+}
+
+// Basic fragment shader that draws fragments in blue.
+std::string getBasicFragShader ()
+{
+ return
+ "#version 460\n"
+ "#extension GL_NV_mesh_shader : enable\n"
+ "\n"
+ "layout (location=0) out vec4 outColor;\n"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ "}\n"
+ ;
+}
+
+struct IterationParams
+{
+ VkExtent2D colorExtent;
+ uint32_t numLayers;
+ DrawCommandVec drawArgs;
+ bool indirect;
+ ViewportVec viewports; // If empty, a single default viewport is used.
+};
+
+class MeshShaderBuiltinInstance : public vkt::TestInstance
+{
+public:
+ MeshShaderBuiltinInstance (Context& context, const IterationParams& params)
+ : vkt::TestInstance (context)
+ , m_params (params)
+ {}
+ virtual ~MeshShaderBuiltinInstance (void) {}
+
+ tcu::TestStatus iterate () override;
+ virtual void verifyResults (const tcu::ConstPixelBufferAccess& result) = 0;
+
+protected:
+ IterationParams m_params;
+};
+
+tcu::TestStatus MeshShaderBuiltinInstance::iterate ()
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+ const auto& binaries = m_context.getBinaryCollection();
+
+ const auto useTask = binaries.contains("task");
+ const auto useFrag = binaries.contains("frag");
+ const auto extent = makeExtent3D(m_params.colorExtent.width, m_params.colorExtent.height, 1u);
+ const auto iExtent3D = tcu::IVec3(static_cast<int>(extent.width), static_cast<int>(extent.height), static_cast<int>(m_params.numLayers));
+ const auto format = VK_FORMAT_R8G8B8A8_UNORM;
+ const auto tcuFormat = mapVkFormat(format);
+ const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ const auto viewType = ((m_params.numLayers > 1u) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_params.numLayers);
+ const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_params.numLayers);
+ const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
+
+ ImageWithMemoryPtr colorBuffer;
+ Move<VkImageView> colorBufferView;
+ {
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ format, // VkFormat format;
+ extent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ m_params.numLayers, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ colorUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+ colorBuffer = ImageWithMemoryPtr(new ImageWithMemory(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any));
+ colorBufferView = makeImageView(vkd, device, colorBuffer->get(), viewType, format, colorSRR);
+ }
+
+ // Empty descriptor set layout.
+ DescriptorSetLayoutBuilder layoutBuilder;
+ const auto setLayout = layoutBuilder.build(vkd, device);
+
+ // Pipeline layout.
+ const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+
+ // Render pass and framebuffer.
+ const auto renderPass = makeRenderPass(vkd, device, format);
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), extent.width, extent.height, m_params.numLayers);
+
+ // Pipeline.
+ Move<VkShaderModule> taskModule;
+ Move<VkShaderModule> meshModule;
+ Move<VkShaderModule> fragModule;
+
+ if (useTask)
+ taskModule = createShaderModule(vkd, device, binaries.get("task"));
+ if (useFrag)
+ fragModule = createShaderModule(vkd, device, binaries.get("frag"));
+ meshModule = createShaderModule(vkd, device, binaries.get("mesh"));
+
+ std::vector<VkViewport> viewports;
+ std::vector<VkRect2D> scissors;
+ if (m_params.viewports.empty())
+ {
+ // Default ones.
+ viewports.push_back(makeViewport(extent));
+ scissors.push_back(makeRect2D(extent));
+ }
+ else
+ {
+ // The desired viewports and the same number of default scissors.
+ viewports.reserve(m_params.viewports.size());
+ std::copy(begin(m_params.viewports), end(m_params.viewports), std::back_inserter(viewports));
+ scissors.resize(viewports.size(), makeRect2D(extent));
+ }
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskModule.get(), meshModule.get(), fragModule.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ // Indirect buffer if needed.
+ BufferWithMemoryPtr indirectBuffer;
+
+ DE_ASSERT(!m_params.drawArgs.empty());
+ if (m_params.indirect)
+ {
+ // Indirect draws.
+ const auto indirectBufferSize = static_cast<VkDeviceSize>(de::dataSize(m_params.drawArgs));
+ const auto indirectBufferUsage = (VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
+ const auto indirectBufferInfo = makeBufferCreateInfo(indirectBufferSize, indirectBufferUsage);
+ indirectBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, indirectBufferInfo, MemoryRequirement::HostVisible));
+ auto& indirectBufferAlloc = indirectBuffer->getAllocation();
+ void* indirectBufferData = indirectBufferAlloc.getHostPtr();
+
+ deMemcpy(indirectBufferData, m_params.drawArgs.data(), static_cast<size_t>(indirectBufferSize));
+ flushAlloc(vkd, device, indirectBufferAlloc);
+ }
+
+ // Submit commands.
+ beginCommandBuffer(vkd, cmdBuffer);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+
+ if (!m_params.indirect)
+ {
+ for (const auto& command : m_params.drawArgs)
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, command.taskCount, command.firstTask);
+ }
+ else
+ {
+ const auto numDraws = static_cast<uint32_t>(m_params.drawArgs.size());
+ const auto stride = static_cast<uint32_t>(sizeof(decltype(m_params.drawArgs)::value_type));
+ vkd.cmdDrawMeshTasksIndirectNV(cmdBuffer, indirectBuffer->get(), 0ull, numDraws, stride);
+ }
+
+ endRenderPass(vkd, cmdBuffer);
+
+ // Output buffer to extract the color buffer contents.
+ BufferWithMemoryPtr outBuffer;
+ void* outBufferData = nullptr;
+ {
+ const auto layerSize = static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * extent.width * extent.height);
+ const auto outBufferSize = layerSize * m_params.numLayers;
+ const auto outBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ const auto outBufferInfo = makeBufferCreateInfo(outBufferSize, outBufferUsage);
+
+ outBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible));
+ outBufferData = outBuffer->getAllocation().getHostPtr();
+ }
+
+ // Transition image layout.
+ const auto preTransferBarrier = makeImageMemoryBarrier(
+ (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), VK_ACCESS_TRANSFER_READ_BIT,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ colorBuffer->get(), colorSRR);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTransferBarrier);
+
+ // Copy image to output buffer.
+ const std::vector<VkBufferImageCopy> regions (1u, makeBufferImageCopy(extent, colorSRL));
+ vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outBuffer->get(), static_cast<uint32_t>(regions.size()), de::dataOrNull(regions));
+
+ // Transfer to host barrier.
+ const auto postTransferBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postTransferBarrier, 0u, nullptr, 0u, nullptr);
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Invalidate alloc and verify result.
+ {
+ auto& outBufferAlloc = outBuffer->getAllocation();
+ invalidateAlloc(vkd, device, outBufferAlloc);
+
+ tcu::ConstPixelBufferAccess result (tcuFormat, iExtent3D, outBufferData);
+ verifyResults(result);
+ }
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+// Abstract case that implements the generic checkSupport method.
+class MeshShaderBuiltinCase : public vkt::TestCase
+{
+public:
+ MeshShaderBuiltinCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
+ : vkt::TestCase (testCtx, name, description)
+ , m_taskNeeded (taskNeeded)
+ {}
+ virtual ~MeshShaderBuiltinCase (void) {}
+
+ void checkSupport (Context& context) const override;
+
+protected:
+ const bool m_taskNeeded;
+};
+
+void MeshShaderBuiltinCase::checkSupport (Context& context) const
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (!meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shader not supported");
+
+ if (m_taskNeeded && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shader not supported");
+}
+
+// Instance that verifies color layers.
+class FullScreenColorInstance : public MeshShaderBuiltinInstance
+{
+public:
+ FullScreenColorInstance (Context& context, const IterationParams& params, const ColorVec& expectedColors)
+ : MeshShaderBuiltinInstance (context, params)
+ , m_expectedColors (expectedColors)
+ {}
+ virtual ~FullScreenColorInstance (void) {}
+
+ void verifyResults (const tcu::ConstPixelBufferAccess& result) override;
+
+protected:
+ const ColorVec m_expectedColors;
+};
+
+void FullScreenColorInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
+{
+ auto& log = m_context.getTestContext().getLog();
+ bool fail = false;
+ const auto width = result.getWidth();
+ const auto height = result.getHeight();
+ const auto depth = result.getDepth();
+
+ for (int z = 0; z < depth; ++z)
+ {
+ const auto& expected = m_expectedColors.at(z);
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ const auto resultColor = result.getPixel(x, y, z);
+ if (resultColor != expected)
+ {
+ std::ostringstream msg;
+ msg << "Pixel (" << x << ", " << y << ", " << z << ") failed: expected " << expected << " and found " << resultColor;
+ log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
+ fail = true;
+ }
+ }
+ }
+
+ if (fail)
+ {
+ log << tcu::TestLog::Image("Result", "", result);
+ TCU_FAIL("Check log for details");
+ }
+}
+
+// Instance that verifies single-layer framebuffers divided into 4 quadrants.
+class QuadrantsInstance : public MeshShaderBuiltinInstance
+{
+public:
+ QuadrantsInstance (Context& context, const IterationParams& params,
+ const tcu::Vec4 topLeft,
+ const tcu::Vec4 topRight,
+ const tcu::Vec4 bottomLeft,
+ const tcu::Vec4 bottomRight)
+ : MeshShaderBuiltinInstance (context, params)
+ , m_topLeft (topLeft)
+ , m_topRight (topRight)
+ , m_bottomLeft (bottomLeft)
+ , m_bottomRight (bottomRight)
+ {}
+ virtual ~QuadrantsInstance (void) {}
+
+ void verifyResults (const tcu::ConstPixelBufferAccess& result) override;
+
+protected:
+ const tcu::Vec4 m_topLeft;
+ const tcu::Vec4 m_topRight;
+ const tcu::Vec4 m_bottomLeft;
+ const tcu::Vec4 m_bottomRight;
+};
+
+void QuadrantsInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
+{
+ const auto width = result.getWidth();
+ const auto height = result.getHeight();
+ const auto depth = result.getDepth();
+
+ DE_ASSERT(depth == 1);
+ DE_ASSERT(width > 0 && width % 2 == 0);
+ DE_ASSERT(height > 0 && height % 2 == 0);
+ DE_UNREF(depth); // For release builds.
+
+ const auto halfWidth = width / 2;
+ const auto halfHeight = height / 2;
+ tcu::Vec4 expected;
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ // Choose the right quadrant
+ if (y < halfHeight)
+ expected = ((x < halfWidth) ? m_topLeft : m_topRight);
+ else
+ expected = ((x < halfWidth) ? m_bottomLeft : m_bottomRight);
+
+ const auto resultColor = result.getPixel(x, y);
+ if (resultColor != expected)
+ {
+ std::ostringstream msg;
+ msg << "Pixel (" << x << ", " << y << ") failed: expected " << expected << " and found " << resultColor;
+ TCU_FAIL(msg.str());
+ }
+ }
+}
+
+// Instance that verifies single-layer framebuffers with specific pixels set to some color.
+struct PixelVerifierParams
+{
+ const tcu::Vec4 background;
+ const PixelMap pixelMap;
+};
+
+class PixelsInstance : public MeshShaderBuiltinInstance
+{
+public:
+ PixelsInstance (Context& context, const IterationParams& params, const PixelVerifierParams& pixelParams)
+ : MeshShaderBuiltinInstance (context, params)
+ , m_pixelParams (pixelParams)
+ {}
+ virtual ~PixelsInstance (void) {}
+
+ void verifyResults (const tcu::ConstPixelBufferAccess& result) override;
+
+protected:
+ const PixelVerifierParams m_pixelParams;
+};
+
+void PixelsInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
+{
+ const auto width = result.getWidth();
+ const auto height = result.getHeight();
+ const auto depth = result.getDepth();
+
+ DE_ASSERT(depth == 1);
+ DE_UNREF(depth); // For release builds.
+
+ for (int y = 0; y < height; ++y)
+ for (int x = 0; x < width; ++x)
+ {
+ const tcu::IVec2 coords (x, y);
+ const auto iter = m_pixelParams.pixelMap.find(coords);
+ const auto expected = ((iter == m_pixelParams.pixelMap.end()) ? m_pixelParams.background : iter->second);
+ const auto resultColor = result.getPixel(x, y);
+
+ if (resultColor != expected)
+ {
+ std::ostringstream msg;
+ msg << "Pixel (" << x << ", " << y << ") failed: expected " << expected << " and found " << resultColor;
+ TCU_FAIL(msg.str());
+ }
+ }
+}
+
+// Primitive ID cases.
+class PrimitiveIdCase : public MeshShaderBuiltinCase
+{
+public:
+ PrimitiveIdCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool glslFrag)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ , m_glslFrag (glslFrag)
+ {}
+ virtual ~PrimitiveIdCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ void checkSupport (Context& context) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ // Fragment shader in GLSL means glslang will use the Geometry capability due to gl_PrimitiveID.
+ const bool m_glslFrag;
+};
+
+void PrimitiveIdCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Mesh shader.
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
+ << " int gl_PrimitiveID;\n"
+ << "} gl_MeshPrimitivesNV[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
+ << "\n"
+ // Sets an arbitrary primitive id.
+ << " gl_MeshPrimitivesNV[0].gl_PrimitiveID = 1629198956;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Frag shader.
+ if (m_glslFrag)
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ // Checks the primitive id matches.
+ << " outColor = ((gl_PrimitiveID == 1629198956) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+ else
+ {
+ // This is the same shader as above, but OpCapability Geometry has been replaced by OpCapability MeshShadingNV in order to
+ // access gl_PrimitiveID. This also needs the SPV_NV_mesh_shader extension.
+ std::ostringstream frag;
+ frag
+ << "; Version: 1.0\n"
+ << "; Generator: Khronos Glslang Reference Front End; 10\n"
+ << "; Bound: 24\n"
+ << "; Schema: 0\n"
+ << " OpCapability Shader\n"
+
+ // Manual change in these lines.
+ //<< " OpCapability Geometry\n"
+ << " OpCapability MeshShadingNV\n"
+ << " OpExtension \"SPV_NV_mesh_shader\"\n"
+
+ << " %1 = OpExtInstImport \"GLSL.std.450\"\n"
+ << " OpMemoryModel Logical GLSL450\n"
+ << " OpEntryPoint Fragment %4 \"main\" %9 %12\n"
+ << " OpExecutionMode %4 OriginUpperLeft\n"
+ << " OpDecorate %9 Location 0\n"
+ << " OpDecorate %12 Flat\n"
+ << " OpDecorate %12 BuiltIn PrimitiveId\n"
+ << " %2 = OpTypeVoid\n"
+ << " %3 = OpTypeFunction %2\n"
+ << " %6 = OpTypeFloat 32\n"
+ << " %7 = OpTypeVector %6 4\n"
+ << " %8 = OpTypePointer Output %7\n"
+ << " %9 = OpVariable %8 Output\n"
+ << "%10 = OpTypeInt 32 1\n"
+ << "%11 = OpTypePointer Input %10\n"
+ << "%12 = OpVariable %11 Input\n"
+ << "%14 = OpConstant %10 1629198956\n"
+ << "%15 = OpTypeBool\n"
+ << "%17 = OpConstant %6 0\n"
+ << "%18 = OpConstant %6 1\n"
+ << "%19 = OpConstantComposite %7 %17 %17 %18 %18\n"
+ << "%20 = OpConstantComposite %7 %17 %17 %17 %18\n"
+ << "%21 = OpTypeVector %15 4\n"
+ << " %4 = OpFunction %2 None %3\n"
+ << " %5 = OpLabel\n"
+ << "%13 = OpLoad %10 %12\n"
+ << "%16 = OpIEqual %15 %13 %14\n"
+ << "%22 = OpCompositeConstruct %21 %16 %16 %16 %16\n"
+ << "%23 = OpSelect %7 %22 %19 %20\n"
+ << " OpStore %9 %23\n"
+ << " OpReturn\n"
+ << " OpFunctionEnd\n"
+ ;
+ programCollection.spirvAsmSources.add("frag") << frag.str();
+ }
+}
+
+void PrimitiveIdCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+
+ // Fragment shader in GLSL means glslang will use the Geometry capability due to gl_PrimitiveID.
+ if (m_glslFrag)
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
+}
+
+TestInstance* PrimitiveIdCase::createInstance (Context& context) const
+{
+ const ColorVec expectedColors (1u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+// Layer builtin case.
+class LayerCase : public MeshShaderBuiltinCase
+{
+public:
+ LayerCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool shareVertices)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ , m_shareVertices (shareVertices)
+ {}
+ virtual ~LayerCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ void checkSupport (Context& context) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+ static constexpr uint32_t kNumLayers = 4u;
+
+protected:
+ const bool m_shareVertices;
+};
+
+void LayerCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto localSize = (m_shareVertices ? kNumLayers : 1u);
+ const auto numPrimitives = (m_shareVertices ? kNumLayers : 1u);
+ const auto layerNumber = (m_shareVertices ? "gl_LocalInvocationIndex" : "gl_WorkGroupID.x");
+
+ // One layer per local invocation or work group (shared vertices or not, respectively).
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << localSize << ") in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=" << numPrimitives << ") out;\n"
+ << "\n"
+ << "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
+ << " int gl_Layer;\n"
+ << "} gl_MeshPrimitivesNV[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = " << numPrimitives << ";\n"
+ << "\n"
+ << " if (gl_LocalInvocationIndex == 0u)\n"
+ << " {\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
+ << " }\n"
+ << "\n"
+ << " const uint baseIndex = gl_LocalInvocationIndex * 3u;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 2] = 2;\n"
+ << "\n"
+ << " gl_MeshPrimitivesNV[gl_LocalInvocationIndex].gl_Layer = int(" << layerNumber << ");\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Fragment shader chooses one color per layer.
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "vec4 colors[" << kNumLayers << "] = vec4[](\n"
+ << " vec4(0.0, 0.0, 1.0, 1.0),\n"
+ << " vec4(1.0, 0.0, 1.0, 1.0),\n"
+ << " vec4(0.0, 1.0, 1.0, 1.0),\n"
+ << " vec4(1.0, 1.0, 0.0, 1.0)\n"
+ << ");\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " outColor = colors[gl_Layer];\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+void LayerCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+
+ if (!context.contextSupports(vk::ApiVersion(1u, 2u, 0u)))
+ context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
+ else
+ {
+ const auto& features = context.getDeviceVulkan12Features();
+ if (!features.shaderOutputLayer)
+ TCU_THROW(NotSupportedError, "shaderOutputLayer feature not supported");
+ }
+}
+
+TestInstance* LayerCase::createInstance (Context& context) const
+{
+ ColorVec expectedColors;
+
+ expectedColors.reserve(kNumLayers);
+ expectedColors.push_back(tcu::Vec4(0.0, 0.0, 1.0, 1.0));
+ expectedColors.push_back(tcu::Vec4(1.0, 0.0, 1.0, 1.0));
+ expectedColors.push_back(tcu::Vec4(0.0, 1.0, 1.0, 1.0));
+ expectedColors.push_back(tcu::Vec4(1.0, 1.0, 0.0, 1.0));
+
+ const auto numWorkGroups = (m_shareVertices ? 1u : kNumLayers);
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ kNumLayers, // uint32_t numLayers;
+ getDefaultDrawCommands(numWorkGroups), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+// ViewportIndex builtin case.
+class ViewportIndexCase : public MeshShaderBuiltinCase
+{
+public:
+ ViewportIndexCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool shareVertices)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ , m_shareVertices (shareVertices)
+ {}
+ virtual ~ViewportIndexCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ void checkSupport (Context& context) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+ static constexpr uint32_t kQuadrants = 4u;
+
+protected:
+ const bool m_shareVertices;
+};
+
+void ViewportIndexCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto localSize = (m_shareVertices ? kQuadrants : 1u);
+ const auto numPrimitives = (m_shareVertices ? kQuadrants : 1u);
+ const auto viewportIndex = (m_shareVertices ? "gl_LocalInvocationIndex" : "gl_WorkGroupID.x");
+
+ // One viewport per local invocation or work group (sharing vertices or not, respectively).
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << localSize << ") in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=" << numPrimitives << ") out;\n"
+ << "\n"
+ << "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
+ << " int gl_ViewportIndex;\n"
+ << "} gl_MeshPrimitivesNV[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = " << numPrimitives << ";\n"
+ << "\n"
+ << " if (gl_LocalInvocationIndex == 0u)\n"
+ << " {\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
+ << " }\n"
+ << "\n"
+ << " const uint baseIndex = gl_LocalInvocationIndex * 3u;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[baseIndex + 2] = 2;\n"
+ << "\n"
+ << " gl_MeshPrimitivesNV[gl_LocalInvocationIndex].gl_ViewportIndex = int(" << viewportIndex << ");\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Fragment shader chooses one color per viewport.
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "vec4 colors[" << kQuadrants << "] = vec4[](\n"
+ << " vec4(0.0, 0.0, 1.0, 1.0),\n"
+ << " vec4(1.0, 0.0, 1.0, 1.0),\n"
+ << " vec4(0.0, 1.0, 1.0, 1.0),\n"
+ << " vec4(1.0, 1.0, 0.0, 1.0)\n"
+ << ");\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " outColor = colors[gl_ViewportIndex];\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+void ViewportIndexCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
+
+ if (!context.contextSupports(vk::ApiVersion(1u, 2u, 0u)))
+ context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
+ else
+ {
+ const auto& features = context.getDeviceVulkan12Features();
+ if (!features.shaderOutputViewportIndex)
+ TCU_THROW(NotSupportedError, "shaderOutputViewportIndex feature not supported");
+ }
+}
+
+TestInstance* ViewportIndexCase::createInstance (Context& context) const
+{
+ const auto extent = getDefaultExtent();
+
+ DE_ASSERT(extent.width > 0u && extent.width % 2u == 0u);
+ DE_ASSERT(extent.height > 0u && extent.height % 2u == 0u);
+
+ const auto halfWidth = static_cast<float>(extent.width / 2u);
+ const auto halfHeight = static_cast<float>(extent.height / 2u);
+
+ const auto topLeft = tcu::Vec4(0.0, 0.0, 1.0, 1.0);
+ const auto topRight = tcu::Vec4(1.0, 0.0, 1.0, 1.0);
+ const auto bottomLeft = tcu::Vec4(0.0, 1.0, 1.0, 1.0);
+ const auto bottomRight = tcu::Vec4(1.0, 1.0, 0.0, 1.0);
+
+ ViewportVec viewports;
+ viewports.reserve(kQuadrants);
+ viewports.emplace_back(makeViewport(0.0f, 0.0f, halfWidth, halfHeight, 0.0f, 1.0f));
+ viewports.emplace_back(makeViewport(halfWidth, 0.0f, halfWidth, halfHeight, 0.0f, 1.0f));
+ viewports.emplace_back(makeViewport(0.0f, halfHeight, halfWidth, halfHeight, 0.0f, 1.0f));
+ viewports.emplace_back(makeViewport(halfWidth, halfHeight, halfWidth, halfHeight, 0.0f, 1.0f));
+
+ const auto numWorkGroups = (m_shareVertices ? 1u : kQuadrants);
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(numWorkGroups), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ std::move(viewports), // ViewportVec viewports;
+ };
+ return new QuadrantsInstance(context, iterationParams, topLeft, topRight, bottomLeft, bottomRight);
+}
+
+// Position builtin case.
+class PositionCase : public MeshShaderBuiltinCase
+{
+public:
+ PositionCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ {}
+ virtual ~PositionCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+void PositionCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Mesh shader: emit single triangle around the center of the top left pixel.
+ {
+ const auto extent = getDefaultExtent();
+ const auto fWidth = static_cast<float>(extent.width);
+ const auto fHeight = static_cast<float>(extent.height);
+
+ const auto pxWidth = 2.0f / fWidth;
+ const auto pxHeight = 2.0f / fHeight;
+
+ const auto halfXPix = pxWidth / 2.0f;
+ const auto halfYPix = pxHeight / 2.0f;
+
+ // Center of top left pixel.
+ const auto x = -1.0f + halfXPix;
+ const auto y = -1.0f + halfYPix;
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(" << (x - halfXPix) << ", " << (y + halfYPix) << ", 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(" << (x + halfXPix) << ", " << (y + halfYPix) << ", 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4(" << x << ", " << (y - halfYPix) << ", 0.0, 1.0);\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* PositionCase::createInstance (Context& context) const
+{
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+
+ // Must match the shader.
+ PixelMap pixelMap;
+ pixelMap[tcu::IVec2(0, 0)] = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
+
+ const PixelVerifierParams verifierParams =
+ {
+ tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), // const tcu::Vec4 background;
+ std::move(pixelMap), // const PixelMap pixelMap;
+ };
+ return new PixelsInstance(context, iterationParams, verifierParams);
+}
+
+// PointSize builtin case.
+class PointSizeCase : public MeshShaderBuiltinCase
+{
+public:
+ PointSizeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ {}
+ virtual ~PointSizeCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr float kPointSize = 4.0f;
+};
+
+void PointSizeCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Mesh shader: large point covering the top left quadrant.
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (points) out;\n"
+ << "layout (max_vertices=1, max_primitives=1) out;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[0].gl_PointSize = " << kPointSize << ";\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* PointSizeCase::createInstance (Context& context) const
+{
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+
+ // Must match the shader.
+ const tcu::Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
+ const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
+
+ return new QuadrantsInstance(context, iterationParams, blue, black, black, black);
+}
+
+void PointSizeCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);
+
+ const auto& properties = context.getDeviceProperties();
+ if (kPointSize < properties.limits.pointSizeRange[0] || kPointSize > properties.limits.pointSizeRange[1])
+ TCU_THROW(NotSupportedError, "Required point size outside point size range");
+}
+
+// ClipDistance builtin case.
+class ClipDistanceCase : public MeshShaderBuiltinCase
+{
+public:
+ ClipDistanceCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ {}
+ virtual ~ClipDistanceCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+};
+
+void ClipDistanceCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Mesh shader: full-screen quad using different clip distances.
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=4, max_primitives=2) out;\n"
+ << "\n"
+ << "out gl_MeshPerVertexNV {\n"
+ << " vec4 gl_Position;\n"
+ << " float gl_ClipDistance[2];\n"
+ << "} gl_MeshVerticesNV[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 2u;\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << " gl_PrimitiveIndicesNV[3] = 1;\n"
+ << " gl_PrimitiveIndicesNV[4] = 3;\n"
+ << " gl_PrimitiveIndicesNV[5] = 2;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[3].gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
+ << "\n"
+ // The first clip plane keeps the left half of the frame buffer.
+ << " gl_MeshVerticesNV[0].gl_ClipDistance[0] = 1.0;\n"
+ << " gl_MeshVerticesNV[1].gl_ClipDistance[0] = 1.0;\n"
+ << " gl_MeshVerticesNV[2].gl_ClipDistance[0] = -1.0;\n"
+ << " gl_MeshVerticesNV[3].gl_ClipDistance[0] = -1.0;\n"
+ << "\n"
+ // The second clip plane keeps the top half of the frame buffer.
+ << " gl_MeshVerticesNV[0].gl_ClipDistance[1] = 1.0;\n"
+ << " gl_MeshVerticesNV[1].gl_ClipDistance[1] = -1.0;\n"
+ << " gl_MeshVerticesNV[2].gl_ClipDistance[1] = 1.0;\n"
+ << " gl_MeshVerticesNV[3].gl_ClipDistance[1] = -1.0;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Fragment shader chooses a constant color.
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ // White color should not actually be used, as those fragments are supposed to be discarded.
+ << " outColor = ((gl_ClipDistance[0] >= 0.0 && gl_ClipDistance[1] >= 0.0) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(1.0, 1.0, 1.0, 1.0));\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+TestInstance* ClipDistanceCase::createInstance (Context& context) const
+{
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+
+ // Must match the shader.
+ const tcu::Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
+ const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
+
+ return new QuadrantsInstance(context, iterationParams, blue, black, black, black);
+}
+
+void ClipDistanceCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
+}
+
+// CullDistance builtin case.
+class CullDistanceCase : public MeshShaderBuiltinCase
+{
+public:
+ CullDistanceCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
+ {}
+ virtual ~CullDistanceCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+};
+
+void CullDistanceCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Mesh shader: two quads covering the whole screen, one on top of the other.
+ // Use cull distances to discard the bottom quad.
+ // Use cull distances to paint the top one in two colors: blue on the left, white on the right.
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=6, max_primitives=4) out;\n"
+ << "\n"
+ << "out gl_MeshPerVertexNV {\n"
+ << " vec4 gl_Position;\n"
+ << " float gl_CullDistance[2];\n"
+ << "} gl_MeshVerticesNV[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 4u;\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 3;\n"
+ << " gl_PrimitiveIndicesNV[3] = 1;\n"
+ << " gl_PrimitiveIndicesNV[4] = 4;\n"
+ << " gl_PrimitiveIndicesNV[5] = 3;\n"
+ << " gl_PrimitiveIndicesNV[6] = 1;\n"
+ << " gl_PrimitiveIndicesNV[7] = 2;\n"
+ << " gl_PrimitiveIndicesNV[8] = 4;\n"
+ << " gl_PrimitiveIndicesNV[9] = 2;\n"
+ << " gl_PrimitiveIndicesNV[10] = 5;\n"
+ << " gl_PrimitiveIndicesNV[11] = 4;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 0.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[3].gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[4].gl_Position = vec4( 1.0, 0.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[5].gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
+ << "\n"
+ // The first cull plane discards the bottom quad
+ << " gl_MeshVerticesNV[0].gl_CullDistance[0] = 1.0;\n"
+ << " gl_MeshVerticesNV[1].gl_CullDistance[0] = -1.0;\n"
+ << " gl_MeshVerticesNV[2].gl_CullDistance[0] = -2.0;\n"
+ << " gl_MeshVerticesNV[3].gl_CullDistance[0] = 1.0;\n"
+ << " gl_MeshVerticesNV[4].gl_CullDistance[0] = -1.0;\n"
+ << " gl_MeshVerticesNV[5].gl_CullDistance[0] = -2.0;\n"
+ << "\n"
+ // The second cull plane helps paint left and right different.
+ << " gl_MeshVerticesNV[0].gl_CullDistance[1] = 1.0;\n"
+ << " gl_MeshVerticesNV[1].gl_CullDistance[1] = 1.0;\n"
+ << " gl_MeshVerticesNV[2].gl_CullDistance[1] = 1.0;\n"
+ << " gl_MeshVerticesNV[3].gl_CullDistance[1] = -1.0;\n"
+ << " gl_MeshVerticesNV[4].gl_CullDistance[1] = -1.0;\n"
+ << " gl_MeshVerticesNV[5].gl_CullDistance[1] = -1.0;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Fragment shader chooses color based on the second cull distance.
+ {
+ std::ostringstream frag;
+ frag
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " outColor = ((gl_CullDistance[1] >= 0.0) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(1.0, 1.0, 1.0, 1.0));\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+TestInstance* CullDistanceCase::createInstance (Context& context) const
+{
+ const IterationParams iterationParams =
+ {
+ getDefaultExtent(), // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+
+ // Must match the shader.
+ const tcu::Vec4 black (0.0f, 0.0f, 0.0f, 1.0f);
+ const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f);
+ const tcu::Vec4 white (1.0f, 1.0f, 1.0f, 1.0f);
+
+ return new QuadrantsInstance(context, iterationParams, blue, white, black, black);
+}
+
+void CullDistanceCase::checkSupport (Context& context) const
+{
+ MeshShaderBuiltinCase::checkSupport(context);
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CULL_DISTANCE);
+}
+
+// Generates statements to draw a triangle around the given pixel number, knowing the framebuffer width (len).
+// Supposes the height of the framebuffer is 1.
+std::string triangleForPixel(const std::string& pixel, const std::string& len, const std::string& baseIndex)
+{
+ std::ostringstream statements;
+ statements
+ << " const float imgWidth = float(" << len << ");\n"
+ << " const float pixWidth = (2.0 / imgWidth);\n"
+ << " const float halfPix = (pixWidth / 2.0);\n"
+ << " const float xCenter = (((float(" << pixel << ") + 0.5) / imgWidth) * 2.0 - 1.0);\n"
+ << " const float xLeft = (xCenter - halfPix);\n"
+ << " const float xRight = (xCenter + halfPix);\n"
+ << " const uvec3 indices = uvec3(" << baseIndex << " + 0, " << baseIndex << " + 1, " << baseIndex << " + 2);\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[indices.x] = indices.x;\n"
+ << " gl_PrimitiveIndicesNV[indices.y] = indices.y;\n"
+ << " gl_PrimitiveIndicesNV[indices.z] = indices.z;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[indices.x].gl_Position = vec4(xLeft, 0.5, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[indices.y].gl_Position = vec4(xRight, 0.5, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[indices.z].gl_Position = vec4(xCenter, -0.5, 0.0, 1.0);\n"
+ ;
+ return statements.str();
+}
+
+// WorkGroupID builtin case.
+class WorkGroupIdCase : public MeshShaderBuiltinCase
+{
+public:
+ WorkGroupIdCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
+ : MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
+ , m_extent (getLinearExtent())
+ {}
+ virtual ~WorkGroupIdCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ const VkExtent2D m_extent;
+};
+
+void WorkGroupIdCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const std::string taskDataDecl =
+ "taskNV TaskData {\n"
+ " uint id;\n"
+ " uint size;\n"
+ "} td;\n"
+ ;
+
+ // Mesh shader: each work group fills one pixel.
+ {
+ const std::string pixel = (m_taskNeeded ? "td.id" : "gl_WorkGroupID.x" );
+ const std::string len = (m_taskNeeded ? "td.size" : de::toString(m_extent.width) );
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << (m_taskNeeded ? ("in " + taskDataDecl) : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << "\n"
+ << triangleForPixel(pixel, len, "0")
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ if (m_taskNeeded)
+ {
+ std::ostringstream task;
+ task
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 1u;\n"
+ << " td.id = gl_WorkGroupID.x;\n"
+ << " td.size = " << m_extent.width << ";\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* WorkGroupIdCase::createInstance (Context& context) const
+{
+ // Must match the shader.
+ const ColorVec expectedColors (1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
+ const IterationParams iterationParams =
+ {
+ m_extent, // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(m_extent.width), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+// Variable to use.
+enum class LocalInvocation { ID=0, INDEX };
+
+// LocalInvocationId and LocalInvocationIndex builtin cases. These are also used to test WorkGroupSize.
+class LocalInvocationCase : public MeshShaderBuiltinCase
+{
+public:
+ LocalInvocationCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded, LocalInvocation variable)
+ : MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
+ , m_extent (getLinearExtent())
+ , m_variable (variable)
+ {}
+ virtual ~LocalInvocationCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ const VkExtent2D m_extent;
+ const LocalInvocation m_variable;
+};
+
+void LocalInvocationCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Invocation index to use.
+ const std::string localIndex = ((m_variable == LocalInvocation::ID) ? "gl_LocalInvocationID.x" : "gl_LocalInvocationIndex");
+
+ // Task data.
+ std::ostringstream taskDataDecl;
+ taskDataDecl
+ << "taskNV TaskData {\n"
+ // indexNumber[x] == x
+ << " uint indexNumber[" << m_extent.width << "];\n"
+ << " uint size;\n"
+ << "} td;\n"
+ ;
+ const auto taskDataDeclStr = taskDataDecl.str();
+
+ // Mesh shader: each work group fills one pixel.
+ {
+ const std::string pixel = (m_taskNeeded ? "td.indexNumber[gl_WorkGroupID.x]" : localIndex);
+ const std::string len = (m_taskNeeded ? "td.size" : "gl_WorkGroupSize.x");
+ const auto localSize = (m_taskNeeded ? 1u : m_extent.width);
+ const auto maxVert = localSize * 3u;
+ const std::string baseIndex = (m_taskNeeded ? "0" : "(" + localIndex + " * 3u)");
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << localSize << ") in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=" << maxVert << ", max_primitives=" << localSize << ") out;\n"
+ << "\n"
+ << (m_taskNeeded ? ("in " + taskDataDeclStr) : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = " << localSize << ";\n"
+ << "\n"
+ << triangleForPixel(pixel, len, baseIndex)
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ if (m_taskNeeded)
+ {
+ std::ostringstream task;
+ task
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << m_extent.width << ") in;\n"
+ << "\n"
+ << "out " << taskDataDeclStr
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = " << m_extent.width << ";\n"
+ << " td.indexNumber[" << localIndex << "] = " << localIndex << ";\n"
+ << " td.size = gl_WorkGroupSize.x;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* LocalInvocationCase::createInstance (Context& context) const
+{
+ // Must match the shader.
+ const ColorVec expectedColors (1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
+ const IterationParams iterationParams =
+ {
+ m_extent, // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+// GlobalInvocationId builtin case.
+class GlobalInvocationIdCase : public MeshShaderBuiltinCase
+{
+public:
+ GlobalInvocationIdCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
+ : MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
+ , m_jobSize (getLargeJobSize())
+ , m_extent {m_jobSize.numTasks * m_jobSize.localSize, 1u}
+ {}
+ virtual ~GlobalInvocationIdCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ const JobSize m_jobSize;
+ const VkExtent2D m_extent;
+};
+
+void GlobalInvocationIdCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto& localSize = m_jobSize.localSize;
+
+ // Task data.
+ std::ostringstream taskDataDecl;
+ taskDataDecl
+ << "taskNV TaskData {\n"
+ << " uint pixelId[" << localSize << "];\n"
+ << " uint size;\n"
+ << "} td;\n"
+ ;
+ const auto taskDataDeclStr = taskDataDecl.str();
+
+ // Mesh shader: each work group fills one pixel.
+ {
+ const std::string pixel = (m_taskNeeded ? "td.pixelId[gl_LocalInvocationIndex]" : "gl_GlobalInvocationID.x");
+ const std::string len = (m_taskNeeded ? "td.size" : de::toString(m_extent.width));
+ const std::string baseIndex = "(gl_LocalInvocationIndex * 3u)";
+ const auto maxVert = localSize * 3u;
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << localSize << ") in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=" << maxVert << ", max_primitives=" << localSize << ") out;\n"
+ << "\n"
+ << (m_taskNeeded ? ("in " + taskDataDeclStr) : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = " << localSize << ";\n"
+ << "\n"
+ << triangleForPixel(pixel, len, baseIndex)
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ if (m_taskNeeded)
+ {
+ std::ostringstream task;
+ task
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << localSize << ") in;\n"
+ << "\n"
+ << "out " << taskDataDeclStr
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 1;\n"
+ << " td.pixelId[gl_LocalInvocationIndex] = gl_GlobalInvocationID.x;\n"
+ << " td.size = " << m_extent.width << ";\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* GlobalInvocationIdCase::createInstance (Context& context) const
+{
+ // Must match the shader.
+ const ColorVec expectedColors (1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
+ const IterationParams iterationParams =
+ {
+ m_extent, // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ getDefaultDrawCommands(m_jobSize.numTasks), // DrawCommandVec drawArgs;
+ false, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+// DrawIndex builtin case.
+class DrawIndexCase : public MeshShaderBuiltinCase
+{
+public:
+ DrawIndexCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
+ : MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
+ , m_extent (getLinearExtent())
+ {}
+ virtual ~DrawIndexCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ const VkExtent2D m_extent;
+};
+
+void DrawIndexCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const std::string taskDataDecl =
+ "taskNV TaskData {\n"
+ " uint id;\n"
+ " uint size;\n"
+ "} td;\n"
+ ;
+
+ const auto drawIndex = "uint(gl_DrawID)";
+
+ // Mesh shader: each work group fills one pixel.
+ {
+ const std::string pixel = (m_taskNeeded ? "td.id" : drawIndex);
+ const std::string len = (m_taskNeeded ? "td.size" : de::toString(m_extent.width));
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (triangles) out;\n"
+ << "layout (max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << (m_taskNeeded ? ("in " + taskDataDecl) : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << "\n"
+ << triangleForPixel(pixel, len, "0")
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ if (m_taskNeeded)
+ {
+ std::ostringstream task;
+ task
+ << "#version 460\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 1u;\n"
+ << " td.id = " << drawIndex << ";\n"
+ << " td.size = " << m_extent.width << ";\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Basic fragment shader.
+ {
+ const auto frag = getBasicFragShader();
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+}
+
+TestInstance* DrawIndexCase::createInstance (Context& context) const
+{
+ // Must match the shader.
+ const ColorVec expectedColors (1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
+ const DrawCommandVec commands (m_extent.width, makeDrawMeshTasksIndirectCommandNV(1u, 0u));
+ const IterationParams iterationParams =
+ {
+ m_extent, // VkExtent2D colorExtent;
+ 1u, // uint32_t numLayers;
+ commands, // DrawCommandVec drawArgs;
+ true, // bool indirect;
+ {}, // ViewportVec viewports; // If empty, a single default viewport is used.
+ };
+ return new FullScreenColorInstance(context, iterationParams, expectedColors);
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createMeshShaderBuiltinTests (tcu::TestContext& testCtx)
+{
+ GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "builtin", "Mesh Shader Builtin Tests"));
+
+ mainGroup->addChild(new PositionCase (testCtx, "position", ""));
+ mainGroup->addChild(new PointSizeCase (testCtx, "point_size", ""));
+ mainGroup->addChild(new ClipDistanceCase (testCtx, "clip_distance", ""));
+ mainGroup->addChild(new CullDistanceCase (testCtx, "cull_distance", ""));
+ mainGroup->addChild(new PrimitiveIdCase (testCtx, "primitive_id_glsl", "", true/*glslFrag*/));
+ mainGroup->addChild(new PrimitiveIdCase (testCtx, "primitive_id_spirv", "", false/*glslFrag*/));
+ mainGroup->addChild(new LayerCase (testCtx, "layer", "", false/*shareVertices*/));
+ mainGroup->addChild(new LayerCase (testCtx, "layer_shared", "", true/*shareVertices*/));
+ mainGroup->addChild(new ViewportIndexCase (testCtx, "viewport_index", "", false/*shareVertices*/));
+ mainGroup->addChild(new ViewportIndexCase (testCtx, "viewport_index_shared", "", true/*shareVertices*/));
+ mainGroup->addChild(new WorkGroupIdCase (testCtx, "work_group_id_in_mesh", "", false/*taskNeeded*/));
+ mainGroup->addChild(new WorkGroupIdCase (testCtx, "work_group_id_in_task", "", true/*taskNeeded*/));
+ mainGroup->addChild(new LocalInvocationCase (testCtx, "local_invocation_id_in_mesh", "", false/*taskNeeded*/, LocalInvocation::ID));
+ mainGroup->addChild(new LocalInvocationCase (testCtx, "local_invocation_id_in_task", "", true/*taskNeeded*/, LocalInvocation::ID));
+ mainGroup->addChild(new LocalInvocationCase (testCtx, "local_invocation_index_in_task", "", true/*taskNeeded*/, LocalInvocation::INDEX));
+ mainGroup->addChild(new LocalInvocationCase (testCtx, "local_invocation_index_in_mesh", "", false/*taskNeeded*/, LocalInvocation::INDEX));
+ mainGroup->addChild(new GlobalInvocationIdCase (testCtx, "global_invocation_id_in_mesh", "", false/*taskNeeded*/));
+ mainGroup->addChild(new GlobalInvocationIdCase (testCtx, "global_invocation_id_in_task", "", true/*taskNeeded*/));
+ mainGroup->addChild(new DrawIndexCase (testCtx, "draw_index_in_mesh", "", false/*taskNeeded*/));
+ mainGroup->addChild(new DrawIndexCase (testCtx, "draw_index_in_task", "", true/*taskNeeded*/));
+
+ return mainGroup.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERBUILTINTESTS_HPP
+#define _VKTMESHSHADERBUILTINTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Builtin Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderBuiltinTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERBUILTINTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Misc Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderMiscTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkBuilderUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkObjUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkBarrierUtil.hpp"
+
+#include "tcuImageCompare.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuMaybe.hpp"
+#include "tcuStringTemplate.hpp"
+#include "tcuTestLog.hpp"
+
+#include <memory>
+#include <utility>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <map>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+
+using namespace vk;
+
+// Output images will use this format.
+VkFormat getOutputFormat ()
+{
+ return VK_FORMAT_R8G8B8A8_UNORM;
+}
+
+// Threshold that's reasonable for the previous format.
+float getCompareThreshold ()
+{
+ return 0.005f; // 1/256 < 0.005 < 2/256
+}
+
+// Check mesh shader support.
+void genericCheckSupport (Context& context, bool requireTaskShader, bool requireVertexStores)
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (!meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shader not supported");
+
+ if (requireTaskShader && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shader not supported");
+
+ if (requireVertexStores)
+ {
+ const auto& features = context.getDeviceFeatures();
+ if (!features.vertexPipelineStoresAndAtomics)
+ TCU_THROW(NotSupportedError, "Vertex pieline stores and atomics not supported");
+ }
+}
+
+struct MiscTestParams
+{
+ tcu::Maybe<uint32_t> taskCount;
+ uint32_t meshCount;
+
+ uint32_t width;
+ uint32_t height;
+
+ // Makes the class polymorphic and allows the right destructor to be used for subclasses.
+ virtual ~MiscTestParams () {}
+
+ bool needsTaskShader () const
+ {
+ return static_cast<bool>(taskCount);
+ }
+
+ uint32_t drawCount () const
+ {
+ if (needsTaskShader())
+ return taskCount.get();
+ return meshCount;
+ }
+};
+
+using ParamsPtr = std::unique_ptr<MiscTestParams>;
+
+class MeshShaderMiscCase : public vkt::TestCase
+{
+public:
+ MeshShaderMiscCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params);
+ virtual ~MeshShaderMiscCase (void) {}
+
+ void checkSupport (Context& context) const override;
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+
+protected:
+ std::unique_ptr<MiscTestParams> m_params;
+};
+
+MeshShaderMiscCase::MeshShaderMiscCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : vkt::TestCase (testCtx, name, description)
+ , m_params (params.release())
+{}
+
+void MeshShaderMiscCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, m_params->needsTaskShader(), /*requireVertexStores*/false);
+}
+
+// Adds the generic fragment shader. To be called by subclasses.
+void MeshShaderMiscCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ std::string frag =
+ "#version 450\n"
+ "#extension GL_NV_mesh_shader : enable\n"
+ "\n"
+ "layout (location=0) in perprimitiveNV vec4 primitiveColor;\n"
+ "layout (location=0) out vec4 outColor;\n"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " outColor = primitiveColor;\n"
+ "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+}
+
+class MeshShaderMiscInstance : public vkt::TestInstance
+{
+public:
+ MeshShaderMiscInstance (Context& context, const MiscTestParams* params)
+ : vkt::TestInstance (context)
+ , m_params (params)
+ , m_referenceLevel ()
+ {
+ }
+
+ void generateSolidRefLevel (const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output);
+ virtual void generateReferenceLevel () = 0;
+
+ virtual bool verifyResult (const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const;
+ virtual bool verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const;
+ tcu::TestStatus iterate () override;
+
+protected:
+ const MiscTestParams* m_params;
+ std::unique_ptr<tcu::TextureLevel> m_referenceLevel;
+};
+
+void MeshShaderMiscInstance::generateSolidRefLevel (const tcu::Vec4& color, std::unique_ptr<tcu::TextureLevel>& output)
+{
+ const auto format = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(format);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto iHeight = static_cast<int>(m_params->height);
+
+ output.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
+
+ const auto access = output->getAccess();
+
+ // Fill with solid color.
+ tcu::clear(access, color);
+}
+
+bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
+{
+ return verifyResult(resultAccess, *m_referenceLevel);
+}
+
+bool MeshShaderMiscInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess, const tcu::TextureLevel& referenceLevel) const
+{
+ const auto referenceAccess = referenceLevel.getAccess();
+
+ const auto refWidth = referenceAccess.getWidth();
+ const auto refHeight = referenceAccess.getHeight();
+ const auto refDepth = referenceAccess.getDepth();
+
+ const auto resWidth = resultAccess.getWidth();
+ const auto resHeight = resultAccess.getHeight();
+ const auto resDepth = resultAccess.getDepth();
+
+ DE_ASSERT(resWidth == refWidth || resHeight == refHeight || resDepth == refDepth);
+
+ // For release builds.
+ DE_UNREF(refWidth);
+ DE_UNREF(refHeight);
+ DE_UNREF(refDepth);
+ DE_UNREF(resWidth);
+ DE_UNREF(resHeight);
+ DE_UNREF(resDepth);
+
+ const auto outputFormat = getOutputFormat();
+ const auto expectedFormat = mapVkFormat(outputFormat);
+ const auto resFormat = resultAccess.getFormat();
+ const auto refFormat = referenceAccess.getFormat();
+
+ DE_ASSERT(resFormat == expectedFormat && refFormat == expectedFormat);
+
+ // For release builds
+ DE_UNREF(expectedFormat);
+ DE_UNREF(resFormat);
+ DE_UNREF(refFormat);
+
+ auto& log = m_context.getTestContext().getLog();
+ const auto threshold = getCompareThreshold();
+ const tcu::Vec4 thresholdVec (threshold, threshold, threshold, threshold);
+
+ return tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, thresholdVec, tcu::COMPARE_LOG_ON_ERROR);
+}
+
+tcu::TestStatus MeshShaderMiscInstance::iterate ()
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto imageFormat = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(imageFormat);
+ const auto imageExtent = makeExtent3D(m_params->width, m_params->height, 1u);
+ const auto imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ imageExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ imageUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ // Create color image and view.
+ ImageWithMemory colorImage (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
+ const auto colorView = makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
+
+ // Create a memory buffer for verification.
+ const auto verificationBufferSize = static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
+ const auto verificationBufferUsage = (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ const auto verificationBufferInfo = makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
+
+ BufferWithMemory verificationBuffer (vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
+ auto& verificationBufferAlloc = verificationBuffer.getAllocation();
+ void* verificationBufferData = verificationBufferAlloc.getHostPtr();
+
+ // Pipeline layout.
+ const auto pipelineLayout = makePipelineLayout(vkd, device);
+
+ // Shader modules.
+ const auto& binaries = m_context.getBinaryCollection();
+ const auto hasTask = binaries.contains("task");
+
+ const auto meshShader = createShaderModule(vkd, device, binaries.get("mesh"));
+ const auto fragShader = createShaderModule(vkd, device, binaries.get("frag"));
+
+ Move<VkShaderModule> taskShader;
+ if (hasTask)
+ taskShader = createShaderModule(vkd, device, binaries.get("task"));
+
+ // Render pass.
+ const auto renderPass = makeRenderPass(vkd, device, imageFormat);
+
+ // Framebuffer.
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
+
+ // Viewport and scissor.
+ const std::vector<VkViewport> viewports (1u, makeViewport(imageExtent));
+ const std::vector<VkRect2D> scissors (1u, makeRect2D(imageExtent));
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskShader.get(), meshShader.get(), fragShader.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ beginCommandBuffer(vkd, cmdBuffer);
+
+ // Run pipeline.
+ const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ // Copy color buffer to verification buffer.
+ const auto colorAccess = (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
+ const auto transferRead = VK_ACCESS_TRANSFER_READ_BIT;
+ const auto transferWrite = VK_ACCESS_TRANSFER_WRITE_BIT;
+ const auto hostRead = VK_ACCESS_HOST_READ_BIT;
+
+ const auto preCopyBarrier = makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
+ const auto postCopyBarrier = makeMemoryBarrier(transferWrite, hostRead);
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
+ vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, ©Region);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Generate reference image and compare results.
+ const tcu::IVec3 iExtent (static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
+ const tcu::ConstPixelBufferAccess verificationAccess (tcuFormat, iExtent, verificationBufferData);
+
+ generateReferenceLevel();
+ invalidateAlloc(vkd, device, verificationBufferAlloc);
+ if (!verifyResult(verificationAccess))
+ TCU_FAIL("Result does not match reference; check log for details");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+// Verify passing more complex data between the task and mesh shaders.
+class ComplexTaskDataCase : public MeshShaderMiscCase
+{
+public:
+ ComplexTaskDataCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class ComplexTaskDataInstance : public MeshShaderMiscInstance
+{
+public:
+ ComplexTaskDataInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+void ComplexTaskDataInstance::generateReferenceLevel ()
+{
+ const auto format = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(format);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto iHeight = static_cast<int>(m_params->height);
+
+ const auto halfWidth = iWidth / 2;
+ const auto halfHeight = iHeight / 2;
+
+ m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
+
+ const auto access = m_referenceLevel->getAccess();
+
+ // Each image quadrant gets a different color.
+ for (int y = 0; y < iHeight; ++y)
+ for (int x = 0; x < iWidth; ++x)
+ {
+ const float red = ((y < halfHeight) ? 0.0f : 1.0f);
+ const float green = ((x < halfWidth) ? 0.0f : 1.0f);
+ const auto refColor = tcu::Vec4(red, green, 1.0f, 1.0f);
+ access.setPixel(refColor, x, y);
+ }
+}
+
+void ComplexTaskDataCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Add the generic fragment shader.
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ const std::string taskDataDeclTemplate =
+ "struct RowId {\n"
+ " uint id;\n"
+ "};\n"
+ "\n"
+ "struct WorkGroupData {\n"
+ " float WorkGroupIdPlusOnex1000Iota[10];\n"
+ " RowId rowId;\n"
+ " uvec3 WorkGroupIdPlusOnex2000Iota;\n"
+ " vec2 WorkGroupIdPlusOnex3000Iota;\n"
+ "};\n"
+ "\n"
+ "struct ExternalData {\n"
+ " float OneMillion;\n"
+ " uint TwoMillion;\n"
+ " WorkGroupData workGroupData;\n"
+ "};\n"
+ "\n"
+ "${INOUT} taskNV TaskData {\n"
+ " uint yes;\n"
+ " ExternalData externalData;\n"
+ "} td;\n"
+ ;
+ const tcu::StringTemplate taskDataDecl(taskDataDeclTemplate);
+
+ {
+ std::map<std::string, std::string> taskMap;
+ taskMap["INOUT"] = "out";
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "\n"
+ << taskDataDecl.specialize(taskMap)
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 2u;\n"
+ << " td.yes = 1u;\n"
+ << " td.externalData.OneMillion = 1000000.0;\n"
+ << " td.externalData.TwoMillion = 2000000u;\n"
+ << " for (uint i = 0; i < 10; i++) {\n"
+ << " td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] = float((gl_WorkGroupID.x + 1u) * 1000 + i);\n"
+ << " }\n"
+ << " {\n"
+ << " uint baseVal = (gl_WorkGroupID.x + 1u) * 2000;\n"
+ << " td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
+ << " }\n"
+ << " {\n"
+ << " uint baseVal = (gl_WorkGroupID.x + 1u) * 3000;\n"
+ << " td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota = vec2(baseVal, baseVal + 1);\n"
+ << " }\n"
+ << " td.externalData.workGroupData.rowId.id = gl_WorkGroupID.x;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ {
+ std::map<std::string, std::string> meshMap;
+ meshMap["INOUT"] = "in";
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=2) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=4, max_primitives=2) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << taskDataDecl.specialize(meshMap)
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " bool dataOK = true;\n"
+ << " dataOK = (dataOK && (td.yes == 1u));\n"
+ << " dataOK = (dataOK && (td.externalData.OneMillion == 1000000.0 && td.externalData.TwoMillion == 2000000u));\n"
+ << " uint rowId = td.externalData.workGroupData.rowId.id;\n"
+ << " dataOK = (dataOK && (rowId == 0u || rowId == 1u));\n"
+ << "\n"
+ << " {\n"
+ << " uint baseVal = (rowId + 1u) * 1000u;\n"
+ << " for (uint i = 0; i < 10; i++) {\n"
+ << " if (td.externalData.workGroupData.WorkGroupIdPlusOnex1000Iota[i] != float(baseVal + i)) {\n"
+ << " dataOK = false;\n"
+ << " break;\n"
+ << " }\n"
+ << " }\n"
+ << " }\n"
+ << "\n"
+ << " {\n"
+ << " uint baseVal = (rowId + 1u) * 2000;\n"
+ << " uvec3 expected = uvec3(baseVal, baseVal + 1, baseVal + 2);\n"
+ << " if (td.externalData.workGroupData.WorkGroupIdPlusOnex2000Iota != expected) {\n"
+ << " dataOK = false;\n"
+ << " }\n"
+ << " }\n"
+ << "\n"
+ << " {\n"
+ << " uint baseVal = (rowId + 1u) * 3000;\n"
+ << " vec2 expected = vec2(baseVal, baseVal + 1);\n"
+ << " if (td.externalData.workGroupData.WorkGroupIdPlusOnex3000Iota != expected) {\n"
+ << " dataOK = false;\n"
+ << " }\n"
+ << " }\n"
+ << "\n"
+ << " uint columnId = gl_WorkGroupID.x;\n"
+ << "\n"
+ << " if (dataOK) {\n"
+ << " gl_PrimitiveCountNV = 2u;\n"
+ << " }\n"
+ << " else {\n"
+ << " gl_PrimitiveCountNV = 0u;\n"
+ << " return;\n"
+ << " }\n"
+ << "\n"
+ << " const vec4 outColor = vec4(rowId, columnId, 1.0f, 1.0f);\n"
+ << " triangleColor[0] = outColor;\n"
+ << " triangleColor[1] = outColor;\n"
+ << "\n"
+ << " // Each local invocation will generate two points and one triangle from the quad.\n"
+ << " // The first local invocation will generate the top quad vertices.\n"
+ << " // The second invocation will generate the two bottom vertices.\n"
+ << " vec4 left = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ << " vec4 right = vec4(1.0, 0.0, 0.0, 1.0);\n"
+ << "\n"
+ << " float localInvocationOffsetY = float(gl_LocalInvocationID.x);\n"
+ << " left.y += localInvocationOffsetY;\n"
+ << " right.y += localInvocationOffsetY;\n"
+ << "\n"
+ << " // The code above creates a quad from (0, 0) to (1, 1) but we need to offset it\n"
+ << " // in X and/or Y depending on the row and column, to place it in other quadrants.\n"
+ << " float quadrantOffsetX = float(int(columnId) - 1);\n"
+ << " float quadrantOffsetY = float(int(rowId) - 1);\n"
+ << "\n"
+ << " left.x += quadrantOffsetX;\n"
+ << " right.x += quadrantOffsetX;\n"
+ << "\n"
+ << " left.y += quadrantOffsetY;\n"
+ << " right.y += quadrantOffsetY;\n"
+ << "\n"
+ << " uint baseVertexId = 2*gl_LocalInvocationID.x;\n"
+ << " gl_MeshVerticesNV[baseVertexId + 0].gl_Position = left;\n"
+ << " gl_MeshVerticesNV[baseVertexId + 1].gl_Position = right;\n"
+ << "\n"
+ << " uint baseIndexId = 3*gl_LocalInvocationID.x;\n"
+ << " // 0,1,2 or 1,2,3 (note: triangles alternate front face this way)\n"
+ << " gl_PrimitiveIndicesNV[baseIndexId + 0] = 0 + gl_LocalInvocationID.x;\n"
+ << " gl_PrimitiveIndicesNV[baseIndexId + 1] = 1 + gl_LocalInvocationID.x;\n"
+ << " gl_PrimitiveIndicesNV[baseIndexId + 2] = 2 + gl_LocalInvocationID.x;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+}
+
+TestInstance* ComplexTaskDataCase::createInstance (Context& context) const
+{
+ return new ComplexTaskDataInstance(context, m_params.get());
+}
+
+// Verify drawing a single point.
+class SinglePointCase : public MeshShaderMiscCase
+{
+public:
+ SinglePointCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class SinglePointInstance : public MeshShaderMiscInstance
+{
+public:
+ SinglePointInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* SinglePointCase::createInstance (Context& context) const
+{
+ return new SinglePointInstance (context, m_params.get());
+}
+
+void SinglePointCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "layout(points) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " pointColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[0].gl_PointSize = 1.0f;\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void SinglePointInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
+
+ const auto halfWidth = static_cast<int>(m_params->width / 2u);
+ const auto halfHeight = static_cast<int>(m_params->height / 2u);
+ const auto access = m_referenceLevel->getAccess();
+
+ access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
+}
+
+// Verify drawing a single line.
+class SingleLineCase : public MeshShaderMiscCase
+{
+public:
+ SingleLineCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class SingleLineInstance : public MeshShaderMiscInstance
+{
+public:
+ SingleLineInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* SingleLineCase::createInstance (Context& context) const
+{
+ return new SingleLineInstance (context, m_params.get());
+}
+
+void SingleLineCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "layout(lines) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 lineColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " lineColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0f, 0.0f, 0.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4( 1.0f, 0.0f, 0.0f, 1.0f);\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void SingleLineInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto halfHeight = static_cast<int>(m_params->height / 2u);
+ const auto access = m_referenceLevel->getAccess();
+
+ // Center row.
+ for (int x = 0; x < iWidth; ++x)
+ access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), x, halfHeight);
+}
+
+// Verify drawing a single triangle.
+class SingleTriangleCase : public MeshShaderMiscCase
+{
+public:
+ SingleTriangleCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class SingleTriangleInstance : public MeshShaderMiscInstance
+{
+public:
+ SingleTriangleInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* SingleTriangleCase::createInstance (Context& context) const
+{
+ return new SingleTriangleInstance (context, m_params.get());
+}
+
+void SingleTriangleCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ const float halfPixelX = 2.0f / static_cast<float>(m_params->width);
+ const float halfPixelY = 2.0f / static_cast<float>(m_params->height);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " triangleColor[0] = vec4(0.0f, 1.0f, 1.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(" << halfPixelY << ", " << -halfPixelX << ", 0.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(" << halfPixelY << ", " << halfPixelX << ", 0.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4(" << -halfPixelY << ", 0.0f, 0.0f, 1.0f);\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void SingleTriangleInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
+
+ const auto halfWidth = static_cast<int>(m_params->width / 2u);
+ const auto halfHeight = static_cast<int>(m_params->height / 2u);
+ const auto access = m_referenceLevel->getAccess();
+
+ // Single pixel in the center.
+ access.setPixel(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), halfWidth, halfHeight);
+}
+
+// Verify drawing the maximum number of points.
+class MaxPointsCase : public MeshShaderMiscCase
+{
+public:
+ MaxPointsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class MaxPointsInstance : public MeshShaderMiscInstance
+{
+public:
+ MaxPointsInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* MaxPointsCase::createInstance (Context& context) const
+{
+ return new MaxPointsInstance (context, m_params.get());
+}
+
+void MaxPointsCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ // Fill a 16x16 image with 256 points. Each of the 32 local invocations will handle a segment of 8 pixels. Two segments per row.
+ DE_ASSERT(m_params->width == 16u && m_params->height == 16u);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=32) in;\n"
+ << "layout(points) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 256u;\n"
+ << " uint firstPixel = 8u * gl_LocalInvocationID.x;\n"
+ << " uint row = firstPixel / 16u;\n"
+ << " uint col = firstPixel % 16u;\n"
+ << " float pixSize = 2.0f / 16.0f;\n"
+ << " float yCoord = pixSize * (float(row) + 0.5f) - 1.0f;\n"
+ << " float baseXCoord = pixSize * (float(col) + 0.5f) - 1.0f;\n"
+ << " for (uint i = 0; i < 8u; i++) {\n"
+ << " float xCoord = baseXCoord + pixSize * float(i);\n"
+ << " uint pixId = firstPixel + i;\n"
+ << " gl_MeshVerticesNV[pixId].gl_Position = vec4(xCoord, yCoord, 0.0f, 1.0f);\n"
+ << " gl_MeshVerticesNV[pixId].gl_PointSize = 1.0f;\n"
+ << " gl_PrimitiveIndicesNV[pixId] = pixId;\n"
+ << " pointColor[pixId] = vec4(((xCoord + 1.0f) / 2.0f), ((yCoord + 1.0f) / 2.0f), 0.0f, 1.0f);\n"
+ << " }\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void MaxPointsInstance::generateReferenceLevel ()
+{
+ const auto format = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(format);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto iHeight = static_cast<int>(m_params->height);
+ const auto fWidth = static_cast<float>(m_params->width);
+ const auto fHeight = static_cast<float>(m_params->height);
+
+ m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
+
+ const auto access = m_referenceLevel->getAccess();
+
+ // Fill with gradient like the shader does.
+ for (int y = 0; y < iHeight; ++y)
+ for (int x = 0; x < iWidth; ++x)
+ {
+ const tcu::Vec4 color (
+ ((static_cast<float>(x) + 0.5f) / fWidth),
+ ((static_cast<float>(y) + 0.5f) / fHeight),
+ 0.0f, 1.0f);
+ access.setPixel(color, x, y);
+ }
+}
+
+// Verify drawing the maximum number of lines.
+class MaxLinesCase : public MeshShaderMiscCase
+{
+public:
+ MaxLinesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class MaxLinesInstance : public MeshShaderMiscInstance
+{
+public:
+ MaxLinesInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* MaxLinesCase::createInstance (Context& context) const
+{
+ return new MaxLinesInstance (context, m_params.get());
+}
+
+void MaxLinesCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ // Fill a 1x1020 image with 255 lines, each line being 4 pixels tall. Each invocation will generate ~8 lines.
+ DE_ASSERT(m_params->width == 1u && m_params->height == 1020u);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=32) in;\n"
+ << "layout(lines) out;\n"
+ << "layout(max_vertices=256, max_primitives=255) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 lineColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 255u;\n"
+ << " uint firstLine = 8u * gl_LocalInvocationID.x;\n"
+ << " for (uint i = 0u; i < 8u; i++) {\n"
+ << " uint lineId = firstLine + i;\n"
+ << " uint topPixel = 4u * lineId;\n"
+ << " uint bottomPixel = 3u + topPixel;\n"
+ << " if (bottomPixel < 1020u) {\n"
+ << " float bottomCoord = ((float(bottomPixel) + 1.0f) / 1020.0) * 2.0 - 1.0;\n"
+ << " gl_MeshVerticesNV[lineId + 1u].gl_Position = vec4(0.0, bottomCoord, 0.0f, 1.0f);\n"
+ << " gl_PrimitiveIndicesNV[lineId * 2u] = lineId;\n"
+ << " gl_PrimitiveIndicesNV[lineId * 2u + 1u] = lineId + 1u;\n"
+ << " lineColor[lineId] = vec4(0.0f, 1.0f, float(lineId) / 255.0f, 1.0f);\n"
+ << " } else {\n"
+ << " // The last iteration of the last invocation emits the first point\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(0.0, -1.0, 0.0f, 1.0f);\n"
+ << " }\n"
+ << " }\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void MaxLinesInstance::generateReferenceLevel ()
+{
+ const auto format = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(format);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto iHeight = static_cast<int>(m_params->height);
+
+ m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
+
+ const auto access = m_referenceLevel->getAccess();
+
+ // Fill lines, 4 pixels per line.
+ const uint32_t kNumLines = 255u;
+ const uint32_t kLineHeight = 4u;
+
+ for (uint32_t i = 0u; i < kNumLines; ++i)
+ {
+ const tcu::Vec4 color (0.0f, 1.0f, static_cast<float>(i) / static_cast<float>(kNumLines), 1.0f);
+ for (uint32_t j = 0u; j < kLineHeight; ++j)
+ access.setPixel(color, 0, i*kLineHeight + j);
+ }
+}
+
+// Verify drawing the maximum number of triangles.
+class MaxTrianglesCase : public MeshShaderMiscCase
+{
+public:
+ MaxTrianglesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class MaxTrianglesInstance : public MeshShaderMiscInstance
+{
+public:
+ MaxTrianglesInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* MaxTrianglesCase::createInstance (Context& context) const
+{
+ return new MaxTrianglesInstance (context, m_params.get());
+}
+
+void MaxTrianglesCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ DE_ASSERT(!m_params->needsTaskShader());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ // Fill a sufficiently large image with solid color. Generate a quarter of a circle with the center in the top left corner,
+ // using a triangle fan that advances from top to bottom. Each invocation will generate ~8 triangles.
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=32) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=256, max_primitives=254) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << "const float PI_2 = 1.57079632679489661923;\n"
+ << "const float RADIUS = 4.5;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 254u;\n"
+ << " uint firstTriangle = 8u * gl_LocalInvocationID.x;\n"
+ << " for (uint i = 0u; i < 8u; i++) {\n"
+ << " uint triangleId = firstTriangle + i;\n"
+ << " if (triangleId < 254u) {\n"
+ << " uint vertexId = triangleId + 2u;\n"
+ << " float angleProportion = float(vertexId - 1u) / 254.0f;\n"
+ << " float angle = PI_2 * angleProportion;\n"
+ << " float xCoord = cos(angle) * RADIUS - 1.0;\n"
+ << " float yCoord = sin(angle) * RADIUS - 1.0;\n"
+ << " gl_MeshVerticesNV[vertexId].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
+ << " gl_PrimitiveIndicesNV[triangleId * 3u + 0u] = 0u;\n"
+ << " gl_PrimitiveIndicesNV[triangleId * 3u + 1u] = triangleId + 1u;\n"
+ << " gl_PrimitiveIndicesNV[triangleId * 3u + 2u] = triangleId + 2u;\n"
+ << " triangleColor[triangleId] = vec4(0.0f, 0.0f, 1.0f, 1.0f);\n"
+ << " } else {\n"
+ << " // The last iterations of the last invocation emit the first two vertices\n"
+ << " uint vertexId = triangleId - 254u;\n"
+ << " if (vertexId == 0u) {\n"
+ << " gl_MeshVerticesNV[0u].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " } else {\n"
+ << " gl_MeshVerticesNV[1u].gl_Position = vec4(RADIUS, -1.0, 0.0, 1.0);\n"
+ << " }\n"
+ << " }\n"
+ << " }\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+void MaxTrianglesInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
+}
+
+// Large work groups with many threads.
+class LargeWorkGroupCase : public MeshShaderMiscCase
+{
+public:
+ LargeWorkGroupCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+ static constexpr uint32_t kLocalInvocations = 32u;
+};
+
+class LargeWorkGroupInstance : public MeshShaderMiscInstance
+{
+public:
+ LargeWorkGroupInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* LargeWorkGroupCase::createInstance (Context& context) const
+{
+ return new LargeWorkGroupInstance(context, m_params.get());
+}
+
+void LargeWorkGroupInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
+}
+
+void LargeWorkGroupCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto useTaskShader = m_params->needsTaskShader();
+ const auto taskMultiplier = (useTaskShader ? m_params->taskCount.get() : 1u);
+
+ // Add the frag shader.
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ std::ostringstream taskData;
+ taskData
+ << "taskNV TaskData {\n"
+ << " uint parentTask[" << kLocalInvocations << "];\n"
+ << "} td;\n"
+ ;
+ const auto taskDataStr = taskData.str();
+
+ if (useTaskShader)
+ {
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "\n"
+ << "out " << taskDataStr
+ << "\n"
+ << "void main () {\n"
+ << " gl_TaskCountNV = " << m_params->meshCount << ";\n"
+ << " td.parentTask[gl_LocalInvocationID.x] = gl_WorkGroupID.x;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ // Needed for the code below to work.
+ DE_ASSERT(m_params->width * m_params->height == taskMultiplier * m_params->meshCount * kLocalInvocations);
+ DE_UNREF(taskMultiplier); // For release builds.
+
+ // Emit one point per framebuffer pixel. The number of jobs (kLocalInvocations in each mesh shader work group, multiplied by the
+ // number of mesh work groups emitted by each task work group) must be the same as the total framebuffer size. Calculate a job
+ // ID corresponding to the current mesh shader invocation, and assign a pixel position to it. Draw a point at that position.
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "layout (points) out;\n"
+ << "layout (max_vertices=" << kLocalInvocations << ", max_primitives=" << kLocalInvocations << ") out;\n"
+ << "\n"
+ << (useTaskShader ? "in " + taskDataStr : "")
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 pointColor[];\n"
+ << "\n"
+ << "void main () {\n"
+ ;
+
+ if (useTaskShader)
+ {
+ mesh
+ << " uint parentTask = td.parentTask[0];\n"
+ << " if (td.parentTask[gl_LocalInvocationID.x] != parentTask) {\n"
+ << " return;\n"
+ << " }\n"
+ ;
+ }
+ else
+ {
+ mesh << " uint parentTask = 0;\n";
+ }
+
+ mesh
+ << " gl_PrimitiveCountNV = " << kLocalInvocations << ";\n"
+ << " uint jobId = ((parentTask * " << m_params->meshCount << ") + gl_WorkGroupID.x) * " << kLocalInvocations << " + gl_LocalInvocationID.x;\n"
+ << " uint row = jobId / " << m_params->width << ";\n"
+ << " uint col = jobId % " << m_params->width << ";\n"
+ << " float yCoord = (float(row + 0.5) / " << m_params->height << ".0) * 2.0 - 1.0;\n"
+ << " float xCoord = (float(col + 0.5) / " << m_params->width << ".0) * 2.0 - 1.0;\n"
+ << " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_PointSize = 1.0;\n"
+ << " gl_PrimitiveIndicesNV[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
+ << " pointColor[gl_LocalInvocationID.x] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+// Tests that generate no primitives of a given type.
+enum class PrimitiveType { POINTS=0, LINES, TRIANGLES };
+
+std::string primitiveTypeName (PrimitiveType primitiveType)
+{
+ std::string primitiveName;
+
+ switch (primitiveType)
+ {
+ case PrimitiveType::POINTS: primitiveName = "points"; break;
+ case PrimitiveType::LINES: primitiveName = "lines"; break;
+ case PrimitiveType::TRIANGLES: primitiveName = "triangles"; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ return primitiveName;
+}
+
+struct NoPrimitivesParams : public MiscTestParams
+{
+ PrimitiveType primitiveType;
+};
+
+class NoPrimitivesCase : public MeshShaderMiscCase
+{
+public:
+ NoPrimitivesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class NoPrimitivesInstance : public MeshShaderMiscInstance
+{
+public:
+ NoPrimitivesInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+void NoPrimitivesInstance::generateReferenceLevel ()
+{
+ // No primitives: clear color.
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), m_referenceLevel);
+}
+
+TestInstance* NoPrimitivesCase::createInstance (Context& context) const
+{
+ return new NoPrimitivesInstance(context, m_params.get());
+}
+
+void NoPrimitivesCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto params = dynamic_cast<NoPrimitivesParams*>(m_params.get());
+
+ DE_ASSERT(params);
+ DE_ASSERT(!params->needsTaskShader());
+
+ const auto primitiveName = primitiveTypeName(params->primitiveType);
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=32) in;\n"
+ << "layout (" << primitiveName << ") out;\n"
+ << "layout (max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
+ << "\n"
+ << "void main () {\n"
+ << " gl_PrimitiveCountNV = 0u;\n"
+ << "}\n"
+ ;
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+}
+
+class NoPrimitivesExtraWritesCase : public NoPrimitivesCase
+{
+public:
+ NoPrimitivesExtraWritesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : NoPrimitivesCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+
+ static constexpr uint32_t kLocalInvocations = 32u;
+};
+
+void NoPrimitivesExtraWritesCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto params = dynamic_cast<NoPrimitivesParams*>(m_params.get());
+
+ DE_ASSERT(params);
+ DE_ASSERT(m_params->needsTaskShader());
+
+ std::ostringstream taskData;
+ taskData
+ << "taskNV TaskData {\n"
+ << " uint localInvocations[" << kLocalInvocations << "];\n"
+ << "} td;\n"
+ ;
+ const auto taskDataStr = taskData.str();
+
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "\n"
+ << "out " << taskDataStr
+ << "\n"
+ << "void main () {\n"
+ << " gl_TaskCountNV = " << params->meshCount << ";\n"
+ << " td.localInvocations[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+
+ const auto primitiveName = primitiveTypeName(params->primitiveType);
+
+ // Otherwise the shader would be illegal.
+ DE_ASSERT(kLocalInvocations > 2u);
+
+ uint32_t maxPrimitives = 0u;
+ switch (params->primitiveType)
+ {
+ case PrimitiveType::POINTS: maxPrimitives = kLocalInvocations - 0u; break;
+ case PrimitiveType::LINES: maxPrimitives = kLocalInvocations - 1u; break;
+ case PrimitiveType::TRIANGLES: maxPrimitives = kLocalInvocations - 2u; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ const std::string pointSizeDecl = ((params->primitiveType == PrimitiveType::POINTS)
+ ? " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_PointSize = 1.0;\n"
+ : "");
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "layout (" << primitiveName << ") out;\n"
+ << "layout (max_vertices=" << kLocalInvocations << ", max_primitives=" << maxPrimitives << ") out;\n"
+ << "\n"
+ << "in " << taskDataStr
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
+ << "\n"
+ << "shared uint sumOfIds;\n"
+ << "\n"
+ << "const float PI_2 = 1.57079632679489661923;\n"
+ << "const float RADIUS = 1.0f;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " sumOfIds = 0u;\n"
+ << " barrier();\n"
+ << " atomicAdd(sumOfIds, td.localInvocations[gl_LocalInvocationID.x]);\n"
+ << " barrier();\n"
+ << " // This should dynamically give 0\n"
+ << " gl_PrimitiveCountNV = sumOfIds - (" << kLocalInvocations * (kLocalInvocations - 1u) / 2u << ");\n"
+ << "\n"
+ << " // Emit points and primitives to the arrays in any case\n"
+ << " if (gl_LocalInvocationID.x > 0u) {\n"
+ << " float proportion = (float(gl_LocalInvocationID.x - 1u) + 0.5f) / float(" << kLocalInvocations << " - 1u);\n"
+ << " float angle = PI_2 * proportion;\n"
+ << " float xCoord = cos(angle) * RADIUS - 1.0;\n"
+ << " float yCoord = sin(angle) * RADIUS - 1.0;\n"
+ << " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(xCoord, yCoord, 0.0, 1.0);\n"
+ << pointSizeDecl
+ << " } else {\n"
+ << " gl_MeshVerticesNV[gl_LocalInvocationID.x].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ << pointSizeDecl
+ << " }\n"
+ << " uint primitiveId = max(gl_LocalInvocationID.x, " << (maxPrimitives - 1u) << ");\n"
+ << " primitiveColor[primitiveId] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ ;
+
+ if (params->primitiveType == PrimitiveType::POINTS)
+ {
+ mesh
+ << " gl_PrimitiveIndicesNV[primitiveId] = primitiveId;\n"
+ ;
+ }
+ else if (params->primitiveType == PrimitiveType::LINES)
+ {
+ mesh
+ << " gl_PrimitiveIndicesNV[primitiveId * 2u + 0u] = primitiveId + 0u;\n"
+ << " gl_PrimitiveIndicesNV[primitiveId * 2u + 1u] = primitiveId + 1u;\n"
+ ;
+ }
+ else if (params->primitiveType == PrimitiveType::TRIANGLES)
+ {
+ mesh
+ << " gl_PrimitiveIndicesNV[primitiveId * 3u + 0u] = 0u;\n"
+ << " gl_PrimitiveIndicesNV[primitiveId * 3u + 1u] = primitiveId + 1u;\n"
+ << " gl_PrimitiveIndicesNV[primitiveId * 3u + 2u] = primitiveId + 3u;\n"
+ ;
+ }
+ else
+ DE_ASSERT(false);
+
+ mesh
+ << "}\n"
+ ;
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+
+ MeshShaderMiscCase::initPrograms(programCollection);
+}
+
+// Case testing barrier().
+class SimpleBarrierCase : public MeshShaderMiscCase
+{
+public:
+ SimpleBarrierCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+ static constexpr uint32_t kLocalInvocations = 32u;
+};
+
+class SimpleBarrierInstance : public MeshShaderMiscInstance
+{
+public:
+ SimpleBarrierInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+};
+
+TestInstance* SimpleBarrierCase::createInstance (Context& context) const
+{
+ return new SimpleBarrierInstance(context, m_params.get());
+}
+
+void SimpleBarrierInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
+}
+
+void SimpleBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ // Generate frag shader.
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ DE_ASSERT(m_params->meshCount == 1u);
+ DE_ASSERT(m_params->width == 1u && m_params->height == 1u);
+
+ std::ostringstream meshPrimData;
+ meshPrimData
+ << "gl_PrimitiveCountNV = 1u;\n"
+ << "gl_MeshVerticesNV[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ << "gl_MeshVerticesNV[0].gl_PointSize = 1.0;\n"
+ << "primitiveColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << "gl_PrimitiveIndicesNV[0] = 0;\n"
+ ;
+ const std::string meshPrimStr = meshPrimData.str();
+
+ const std::string taskOK = "gl_TaskCountNV = 1u;\n";
+ const std::string taskFAIL = "gl_TaskCountNV = 0u;\n";
+
+ const std::string meshOK = meshPrimStr;
+ const std::string meshFAIL = "gl_PrimitiveCountNV = 0u;\n";
+
+ const std::string okStatement = (m_params->needsTaskShader() ? taskOK : meshOK);
+ const std::string failStatement = (m_params->needsTaskShader() ? taskFAIL : meshFAIL);
+
+ const std::string sharedDecl = "shared uint counter;\n\n";
+ std::ostringstream verification;
+ verification
+ << "counter = 0;\n"
+ << "barrier();\n"
+ << "atomicAdd(counter, 1u);\n"
+ << "barrier();\n"
+ << "if (gl_LocalInvocationID.x == 0u) {\n"
+ << " if (counter == " << kLocalInvocations << ") {\n"
+ << "\n"
+ << okStatement
+ << "\n"
+ << " } else {\n"
+ << "\n"
+ << failStatement
+ << "\n"
+ << " }\n"
+ << "}\n"
+ ;
+
+ // The mesh shader is very similar in both cases, so we use a template.
+ std::ostringstream meshTemplateStr;
+ meshTemplateStr
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=${LOCAL_SIZE}) in;\n"
+ << "layout (points) out;\n"
+ << "layout (max_vertices=1, max_primitives=1) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
+ << "\n"
+ << "${GLOBALS:opt}"
+ << "void main ()\n"
+ << "{\n"
+ << "${BODY}"
+ << "}\n"
+ ;
+ const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
+
+ if (m_params->needsTaskShader())
+ {
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "\n"
+ << sharedDecl
+ << "void main ()\n"
+ << "{\n"
+ << verification.str()
+ << "}\n"
+ ;
+
+ std::map<std::string, std::string> replacements;
+ replacements["LOCAL_SIZE"] = "1";
+ replacements["BODY"] = meshPrimStr;
+
+ const auto meshStr = meshTemplate.specialize(replacements);
+
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
+ }
+ else
+ {
+ std::map<std::string, std::string> replacements;
+ replacements["LOCAL_SIZE"] = std::to_string(kLocalInvocations);
+ replacements["BODY"] = verification.str();
+ replacements["GLOBALS"] = sharedDecl;
+
+ const auto meshStr = meshTemplate.specialize(replacements);
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
+ }
+}
+
+// Case testing memoryBarrierShared() and groupMemoryBarrier().
+enum class MemoryBarrierType { SHARED = 0, GROUP };
+
+struct MemoryBarrierParams : public MiscTestParams
+{
+ MemoryBarrierType memBarrierType;
+
+ std::string glslFunc () const
+ {
+ std::string funcName;
+
+ switch (memBarrierType)
+ {
+ case MemoryBarrierType::SHARED: funcName = "memoryBarrierShared"; break;
+ case MemoryBarrierType::GROUP: funcName = "groupMemoryBarrier"; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ return funcName;
+ }
+
+};
+
+class MemoryBarrierCase : public MeshShaderMiscCase
+{
+public:
+ MemoryBarrierCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+ static constexpr uint32_t kLocalInvocations = 2u;
+};
+
+class MemoryBarrierInstance : public MeshShaderMiscInstance
+{
+public:
+ MemoryBarrierInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+ bool verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const override;
+
+protected:
+ // Allow two possible outcomes.
+ std::unique_ptr<tcu::TextureLevel> m_referenceLevel2;
+};
+
+TestInstance* MemoryBarrierCase::createInstance (Context& context) const
+{
+ return new MemoryBarrierInstance(context, m_params.get());
+}
+
+void MemoryBarrierInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), m_referenceLevel2);
+}
+
+bool MemoryBarrierInstance::verifyResult (const tcu::ConstPixelBufferAccess& resultAccess) const
+{
+ // Any of the two results is considered valid.
+ constexpr auto Message = tcu::TestLog::Message;
+ constexpr auto EndMessage = tcu::TestLog::EndMessage;
+
+ // Clarify what we are checking in the logs; otherwise, they could be confusing.
+ auto& log = m_context.getTestContext().getLog();
+ const std::vector<tcu::TextureLevel*> levels = { m_referenceLevel.get(), m_referenceLevel2.get() };
+
+ bool good = false;
+ for (size_t i = 0; i < levels.size(); ++i)
+ {
+ log << Message << "Comparing result with reference " << i << "..." << EndMessage;
+ const auto success = MeshShaderMiscInstance::verifyResult(resultAccess, *levels[i]);
+ if (success)
+ {
+ log << Message << "Match! The test has passed" << EndMessage;
+ good = true;
+ break;
+ }
+ }
+
+ return good;
+}
+
+void MemoryBarrierCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto params = dynamic_cast<MemoryBarrierParams*>(m_params.get());
+ DE_ASSERT(params);
+
+ // Generate frag shader.
+ MeshShaderMiscCase::initPrograms(programCollection);
+
+ DE_ASSERT(params->meshCount == 1u);
+ DE_ASSERT(params->width == 1u && params->height == 1u);
+
+ const bool taskShader = params->needsTaskShader();
+
+ const std::string taskDataDecl = "taskNV TaskData { float blue; } td;\n\n";
+ const std::string inTaskData = "in " + taskDataDecl;
+ const std::string outTaskData = "out " + taskDataDecl;
+ const auto barrierFunc = params->glslFunc();
+
+ std::ostringstream meshPrimData;
+ meshPrimData
+ << "gl_PrimitiveCountNV = 1u;\n"
+ << "gl_MeshVerticesNV[0].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ << "gl_MeshVerticesNV[0].gl_PointSize = 1.0;\n"
+ << "primitiveColor[0] = vec4(0.0, 0.0, " << (taskShader ? "td.blue" : "float(iterations % 2u)") << ", 1.0);\n"
+ << "gl_PrimitiveIndicesNV[0] = 0;\n"
+ ;
+ const std::string meshPrimStr = meshPrimData.str();
+
+ const std::string taskAction = "gl_TaskCountNV = 1u;\ntd.blue = float(iterations % 2u);\n";
+ const std::string meshAction = meshPrimStr;
+ const std::string action = (taskShader ? taskAction : meshAction);
+
+ const std::string sharedDecl = "shared uint flags[2];\n\n";
+ std::ostringstream verification;
+ verification
+ << "flags[gl_LocalInvocationID.x] = 0u;\n"
+ << "barrier();\n"
+ << "flags[gl_LocalInvocationID.x] = 1u;\n"
+ << barrierFunc << "();\n"
+ << "uint otherInvocation = 1u - gl_LocalInvocationID.x;\n"
+ << "uint iterations = 0u;\n"
+ << "while (flags[otherInvocation] != 1u) {\n"
+ << " iterations++;\n"
+ << "}\n"
+ << "if (gl_LocalInvocationID.x == 0u) {\n"
+ << "\n"
+ << action
+ << "\n"
+ << "}\n"
+ ;
+
+ // The mesh shader is very similar in both cases, so we use a template.
+ std::ostringstream meshTemplateStr;
+ meshTemplateStr
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=${LOCAL_SIZE}) in;\n"
+ << "layout (points) out;\n"
+ << "layout (max_vertices=1, max_primitives=1) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 primitiveColor[];\n"
+ << "\n"
+ << "${GLOBALS}"
+ << "void main ()\n"
+ << "{\n"
+ << "${BODY}"
+ << "}\n"
+ ;
+ const tcu::StringTemplate meshTemplate = meshTemplateStr.str();
+
+ if (params->needsTaskShader())
+ {
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=" << kLocalInvocations << ") in;\n"
+ << "\n"
+ << sharedDecl
+ << outTaskData
+ << "void main ()\n"
+ << "{\n"
+ << verification.str()
+ << "}\n"
+ ;
+
+ std::map<std::string, std::string> replacements;
+ replacements["LOCAL_SIZE"] = "1";
+ replacements["BODY"] = meshPrimStr;
+ replacements["GLOBALS"] = inTaskData;
+
+ const auto meshStr = meshTemplate.specialize(replacements);
+
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
+ }
+ else
+ {
+ std::map<std::string, std::string> replacements;
+ replacements["LOCAL_SIZE"] = std::to_string(kLocalInvocations);
+ replacements["BODY"] = verification.str();
+ replacements["GLOBALS"] = sharedDecl;
+
+ const auto meshStr = meshTemplate.specialize(replacements);
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshStr);
+ }
+}
+
+class CustomAttributesCase : public MeshShaderMiscCase
+{
+public:
+ CustomAttributesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase(testCtx, name, description, std::move(params)) {}
+ virtual ~CustomAttributesCase (void) {}
+
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+};
+
+class CustomAttributesInstance : public MeshShaderMiscInstance
+{
+public:
+ CustomAttributesInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance(context, params) {}
+ virtual ~CustomAttributesInstance (void) {}
+
+ void generateReferenceLevel () override;
+ tcu::TestStatus iterate (void) override;
+};
+
+TestInstance* CustomAttributesCase::createInstance (Context& context) const
+{
+ return new CustomAttributesInstance(context, m_params.get());
+}
+
+void CustomAttributesCase::checkSupport (Context& context) const
+{
+ MeshShaderMiscCase::checkSupport(context);
+
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);
+ context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
+}
+
+void CustomAttributesCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ std::ostringstream frag;
+ frag
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) in vec4 customAttribute1;\n"
+ << "layout (location=1) in flat float customAttribute2;\n"
+ << "layout (location=2) in flat int customAttribute3;\n"
+ << "\n"
+ << "layout (location=3) in perprimitiveNV flat uvec4 customAttribute4;\n"
+ << "layout (location=4) in perprimitiveNV float customAttribute5;\n"
+ << "\n"
+ << "layout (location=0) out vec4 outColor;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " bool goodPrimitiveID = (gl_PrimitiveID == 1000 || gl_PrimitiveID == 1001);\n"
+ << " bool goodViewportIndex = (gl_ViewportIndex == 1);\n"
+ << " bool goodCustom1 = (customAttribute1.x >= 0.25 && customAttribute1.x <= 0.5 &&\n"
+ << " customAttribute1.y >= 0.5 && customAttribute1.y <= 1.0 &&\n"
+ << " customAttribute1.z >= 10.0 && customAttribute1.z <= 20.0 &&\n"
+ << " customAttribute1.w == 3.0);\n"
+ << " bool goodCustom2 = (customAttribute2 == 1.0 || customAttribute2 == 2.0);\n"
+ << " bool goodCustom3 = (customAttribute3 == 3 || customAttribute3 == 4);\n"
+ << " bool goodCustom4 = ((gl_PrimitiveID == 1000 && customAttribute4 == uvec4(100, 101, 102, 103)) ||\n"
+ << " (gl_PrimitiveID == 1001 && customAttribute4 == uvec4(200, 201, 202, 203)));\n"
+ << " bool goodCustom5 = ((gl_PrimitiveID == 1000 && customAttribute5 == 6.0) ||\n"
+ << " (gl_PrimitiveID == 1001 && customAttribute5 == 7.0));\n"
+ << " \n"
+ << " if (goodPrimitiveID && goodViewportIndex && goodCustom1 && goodCustom2 && goodCustom3 && goodCustom4 && goodCustom5) {\n"
+ << " outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << " } else {\n"
+ << " outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
+ << " }\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+
+ std::ostringstream pvdDataDeclStream;
+ pvdDataDeclStream
+ << " vec4 positions[4];\n"
+ << " float pointSizes[4];\n"
+ << " float clipDistances[4];\n"
+ << " vec4 custom1[4];\n"
+ << " float custom2[4];\n"
+ << " int custom3[4];\n"
+ ;
+ const auto pvdDataDecl = pvdDataDeclStream.str();
+
+ std::ostringstream ppdDataDeclStream;
+ ppdDataDeclStream
+ << " int primitiveIds[2];\n"
+ << " int viewportIndices[2];\n"
+ << " uvec4 custom4[2];\n"
+ << " float custom5[2];\n"
+ ;
+ const auto ppdDataDecl = ppdDataDeclStream.str();
+
+ std::ostringstream bindingsDeclStream;
+ bindingsDeclStream
+ << "layout (set=0, binding=0, std430) buffer PerVertexData {\n"
+ << pvdDataDecl
+ << "} pvd;\n"
+ << "layout (set=0, binding=1) uniform PerPrimitiveData {\n"
+ << ppdDataDecl
+ << "} ppd;\n"
+ << "\n"
+ ;
+ const auto bindingsDecl = bindingsDeclStream.str();
+
+ std::ostringstream taskDataStream;
+ taskDataStream
+ << "taskNV TaskData {\n"
+ << pvdDataDecl
+ << ppdDataDecl
+ << "} td;\n"
+ << "\n"
+ ;
+ const auto taskDataDecl = taskDataStream.str();
+
+ const auto taskShader = m_params->needsTaskShader();
+
+ const auto meshPvdPrefix = (taskShader ? "td" : "pvd");
+ const auto meshPpdPrefix = (taskShader ? "td" : "ppd");
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (local_size_x=1) in;\n"
+ << "layout (max_primitives=2, max_vertices=4) out;\n"
+ << "layout (triangles) out;\n"
+ << "\n"
+ << "out gl_MeshPerVertexNV {\n"
+ << " vec4 gl_Position;\n"
+ << " float gl_PointSize;\n"
+ << " float gl_ClipDistance[1];\n"
+ << "} gl_MeshVerticesNV[];\n"
+ << "\n"
+ << "layout (location=0) out vec4 customAttribute1[];\n"
+ << "layout (location=1) out flat float customAttribute2[];\n"
+ << "layout (location=2) out int customAttribute3[];\n"
+ << "\n"
+ << "layout (location=3) out perprimitiveNV uvec4 customAttribute4[];\n"
+ << "layout (location=4) out perprimitiveNV float customAttribute5[];\n"
+ << "\n"
+ << "out perprimitiveNV gl_MeshPerPrimitiveNV {\n"
+ << " int gl_PrimitiveID;\n"
+ << " int gl_ViewportIndex;\n"
+ << "} gl_MeshPrimitivesNV[];\n"
+ << "\n"
+ << (taskShader ? "in " + taskDataDecl : bindingsDecl)
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 2u;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = " << meshPvdPrefix << ".positions[0]; //vec4(-1.0, -1.0, 0.0, 1.0)\n"
+ << " gl_MeshVerticesNV[1].gl_Position = " << meshPvdPrefix << ".positions[1]; //vec4( 1.0, -1.0, 0.0, 1.0)\n"
+ << " gl_MeshVerticesNV[2].gl_Position = " << meshPvdPrefix << ".positions[2]; //vec4(-1.0, 1.0, 0.0, 1.0)\n"
+ << " gl_MeshVerticesNV[3].gl_Position = " << meshPvdPrefix << ".positions[3]; //vec4( 1.0, 1.0, 0.0, 1.0)\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_PointSize = " << meshPvdPrefix << ".pointSizes[0]; //1.0\n"
+ << " gl_MeshVerticesNV[1].gl_PointSize = " << meshPvdPrefix << ".pointSizes[1]; //1.0\n"
+ << " gl_MeshVerticesNV[2].gl_PointSize = " << meshPvdPrefix << ".pointSizes[2]; //1.0\n"
+ << " gl_MeshVerticesNV[3].gl_PointSize = " << meshPvdPrefix << ".pointSizes[3]; //1.0\n"
+ << "\n"
+ << " // Remove geometry on the right side.\n"
+ << " gl_MeshVerticesNV[0].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[0]; // 1.0\n"
+ << " gl_MeshVerticesNV[1].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[1]; //-1.0\n"
+ << " gl_MeshVerticesNV[2].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[2]; // 1.0\n"
+ << " gl_MeshVerticesNV[3].gl_ClipDistance[0] = " << meshPvdPrefix << ".clipDistances[3]; //-1.0\n"
+ << " \n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 2;\n"
+ << " gl_PrimitiveIndicesNV[2] = 1;\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[3] = 2;\n"
+ << " gl_PrimitiveIndicesNV[4] = 3;\n"
+ << " gl_PrimitiveIndicesNV[5] = 1;\n"
+ << "\n"
+ << " gl_MeshPrimitivesNV[0].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[0]; //1000\n"
+ << " gl_MeshPrimitivesNV[1].gl_PrimitiveID = " << meshPpdPrefix << ".primitiveIds[1]; //1001\n"
+ << "\n"
+ << " gl_MeshPrimitivesNV[0].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[0]; //1\n"
+ << " gl_MeshPrimitivesNV[1].gl_ViewportIndex = " << meshPpdPrefix << ".viewportIndices[1]; //1\n"
+ << "\n"
+ << " // Custom per-vertex attributes\n"
+ << " customAttribute1[0] = " << meshPvdPrefix << ".custom1[0]; //vec4(0.25, 0.5, 10.0, 3.0)\n"
+ << " customAttribute1[1] = " << meshPvdPrefix << ".custom1[1]; //vec4(0.25, 1.0, 20.0, 3.0)\n"
+ << " customAttribute1[2] = " << meshPvdPrefix << ".custom1[2]; //vec4( 0.5, 0.5, 20.0, 3.0)\n"
+ << " customAttribute1[3] = " << meshPvdPrefix << ".custom1[3]; //vec4( 0.5, 1.0, 10.0, 3.0)\n"
+ << "\n"
+ << " customAttribute2[0] = " << meshPvdPrefix << ".custom2[0]; //1.0f\n"
+ << " customAttribute2[1] = " << meshPvdPrefix << ".custom2[1]; //1.0f\n"
+ << " customAttribute2[2] = " << meshPvdPrefix << ".custom2[2]; //2.0f\n"
+ << " customAttribute2[3] = " << meshPvdPrefix << ".custom2[3]; //2.0f\n"
+ << "\n"
+ << " customAttribute3[0] = " << meshPvdPrefix << ".custom3[0]; //3\n"
+ << " customAttribute3[1] = " << meshPvdPrefix << ".custom3[1]; //3\n"
+ << " customAttribute3[2] = " << meshPvdPrefix << ".custom3[2]; //4\n"
+ << " customAttribute3[3] = " << meshPvdPrefix << ".custom3[3]; //4\n"
+ << "\n"
+ << " // Custom per-primitive attributes.\n"
+ << " customAttribute4[0] = " << meshPpdPrefix << ".custom4[0]; //uvec4(100, 101, 102, 103)\n"
+ << " customAttribute4[1] = " << meshPpdPrefix << ".custom4[1]; //uvec4(200, 201, 202, 203)\n"
+ << "\n"
+ << " customAttribute5[0] = " << meshPpdPrefix << ".custom5[0]; //6.0\n"
+ << " customAttribute5[1] = " << meshPpdPrefix << ".custom5[1]; //7.0\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+
+ if (taskShader)
+ {
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << bindingsDecl
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = " << m_params->meshCount << ";\n"
+ << "\n"
+ << " td.positions[0] = pvd.positions[0];\n"
+ << " td.positions[1] = pvd.positions[1];\n"
+ << " td.positions[2] = pvd.positions[2];\n"
+ << " td.positions[3] = pvd.positions[3];\n"
+ << "\n"
+ << " td.pointSizes[0] = pvd.pointSizes[0];\n"
+ << " td.pointSizes[1] = pvd.pointSizes[1];\n"
+ << " td.pointSizes[2] = pvd.pointSizes[2];\n"
+ << " td.pointSizes[3] = pvd.pointSizes[3];\n"
+ << "\n"
+ << " td.clipDistances[0] = pvd.clipDistances[0];\n"
+ << " td.clipDistances[1] = pvd.clipDistances[1];\n"
+ << " td.clipDistances[2] = pvd.clipDistances[2];\n"
+ << " td.clipDistances[3] = pvd.clipDistances[3];\n"
+ << "\n"
+ << " td.custom1[0] = pvd.custom1[0];\n"
+ << " td.custom1[1] = pvd.custom1[1];\n"
+ << " td.custom1[2] = pvd.custom1[2];\n"
+ << " td.custom1[3] = pvd.custom1[3];\n"
+ << "\n"
+ << " td.custom2[0] = pvd.custom2[0];\n"
+ << " td.custom2[1] = pvd.custom2[1];\n"
+ << " td.custom2[2] = pvd.custom2[2];\n"
+ << " td.custom2[3] = pvd.custom2[3];\n"
+ << "\n"
+ << " td.custom3[0] = pvd.custom3[0];\n"
+ << " td.custom3[1] = pvd.custom3[1];\n"
+ << " td.custom3[2] = pvd.custom3[2];\n"
+ << " td.custom3[3] = pvd.custom3[3];\n"
+ << "\n"
+ << " td.primitiveIds[0] = ppd.primitiveIds[0];\n"
+ << " td.primitiveIds[1] = ppd.primitiveIds[1];\n"
+ << "\n"
+ << " td.viewportIndices[0] = ppd.viewportIndices[0];\n"
+ << " td.viewportIndices[1] = ppd.viewportIndices[1];\n"
+ << "\n"
+ << " td.custom4[0] = ppd.custom4[0];\n"
+ << " td.custom4[1] = ppd.custom4[1];\n"
+ << "\n"
+ << " td.custom5[0] = ppd.custom5[0];\n"
+ << " td.custom5[1] = ppd.custom5[1];\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+}
+
+void CustomAttributesInstance::generateReferenceLevel ()
+{
+ const auto format = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(format);
+
+ const auto iWidth = static_cast<int>(m_params->width);
+ const auto iHeight = static_cast<int>(m_params->height);
+
+ const auto halfWidth = iWidth / 2;
+ const auto halfHeight = iHeight / 2;
+
+ m_referenceLevel.reset(new tcu::TextureLevel(tcuFormat, iWidth, iHeight));
+
+ const auto access = m_referenceLevel->getAccess();
+ const auto clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
+ const auto blueColor = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
+
+ tcu::clear(access, clearColor);
+
+ // Fill the top left quarter.
+ for (int y = 0; y < halfWidth; ++y)
+ for (int x = 0; x < halfHeight; ++x)
+ {
+ access.setPixel(blueColor, x, y);
+ }
+}
+
+tcu::TestStatus CustomAttributesInstance::iterate ()
+{
+ struct PerVertexData
+ {
+ tcu::Vec4 positions[4];
+ float pointSizes[4];
+ float clipDistances[4];
+ tcu::Vec4 custom1[4];
+ float custom2[4];
+ int32_t custom3[4];
+ };
+
+ struct PerPrimitiveData
+ {
+ // Note some of these are declared as vectors to match the std140 layout.
+ tcu::IVec4 primitiveIds[2];
+ tcu::IVec4 viewportIndices[2];
+ tcu::UVec4 custom4[2];
+ tcu::Vec4 custom5[2];
+ };
+
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto imageFormat = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(imageFormat);
+ const auto imageExtent = makeExtent3D(m_params->width, m_params->height, 1u);
+ const auto imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+
+ const auto& binaries = m_context.getBinaryCollection();
+ const auto hasTask = binaries.contains("task");
+ const auto bufStages = (hasTask ? VK_SHADER_STAGE_TASK_BIT_NV : VK_SHADER_STAGE_MESH_BIT_NV);
+
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ imageExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ imageUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ // Create color image and view.
+ ImageWithMemory colorImage (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
+ const auto colorView = makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
+
+ // Create a memory buffer for verification.
+ const auto verificationBufferSize = static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
+ const auto verificationBufferUsage = (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ const auto verificationBufferInfo = makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
+
+ BufferWithMemory verificationBuffer (vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
+ auto& verificationBufferAlloc = verificationBuffer.getAllocation();
+ void* verificationBufferData = verificationBufferAlloc.getHostPtr();
+
+ // This needs to match what the fragment shader will expect.
+ const PerVertexData perVertexData =
+ {
+ // tcu::Vec4 positions[4];
+ {
+ tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
+ tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f),
+ },
+ // float pointSizes[4];
+ { 1.0f, 1.0f, 1.0f, 1.0f, },
+ // float clipDistances[4];
+ {
+ 1.0f,
+ -1.0f,
+ 1.0f,
+ -1.0f,
+ },
+ // tcu::Vec4 custom1[4];
+ {
+ tcu::Vec4(0.25, 0.5, 10.0, 3.0),
+ tcu::Vec4(0.25, 1.0, 20.0, 3.0),
+ tcu::Vec4( 0.5, 0.5, 20.0, 3.0),
+ tcu::Vec4( 0.5, 1.0, 10.0, 3.0),
+ },
+ // float custom2[4];
+ { 1.0f, 1.0f, 2.0f, 2.0f, },
+ // int32_t custom3[4];
+ { 3, 3, 4, 4 },
+ };
+
+ // This needs to match what the fragment shader will expect. Reminder: some of these are declared as gvec4 to match the std140
+ // layout, but only the first component is actually used.
+ const PerPrimitiveData perPrimitiveData =
+ {
+ // int primitiveIds[2];
+ {
+ tcu::IVec4(1000, 0, 0, 0),
+ tcu::IVec4(1001, 0, 0, 0),
+ },
+ // int viewportIndices[2];
+ {
+ tcu::IVec4(1, 0, 0, 0),
+ tcu::IVec4(1, 0, 0, 0),
+ },
+ // uvec4 custom4[2];
+ {
+ tcu::UVec4(100u, 101u, 102u, 103u),
+ tcu::UVec4(200u, 201u, 202u, 203u),
+ },
+ // float custom5[2];
+ {
+ tcu::Vec4(6.0f, 0.0f, 0.0f, 0.0f),
+ tcu::Vec4(7.0f, 0.0f, 0.0f, 0.0f),
+ },
+ };
+
+ // Create and fill buffers with this data.
+ const auto pvdSize = static_cast<VkDeviceSize>(sizeof(perVertexData));
+ const auto pvdInfo = makeBufferCreateInfo(pvdSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+ BufferWithMemory pvdData (vkd, device, alloc, pvdInfo, MemoryRequirement::HostVisible);
+ auto& pvdAlloc = pvdData.getAllocation();
+ void* pvdPtr = pvdAlloc.getHostPtr();
+
+ const auto ppdSize = static_cast<VkDeviceSize>(sizeof(perPrimitiveData));
+ const auto ppdInfo = makeBufferCreateInfo(ppdSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
+ BufferWithMemory ppdData (vkd, device, alloc, ppdInfo, MemoryRequirement::HostVisible);
+ auto& ppdAlloc = ppdData.getAllocation();
+ void* ppdPtr = ppdAlloc.getHostPtr();
+
+ deMemcpy(pvdPtr, &perVertexData, sizeof(perVertexData));
+ deMemcpy(ppdPtr, &perPrimitiveData, sizeof(perPrimitiveData));
+
+ flushAlloc(vkd, device, pvdAlloc);
+ flushAlloc(vkd, device, ppdAlloc);
+
+ // Descriptor set layout.
+ DescriptorSetLayoutBuilder setLayoutBuilder;
+ setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, bufStages);
+ setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, bufStages);
+ const auto setLayout = setLayoutBuilder.build(vkd, device);
+
+ // Create and update descriptor set.
+ DescriptorPoolBuilder descriptorPoolBuilder;
+ descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
+ descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+ const auto descriptorPool = descriptorPoolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+ const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
+
+ DescriptorSetUpdateBuilder updateBuilder;
+ const auto storageBufferInfo = makeDescriptorBufferInfo(pvdData.get(), 0ull, pvdSize);
+ const auto uniformBufferInfo = makeDescriptorBufferInfo(ppdData.get(), 0ull, ppdSize);
+ updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &storageBufferInfo);
+ updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &uniformBufferInfo);
+ updateBuilder.update(vkd, device);
+
+ // Pipeline layout.
+ const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+
+ // Shader modules.
+ const auto meshShader = createShaderModule(vkd, device, binaries.get("mesh"));
+ const auto fragShader = createShaderModule(vkd, device, binaries.get("frag"));
+
+ Move<VkShaderModule> taskShader;
+ if (hasTask)
+ taskShader = createShaderModule(vkd, device, binaries.get("task"));
+
+ // Render pass.
+ const auto renderPass = makeRenderPass(vkd, device, imageFormat);
+
+ // Framebuffer.
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
+
+ // Viewport and scissor.
+ const auto topHalf = makeViewport(imageExtent.width, imageExtent.height / 2u);
+ const std::vector<VkViewport> viewports { makeViewport(imageExtent), topHalf };
+ const std::vector<VkRect2D> scissors (2u, makeRect2D(imageExtent));
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskShader.get(), meshShader.get(), fragShader.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ beginCommandBuffer(vkd, cmdBuffer);
+
+ // Run pipeline.
+ const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+ vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ // Copy color buffer to verification buffer.
+ const auto colorAccess = (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
+ const auto transferRead = VK_ACCESS_TRANSFER_READ_BIT;
+ const auto transferWrite = VK_ACCESS_TRANSFER_WRITE_BIT;
+ const auto hostRead = VK_ACCESS_HOST_READ_BIT;
+
+ const auto preCopyBarrier = makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
+ const auto postCopyBarrier = makeMemoryBarrier(transferWrite, hostRead);
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
+ vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, ©Region);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Generate reference image and compare results.
+ const tcu::IVec3 iExtent (static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
+ const tcu::ConstPixelBufferAccess verificationAccess (tcuFormat, iExtent, verificationBufferData);
+
+ generateReferenceLevel();
+ invalidateAlloc(vkd, device, verificationBufferAlloc);
+ if (!verifyResult(verificationAccess))
+ TCU_FAIL("Result does not match reference; check log for details");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+// Tests that use push constants in the new stages.
+class PushConstantCase : public MeshShaderMiscCase
+{
+public:
+ PushConstantCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, ParamsPtr params)
+ : MeshShaderMiscCase (testCtx, name, description, std::move(params))
+ {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+};
+
+class PushConstantInstance : public MeshShaderMiscInstance
+{
+public:
+ PushConstantInstance (Context& context, const MiscTestParams* params)
+ : MeshShaderMiscInstance (context, params)
+ {}
+
+ void generateReferenceLevel () override;
+ tcu::TestStatus iterate () override;
+};
+
+TestInstance* PushConstantCase::createInstance (Context& context) const
+{
+ return new PushConstantInstance(context, m_params.get());
+}
+
+void PushConstantInstance::generateReferenceLevel ()
+{
+ generateSolidRefLevel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), m_referenceLevel);
+}
+
+void PushConstantCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto useTaskShader = m_params->needsTaskShader();
+ const auto pcNumFloats = (useTaskShader ? 2u : 4u);
+
+ std::ostringstream pushConstantStream;
+ pushConstantStream
+ << "layout (push_constant, std430) uniform PushConstantBlock {\n"
+ << " layout (offset=${PCOFFSET}) float values[" << pcNumFloats << "];\n"
+ << "} pc;\n"
+ << "\n"
+ ;
+ const tcu::StringTemplate pushConstantsTemplate (pushConstantStream.str());
+ using TemplateMap = std::map<std::string, std::string>;
+
+ std::ostringstream taskDataStream;
+ taskDataStream
+ << "taskNV TaskData {\n"
+ << " float values[2];\n"
+ << "} td;\n"
+ << "\n"
+ ;
+ const auto taskDataDecl = taskDataStream.str();
+
+ if (useTaskShader)
+ {
+ TemplateMap taskMap;
+ taskMap["PCOFFSET"] = std::to_string(2u * sizeof(float));
+
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << pushConstantsTemplate.specialize(taskMap)
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = " << m_params->meshCount << ";\n"
+ << "\n"
+ << " td.values[0] = pc.values[0];\n"
+ << " td.values[1] = pc.values[1];\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ {
+ const std::string blue = (useTaskShader ? "td.values[0] + pc.values[0]" : "pc.values[0] + pc.values[2]");
+ const std::string alpha = (useTaskShader ? "td.values[1] + pc.values[1]" : "pc.values[1] + pc.values[3]");
+
+ TemplateMap meshMap;
+ meshMap["PCOFFSET"] = "0";
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << pushConstantsTemplate.specialize(meshMap)
+ << (useTaskShader ? "in " + taskDataDecl : "")
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1;\n"
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
+ << "\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << "\n"
+ << " triangleColor[0] = vec4(0.0, 0.0, " << blue << ", " << alpha << ");\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ // Add default fragment shader.
+ MeshShaderMiscCase::initPrograms(programCollection);
+}
+
+tcu::TestStatus PushConstantInstance::iterate ()
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto imageFormat = getOutputFormat();
+ const auto tcuFormat = mapVkFormat(imageFormat);
+ const auto imageExtent = makeExtent3D(m_params->width, m_params->height, 1u);
+ const auto imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+
+ const auto& binaries = m_context.getBinaryCollection();
+ const auto hasTask = binaries.contains("task");
+
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ imageExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ imageUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+
+ // Create color image and view.
+ ImageWithMemory colorImage (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
+ const auto colorView = makeImageView(vkd, device, colorImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
+
+ // Create a memory buffer for verification.
+ const auto verificationBufferSize = static_cast<VkDeviceSize>(imageExtent.width * imageExtent.height * tcu::getPixelSize(tcuFormat));
+ const auto verificationBufferUsage = (VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ const auto verificationBufferInfo = makeBufferCreateInfo(verificationBufferSize, verificationBufferUsage);
+
+ BufferWithMemory verificationBuffer (vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
+ auto& verificationBufferAlloc = verificationBuffer.getAllocation();
+ void* verificationBufferData = verificationBufferAlloc.getHostPtr();
+
+ // Push constant ranges.
+ std::vector<float> pcData { 0.25f, 0.25f, 0.75f, 0.75f };
+ const auto pcSize = static_cast<uint32_t>(de::dataSize(pcData));
+ const auto pcHalfSize = pcSize / 2u;
+
+ std::vector<VkPushConstantRange> pcRanges;
+ if (hasTask)
+ {
+ pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_NV, 0u, pcHalfSize));
+ pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_TASK_BIT_NV, pcHalfSize, pcHalfSize));
+ }
+ else
+ {
+ pcRanges.push_back(makePushConstantRange(VK_SHADER_STAGE_MESH_BIT_NV, 0u, pcSize));
+ }
+
+ // Pipeline layout.
+ const auto pipelineLayout = makePipelineLayout(vkd, device, 0u, nullptr, static_cast<uint32_t>(pcRanges.size()), de::dataOrNull(pcRanges));
+
+ // Shader modules.
+ const auto meshShader = createShaderModule(vkd, device, binaries.get("mesh"));
+ const auto fragShader = createShaderModule(vkd, device, binaries.get("frag"));
+
+ Move<VkShaderModule> taskShader;
+ if (hasTask)
+ taskShader = createShaderModule(vkd, device, binaries.get("task"));
+
+ // Render pass.
+ const auto renderPass = makeRenderPass(vkd, device, imageFormat);
+
+ // Framebuffer.
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), imageExtent.width, imageExtent.height);
+
+ // Viewport and scissor.
+ const std::vector<VkViewport> viewports (1u, makeViewport(imageExtent));
+ const std::vector<VkRect2D> scissors (1u, makeRect2D(imageExtent));
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskShader.get(), meshShader.get(), fragShader.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ beginCommandBuffer(vkd, cmdBuffer);
+
+ // Run pipeline.
+ const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+ for (const auto& range : pcRanges)
+ vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), range.stageFlags, range.offset, range.size, reinterpret_cast<const char*>(pcData.data()) + range.offset);
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params->drawCount(), 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ // Copy color buffer to verification buffer.
+ const auto colorAccess = (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
+ const auto transferRead = VK_ACCESS_TRANSFER_READ_BIT;
+ const auto transferWrite = VK_ACCESS_TRANSFER_WRITE_BIT;
+ const auto hostRead = VK_ACCESS_HOST_READ_BIT;
+
+ const auto preCopyBarrier = makeImageMemoryBarrier(colorAccess, transferRead, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSRR);
+ const auto postCopyBarrier = makeMemoryBarrier(transferWrite, hostRead);
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
+ vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, ©Region);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postCopyBarrier, 0u, nullptr, 0u, nullptr);
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Generate reference image and compare results.
+ const tcu::IVec3 iExtent (static_cast<int>(imageExtent.width), static_cast<int>(imageExtent.height), 1);
+ const tcu::ConstPixelBufferAccess verificationAccess (tcuFormat, iExtent, verificationBufferData);
+
+ generateReferenceLevel();
+ invalidateAlloc(vkd, device, verificationBufferAlloc);
+ if (!verifyResult(verificationAccess))
+ TCU_FAIL("Result does not match reference; check log for details");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+}
+
+tcu::TestCaseGroup* createMeshShaderMiscTests (tcu::TestContext& testCtx)
+{
+ GroupPtr miscTests (new tcu::TestCaseGroup(testCtx, "misc", "Mesh Shader Misc Tests"));
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::just(2u);
+ paramsPtr->meshCount = 2u;
+ paramsPtr->width = 8u;
+ paramsPtr->height = 8u;
+
+ miscTests->addChild(new ComplexTaskDataCase(testCtx, "complex_task_data", "Pass a complex structure from the task to the mesh shader", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 5u; // Use an odd value so there's a pixel in the exact center.
+ paramsPtr->height = 7u; // Idem.
+
+ miscTests->addChild(new SinglePointCase(testCtx, "single_point", "Draw a single point", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 8u;
+ paramsPtr->height = 5u; // Use an odd value so there's a center line.
+
+ miscTests->addChild(new SingleLineCase(testCtx, "single_line", "Draw a single line", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 5u; // Use an odd value so there's a pixel in the exact center.
+ paramsPtr->height = 7u; // Idem.
+
+ miscTests->addChild(new SingleTriangleCase(testCtx, "single_triangle", "Draw a single triangle", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 16u;
+ paramsPtr->height = 16u;
+
+ miscTests->addChild(new MaxPointsCase(testCtx, "max_points", "Draw the maximum number of points", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 1u;
+ paramsPtr->height = 1020u;
+
+ miscTests->addChild(new MaxLinesCase(testCtx, "max_lines", "Draw the maximum number of lines", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 512u;
+ paramsPtr->height = 512u;
+
+ miscTests->addChild(new MaxTrianglesCase(testCtx, "max_triangles", "Draw the maximum number of triangles", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::just(65535u);
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 1360u;
+ paramsPtr->height = 1542u;
+
+ miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_task_work_groups", "Generate a large number of task work groups", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::nothing<uint32_t>();
+ paramsPtr->meshCount = 65535u;
+ paramsPtr->width = 1360u;
+ paramsPtr->height = 1542u;
+
+ miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_mesh_work_groups", "Generate a large number of mesh work groups", std::move(paramsPtr)));
+ }
+
+ {
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = tcu::just(512u);
+ paramsPtr->meshCount = 512u;
+ paramsPtr->width = 4096u;
+ paramsPtr->height = 2048u;
+
+ miscTests->addChild(new LargeWorkGroupCase(testCtx, "many_task_mesh_work_groups", "Generate a large number of task and mesh work groups", std::move(paramsPtr)));
+ }
+
+ {
+ const PrimitiveType types[] = {
+ PrimitiveType::POINTS,
+ PrimitiveType::LINES,
+ PrimitiveType::TRIANGLES,
+ };
+
+ for (int i = 0; i < 2; ++i)
+ {
+ const bool extraWrites = (i > 0);
+
+ for (const auto primType : types)
+ {
+ std::unique_ptr<NoPrimitivesParams> params (new NoPrimitivesParams);
+ params->taskCount = (extraWrites ? tcu::just(1u) : tcu::nothing<uint32_t>());
+ params->meshCount = 1u;
+ params->width = 16u;
+ params->height = 16u;
+ params->primitiveType = primType;
+
+ ParamsPtr paramsPtr (params.release());
+ const auto primName = primitiveTypeName(primType);
+ const std::string name = "no_" + primName + (extraWrites ? "_extra_writes" : "");
+ const std::string desc = "Run a pipeline that generates no " + primName + (extraWrites ? " but generates primitive data" : "");
+
+ miscTests->addChild(extraWrites
+ ? (new NoPrimitivesExtraWritesCase(testCtx, name, desc, std::move(paramsPtr)))
+ : (new NoPrimitivesCase(testCtx, name, desc, std::move(paramsPtr))));
+ }
+ }
+ }
+
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ const bool useTaskShader = (i == 0);
+
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 1u;
+ paramsPtr->height = 1u;
+
+ const std::string shader = (useTaskShader ? "task" : "mesh");
+ const std::string name = "barrier_in_" + shader;
+ const std::string desc = "Use a control barrier in the " + shader + " shader";
+
+ miscTests->addChild(new SimpleBarrierCase(testCtx, name, desc, std::move(paramsPtr)));
+ }
+ }
+
+ {
+ const struct
+ {
+ MemoryBarrierType memBarrierType;
+ std::string caseName;
+ } barrierTypes[] =
+ {
+ { MemoryBarrierType::SHARED, "memory_barrier_shared" },
+ { MemoryBarrierType::GROUP, "group_memory_barrier" },
+ };
+
+ for (const auto& barrierCase : barrierTypes)
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ const bool useTaskShader = (i == 0);
+
+ std::unique_ptr<MemoryBarrierParams> paramsPtr (new MemoryBarrierParams);
+
+ paramsPtr->taskCount = (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 1u;
+ paramsPtr->height = 1u;
+ paramsPtr->memBarrierType = barrierCase.memBarrierType;
+
+ const std::string shader = (useTaskShader ? "task" : "mesh");
+ const std::string name = barrierCase.caseName + "_in_" + shader;
+ const std::string desc = "Use " + paramsPtr->glslFunc() + "() in the " + shader + " shader";
+
+ miscTests->addChild(new MemoryBarrierCase(testCtx, name, desc, std::move(paramsPtr)));
+ }
+ }
+ }
+
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ const bool useTaskShader = (i > 0);
+ const auto name = std::string("custom_attributes") + (useTaskShader ? "_and_task_shader" : "");
+ const auto desc = std::string("Use several custom vertex and primitive attributes") + (useTaskShader ? " and also a task shader" : "");
+
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 32u;
+ paramsPtr->height = 32u;
+
+ miscTests->addChild(new CustomAttributesCase(testCtx, name, desc, std::move(paramsPtr)));
+ }
+ }
+
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ const bool useTaskShader = (i > 0);
+ const auto name = std::string("push_constant") + (useTaskShader ? "_and_task_shader" : "");
+ const auto desc = std::string("Use push constants in the mesh shader stage") + (useTaskShader ? " and also in the task shader stage" : "");
+
+ ParamsPtr paramsPtr (new MiscTestParams);
+
+ paramsPtr->taskCount = (useTaskShader ? tcu::just(1u) : tcu::nothing<uint32_t>());
+ paramsPtr->meshCount = 1u;
+ paramsPtr->width = 16u;
+ paramsPtr->height = 16u;
+
+ miscTests->addChild(new PushConstantCase(testCtx, name, desc, std::move(paramsPtr)));
+ }
+ }
+
+ return miscTests.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERMISCTESTS_HPP
+#define _VKTMESHSHADERMISCTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Misc Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderMiscTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERMISCTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Property Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderPropertyTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkBufferWithMemory.hpp"
+#include "vkObjUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkBarrierUtil.hpp"
+
+#include "tcuStringTemplate.hpp"
+
+#include <vector>
+#include <string>
+#include <map>
+#include <sstream>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+using ReplacementsMap = std::map<std::string, std::string>;
+
+using namespace vk;
+
+tcu::StringTemplate getTaskShaderTemplate ()
+{
+ return tcu::StringTemplate(
+ "#version 460\n"
+ "#extension GL_NV_mesh_shader : enable\n"
+ "\n"
+ "layout (local_size_x=${TASK_LOCAL_SIZE_X:default=1}) in;\n"
+ "\n"
+ "${TASK_GLOBAL_DECL:opt}"
+ "\n"
+ "${TASK_MESH_INTERFACE_OUT:opt}"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " gl_TaskCountNV = ${TASK_TASK_COUNT:default=0};\n"
+ "${TASK_BODY:opt}"
+ "}\n");
+}
+
+tcu::StringTemplate getMeshShaderTemplate ()
+{
+ return tcu::StringTemplate(
+ "#version 460\n"
+ "#extension GL_NV_mesh_shader : enable\n"
+ "\n"
+ "layout (local_size_x=${MESH_LOCAL_SIZE_X:default=1}) in;\n"
+ "layout (triangles) out;\n"
+ "layout (max_vertices=3, max_primitives=1) out;\n"
+ "\n"
+ "${MESH_GLOBAL_DECL:opt}"
+ "\n"
+ "${TASK_MESH_INTERFACE_IN:opt}"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " gl_PrimitiveCountNV = 0u;\n"
+ "${MESH_BODY:opt}"
+ "}\n");
+}
+
+std::string getCommonStorageBufferDecl ()
+{
+ return "layout (set=0, binding=0) buffer OutputBlock { uint values[]; } ov;\n";
+}
+
+void genericCheckSupport (Context& context, bool taskShaderNeeded)
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (!meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shaders not supported");
+
+ if (taskShaderNeeded && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shaders not supported");
+
+ const auto& features = context.getDeviceFeatures();
+ if (!features.vertexPipelineStoresAndAtomics)
+ TCU_THROW(NotSupportedError, "Vertex pipeline stores and atomics not supported");
+}
+
+struct InstanceParams
+{
+ uint32_t bufferElements;
+ uint32_t taskCount;
+};
+
+class MeshShaderPropertyInstance : public vkt::TestInstance
+{
+public:
+ MeshShaderPropertyInstance (Context& context, const InstanceParams& params)
+ : vkt::TestInstance (context)
+ , m_params (params)
+ {}
+ virtual ~MeshShaderPropertyInstance (void) {}
+
+ tcu::TestStatus iterate () override;
+
+protected:
+ InstanceParams m_params;
+};
+
+tcu::TestStatus MeshShaderPropertyInstance::iterate ()
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+ const auto& binaries = m_context.getBinaryCollection();
+ const auto extent = makeExtent3D(1u, 1u, 1u);
+ const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ const auto useTask = binaries.contains("task");
+
+ const auto storageBufferSize = static_cast<VkDeviceSize>(m_params.bufferElements) * static_cast<VkDeviceSize>(sizeof(uint32_t));
+ const auto storageBufferUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ const auto storageBufferType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ const auto storageBufferStages = (VK_SHADER_STAGE_MESH_BIT_NV | (useTask ? VK_SHADER_STAGE_TASK_BIT_NV : 0));
+
+ // Create storage buffer with the required space.
+ const auto storageBufferInfo = makeBufferCreateInfo(storageBufferSize, storageBufferUsage);
+ BufferWithMemory storageBuffer (vkd, device, alloc, storageBufferInfo, MemoryRequirement::HostVisible);
+ auto& storageBufferAlloc = storageBuffer.getAllocation();
+ void* storageBufferDataPtr = storageBufferAlloc.getHostPtr();
+ const auto storageBufferDescInfo = makeDescriptorBufferInfo(storageBuffer.get(), 0ull, storageBufferSize);
+
+ deMemset(storageBufferDataPtr, 0xFF, static_cast<size_t>(storageBufferSize));
+ flushAlloc(vkd, device, storageBufferAlloc);
+
+ // Descriptor pool.
+ DescriptorPoolBuilder poolBuilder;
+ poolBuilder.addType(storageBufferType);
+ const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ // Descriptor set layout and pipeline layout.
+ DescriptorSetLayoutBuilder layoutBuilder;
+ layoutBuilder.addSingleBinding(storageBufferType, storageBufferStages);
+ const auto setLayout = layoutBuilder.build(vkd, device);
+ const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+
+ // Allocate and prepare descriptor set.
+ const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
+
+ DescriptorSetUpdateBuilder setUpdateBuilder;
+ setUpdateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), storageBufferType, &storageBufferDescInfo);
+ setUpdateBuilder.update(vkd, device);
+
+ // Create empty render pass and framebuffer.
+ const auto renderPass = makeRenderPass(vkd, device);
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), 0u, nullptr, extent.width, extent.height);
+
+ // Shader modules and pipeline.
+ Move<VkShaderModule> taskModule;
+ Move<VkShaderModule> meshModule;
+ const Move<VkShaderModule> fragModule; // No fragment shader.
+
+ if (useTask)
+ taskModule = createShaderModule(vkd, device, binaries.get("task"));
+ meshModule = createShaderModule(vkd, device, binaries.get("mesh"));
+
+ const std::vector<VkViewport> viewports (1u, makeViewport(extent));
+ const std::vector<VkRect2D> scissors (1u, makeRect2D(extent));
+
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+ taskModule.get(), meshModule.get(), fragModule.get(),
+ renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ // Run the pipeline.
+ beginCommandBuffer(vkd, cmdBuffer);
+
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0));
+ vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
+ vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipeline.get());
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params.taskCount, 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ const auto shaderToHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &shaderToHostBarrier, 0u, nullptr, 0u, nullptr);
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Verify the storage buffer has the expected results.
+ invalidateAlloc(vkd, device, storageBufferAlloc);
+
+ std::vector<uint32_t> bufferData (m_params.bufferElements);
+ deMemcpy(bufferData.data(), storageBufferDataPtr, de::dataSize(bufferData));
+
+ for (size_t idx = 0u; idx < bufferData.size(); ++idx)
+ {
+ const auto expected = static_cast<uint32_t>(idx);
+ const auto& bufferValue = bufferData[idx];
+
+ if (bufferValue != expected)
+ TCU_FAIL("Unexpected value found in buffer position " + de::toString(idx) + ": " + de::toString(bufferValue));
+ }
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+class MaxDrawMeshTasksCountCase : public vkt::TestCase
+{
+public:
+ enum class TestType { TASK=0, MESH };
+
+ MaxDrawMeshTasksCountCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, TestType testType)
+ : vkt::TestCase (testCtx, name, description)
+ , m_testType (testType)
+ {}
+ virtual ~MaxDrawMeshTasksCountCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minLimit = 65535u;
+
+protected:
+ TestType m_testType;
+};
+
+void MaxDrawMeshTasksCountCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, (m_testType == TestType::TASK));
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxDrawMeshTasksCount < minLimit)
+ TCU_FAIL("maxDrawMeshTasksCount property below the minimum limit");
+}
+
+TestInstance* MaxDrawMeshTasksCountCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ minLimit, // uint32_t bufferElements;
+ minLimit, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxDrawMeshTasksCountCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ ReplacementsMap meshReplacements;
+ ReplacementsMap taskReplacements;
+
+ const auto meshTemplate = getMeshShaderTemplate();
+
+ const std::string desc = getCommonStorageBufferDecl();
+ const std::string body = " ov.values[gl_WorkGroupID.x] = gl_WorkGroupID.x;\n";
+
+ if (m_testType == TestType::TASK)
+ {
+ const auto taskTemplate = getTaskShaderTemplate();
+ taskReplacements["TASK_GLOBAL_DECL"] = desc;
+ taskReplacements["TASK_BODY"] = body;
+
+ programCollection.glslSources.add("task") << glu::TaskSource(taskTemplate.specialize(taskReplacements));
+ }
+ else
+ {
+ meshReplacements["MESH_GLOBAL_DECL"] = desc;
+ meshReplacements["MESH_BODY"] = body;
+ }
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+}
+
+class MaxTaskWorkGroupInvocationsCase : public vkt::TestCase
+{
+public:
+ MaxTaskWorkGroupInvocationsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MaxTaskWorkGroupInvocationsCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minLimit = 32u;
+};
+
+void MaxTaskWorkGroupInvocationsCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, true/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxTaskWorkGroupInvocations < minLimit)
+ TCU_FAIL("maxTaskWorkGroupInvocations property below the minimum limit");
+}
+
+TestInstance* MaxTaskWorkGroupInvocationsCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ minLimit, // uint32_t bufferElements;
+ 1u, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxTaskWorkGroupInvocationsCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const ReplacementsMap meshReplacements;
+ const auto meshTemplate = getMeshShaderTemplate();
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+
+ ReplacementsMap taskReplacements;
+ const auto taskTemplate = getTaskShaderTemplate();
+
+ taskReplacements["TASK_GLOBAL_DECL"] = getCommonStorageBufferDecl();
+ taskReplacements["TASK_BODY"] = " ov.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n";
+ taskReplacements["TASK_LOCAL_SIZE_X"] = de::toString(uint32_t{minLimit});
+
+ programCollection.glslSources.add("task") << glu::TaskSource(taskTemplate.specialize(taskReplacements));
+}
+
+// In the case of the NV extension, this is very similar to the test above. Added for completion.
+class MaxTaskWorkGroupSizeCase : public MaxTaskWorkGroupInvocationsCase
+{
+public:
+ MaxTaskWorkGroupSizeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MaxTaskWorkGroupInvocationsCase (testCtx, name, description) {}
+
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minSizeX = 32u;
+ static constexpr uint32_t minSizeY = 1u;
+ static constexpr uint32_t minSizeZ = 1u;
+};
+
+void MaxTaskWorkGroupSizeCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, true/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxTaskWorkGroupSize[0] < minSizeX ||
+ properties.maxTaskWorkGroupSize[1] < minSizeY ||
+ properties.maxTaskWorkGroupSize[2] < minSizeZ)
+ {
+ TCU_FAIL("maxTaskWorkGroupSize property below the minimum limit");
+ }
+}
+
+class MaxTaskOutputCountCase : public vkt::TestCase
+{
+public:
+ MaxTaskOutputCountCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MaxTaskOutputCountCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minLimit = 65535u;
+};
+
+void MaxTaskOutputCountCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, true/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxTaskOutputCount < minLimit)
+ TCU_FAIL("maxTaskOutputCount property below the minimum limit");
+}
+
+TestInstance* MaxTaskOutputCountCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ minLimit, // uint32_t bufferElements;
+ 1u, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxTaskOutputCountCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ ReplacementsMap meshReplacements;
+ ReplacementsMap taskReplacements;
+ const auto meshTemplate = getMeshShaderTemplate();
+ const auto taskTemplate = getTaskShaderTemplate();
+
+ taskReplacements["TASK_TASK_COUNT"] = de::toString(uint32_t{minLimit});
+ meshReplacements["MESH_GLOBAL_DECL"] = getCommonStorageBufferDecl();
+ meshReplacements["MESH_BODY"] = " ov.values[gl_WorkGroupID.x] = gl_WorkGroupID.x;\n";
+
+ programCollection.glslSources.add("task") << glu::TaskSource(taskTemplate.specialize(taskReplacements));
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+}
+
+class MaxMeshWorkGroupInvocationsCase : public vkt::TestCase
+{
+public:
+ MaxMeshWorkGroupInvocationsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MaxMeshWorkGroupInvocationsCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minLimit = 32u;
+};
+
+void MaxMeshWorkGroupInvocationsCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, false/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxMeshWorkGroupInvocations < minLimit)
+ TCU_FAIL("maxMeshWorkGroupInvocations property below the minimum limit");
+}
+
+TestInstance* MaxMeshWorkGroupInvocationsCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ minLimit, // uint32_t bufferElements;
+ 1u, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxMeshWorkGroupInvocationsCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ ReplacementsMap meshReplacements;
+ const auto meshTemplate = getMeshShaderTemplate();
+
+ meshReplacements["MESH_LOCAL_SIZE_X"] = de::toString(uint32_t{minLimit});
+ meshReplacements["MESH_GLOBAL_DECL"] = getCommonStorageBufferDecl();
+ meshReplacements["MESH_BODY"] = " ov.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n";
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+}
+
+// In the case of the NV extension, this is very similar to the test above. Added for completion.
+class MaxMeshWorkGroupSizeCase : public MaxMeshWorkGroupInvocationsCase
+{
+public:
+ MaxMeshWorkGroupSizeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : MaxMeshWorkGroupInvocationsCase (testCtx, name, description) {}
+
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t minSizeX = 32u;
+ static constexpr uint32_t minSizeY = 1u;
+ static constexpr uint32_t minSizeZ = 1u;
+};
+
+void MaxMeshWorkGroupSizeCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, false/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxMeshWorkGroupSize[0] < minSizeX ||
+ properties.maxMeshWorkGroupSize[1] < minSizeY ||
+ properties.maxMeshWorkGroupSize[2] < minSizeZ)
+ {
+ TCU_FAIL("maxMeshWorkGroupSize property below the minimum limit");
+ }
+}
+
+std::string getSharedArrayDecl (uint32_t numElements)
+{
+ std::ostringstream decl;
+ decl
+ << "const uint arrayElements = " << de::toString(numElements) << ";\n"
+ << "shared uint sharedArray[arrayElements];\n"
+ ;
+ return decl.str();
+}
+
+std::string getSharedMemoryBody (uint32_t localSize)
+{
+ std::ostringstream body;
+ body
+ << "\n"
+ << " if (gl_LocalInvocationID.x == 0u)\n"
+ << " {\n"
+ << " for (uint i = 0; i < arrayElements; ++i)\n"
+ << " sharedArray[i] = 0u;\n"
+ << " }\n"
+ << "\n"
+ << " barrier();\n"
+ << "\n"
+ << " for (uint i = 0; i < arrayElements; ++i)\n"
+ << " atomicAdd(sharedArray[i], 1u);\n"
+ << "\n"
+ << " barrier();\n"
+ << "\n"
+ << " uint allGood = 1u;\n"
+ << " for (uint i = 0; i < arrayElements; ++i)\n"
+ << " {\n"
+ << " if (sharedArray[i] != " << localSize << ")\n"
+ << " {\n"
+ << " allGood = 0u;\n"
+ << " break;\n"
+ << " }\n"
+ << " }\n"
+ << "\n"
+ << " ov.values[gl_LocalInvocationID.x] = ((allGood == 1u) ? gl_LocalInvocationID.x : gl_WorkGroupSize.x);\n"
+ ;
+
+ return body.str();
+}
+
+class MaxTaskTotalMemorySizeCase : public vkt::TestCase
+{
+public:
+ MaxTaskTotalMemorySizeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MaxTaskTotalMemorySizeCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t localSize = 32u;
+ static constexpr uint32_t minLimit = 16384u;
+};
+
+TestInstance* MaxTaskTotalMemorySizeCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ localSize, // uint32_t bufferElements;
+ 1u, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxTaskTotalMemorySizeCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, true/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxTaskTotalMemorySize < minLimit)
+ TCU_FAIL("maxTaskTotalMemorySize property below the minimum limit");
+}
+
+void MaxTaskTotalMemorySizeCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const ReplacementsMap meshReplacements;
+ const auto meshTemplate = getMeshShaderTemplate();
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+
+ const auto taskTemplate = getTaskShaderTemplate();
+ const auto arrayElements = minLimit / static_cast<uint32_t>(sizeof(uint32_t));
+
+ const auto globalDecls = getCommonStorageBufferDecl() + getSharedArrayDecl(arrayElements);
+ const auto body = getSharedMemoryBody(localSize);
+
+ ReplacementsMap taskReplacements;
+ taskReplacements["TASK_LOCAL_SIZE_X"] = de::toString(uint32_t{localSize});
+ taskReplacements["TASK_GLOBAL_DECL"] = globalDecls;
+ taskReplacements["TASK_BODY"] = body;
+
+ programCollection.glslSources.add("task") << glu::TaskSource(taskTemplate.specialize(taskReplacements));
+}
+
+// Very similar to the previous one in NV.
+class MaxMeshTotalMemorySizeCase : public vkt::TestCase
+{
+public:
+ MaxMeshTotalMemorySizeCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
+ : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MaxMeshTotalMemorySizeCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+
+ static constexpr uint32_t localSize = 32u;
+ static constexpr uint32_t minLimit = 16384u;
+};
+
+TestInstance* MaxMeshTotalMemorySizeCase::createInstance (Context& context) const
+{
+ const InstanceParams params =
+ {
+ localSize, // uint32_t bufferElements;
+ 1u, // uint32_t taskCount;
+ };
+ return new MeshShaderPropertyInstance(context, params);
+}
+
+void MaxMeshTotalMemorySizeCase::checkSupport (Context& context) const
+{
+ genericCheckSupport(context, false/*taskShaderNeeded*/);
+
+ const auto& properties = context.getMeshShaderProperties();
+ if (properties.maxMeshTotalMemorySize < minLimit)
+ TCU_FAIL("maxMeshTotalMemorySize property below the minimum limit");
+}
+
+void MaxMeshTotalMemorySizeCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const auto meshTemplate = getMeshShaderTemplate();
+ const auto arrayElements = minLimit / static_cast<uint32_t>(sizeof(uint32_t));
+
+ const auto globalDecls = getCommonStorageBufferDecl() + getSharedArrayDecl(arrayElements);
+ const auto body = getSharedMemoryBody(localSize);
+
+ ReplacementsMap meshReplacements;
+ meshReplacements["MESH_LOCAL_SIZE_X"] = de::toString(uint32_t{localSize});
+ meshReplacements["MESH_GLOBAL_DECL"] = globalDecls;
+ meshReplacements["MESH_BODY"] = body;
+
+ programCollection.glslSources.add("mesh") << glu::MeshSource(meshTemplate.specialize(meshReplacements));
+}
+
+}
+
+tcu::TestCaseGroup* createMeshShaderPropertyTests (tcu::TestContext& testCtx)
+{
+ GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "property", "Mesh Shader Property Tests"));
+
+ mainGroup->addChild(new MaxDrawMeshTasksCountCase (testCtx, "max_draw_mesh_tasks_count_with_task", "", MaxDrawMeshTasksCountCase::TestType::TASK));
+ mainGroup->addChild(new MaxDrawMeshTasksCountCase (testCtx, "max_draw_mesh_tasks_count_with_mesh", "", MaxDrawMeshTasksCountCase::TestType::MESH));
+ mainGroup->addChild(new MaxTaskWorkGroupInvocationsCase (testCtx, "max_task_work_group_invocations", ""));
+ mainGroup->addChild(new MaxTaskWorkGroupSizeCase (testCtx, "max_task_work_group_size", ""));
+ mainGroup->addChild(new MaxTaskOutputCountCase (testCtx, "max_task_output_count", ""));
+ mainGroup->addChild(new MaxMeshWorkGroupInvocationsCase (testCtx, "max_mesh_work_group_invocations", ""));
+ mainGroup->addChild(new MaxMeshWorkGroupSizeCase (testCtx, "max_mesh_work_group_size", ""));
+ mainGroup->addChild(new MaxTaskTotalMemorySizeCase (testCtx, "max_task_total_memory_size", ""));
+ mainGroup->addChild(new MaxMeshTotalMemorySizeCase (testCtx, "max_mesh_total_memory_size", ""));
+
+ return mainGroup.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERPROPERTYTESTS_HPP
+#define _VKTMESHSHADERPROPERTYTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Property Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderPropertyTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERPROPERTYTESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Smoke Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderSmokeTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkBuilderUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkObjUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkImageUtil.hpp"
+
+#include "tcuImageCompare.hpp"
+
+#include <utility>
+#include <vector>
+#include <string>
+#include <sstream>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+
+using namespace vk;
+
+void checkTaskMeshShaderSupport (Context& context, bool requireTask, bool requireMesh)
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ DE_ASSERT(requireTask || requireMesh);
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (requireTask && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shader not supported");
+
+ if (requireMesh && !meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shader not supported");
+}
+
+std::string commonMeshFragShader ()
+{
+ std::string frag =
+ "#version 450\n"
+ "#extension GL_NV_mesh_shader : enable\n"
+ "\n"
+ "layout (location=0) in perprimitiveNV vec4 triangleColor;\n"
+ "layout (location=0) out vec4 outColor;\n"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " outColor = triangleColor;\n"
+ "}\n"
+ ;
+ return frag;
+}
+
+struct MeshTriangleRendererParams
+{
+ std::vector<tcu::Vec4> vertexCoords;
+ std::vector<uint32_t> vertexIndices;
+ uint32_t taskCount;
+ tcu::Vec4 expectedColor;
+
+ MeshTriangleRendererParams (std::vector<tcu::Vec4> vertexCoords_, std::vector<uint32_t> vertexIndices_, uint32_t taskCount_, const tcu::Vec4& expectedColor_)
+ : vertexCoords (std::move(vertexCoords_))
+ , vertexIndices (std::move(vertexIndices_))
+ , taskCount (taskCount_)
+ , expectedColor (expectedColor_)
+ {}
+
+ MeshTriangleRendererParams (MeshTriangleRendererParams&& other)
+ : MeshTriangleRendererParams (std::move(other.vertexCoords), std::move(other.vertexIndices), other.taskCount, other.expectedColor)
+ {}
+};
+
+class MeshOnlyTriangleCase : public vkt::TestCase
+{
+public:
+ MeshOnlyTriangleCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description) : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MeshOnlyTriangleCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+};
+
+class MeshTaskTriangleCase : public vkt::TestCase
+{
+public:
+ MeshTaskTriangleCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description) : vkt::TestCase (testCtx, name, description) {}
+ virtual ~MeshTaskTriangleCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+};
+
+// Note: not actually task-only. The task shader will not emit mesh shader work groups.
+class TaskOnlyTriangleCase : public vkt::TestCase
+{
+public:
+ TaskOnlyTriangleCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description) : vkt::TestCase (testCtx, name, description) {}
+ virtual ~TaskOnlyTriangleCase (void) {}
+
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+ void checkSupport (Context& context) const override;
+};
+
+class MeshTriangleRenderer : public vkt::TestInstance
+{
+public:
+ MeshTriangleRenderer (Context& context, MeshTriangleRendererParams params) : vkt::TestInstance(context), m_params(std::move(params)) {}
+ virtual ~MeshTriangleRenderer (void) {}
+
+ tcu::TestStatus iterate (void) override;
+
+protected:
+ MeshTriangleRendererParams m_params;
+};
+
+void MeshOnlyTriangleCase::checkSupport (Context& context) const
+{
+ checkTaskMeshShaderSupport(context, false, true);
+}
+
+void MeshTaskTriangleCase::checkSupport (Context& context) const
+{
+ checkTaskMeshShaderSupport(context, true, true);
+}
+
+void TaskOnlyTriangleCase::checkSupport (Context& context) const
+{
+ checkTaskMeshShaderSupport(context, true, true);
+}
+
+void MeshOnlyTriangleCase::initPrograms (SourceCollections& dst) const
+{
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ // We will actually output a single triangle and most invocations will do no work.
+ << "layout(local_size_x=32) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ // Unique vertex coordinates.
+ << "layout (set=0, binding=0) uniform CoordsBuffer {\n"
+ << " vec4 coords[3];\n"
+ << "} cb;\n"
+ // Unique vertex indices.
+ << "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
+ << " uint indices[3];\n"
+ << "} ib;\n"
+ << "\n"
+ // Triangle color.
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << "\n"
+ << " const uint vertex = gl_LocalInvocationIndex;\n"
+ << " if (vertex < 3u)\n"
+ << " {\n"
+ << " const uint vertexIndex = ib.indices[vertex];\n"
+ << " gl_PrimitiveIndicesNV[vertex] = vertexIndex;\n"
+ << " gl_MeshVerticesNV[vertexIndex].gl_Position = cb.coords[vertexIndex];\n"
+ << " }\n"
+ << "}\n"
+ ;
+ dst.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+
+ dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader());
+}
+
+void MeshTaskTriangleCase::initPrograms (SourceCollections& dst) const
+{
+ std::string taskDataDecl =
+ "taskNV TaskData {\n"
+ " uint triangleIndex;\n"
+ "} td;\n"
+ ;
+
+ std::ostringstream task;
+ task
+ // Each work group spawns 1 task each (2 in total) and each task will draw 1 triangle.
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=32) in;\n"
+ << "\n"
+ << "out " << taskDataDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " if (gl_LocalInvocationIndex == 0u)\n"
+ << " {\n"
+ << " gl_TaskCountNV = 1u;\n"
+ << " td.triangleIndex = gl_WorkGroupID.x;\n"
+ << " }\n"
+ << "}\n"
+ ;
+ dst.glslSources.add("task") << glu::TaskSource(task.str());
+
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ // We will actually output a single triangle and most invocations will do no work.
+ << "layout(local_size_x=32) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ // Unique vertex coordinates.
+ << "layout (set=0, binding=0) uniform CoordsBuffer {\n"
+ << " vec4 coords[4];\n"
+ << "} cb;\n"
+ // Unique vertex indices.
+ << "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
+ << " uint indices[6];\n"
+ << "} ib;\n"
+ << "\n"
+ // Triangle color.
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << "in " << taskDataDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " if (gl_LocalInvocationIndex == 0u)\n"
+ << " {\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << " }\n"
+ << "\n"
+ // Each "active" invocation will copy one vertex.
+ << " if (gl_LocalInvocationIndex < 3u)\n"
+ << " {\n"
+ << "\n"
+ << " const uint triangleVertex = gl_LocalInvocationIndex;\n"
+ << " const uint coordsIndex = ib.indices[td.triangleIndex * 3u + triangleVertex];\n"
+ << "\n"
+ // Copy vertex coordinates.
+ << " gl_MeshVerticesNV[triangleVertex].gl_Position = cb.coords[coordsIndex];\n"
+ // Index renumbering: final indices will always be 0, 1, 2.
+ << " gl_PrimitiveIndicesNV[triangleVertex] = triangleVertex;\n"
+ << " }\n"
+ << "}\n"
+ ;
+ dst.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+
+ dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader());
+}
+
+void TaskOnlyTriangleCase::initPrograms (SourceCollections& dst) const
+{
+ // The task shader does not spawn any mesh shader invocations.
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 0u;\n"
+ << "}\n"
+ ;
+ dst.glslSources.add("task") << glu::TaskSource(task.str());
+
+ // Same shader as the mesh only case, but it should not be launched.
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=32) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=256, max_primitives=256) out;\n"
+ << "\n"
+ << "layout (set=0, binding=0) uniform CoordsBuffer {\n"
+ << " vec4 coords[3];\n"
+ << "} cb;\n"
+ << "layout (set=0, binding=1, std430) readonly buffer IndexBuffer {\n"
+ << " uint indices[3];\n"
+ << "} ib;\n"
+ << "\n"
+ << "layout (location=0) out perprimitiveNV vec4 triangleColor[];\n"
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << " triangleColor[0] = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ << "\n"
+ << " const uint vertex = gl_LocalInvocationIndex;\n"
+ << " if (vertex < 3u)\n"
+ << " {\n"
+ << " const uint vertexIndex = ib.indices[vertex];\n"
+ << " gl_PrimitiveIndicesNV[vertex] = vertexIndex;\n"
+ << " gl_MeshVerticesNV[vertexIndex].gl_Position = cb.coords[vertexIndex];\n"
+ << " }\n"
+ << "}\n"
+ ;
+ dst.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+
+ dst.glslSources.add("frag") << glu::FragmentSource(commonMeshFragShader());
+}
+
+TestInstance* MeshOnlyTriangleCase::createInstance (Context& context) const
+{
+ const std::vector<tcu::Vec4> vertexCoords =
+ {
+ tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4(-1.0f, 3.0f, 0.0f, 1.0f),
+ tcu::Vec4( 3.0f, -1.0f, 0.0f, 1.0f),
+ };
+ const std::vector<uint32_t> vertexIndices = { 0u, 1u, 2u };
+ MeshTriangleRendererParams params (std::move(vertexCoords), std::move(vertexIndices), 1u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
+
+ return new MeshTriangleRenderer(context, std::move(params));
+}
+
+TestInstance* MeshTaskTriangleCase::createInstance (Context& context) const
+{
+ const std::vector<tcu::Vec4> vertexCoords =
+ {
+ tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
+ tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f),
+ };
+ const std::vector<uint32_t> vertexIndices = { 2u, 0u, 1u, 1u, 3u, 2u };
+ MeshTriangleRendererParams params (std::move(vertexCoords), std::move(vertexIndices), 2u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
+
+ return new MeshTriangleRenderer(context, std::move(params));
+}
+
+TestInstance* TaskOnlyTriangleCase::createInstance (Context& context) const
+{
+ const std::vector<tcu::Vec4> vertexCoords =
+ {
+ tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
+ tcu::Vec4(-1.0f, 3.0f, 0.0f, 1.0f),
+ tcu::Vec4( 3.0f, -1.0f, 0.0f, 1.0f),
+ };
+ const std::vector<uint32_t> vertexIndices = { 0u, 1u, 2u };
+ // Note we expect the clear color.
+ MeshTriangleRendererParams params (std::move(vertexCoords), std::move(vertexIndices), 1u, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
+ return new MeshTriangleRenderer(context, std::move(params));
+}
+
+tcu::TestStatus MeshTriangleRenderer::iterate ()
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto qIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto vertexBufferStages = VK_SHADER_STAGE_MESH_BIT_NV;
+ const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(m_params.vertexCoords));
+ const auto vertexBufferUsage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ const auto vertexBufferLoc = DescriptorSetUpdateBuilder::Location::binding(0u);
+ const auto vertexBufferType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+
+ const auto indexBufferStages = VK_SHADER_STAGE_MESH_BIT_NV;
+ const auto indexBufferSize = static_cast<VkDeviceSize>(de::dataSize(m_params.vertexIndices));
+ const auto indexBufferUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ const auto indexBufferLoc = DescriptorSetUpdateBuilder::Location::binding(1u);
+ const auto indexBufferType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+
+ // Vertex buffer.
+ const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, vertexBufferUsage);
+ BufferWithMemory vertexBuffer (vkd, device, alloc, vertexBufferInfo, MemoryRequirement::HostVisible);
+ auto& vertexBufferAlloc = vertexBuffer.getAllocation();
+ void* vertexBufferDataPtr = vertexBufferAlloc.getHostPtr();
+
+ deMemcpy(vertexBufferDataPtr, m_params.vertexCoords.data(), static_cast<size_t>(vertexBufferSize));
+ flushAlloc(vkd, device, vertexBufferAlloc);
+
+ // Index buffer.
+ const auto indexBufferInfo = makeBufferCreateInfo(indexBufferSize, indexBufferUsage);
+ BufferWithMemory indexBuffer (vkd, device, alloc, indexBufferInfo, MemoryRequirement::HostVisible);
+ auto& indexBufferAlloc = indexBuffer.getAllocation();
+ void* indexBufferDataPtr = indexBufferAlloc.getHostPtr();
+
+ deMemcpy(indexBufferDataPtr, m_params.vertexIndices.data(), static_cast<size_t>(indexBufferSize));
+ flushAlloc(vkd, device, indexBufferAlloc);
+
+ // Color buffer.
+ const auto colorBufferFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ const auto colorBufferExtent = makeExtent3D(8u, 8u, 1u);
+ const auto colorBufferUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+
+ const VkImageCreateInfo colorBufferInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ colorBufferFormat, // VkFormat format;
+ colorBufferExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ colorBufferUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+ ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
+
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorBufferFormat, colorSRR);
+
+ // Render pass.
+ const auto renderPass = makeRenderPass(vkd, device, colorBufferFormat);
+
+ // Framebuffer.
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorBufferExtent.width, colorBufferExtent.height);
+
+ // Set layout.
+ DescriptorSetLayoutBuilder layoutBuilder;
+ layoutBuilder.addSingleBinding(vertexBufferType, vertexBufferStages);
+ layoutBuilder.addSingleBinding(indexBufferType, indexBufferStages);
+ const auto setLayout = layoutBuilder.build(vkd, device);
+
+ // Descriptor pool.
+ DescriptorPoolBuilder poolBuilder;
+ poolBuilder.addType(vertexBufferType);
+ poolBuilder.addType(indexBufferType);
+ const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+
+ // Descriptor set.
+ const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
+
+ // Update descriptor set.
+ DescriptorSetUpdateBuilder updateBuilder;
+ const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer.get(), 0ull, vertexBufferSize);
+ const auto indexBufferDescInfo = makeDescriptorBufferInfo(indexBuffer.get(), 0ull, indexBufferSize);
+ updateBuilder.writeSingle(descriptorSet.get(), vertexBufferLoc, vertexBufferType, &vertexBufferDescInfo);
+ updateBuilder.writeSingle(descriptorSet.get(), indexBufferLoc, indexBufferType, &indexBufferDescInfo);
+ updateBuilder.update(vkd, device);
+
+ // Pipeline layout.
+ const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+
+ // Shader modules.
+ Move<VkShaderModule> taskModule;
+ const auto& binaries = m_context.getBinaryCollection();
+
+ if (binaries.contains("task"))
+ taskModule = createShaderModule(vkd, device, binaries.get("task"), 0u);
+ const auto meshModule = createShaderModule(vkd, device, binaries.get("mesh"), 0u);
+ const auto fragModule = createShaderModule(vkd, device, binaries.get("frag"), 0u);
+
+ // Graphics pipeline.
+ std::vector<VkViewport> viewports (1u, makeViewport(colorBufferExtent));
+ std::vector<VkRect2D> scissors (1u, makeRect2D(colorBufferExtent));
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(), taskModule.get(), meshModule.get(), fragModule.get(), renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, qIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ // Output buffer.
+ const auto tcuFormat = mapVkFormat(colorBufferFormat);
+ const auto outBufferSize = static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * colorBufferExtent.width * colorBufferExtent.height);
+ const auto outBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ const auto outBufferInfo = makeBufferCreateInfo(outBufferSize, outBufferUsage);
+ BufferWithMemory outBuffer (vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible);
+ auto& outBufferAlloc = outBuffer.getAllocation();
+ void* outBufferData = outBufferAlloc.getHostPtr();
+
+ // Draw triangle.
+ beginCommandBuffer(vkd, cmdBuffer);
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)/*clear color*/);
+ vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, m_params.taskCount, 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ // Copy color buffer to output buffer.
+ const tcu::IVec3 imageDim (static_cast<int>(colorBufferExtent.width), static_cast<int>(colorBufferExtent.height), static_cast<int>(colorBufferExtent.depth));
+ const tcu::IVec2 imageSize (imageDim.x(), imageDim.y());
+
+ copyImageToBuffer(vkd, cmdBuffer, colorBuffer.get(), outBuffer.get(), imageSize);
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Invalidate alloc.
+ invalidateAlloc(vkd, device, outBufferAlloc);
+ tcu::ConstPixelBufferAccess outPixels(tcuFormat, imageDim, outBufferData);
+
+ auto& log = m_context.getTestContext().getLog();
+ const tcu::Vec4 threshold (0.0f); // The color can be represented exactly.
+
+ if (!tcu::floatThresholdCompare(log, "Result", "", m_params.expectedColor, outPixels, threshold, tcu::COMPARE_LOG_EVERYTHING))
+ return tcu::TestStatus::fail("Failed; check log for details");
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+}
+
+tcu::TestCaseGroup* createMeshShaderSmokeTests (tcu::TestContext& testCtx)
+{
+ GroupPtr smokeTests (new tcu::TestCaseGroup(testCtx, "smoke", "Mesh Shader Smoke Tests"));
+
+ smokeTests->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle", ""));
+ smokeTests->addChild(new MeshTaskTriangleCase(testCtx, "mesh_task_shader_triangle", ""));
+ smokeTests->addChild(new TaskOnlyTriangleCase(testCtx, "task_only_shader_triangle", ""));
+
+ return smokeTests.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERSMOKETESTS_HPP
+#define _VKTMESHSHADERSMOKETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Smoke Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderSmokeTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERSMOKETESTS_HPP
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Synchronization Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderSyncTests.hpp"
+#include "vktTestCase.hpp"
+
+#include "vkDefs.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkObjUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkBarrierUtil.hpp"
+#include "vkImageUtil.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+
+using namespace vk;
+
+// Stages that will be used in these tests.
+enum class Stage
+{
+ HOST = 0,
+ TRANSFER,
+ TASK,
+ MESH,
+ FRAG,
+};
+
+std::ostream& operator<< (std::ostream& stream, Stage stage)
+{
+ switch (stage)
+ {
+ case Stage::HOST: stream << "host"; break;
+ case Stage::TRANSFER: stream << "transfer"; break;
+ case Stage::TASK: stream << "task"; break;
+ case Stage::MESH: stream << "mesh"; break;
+ case Stage::FRAG: stream << "frag"; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ return stream;
+}
+
+bool isShaderStage (Stage stage)
+{
+ return (stage == Stage::TASK || stage == Stage::MESH || stage == Stage::FRAG);
+}
+
+VkPipelineStageFlags stageToFlags (Stage stage)
+{
+ switch (stage)
+ {
+ case Stage::HOST: return VK_PIPELINE_STAGE_HOST_BIT;
+ case Stage::TRANSFER: return VK_PIPELINE_STAGE_TRANSFER_BIT;
+ case Stage::TASK: return VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV;
+ case Stage::MESH: return VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV;
+ case Stage::FRAG: return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+ default: DE_ASSERT(false); break;
+ }
+
+ // Unreachable.
+ DE_ASSERT(false);
+ return 0u;
+}
+
+VkFormat getImageFormat ()
+{
+ return VK_FORMAT_R32_UINT;
+}
+
+VkExtent3D getImageExtent ()
+{
+ return makeExtent3D(1u, 1u, 1u);
+}
+
+// Types of resources we will use.
+enum class ResourceType
+{
+ UNIFORM_BUFFER = 0,
+ STORAGE_BUFFER,
+ STORAGE_IMAGE,
+ SAMPLED_IMAGE,
+};
+
+VkDescriptorType resourceTypeToDescriptor (ResourceType resType)
+{
+ switch (resType)
+ {
+ case ResourceType::UNIFORM_BUFFER: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ case ResourceType::STORAGE_BUFFER: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ case ResourceType::STORAGE_IMAGE: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ case ResourceType::SAMPLED_IMAGE: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ default: DE_ASSERT(false); break;
+ }
+
+ // Unreachable.
+ DE_ASSERT(false);
+ return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
+}
+
+// Will the test use a specific barrier or a general memory barrier?
+enum class BarrierType
+{
+ GENERAL = 0,
+ SPECIFIC,
+ DEPENDENCY,
+};
+
+// Types of writes we will use.
+enum class WriteAccess
+{
+ HOST_WRITE = 0,
+ TRANSFER_WRITE,
+ SHADER_WRITE,
+};
+
+VkAccessFlags writeAccessToFlags (WriteAccess access)
+{
+ switch (access)
+ {
+ case WriteAccess::HOST_WRITE: return VK_ACCESS_HOST_WRITE_BIT;
+ case WriteAccess::TRANSFER_WRITE: return VK_ACCESS_TRANSFER_WRITE_BIT;
+ case WriteAccess::SHADER_WRITE: return VK_ACCESS_SHADER_WRITE_BIT;
+ default: DE_ASSERT(false); break;
+ }
+
+ // Unreachable.
+ DE_ASSERT(false);
+ return 0u;
+}
+
+// Types of reads we will use.
+enum class ReadAccess
+{
+ HOST_READ = 0,
+ TRANSFER_READ,
+ SHADER_READ,
+ UNIFORM_READ,
+};
+
+VkAccessFlags readAccessToFlags (ReadAccess access)
+{
+ switch (access)
+ {
+ case ReadAccess::HOST_READ: return VK_ACCESS_HOST_READ_BIT;
+ case ReadAccess::TRANSFER_READ: return VK_ACCESS_TRANSFER_READ_BIT;
+ case ReadAccess::SHADER_READ: return VK_ACCESS_SHADER_READ_BIT;
+ case ReadAccess::UNIFORM_READ: return VK_ACCESS_UNIFORM_READ_BIT;
+ default: DE_ASSERT(false); break;
+ }
+
+ // Unreachable.
+ DE_ASSERT(false);
+ return 0u;
+}
+
+// Auxiliary functions to verify certain combinations are possible.
+
+// Check if the writing stage can use the specified write access.
+bool canWriteFromStageAsAccess (Stage writeStage, WriteAccess access)
+{
+ switch (writeStage)
+ {
+ case Stage::HOST: return (access == WriteAccess::HOST_WRITE);
+ case Stage::TRANSFER: return (access == WriteAccess::TRANSFER_WRITE);
+ case Stage::TASK: // fallthrough
+ case Stage::MESH: // fallthrough
+ case Stage::FRAG: return (access == WriteAccess::SHADER_WRITE);
+ default: DE_ASSERT(false); break;
+ }
+
+ return false;
+}
+
+// Check if the reading stage can use the specified read access.
+bool canReadFromStageAsAccess (Stage readStage, ReadAccess access)
+{
+ switch (readStage)
+ {
+ case Stage::HOST: return (access == ReadAccess::HOST_READ);
+ case Stage::TRANSFER: return (access == ReadAccess::TRANSFER_READ);
+ case Stage::TASK: // fallthrough
+ case Stage::MESH: // fallthrough
+ case Stage::FRAG: return (access == ReadAccess::SHADER_READ || access == ReadAccess::UNIFORM_READ);
+ default: DE_ASSERT(false); break;
+ }
+
+ return false;
+}
+
+// Check if reading the given resource type is possible with the given type of read access.
+bool canReadResourceAsAccess (ResourceType resType, ReadAccess access)
+{
+ if (access == ReadAccess::UNIFORM_READ)
+ return (resType == ResourceType::UNIFORM_BUFFER);
+ return true;
+}
+
+// Check if writing to the given resource type is possible with the given type of write access.
+bool canWriteResourceAsAccess (ResourceType resType, WriteAccess access)
+{
+ if (resType == ResourceType::UNIFORM_BUFFER)
+ return (access != WriteAccess::SHADER_WRITE);
+ return true;
+}
+
+// Check if the given stage can write to the given resource type.
+bool canWriteTo (Stage stage, ResourceType resType)
+{
+ switch (stage)
+ {
+ case Stage::HOST: return (resType == ResourceType::UNIFORM_BUFFER || resType == ResourceType::STORAGE_BUFFER);
+ case Stage::TRANSFER: return true;
+ case Stage::TASK: // fallthrough
+ case Stage::MESH: return (resType == ResourceType::STORAGE_BUFFER || resType == ResourceType::STORAGE_IMAGE);
+ default: DE_ASSERT(false); break;
+ }
+
+ return false;
+}
+
+// Check if the given stage can read from the given resource type.
+bool canReadFrom (Stage stage, ResourceType resType)
+{
+ switch (stage)
+ {
+ case Stage::HOST: return (resType == ResourceType::UNIFORM_BUFFER || resType == ResourceType::STORAGE_BUFFER);
+ case Stage::TRANSFER: // fallthrough
+ case Stage::TASK: // fallthrough
+ case Stage::MESH:
+ case Stage::FRAG: return true;
+ default: DE_ASSERT(false); break;
+ }
+
+ return false;
+}
+
+// Will we need to store the test value in an auxiliar buffer to be read?
+bool needsAuxiliarSourceBuffer (Stage fromStage, Stage toStage)
+{
+ DE_UNREF(toStage);
+ return (fromStage == Stage::TRANSFER);
+}
+
+// Will we need to store the read operation result into an auxiliar buffer to be checked?
+bool needsAuxiliarDestBuffer (Stage fromStage, Stage toStage)
+{
+ DE_UNREF(fromStage);
+ return (toStage == Stage::TRANSFER);
+}
+
+// Needs any auxiliar buffer for any case?
+bool needsAuxiliarBuffer (Stage fromStage, Stage toStage)
+{
+ return (needsAuxiliarSourceBuffer(fromStage, toStage) || needsAuxiliarDestBuffer(fromStage, toStage));
+}
+
+// Will the final value be stored in the auxiliar destination buffer?
+bool valueInAuxiliarDestBuffer (Stage toStage)
+{
+ return (toStage == Stage::TRANSFER);
+}
+
+// Will the final value be stored in the resource buffer itself?
+bool valueInResourceBuffer (Stage toStage)
+{
+ return (toStage == Stage::HOST);
+}
+
+// Will the final value be stored in the color buffer?
+bool valueInColorBuffer (Stage toStage)
+{
+ return (!valueInAuxiliarDestBuffer(toStage) && !valueInResourceBuffer(toStage));
+}
+
+// Image usage flags for the image resource.
+VkImageUsageFlags resourceImageUsageFlags (ResourceType resourceType)
+{
+ VkImageUsageFlags flags = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+ switch (resourceType)
+ {
+ case ResourceType::STORAGE_IMAGE: flags |= VK_IMAGE_USAGE_STORAGE_BIT; break;
+ case ResourceType::SAMPLED_IMAGE: flags |= VK_IMAGE_USAGE_SAMPLED_BIT; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ return flags;
+}
+
+// Buffer usage flags for the buffer resource.
+VkBufferUsageFlags resourceBufferUsageFlags (ResourceType resourceType)
+{
+ VkBufferUsageFlags flags = (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+
+ switch (resourceType)
+ {
+ case ResourceType::UNIFORM_BUFFER: flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
+ case ResourceType::STORAGE_BUFFER: flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ return flags;
+}
+
+// A subpass dependency is needed if both the source and destination stages are shader stages.
+bool needsSubpassDependency (Stage fromStage, Stage toStage)
+{
+ return (isShaderStage(fromStage) && isShaderStage(toStage));
+}
+
+struct TestParams
+{
+ Stage fromStage;
+ Stage toStage;
+ ResourceType resourceType;
+ BarrierType barrierType;
+ WriteAccess writeAccess;
+ ReadAccess readAccess;
+ uint32_t testValue;
+
+protected:
+ bool readsOrWritesIn (Stage stage) const
+ {
+ DE_ASSERT(fromStage != toStage);
+ return (fromStage == stage || toStage == stage);
+ }
+
+public:
+ bool needsTask () const
+ {
+ return readsOrWritesIn(Stage::TASK);
+ }
+
+ bool readsOrWritesInMesh () const
+ {
+ return readsOrWritesIn(Stage::MESH);
+ }
+
+ std::string getResourceDecl () const
+ {
+ const auto imgFormat = ((resourceType == ResourceType::STORAGE_IMAGE) ? ", r32ui" : "");
+ const auto storagePrefix = ((writeAccess == WriteAccess::SHADER_WRITE) ? "" : "readonly ");
+ std::ostringstream decl;
+
+ decl << "layout (set=0, binding=0" << imgFormat << ") ";
+ switch (resourceType)
+ {
+ case ResourceType::UNIFORM_BUFFER: decl << "uniform UniformBuffer { uint value; } ub;"; break;
+ case ResourceType::STORAGE_BUFFER: decl << storagePrefix << "buffer StorageBuffer { uint value; } sb;"; break;
+ case ResourceType::STORAGE_IMAGE: decl << storagePrefix << "uniform uimage2D si;"; break;
+ case ResourceType::SAMPLED_IMAGE: decl << "uniform usampler2D sampled;"; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ decl << "\n";
+ return decl.str();
+ }
+
+ std::string getReadStatement (const std::string& outName) const
+ {
+ std::ostringstream statement;
+ statement << " " << outName << " = ";
+
+ switch (resourceType)
+ {
+ case ResourceType::UNIFORM_BUFFER: statement << "ub.value"; break;
+ case ResourceType::STORAGE_BUFFER: statement << "sb.value"; break;
+ case ResourceType::STORAGE_IMAGE: statement << "imageLoad(si, ivec2(0, 0)).x"; break;
+ case ResourceType::SAMPLED_IMAGE: statement << "texture(sampled, vec2(0.5, 0.5)).x"; break;
+ default: DE_ASSERT(false); break;
+ }
+
+ statement << ";\n";
+ return statement.str();
+ }
+
+ std::string getWriteStatement (const std::string& valueName) const
+ {
+ std::ostringstream statement;
+ statement << " ";
+
+ switch (resourceType)
+ {
+ case ResourceType::STORAGE_BUFFER: statement << "sb.value = " << valueName; break;
+ case ResourceType::STORAGE_IMAGE: statement << "imageStore(si, ivec2(0, 0), uvec4(" << valueName << ", 0, 0, 0))"; break;
+ case ResourceType::UNIFORM_BUFFER: // fallthrough
+ case ResourceType::SAMPLED_IMAGE: // fallthrough
+ default: DE_ASSERT(false); break;
+ }
+
+ statement << ";\n";
+ return statement.str();
+ }
+
+ VkShaderStageFlags getResourceShaderStages () const
+ {
+ VkShaderStageFlags flags = 0u;
+
+ if (fromStage == Stage::TASK || toStage == Stage::TASK) flags |= VK_SHADER_STAGE_TASK_BIT_NV;
+ if (fromStage == Stage::MESH || toStage == Stage::MESH) flags |= VK_SHADER_STAGE_MESH_BIT_NV;
+ if (fromStage == Stage::FRAG || toStage == Stage::FRAG) flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
+
+ // We assume at least something must be done either on the task or mesh shaders for the tests to be interesting.
+ DE_ASSERT((flags & (VK_SHADER_STAGE_TASK_BIT_NV | VK_SHADER_STAGE_MESH_BIT_NV)) != 0u);
+ return flags;
+ }
+
+ // We'll prefer to keep the image in the general layout if it will be written to from a shader stage or if the barrier is going to be a generic memory barrier.
+ bool preferGeneralLayout () const
+ {
+ return (isShaderStage(fromStage) || (barrierType == BarrierType::GENERAL) || (resourceType == ResourceType::STORAGE_IMAGE));
+ }
+};
+
+class MeshShaderSyncCase : public vkt::TestCase
+{
+public:
+ MeshShaderSyncCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
+ : vkt::TestCase (testCtx, name, description), m_params (params)
+ {}
+
+ virtual ~MeshShaderSyncCase (void) {}
+
+ void checkSupport (Context& context) const override;
+ void initPrograms (vk::SourceCollections& programCollection) const override;
+ TestInstance* createInstance (Context& context) const override;
+
+protected:
+ TestParams m_params;
+};
+
+class MeshShaderSyncInstance : public vkt::TestInstance
+{
+public:
+ MeshShaderSyncInstance (Context& context, const TestParams& params) : vkt::TestInstance(context), m_params(params) {}
+ virtual ~MeshShaderSyncInstance (void) {}
+
+ tcu::TestStatus iterate (void) override;
+
+protected:
+ TestParams m_params;
+};
+
+void MeshShaderSyncCase::checkSupport (Context& context) const
+{
+ context.requireDeviceFunctionality("VK_NV_mesh_shader");
+
+ const auto& meshFeatures = context.getMeshShaderFeatures();
+
+ if (!meshFeatures.meshShader)
+ TCU_THROW(NotSupportedError, "Mesh shaders not supported");
+
+ if (m_params.needsTask() && !meshFeatures.taskShader)
+ TCU_THROW(NotSupportedError, "Task shaders not supported");
+
+ if (m_params.writeAccess == WriteAccess::SHADER_WRITE)
+ {
+ const auto& features = context.getDeviceFeatures();
+ if (!features.vertexPipelineStoresAndAtomics)
+ TCU_THROW(NotSupportedError, "Vertex pipeline stores not supported");
+ }
+}
+
+void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+ const bool needsTaskShader = m_params.needsTask();
+ const auto valueStr = de::toString(m_params.testValue);
+ const auto resourceDecl = m_params.getResourceDecl();
+
+ if (needsTaskShader)
+ {
+
+ std::ostringstream task;
+ task
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "\n"
+ << "out taskNV TaskData { uint value; } td;\n"
+ << "\n"
+ << resourceDecl
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_TaskCountNV = 1u;\n"
+ << " td.value = 0u;\n"
+ << ((m_params.fromStage == Stage::TASK) ? m_params.getWriteStatement(valueStr) : "")
+ << ((m_params.toStage == Stage::TASK) ? m_params.getReadStatement("td.value") : "")
+ << "}\n"
+ ;
+ programCollection.glslSources.add("task") << glu::TaskSource(task.str());
+ }
+
+ {
+ std::ostringstream mesh;
+ mesh
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout(local_size_x=1) in;\n"
+ << "layout(triangles) out;\n"
+ << "layout(max_vertices=3, max_primitives=1) out;\n"
+ << "\n"
+ << (needsTaskShader ? "in taskNV TaskData { uint value; } td;\n" : "")
+ << "layout (location=0) out perprimitiveNV uint primitiveValue[];\n"
+ << "\n"
+ << (m_params.readsOrWritesInMesh() ? resourceDecl : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " gl_PrimitiveCountNV = 1u;\n"
+ << (needsTaskShader ? " primitiveValue[0] = td.value;\n" : "")
+ << ((m_params.fromStage == Stage::MESH) ? m_params.getWriteStatement(valueStr) : "")
+ << ((m_params.toStage == Stage::MESH) ? m_params.getReadStatement("primitiveValue[0]") : "")
+ << "\n"
+ << " gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[1].gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n"
+ << " gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
+ << " gl_PrimitiveIndicesNV[0] = 0;\n"
+ << " gl_PrimitiveIndicesNV[1] = 1;\n"
+ << " gl_PrimitiveIndicesNV[2] = 2;\n"
+ << "}\n"
+ ;
+ programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
+ }
+
+ {
+ const bool readFromFrag = (m_params.toStage == Stage::FRAG);
+ std::ostringstream frag;
+
+ frag
+ << "#version 450\n"
+ << "#extension GL_NV_mesh_shader : enable\n"
+ << "\n"
+ << "layout (location=0) in perprimitiveNV flat uint primitiveValue;\n"
+ << "layout (location=0) out uvec4 outColor;\n"
+ << "\n"
+ << (readFromFrag ? resourceDecl : "")
+ << "\n"
+ << "void main ()\n"
+ << "{\n"
+ << " outColor = uvec4(primitiveValue, 0, 0, 0);\n"
+ << (readFromFrag ? m_params.getReadStatement("const uint readVal") : "")
+ << (readFromFrag ? " outColor = uvec4(readVal, 0, 0, 0);\n" : "")
+ << "}\n"
+ ;
+ programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+ }
+}
+
+TestInstance* MeshShaderSyncCase::createInstance (Context& context) const
+{
+ return new MeshShaderSyncInstance(context, m_params);
+}
+
+// General description behind these tests.
+//
+// From To
+// ==============================
+// HOST TASK Prepare buffer from host. Only valid for uniform and storage buffers. Read value from task into td.value. Verify color buffer.
+// HOST MESH Same situation. Read value from mesh into primitiveValue[0]. Verify color buffer.
+// TRANSFER TASK Prepare auxiliary host-coherent source buffer from host. Copy buffer to buffer or buffer to image. Read from task into td.value. Verify color buffer.
+// TRANSFER MESH Same initial steps. Read from mesh into primitiveValue[0]. Verify color buffer.
+// TASK MESH Write value to buffer or image from task shader. Only valid for storage buffers and images. Read from mesh into primitiveValue[0]. Verify color buffer.
+// TASK FRAG Same write procedure and restrictions. Read from frag into outColor. Verify color buffer.
+// TASK TRANSFER Same write procedure and restrictions. Prepare auxiliary host-coherent read buffer and copy buffer to buffer or image to buffer. Verify auxiliary buffer.
+// TASK HOST Due to From/To restrictions, only valid for storage buffers. Same write procedure. Read and verify buffer directly.
+// MESH FRAG Same as task to frag but the write instructions need to be in the mesh shader.
+// MESH TRANSFER Same as task to transfer but the write instructions need to be in the mesh shader.
+// MESH HOST Same as task to host but the write instructions need to be in the mesh shader.
+//
+
+Move<VkRenderPass> createCustomRenderPass (const DeviceInterface& vkd, VkDevice device, VkFormat colorFormat, const TestParams& params)
+{
+ const std::vector<VkAttachmentDescription> attachmentDescs =
+ {
+ {
+ 0u, // VkAttachmentDescriptionFlags flags;
+ colorFormat, // VkFormat format;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
+ VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
+ VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
+ VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
+ }
+ };
+
+ const std::vector<VkAttachmentReference> attachmentRefs = { { 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } };
+
+ const std::vector<VkSubpassDescription> subpassDescs =
+ {
+ {
+ 0u, // VkSubpassDescriptionFlags flags;
+ VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
+ 0u, // uint32_t inputAttachmentCount;
+ nullptr, // const VkAttachmentReference* pInputAttachments;
+ static_cast<uint32_t>(attachmentRefs.size()), // uint32_t colorAttachmentCount;
+ de::dataOrNull(attachmentRefs), // const VkAttachmentReference* pColorAttachments;
+ nullptr, // const VkAttachmentReference* pResolveAttachments;
+ nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
+ 0u, // uint32_t preserveAttachmentCount;
+ nullptr, // const uint32_t* pPreserveAttachments;
+ }
+ };
+
+ // When both stages are shader stages, the dependency will be expressed as a subpass dependency.
+ std::vector<VkSubpassDependency> dependencies;
+ if (needsSubpassDependency(params.fromStage, params.toStage))
+ {
+ const VkSubpassDependency dependency =
+ {
+ 0u, // uint32_t srcSubpass;
+ 0u, // uint32_t dstSubpass;
+ stageToFlags(params.fromStage), // VkPipelineStageFlags srcStageMask;
+ stageToFlags(params.toStage), // VkPipelineStageFlags dstStageMask;
+ writeAccessToFlags(params.writeAccess), // VkAccessFlags srcAccessMask;
+ readAccessToFlags(params.readAccess), // VkAccessFlags dstAccessMask;
+ 0u, // VkDependencyFlags dependencyFlags;
+ };
+ dependencies.push_back(dependency);
+ }
+
+ const VkRenderPassCreateInfo createInfo =
+ {
+ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkRenderPassCreateFlags flags;
+ static_cast<uint32_t>(attachmentDescs.size()), // uint32_t attachmentCount;
+ de::dataOrNull(attachmentDescs), // const VkAttachmentDescription* pAttachments;
+ static_cast<uint32_t>(subpassDescs.size()), // uint32_t subpassCount;
+ de::dataOrNull(subpassDescs), // const VkSubpassDescription* pSubpasses;
+ static_cast<uint32_t>(dependencies.size()), // uint32_t dependencyCount;
+ de::dataOrNull(dependencies), // const VkSubpassDependency* pDependencies;
+ };
+
+ return createRenderPass(vkd, device, &createInfo);
+}
+
+void hostToTransferMemoryBarrier (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer)
+{
+ const auto barrier = makeMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
+}
+
+void transferToHostMemoryBarrier (const DeviceInterface& vkd, VkCommandBuffer cmdBuffer)
+{
+ const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
+}
+
+tcu::TestStatus MeshShaderSyncInstance::iterate (void)
+{
+ const auto& vkd = m_context.getDeviceInterface();
+ const auto device = m_context.getDevice();
+ auto& alloc = m_context.getDefaultAllocator();
+ const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
+ const auto queue = m_context.getUniversalQueue();
+
+ const auto imageFormat = getImageFormat();
+ const auto imageExtent = getImageExtent();
+ const auto colorBufferUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+ const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
+ const auto bufferSize = static_cast<VkDeviceSize>(sizeof(m_params.testValue));
+ const auto descriptorType = resourceTypeToDescriptor(m_params.resourceType);
+ const auto resourceStages = m_params.getResourceShaderStages();
+ const auto auxiliarBufferUsage = (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ const auto useGeneralLayout = m_params.preferGeneralLayout();
+
+ const auto writeAccessFlags = writeAccessToFlags(m_params.writeAccess);
+ const auto readAccessFlags = readAccessToFlags(m_params.readAccess);
+ const auto fromStageFlags = stageToFlags(m_params.fromStage);
+ const auto toStageFlags = stageToFlags(m_params.toStage);
+
+ // Prepare color buffer.
+ const VkImageCreateInfo colorBufferCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ imageExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ colorBufferUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+ ImageWithMemory colorBuffer (vkd, device, alloc, colorBufferCreateInfo, MemoryRequirement::Any);
+ const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
+
+ // Main resource.
+ using ImageWithMemoryPtr = de::MovePtr<ImageWithMemory>;
+ using BufferWithMemoryPtr = de::MovePtr<BufferWithMemory>;
+
+ ImageWithMemoryPtr imageResource;
+ Move<VkImageView> imageResourceView;
+ VkImageLayout imageDescriptorLayout = (useGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ VkImageLayout currentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ BufferWithMemoryPtr bufferResource;
+
+ bool useImageResource = false;
+ bool useBufferResource = false;
+
+ switch (m_params.resourceType)
+ {
+ case ResourceType::UNIFORM_BUFFER:
+ case ResourceType::STORAGE_BUFFER:
+ useBufferResource = true;
+ break;
+ case ResourceType::STORAGE_IMAGE:
+ case ResourceType::SAMPLED_IMAGE:
+ useImageResource = true;
+ break;
+ default:
+ DE_ASSERT(false);
+ break;
+ }
+
+ // One resource needed.
+ DE_ASSERT(useImageResource != useBufferResource);
+
+ if (useImageResource)
+ {
+ const auto resourceImageUsage = resourceImageUsageFlags(m_params.resourceType);
+
+ const VkImageCreateInfo resourceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkImageCreateFlags flags;
+ VK_IMAGE_TYPE_2D, // VkImageType imageType;
+ imageFormat, // VkFormat format;
+ imageExtent, // VkExtent3D extent;
+ 1u, // uint32_t mipLevels;
+ 1u, // uint32_t arrayLayers;
+ VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
+ VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
+ resourceImageUsage, // VkImageUsageFlags usage;
+ VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
+ 0u, // uint32_t queueFamilyIndexCount;
+ nullptr, // const uint32_t* pQueueFamilyIndices;
+ VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
+ };
+ imageResource = ImageWithMemoryPtr(new ImageWithMemory(vkd, device, alloc, resourceCreateInfo, MemoryRequirement::Any));
+ imageResourceView = makeImageView(vkd, device, imageResource->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
+ }
+ else
+ {
+ const auto resourceBufferUsage = resourceBufferUsageFlags(m_params.resourceType);
+ const auto resourceBufferCreateInfo = makeBufferCreateInfo(bufferSize, resourceBufferUsage);
+ bufferResource = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, resourceBufferCreateInfo, MemoryRequirement::HostVisible));
+ }
+
+ Move<VkSampler> sampler;
+ if (descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
+ {
+ const VkSamplerCreateInfo samplerCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
+ nullptr, // const void* pNext;
+ 0u, // VkSamplerCreateFlags flags;
+ VK_FILTER_NEAREST, // VkFilter magFilter;
+ VK_FILTER_NEAREST, // VkFilter minFilter;
+ VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
+ VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
+ 0.0f, // float mipLodBias;
+ VK_FALSE, // VkBool32 anisotropyEnable;
+ 1.0f, // float maxAnisotropy;
+ VK_FALSE, // VkBool32 compareEnable;
+ VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
+ 0.0f, // float minLod;
+ 0.0f, // float maxLod;
+ VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
+ VK_FALSE, // VkBool32 unnormalizedCoordinates;
+ };
+ sampler = createSampler(vkd, device, &samplerCreateInfo);
+ }
+
+ // Auxiliary host-coherent buffer for some cases. Being host-coherent lets us avoid extra barriers that would "pollute" synchronization tests.
+ BufferWithMemoryPtr hostCoherentBuffer;
+ void* hostCoherentDataPtr = nullptr;
+ if (needsAuxiliarBuffer(m_params.fromStage, m_params.toStage))
+ {
+ const auto auxiliarBufferCreateInfo = makeBufferCreateInfo(bufferSize, auxiliarBufferUsage);
+ hostCoherentBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, auxiliarBufferCreateInfo, (MemoryRequirement::HostVisible | MemoryRequirement::Coherent)));
+ hostCoherentDataPtr = hostCoherentBuffer->getAllocation().getHostPtr();
+ }
+
+ // Descriptor pool.
+ Move<VkDescriptorPool> descriptorPool;
+ {
+ DescriptorPoolBuilder poolBuilder;
+ poolBuilder.addType(descriptorType);
+ descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+ }
+
+ // Descriptor set layout.
+ Move<VkDescriptorSetLayout> setLayout;
+ {
+ DescriptorSetLayoutBuilder layoutBuilder;
+ layoutBuilder.addSingleBinding(descriptorType, resourceStages);
+ setLayout = layoutBuilder.build(vkd, device);
+ }
+
+ // Descriptor set.
+ const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
+
+ // Update descriptor set.
+ {
+ DescriptorSetUpdateBuilder updateBuilder;
+ const auto location = DescriptorSetUpdateBuilder::Location::binding(0u);
+
+ switch (descriptorType)
+ {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ {
+ const auto bufferInfo = makeDescriptorBufferInfo(bufferResource->get(), 0ull, bufferSize);
+ updateBuilder.writeSingle(descriptorSet.get(), location, descriptorType, &bufferInfo);
+ }
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+ {
+ auto descriptorImageInfo = makeDescriptorImageInfo(sampler.get(), imageResourceView.get(), imageDescriptorLayout);
+ updateBuilder.writeSingle(descriptorSet.get(), location, descriptorType, &descriptorImageInfo);
+ }
+ break;
+ default:
+ DE_ASSERT(false); break;
+ }
+
+ updateBuilder.update(vkd, device);
+ }
+
+ // Shader modules.
+ Move<VkShaderModule> taskShader;
+ Move<VkShaderModule> meshShader;
+ Move<VkShaderModule> fragShader;
+
+ const auto& binaries = m_context.getBinaryCollection();
+
+ if (m_params.needsTask())
+ taskShader = createShaderModule(vkd, device, binaries.get("task"), 0u);
+ meshShader = createShaderModule(vkd, device, binaries.get("mesh"), 0u);
+ fragShader = createShaderModule(vkd, device, binaries.get("frag"), 0u);
+
+ // Pipeline layout, render pass, framebuffer.
+ const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+ const auto renderPass = createCustomRenderPass(vkd, device, imageFormat, m_params);
+ const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), imageExtent.width, imageExtent.height);
+
+ // Pipeline.
+ std::vector<VkViewport> viewports (1u, makeViewport(imageExtent));
+ std::vector<VkRect2D> scissors (1u, makeRect2D(imageExtent));
+ const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(), taskShader.get(), meshShader.get(), fragShader.get(), renderPass.get(), viewports, scissors);
+
+ // Command pool and buffer.
+ const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
+ const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+ const auto cmdBuffer = cmdBufferPtr.get();
+
+ beginCommandBuffer(vkd, cmdBuffer);
+
+ if (m_params.fromStage == Stage::HOST)
+ {
+ // Prepare buffer from host when the source stage is the host.
+ DE_ASSERT(useBufferResource);
+
+ auto& resourceBufferAlloc = bufferResource->getAllocation();
+ void* resourceBufferDataPtr = resourceBufferAlloc.getHostPtr();
+
+ deMemcpy(resourceBufferDataPtr, &m_params.testValue, sizeof(m_params.testValue));
+ flushAlloc(vkd, device, resourceBufferAlloc);
+ }
+ else if (m_params.fromStage == Stage::TRANSFER)
+ {
+ // Put value in host-coherent buffer and transfer it to the resource buffer or image.
+ deMemcpy(hostCoherentDataPtr, &m_params.testValue, sizeof(m_params.testValue));
+ hostToTransferMemoryBarrier(vkd, cmdBuffer);
+
+ if (useBufferResource)
+ {
+ const auto copyRegion = makeBufferCopy(0ull, 0ull, bufferSize);
+ vkd.cmdCopyBuffer(cmdBuffer, hostCoherentBuffer->get(), bufferResource->get(), 1u, ©Region);
+ }
+ else
+ {
+ // Move image to the right layout for transfer.
+ const auto newLayout = (useGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+ if (newLayout != currentLayout)
+ {
+ const auto preCopyBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, currentLayout, newLayout, imageResource->get(), colorSRR);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preCopyBarrier);
+ currentLayout = newLayout;
+ }
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+ vkd.cmdCopyBufferToImage(cmdBuffer, hostCoherentBuffer->get(), imageResource->get(), currentLayout, 1u, ©Region);
+ }
+ }
+ else if (m_params.fromStage == Stage::TASK || m_params.fromStage == Stage::MESH)
+ {
+ // The image or buffer will be written to from shaders. Images need to be in the right layout.
+ if (useImageResource)
+ {
+ const auto newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ if (newLayout != currentLayout)
+ {
+ const auto preWriteBarrier = makeImageMemoryBarrier(0u, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT), currentLayout, newLayout, imageResource->get(), colorSRR);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, fromStageFlags, 0u, 0u, nullptr, 0u, nullptr, 1u, &preWriteBarrier);
+ currentLayout = newLayout;
+ }
+ }
+ }
+ else
+ {
+ DE_ASSERT(false);
+ }
+
+ // If the resource is going to be read from shaders, we'll insert the main barrier before running the pipeline.
+ if (isShaderStage(m_params.toStage))
+ {
+ if (m_params.barrierType == BarrierType::GENERAL)
+ {
+ const auto memoryBarrier = makeMemoryBarrier(writeAccessFlags, readAccessFlags);
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr);
+ }
+ else if (m_params.barrierType == BarrierType::SPECIFIC)
+ {
+ if (useBufferResource)
+ {
+ const auto bufferBarrier = makeBufferMemoryBarrier(writeAccessFlags, readAccessFlags, bufferResource->get(), 0ull, bufferSize);
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
+ }
+ else
+ {
+ const auto newLayout = (useGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+ const auto imageBarrier = makeImageMemoryBarrier(writeAccessFlags, readAccessFlags, currentLayout, newLayout, imageResource->get(), colorSRR);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
+ currentLayout = newLayout;
+ }
+ }
+ // For subpass dependencies, they have already been included in the render pass.
+ }
+
+ // Run the pipeline.
+ beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), tcu::UVec4(0u));
+ vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
+ vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+ vkd.cmdDrawMeshTasksNV(cmdBuffer, 1u, 0u);
+ endRenderPass(vkd, cmdBuffer);
+
+ // If the resource was written to from the shaders, insert the main barrier after running the pipeline.
+ if (isShaderStage(m_params.fromStage))
+ {
+ if (m_params.barrierType == BarrierType::GENERAL)
+ {
+ const auto memoryBarrier = makeMemoryBarrier(writeAccessFlags, readAccessFlags);
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 1u, &memoryBarrier, 0u, nullptr, 0u, nullptr);
+ }
+ else if (m_params.barrierType == BarrierType::SPECIFIC)
+ {
+ if (useBufferResource)
+ {
+ const auto bufferBarrier = makeBufferMemoryBarrier(writeAccessFlags, readAccessFlags, bufferResource->get(), 0ull, bufferSize);
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr);
+ }
+ else
+ {
+ // Note: the image will only be read from shader stages (which is covered in BarrierType::DEPENDENCY) or from the transfer stage.
+ const auto newLayout = (useGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ const auto imageBarrier = makeImageMemoryBarrier(writeAccessFlags, readAccessFlags, currentLayout, newLayout, imageResource->get(), colorSRR);
+
+ vkd.cmdPipelineBarrier(cmdBuffer, fromStageFlags, toStageFlags, 0u, 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
+ currentLayout = newLayout;
+ }
+ }
+ // For subpass dependencies, they have already been included in the render pass.
+ }
+
+ // Read resource from the destination stage if needed.
+ if (m_params.toStage == Stage::HOST)
+ {
+ // Nothing to do. The test value should be in the resource buffer already, which is host-visible.
+ }
+ else if (m_params.toStage == Stage::TRANSFER)
+ {
+ // Copy value from resource to host-coherent buffer to be verified later.
+ if (useBufferResource)
+ {
+ const auto copyRegion = makeBufferCopy(0ull, 0ull, bufferSize);
+ vkd.cmdCopyBuffer(cmdBuffer, bufferResource->get(), hostCoherentBuffer->get(), 1u, ©Region);
+ }
+ else
+ {
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+ vkd.cmdCopyImageToBuffer(cmdBuffer, imageResource->get(), currentLayout, hostCoherentBuffer->get(), 1u, ©Region);
+ }
+
+ transferToHostMemoryBarrier(vkd, cmdBuffer);
+ }
+
+ // If the output value will be available in the color buffer, take the chance to transfer its contents to a host-coherent buffer.
+ BufferWithMemoryPtr colorVerificationBuffer;
+ void* colorVerificationDataPtr = nullptr;
+
+ if (valueInColorBuffer(m_params.toStage))
+ {
+ const auto auxiliarBufferCreateInfo = makeBufferCreateInfo(bufferSize, auxiliarBufferUsage);
+ colorVerificationBuffer = BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, auxiliarBufferCreateInfo, (MemoryRequirement::HostVisible | MemoryRequirement::Coherent)));
+ colorVerificationDataPtr = colorVerificationBuffer->getAllocation().getHostPtr();
+
+ const auto srcAccess = (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
+ const auto dstAccess = VK_ACCESS_TRANSFER_READ_BIT;
+ const auto colorBarrier = makeImageMemoryBarrier(srcAccess, dstAccess, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
+ vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorBarrier);
+
+ const auto copyRegion = makeBufferImageCopy(imageExtent, colorSRL);
+ vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorVerificationBuffer->get(), 1u, ©Region);
+
+ transferToHostMemoryBarrier(vkd, cmdBuffer);
+ }
+
+
+ endCommandBuffer(vkd, cmdBuffer);
+ submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+ // Verify output resources as needed.
+
+ if (valueInAuxiliarDestBuffer(m_params.toStage))
+ {
+ uint32_t bufferValue;
+ deMemcpy(&bufferValue, hostCoherentDataPtr, sizeof(bufferValue));
+
+ if (bufferValue != m_params.testValue)
+ {
+ std::ostringstream msg;
+ msg << "Unexpected value in auxiliar host-coherent buffer: found " << bufferValue << " and expected " << m_params.testValue;
+ TCU_FAIL(msg.str());
+ }
+ }
+
+ if (valueInResourceBuffer(m_params.toStage))
+ {
+ auto& resourceBufferAlloc = bufferResource->getAllocation();
+ void* resourceBufferDataPtr = resourceBufferAlloc.getHostPtr();
+ uint32_t bufferValue;
+
+ invalidateAlloc(vkd, device, resourceBufferAlloc);
+ deMemcpy(&bufferValue, resourceBufferDataPtr, sizeof(bufferValue));
+
+ if (bufferValue != m_params.testValue)
+ {
+ std::ostringstream msg;
+ msg << "Unexpected value in resource buffer: found " << bufferValue << " and expected " << m_params.testValue;
+ TCU_FAIL(msg.str());
+ }
+ }
+
+ if (valueInColorBuffer(m_params.toStage))
+ {
+ uint32_t bufferValue;
+ deMemcpy(&bufferValue, colorVerificationDataPtr, sizeof(bufferValue));
+
+ if (bufferValue != m_params.testValue)
+ {
+ std::ostringstream msg;
+ msg << "Unexpected value in color verification buffer: found " << bufferValue << " and expected " << m_params.testValue;
+ TCU_FAIL(msg.str());
+ }
+ }
+
+ return tcu::TestStatus::pass("Pass");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createMeshShaderSyncTests (tcu::TestContext& testCtx)
+{
+ const struct
+ {
+ Stage fromStage;
+ Stage toStage;
+ } stageCombinations[] =
+ {
+ // Combinations where the source and destination stages involve mesh shaders.
+ // Note: this could be tested procedurally.
+ { Stage::HOST, Stage::TASK },
+ { Stage::HOST, Stage::MESH },
+ { Stage::TRANSFER, Stage::TASK },
+ { Stage::TRANSFER, Stage::MESH },
+ { Stage::TASK, Stage::MESH },
+ { Stage::TASK, Stage::FRAG },
+ { Stage::TASK, Stage::TRANSFER },
+ { Stage::TASK, Stage::HOST },
+ { Stage::MESH, Stage::FRAG },
+ { Stage::MESH, Stage::TRANSFER },
+ { Stage::MESH, Stage::HOST },
+ };
+
+ const struct
+ {
+ ResourceType resourceType;
+ const char* name;
+ } resourceTypes[] =
+ {
+ { ResourceType::UNIFORM_BUFFER, "uniform_buffer" },
+ { ResourceType::STORAGE_BUFFER, "storage_buffer" },
+ { ResourceType::STORAGE_IMAGE, "storage_image" },
+ { ResourceType::SAMPLED_IMAGE, "sampled_image" },
+ };
+
+ const struct
+ {
+ BarrierType barrierType;
+ const char* name;
+ } barrierTypes[] =
+ {
+ { BarrierType::GENERAL, "memory_barrier" },
+ { BarrierType::SPECIFIC, "specific_barrier" },
+ { BarrierType::DEPENDENCY, "subpass_dependency" },
+ };
+
+ const struct
+ {
+ WriteAccess writeAccess;
+ const char* name;
+ } writeAccesses[] =
+ {
+ { WriteAccess::HOST_WRITE, "host_write" },
+ { WriteAccess::TRANSFER_WRITE, "transfer_write" },
+ { WriteAccess::SHADER_WRITE, "shader_write" },
+ };
+
+ const struct
+ {
+ ReadAccess readAccess;
+ const char* name;
+ } readAccesses[] =
+ {
+ { ReadAccess::HOST_READ, "host_read" },
+ { ReadAccess::TRANSFER_READ, "transfer_read" },
+ { ReadAccess::SHADER_READ, "shader_read" },
+ { ReadAccess::UNIFORM_READ, "uniform_read" },
+ };
+
+ uint32_t testValue = 1628510124u;
+
+ GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "synchronization", "Mesh Shader synchronization tests"));
+
+ for (const auto& stageCombination : stageCombinations)
+ {
+ const std::string combinationName = de::toString(stageCombination.fromStage) + "_to_" + de::toString(stageCombination.toStage);
+ GroupPtr combinationGroup (new tcu::TestCaseGroup(testCtx, combinationName.c_str(), ""));
+
+ for (const auto& resourceCase : resourceTypes)
+ {
+ if (!canWriteTo(stageCombination.fromStage, resourceCase.resourceType))
+ continue;
+
+ if (!canReadFrom(stageCombination.toStage, resourceCase.resourceType))
+ continue;
+
+ GroupPtr resourceGroup (new tcu::TestCaseGroup(testCtx, resourceCase.name, ""));
+
+ for (const auto& barrierCase : barrierTypes)
+ {
+ const auto subpassDependencyNeeded = needsSubpassDependency(stageCombination.fromStage, stageCombination.toStage);
+ const auto barrierIsDependency = (barrierCase.barrierType == BarrierType::DEPENDENCY);
+
+ // Subpass dependencies must be used if, and only if, they are needed.
+ if (subpassDependencyNeeded != barrierIsDependency)
+ continue;
+
+ GroupPtr barrierGroup (new tcu::TestCaseGroup(testCtx, barrierCase.name, ""));
+
+ for (const auto& writeCase : writeAccesses)
+ for (const auto& readCase : readAccesses)
+ {
+ if (!canReadResourceAsAccess(resourceCase.resourceType, readCase.readAccess))
+ continue;
+ if (!canWriteResourceAsAccess(resourceCase.resourceType, writeCase.writeAccess))
+ continue;
+ if (!canReadFromStageAsAccess(stageCombination.toStage, readCase.readAccess))
+ continue;
+ if (!canWriteFromStageAsAccess(stageCombination.fromStage, writeCase.writeAccess))
+ continue;
+
+ const std::string accessCaseName = writeCase.name + std::string("_") + readCase.name;
+
+ const TestParams testParams =
+ {
+ stageCombination.fromStage, // Stage fromStage;
+ stageCombination.toStage, // Stage toStage;
+ resourceCase.resourceType, // ResourceType resourceType;
+ barrierCase.barrierType, // BarrierType barrierType;
+ writeCase.writeAccess, // WriteAccess writeAccess;
+ readCase.readAccess, // ReadAccess readAccess;
+ testValue++, // uint32_t testValue;
+ };
+
+ barrierGroup->addChild(new MeshShaderSyncCase(testCtx, accessCaseName, "", testParams));
+ }
+
+ resourceGroup->addChild(barrierGroup.release());
+ }
+
+ combinationGroup->addChild(resourceGroup.release());
+ }
+
+ mainGroup->addChild(combinationGroup.release());
+ }
+
+ return mainGroup.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERSYNCTESTS_HPP
+#define _VKTMESHSHADERSYNCTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Synchronization Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderSyncTests (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERSYNCTESTS_HPP
--- /dev/null
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderTests.hpp"
+#include "vktMeshShaderSmokeTests.hpp"
+#include "vktMeshShaderSyncTests.hpp"
+#include "vktMeshShaderApiTests.hpp"
+#include "vktMeshShaderPropertyTests.hpp"
+#include "vktMeshShaderBuiltinTests.hpp"
+#include "vktMeshShaderMiscTests.hpp"
+
+#include "deUniquePtr.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+}
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
+{
+ GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "mesh_shader", "Mesh Shader Tests"));
+ GroupPtr nvGroup (new tcu::TestCaseGroup(testCtx, "nv", "Tests for VK_NV_mesh_shader"));
+
+ nvGroup->addChild(createMeshShaderSmokeTests(testCtx));
+ nvGroup->addChild(createMeshShaderApiTests(testCtx));
+ nvGroup->addChild(createMeshShaderSyncTests(testCtx));
+ nvGroup->addChild(createMeshShaderPropertyTests(testCtx));
+ nvGroup->addChild(createMeshShaderBuiltinTests(testCtx));
+ nvGroup->addChild(createMeshShaderMiscTests(testCtx));
+
+ mainGroup->addChild(nvGroup.release());
+ return mainGroup.release();
+}
+
+} // MeshShader
+} // vkt
--- /dev/null
+#ifndef _VKTMESHSHADERTESTS_HPP
+#define _VKTMESHSHADERTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Mesh Shader Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx);
+
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERTESTS_HPP
return bufmem;
}
-vk::Move<vk::VkShaderModule> createShaderModule (const vk::DeviceInterface& deviceInterface,
- vk::VkDevice device,
- const vk::ProgramBinary& binary)
-{
- DE_ASSERT(binary.getFormat() == vk::PROGRAM_FORMAT_SPIRV);
-
- const struct vk::VkShaderModuleCreateInfo shaderModuleInfo =
- {
- vk::VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
- DE_NULL,
- 0,
- static_cast<deUintptr>(binary.getSize()),
- reinterpret_cast<const deUint32*>(binary.getBinary()),
- };
-
- return createShaderModule(deviceInterface, device, &shaderModuleInfo);
-}
-
// Make sure the length of the following vectors is a multiple of 4. This will make sure operands can be reused for vectorized tests.
const OperandsVector<double> DOUBLE_OPERANDS =
{
"VK_EXT_extended_dynamic_state2",
"VK_NV_ray_tracing",
"VK_NV_inherited_viewport_scissor",
+ "VK_NV_mesh_shader",
"VK_AMD_mixed_attachment_samples",
"VK_AMD_shader_fragment_mask",
"VK_AMD_buffer_marker",
#include "vktPostmortemTests.hpp"
#include "vktFragmentShadingRateTests.hpp"
#include "vktReconvergenceTests.hpp"
+#include "vktMeshShaderTests.hpp"
#include <vector>
#include <sstream>
addChild(RayQuery::createTests (m_testCtx));
addChild(FragmentShadingRate::createTests (m_testCtx));
addChild(Reconvergence::createTests (m_testCtx, false));
+ addChild(MeshShader::createTests (m_testCtx));
}
void ExperimentalTestPackage::init (void)
vk-default/info.txt
vk-default/memory-model.txt
vk-default/memory.txt
+vk-default/mesh-shader.txt
vk-default/multiview.txt
vk-default/pipeline.txt
vk-default/protected-memory.txt
--- /dev/null
+dEQP-VK.mesh_shader.nv.smoke.mesh_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.nv.smoke.task_only_shader_triangle
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_1.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_2.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_32.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw.draw_count_64.no_indirect_args.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_0.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_0.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_1.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_2.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_32.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_0_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_normal.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect.draw_count_64.offset_alt_stride_large.no_count_limit.no_count_offset.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_0.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_1.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_2.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_32.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_0_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_normal.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_buffer.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_0.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.no_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_zero
+dEQP-VK.mesh_shader.nv.api.draw_indirect_count.draw_count_64.offset_alt_stride_large.count_limit_max_count.count_offset_alt.with_task_shader.first_task_nonzero
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_task.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.memory_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.uniform_buffer.specific_barrier.host_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.memory_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.host_to_mesh.storage_buffer.specific_barrier.host_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_task.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.memory_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.uniform_buffer.specific_barrier.transfer_write_uniform_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_buffer.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.memory_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.sampled_image.specific_barrier.transfer_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_buffer.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.subpass_dependency.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_buffer.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.memory_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_transfer.storage_image.specific_barrier.shader_write_transfer_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.memory_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_host.storage_buffer.specific_barrier.shader_write_host_read
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_task
+dEQP-VK.mesh_shader.nv.property.max_draw_mesh_tasks_count_with_mesh
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_task_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_output_count
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_invocations
+dEQP-VK.mesh_shader.nv.property.max_mesh_work_group_size
+dEQP-VK.mesh_shader.nv.property.max_task_total_memory_size
+dEQP-VK.mesh_shader.nv.property.max_mesh_total_memory_size
+dEQP-VK.mesh_shader.nv.builtin.position
+dEQP-VK.mesh_shader.nv.builtin.point_size
+dEQP-VK.mesh_shader.nv.builtin.clip_distance
+dEQP-VK.mesh_shader.nv.builtin.cull_distance
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_glsl
+dEQP-VK.mesh_shader.nv.builtin.primitive_id_spirv
+dEQP-VK.mesh_shader.nv.builtin.layer
+dEQP-VK.mesh_shader.nv.builtin.layer_shared
+dEQP-VK.mesh_shader.nv.builtin.viewport_index
+dEQP-VK.mesh_shader.nv.builtin.viewport_index_shared
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.work_group_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_task
+dEQP-VK.mesh_shader.nv.builtin.local_invocation_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.global_invocation_id_in_task
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_mesh
+dEQP-VK.mesh_shader.nv.builtin.draw_index_in_task
+dEQP-VK.mesh_shader.nv.misc.complex_task_data
+dEQP-VK.mesh_shader.nv.misc.single_point
+dEQP-VK.mesh_shader.nv.misc.single_line
+dEQP-VK.mesh_shader.nv.misc.single_triangle
+dEQP-VK.mesh_shader.nv.misc.max_points
+dEQP-VK.mesh_shader.nv.misc.max_lines
+dEQP-VK.mesh_shader.nv.misc.max_triangles
+dEQP-VK.mesh_shader.nv.misc.many_task_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.many_task_mesh_work_groups
+dEQP-VK.mesh_shader.nv.misc.no_points
+dEQP-VK.mesh_shader.nv.misc.no_lines
+dEQP-VK.mesh_shader.nv.misc.no_triangles
+dEQP-VK.mesh_shader.nv.misc.no_points_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_lines_extra_writes
+dEQP-VK.mesh_shader.nv.misc.no_triangles_extra_writes
+dEQP-VK.mesh_shader.nv.misc.barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_task
+dEQP-VK.mesh_shader.nv.misc.memory_barrier_shared_in_mesh
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_task
+dEQP-VK.mesh_shader.nv.misc.group_memory_barrier_in_mesh
+dEQP-VK.mesh_shader.nv.misc.custom_attributes
+dEQP-VK.mesh_shader.nv.misc.custom_attributes_and_task_shader
+dEQP-VK.mesh_shader.nv.misc.push_constant
+dEQP-VK.mesh_shader.nv.misc.push_constant_and_task_shader
VK_KHR_format_feature_flags2 DEVICE
VK_KHR_maintenance4 DEVICE
VK_EXT_border_color_swizzle DEVICE
+VK_NV_mesh_shader DEVICE
setString(str);
}
+StringTemplate::StringTemplate (StringTemplate&& other)
+ : m_template(std::move(other.m_template))
+{}
+
StringTemplate::~StringTemplate (void)
{
}
public:
StringTemplate (void);
StringTemplate (const std::string& str);
+ StringTemplate (StringTemplate&& other);
~StringTemplate (void);
void setString (const std::string& str);
0,
0,
0,
- 0
+ 0,
+ 0,
+ 0,
};
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
0,
0,
0,
- 0
+ 0,
+ 0,
+ 0,
};
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typebitMap) == SHADERTYPE_LAST);
DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typebitMap)));
QP_SHADER_TYPE_MISS,
QP_SHADER_TYPE_INTERSECTION,
QP_SHADER_TYPE_CALLABLE,
+ QP_SHADER_TYPE_TASK,
+ QP_SHADER_TYPE_MESH,
};
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_typeMap) == SHADERTYPE_LAST);
DE_ASSERT(de::inBounds<int>(shaderType, 0, DE_LENGTH_OF_ARRAY(s_typeMap)));
{ "MissCompileTime", "Miss shader compile time" },
{ "IntersectionCompileTime", "Intersection shader compile time" },
{ "CallableCompileTime", "Callable shader compile time" },
+ { "TaskCompileTime", "Task shader compile time" },
+ { "MeshCompileTime", "Mesh shader compile time" },
};
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_compileTimeDesc) == SHADERTYPE_LAST);
CallableSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_CALLABLE, source_) {}
};
+struct TaskSource : public ShaderSource
+{
+ TaskSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_TASK, source_) {}
+};
+
+struct MeshSource : public ShaderSource
+{
+ MeshSource(const std::string& source_) : ShaderSource(glu::SHADERTYPE_MESH, source_) {}
+};
+
struct ProgramSources
{
std::vector<std::string> sources[SHADERTYPE_LAST];
"miss",
"intersection",
"callable",
+ "task",
+ "mesh",
};
DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == SHADERTYPE_LAST);
SHADERTYPE_INTERSECTION,
SHADERTYPE_CALLABLE,
+ SHADERTYPE_TASK,
+ SHADERTYPE_MESH,
+
SHADERTYPE_LAST
};
{ QP_SHADER_TYPE_MISS, "MissShader" },
{ QP_SHADER_TYPE_INTERSECTION, "IntersectionShader" },
{ QP_SHADER_TYPE_CALLABLE, "CallableShader" },
+ { QP_SHADER_TYPE_TASK, "TaskShader" },
+ { QP_SHADER_TYPE_MESH, "MeshShader" },
{ QP_SHADER_TYPE_LAST, DE_NULL }
};
QP_SHADER_TYPE_MISS,
QP_SHADER_TYPE_INTERSECTION,
QP_SHADER_TYPE_CALLABLE,
+ QP_SHADER_TYPE_TASK,
+ QP_SHADER_TYPE_MESH,
QP_SHADER_TYPE_LAST
} qpShaderType;
glu::SHADERTYPE_TESSELLATION_EVALUATION,
glu::SHADERTYPE_GEOMETRY,
glu::SHADERTYPE_FRAGMENT,
+
glu::SHADERTYPE_RAYGEN,
glu::SHADERTYPE_ANY_HIT,
glu::SHADERTYPE_CLOSEST_HIT,
glu::SHADERTYPE_MISS,
glu::SHADERTYPE_INTERSECTION,
glu::SHADERTYPE_CALLABLE,
+
+ glu::SHADERTYPE_TASK,
+ glu::SHADERTYPE_MESH,
};
// s_shaderStageOrder does not contain ShaderType_LAST