Additional VK_EXT_mesh_shader tests
authorRicardo Garcia <rgarcia@igalia.com>
Mon, 27 Jun 2022 14:44:05 +0000 (16:44 +0200)
committerRicardo Garcia <rgarcia@igalia.com>
Tue, 16 Aug 2022 10:39:48 +0000 (12:39 +0200)
This commit adds more VK_EXT_mesh_shader tests and corrections after the
main branch was merged to the development branch.

It also reworks the NV and EXT synchronization tests because they were
attempting to use subpass dependencies to synchronize reads and writes
in the same draw call, which is not possible.

New, affected and renamed tests:
dEQP-VK.mesh_shader.ext.smoke.*
dEQP-VK.mesh_shader.ext.properties.*
dEQP-VK.mesh_shader.*.synchronization.*
dEQP-VK.mesh_shader.ext.provoking_vertex.*
dEQP-VK.fragment_shading_rate.*.basic.*

VK-GL-CTS issue: 2991
Components: Vulkan

Change-Id: Iaccf88e08dc319c35f6c937a269c6d9406ed2531

19 files changed:
AndroidGen.mk
android/cts/main/vk-master-2022-03-01/mesh-shader.txt
android/cts/main/vk-master/mesh-shader.txt
external/fetch_sources.py
external/vulkancts/framework/vulkan/generated/vulkan/vkBasicTypes.inl
external/vulkancts/framework/vulkan/generated/vulkan/vkDeviceFeatureTest.inl
external/vulkancts/framework/vulkan/generated/vulkan/vkStrUtilImpl.inl
external/vulkancts/framework/vulkan/generated/vulkan/vkStructTypes.inl
external/vulkancts/framework/vulkan/generated/vulkan/vkVulkan_c.inl
external/vulkancts/modules/vulkan/fragment_shading_rate/vktFragmentShadingRateBasic.cpp
external/vulkancts/modules/vulkan/mesh_shader/CMakeLists.txt
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderPropertyTestsEXT.cpp
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSmokeTestsEXT.cpp
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSyncTests.cpp
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSyncTestsEXT.cpp
external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderTests.cpp
external/vulkancts/mustpass/main/vk-default/mesh-shader.txt

index 68e5c09..2397730 100644 (file)
@@ -229,6 +229,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderMiscTestsEXT.cpp \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderPropertyTests.cpp \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderPropertyTestsEXT.cpp \
+       external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.cpp \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSmokeTests.cpp \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSmokeTestsEXT.cpp \
        external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderSyncTests.cpp \
index cc38064..ed3e2fd 100644 (file)
@@ -472,18 +472,18 @@ dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_bar
 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_mesh.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.memory_barrier.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_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.memory_barrier.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
@@ -1121,15 +1121,35 @@ dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.task_mesh
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.task_mesh
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle_rasterization_disabled
-dEQP-VK.mesh_shader.ext.smoke.mesh_task_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.task_only_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.partial_usage
-dEQP-VK.mesh_shader.ext.smoke.partial_usage_without_compaction
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x2
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.shared_frag_library
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.shared_frag_library
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader_secondary_cmd
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader
@@ -3036,3 +3056,11 @@ dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000100
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000001
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000000
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last_first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last_first
index cc38064..ed3e2fd 100644 (file)
@@ -472,18 +472,18 @@ dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_bar
 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_mesh.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.memory_barrier.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_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.memory_barrier.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
@@ -1121,15 +1121,35 @@ dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.task_mesh
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.task_mesh
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle_rasterization_disabled
-dEQP-VK.mesh_shader.ext.smoke.mesh_task_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.task_only_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.partial_usage
-dEQP-VK.mesh_shader.ext.smoke.partial_usage_without_compaction
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x2
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.shared_frag_library
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.shared_frag_library
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader_secondary_cmd
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader
@@ -3036,3 +3056,11 @@ dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000100
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000001
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000000
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last_first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last_first
index 559b2ee..cc203a5 100644 (file)
@@ -315,7 +315,7 @@ PACKAGES = [
        GitRepo(
                "https://gitlab.khronos.org/vulkan/vulkan.git",
                "git@gitlab.khronos.org:vulkan/vulkan.git",
-               "2eb0a9e794e318bf372d0f98296174bfeb93b8b7",
+               "8858ca756472350d8d2b6ee6466fbd118c72c3a1",
                "vulkan-docs"),
        GitRepo(
                "https://github.com/google/amber.git",
index 6173196..9040b12 100644 (file)
@@ -1431,6 +1431,7 @@ enum VkQueryType
        VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV                                                  = 1000165000,
        VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL                                                                                   = 1000210000,
        VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR                                                   = 1000299000,
+       VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT                                                                             = 1000328000,
        VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT                                                                                  = 1000382000,
        VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR    = 1000386000,
        VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR                                                                   = 1000386001,
@@ -3137,6 +3138,8 @@ enum VkQueryPipelineStatisticFlagBits
        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT                     = 0x00000100,
        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT      = 0x00000200,
        VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT                                      = 0x00000400,
+       VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT                                     = 0x00000800,
+       VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT                                     = 0x00001000,
        VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM                                                          = 0x7FFFFFFF,
 };
 typedef uint32_t VkQueryPipelineStatisticFlags;
index f8a5af0..05fdf1a 100644 (file)
@@ -1372,9 +1372,10 @@ if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(de
                FEATURE_ITEM (VkPhysicalDeviceMeshShaderFeaturesEXT, meshShader),
                FEATURE_ITEM (VkPhysicalDeviceMeshShaderFeaturesEXT, multiviewMeshShader),
                FEATURE_ITEM (VkPhysicalDeviceMeshShaderFeaturesEXT, primitiveFragmentShadingRateMeshShader),
+               FEATURE_ITEM (VkPhysicalDeviceMeshShaderFeaturesEXT, meshShaderQueries),
        };
        auto* supportedFeatures = reinterpret_cast<const VkPhysicalDeviceMeshShaderFeaturesEXT*>(featuresStruct);
-       checkFeatures(vkp, instance, instanceDriver, physicalDevice, 4, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, &extensionNames, emptyDeviceFeatures, isSubProcess);
+       checkFeatures(vkp, instance, instanceDriver, physicalDevice, 5, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, &extensionNames, emptyDeviceFeatures, isSubProcess);
 }
 
 if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<VkPhysicalDevicePortabilitySubsetFeaturesKHR>()))
index d602668..76ed577 100644 (file)
@@ -1233,6 +1233,7 @@ const char* getQueryTypeName (VkQueryType value)
                case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV:                                            return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_NV";
                case VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL:                                                                                     return "VK_QUERY_TYPE_PERFORMANCE_QUERY_INTEL";
                case VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR:                                                     return "VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR";
+               case VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT:                                                                       return "VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT";
                case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:                                                                            return "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT";
                case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR:      return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR";
                case VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR:                                                                     return "VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR";
@@ -3223,6 +3224,8 @@ tcu::Format::Bitfield<32> getQueryPipelineStatisticFlagsStr (VkQueryPipelineStat
                tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT,                       "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT"),
                tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT,        "VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT"),
                tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT,                                        "VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT"),
+               tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT,                                       "VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT"),
+               tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT,                                       "VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT"),
                tcu::Format::BitDesc(VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM,                                                            "VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM"),
        };
        return tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));
@@ -13027,6 +13030,7 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMeshShaderFeatu
        s << "\tmeshShader = " << value.meshShader << '\n';
        s << "\tmultiviewMeshShader = " << value.multiviewMeshShader << '\n';
        s << "\tprimitiveFragmentShadingRateMeshShader = " << value.primitiveFragmentShadingRateMeshShader << '\n';
+       s << "\tmeshShaderQueries = " << value.meshShaderQueries << '\n';
        s << '}';
        return s;
 }
@@ -13064,7 +13068,6 @@ std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceMeshShaderPrope
        s << "\tprefersLocalInvocationPrimitiveOutput = " << value.prefersLocalInvocationPrimitiveOutput << '\n';
        s << "\tprefersCompactVertexOutput = " << value.prefersCompactVertexOutput << '\n';
        s << "\tprefersCompactPrimitiveOutput = " << value.prefersCompactPrimitiveOutput << '\n';
-       s << "\tmeshShadingAffectedPipelineStatistics = " << getQueryPipelineStatisticFlagsStr(value.meshShadingAffectedPipelineStatistics) << '\n';
        s << '}';
        return s;
 }
index d7225d4..a27d333 100644 (file)
@@ -6191,41 +6191,41 @@ struct VkPhysicalDeviceMeshShaderFeaturesEXT
        VkBool32                meshShader;
        VkBool32                multiviewMeshShader;
        VkBool32                primitiveFragmentShadingRateMeshShader;
+       VkBool32                meshShaderQueries;
 };
 
 struct VkPhysicalDeviceMeshShaderPropertiesEXT
 {
-       VkStructureType                                 sType;
-       void*                                                   pNext;
-       uint32_t                                                maxTaskWorkGroupTotalCount;
-       uint32_t                                                maxTaskWorkGroupCount[3];
-       uint32_t                                                maxTaskWorkGroupInvocations;
-       uint32_t                                                maxTaskWorkGroupSize[3];
-       uint32_t                                                maxTaskPayloadSize;
-       uint32_t                                                maxTaskSharedMemorySize;
-       uint32_t                                                maxTaskPayloadAndSharedMemorySize;
-       uint32_t                                                maxMeshWorkGroupTotalCount;
-       uint32_t                                                maxMeshWorkGroupCount[3];
-       uint32_t                                                maxMeshWorkGroupInvocations;
-       uint32_t                                                maxMeshWorkGroupSize[3];
-       uint32_t                                                maxMeshSharedMemorySize;
-       uint32_t                                                maxMeshPayloadAndSharedMemorySize;
-       uint32_t                                                maxMeshOutputMemorySize;
-       uint32_t                                                maxMeshPayloadAndOutputMemorySize;
-       uint32_t                                                maxMeshOutputComponents;
-       uint32_t                                                maxMeshOutputVertices;
-       uint32_t                                                maxMeshOutputPrimitives;
-       uint32_t                                                maxMeshOutputLayers;
-       uint32_t                                                maxMeshMultiviewViewCount;
-       uint32_t                                                meshOutputPerVertexGranularity;
-       uint32_t                                                meshOutputPerPrimitiveGranularity;
-       uint32_t                                                maxPreferredTaskWorkGroupInvocations;
-       uint32_t                                                maxPreferredMeshWorkGroupInvocations;
-       VkBool32                                                prefersLocalInvocationVertexOutput;
-       VkBool32                                                prefersLocalInvocationPrimitiveOutput;
-       VkBool32                                                prefersCompactVertexOutput;
-       VkBool32                                                prefersCompactPrimitiveOutput;
-       VkQueryPipelineStatisticFlags   meshShadingAffectedPipelineStatistics;
+       VkStructureType sType;
+       void*                   pNext;
+       uint32_t                maxTaskWorkGroupTotalCount;
+       uint32_t                maxTaskWorkGroupCount[3];
+       uint32_t                maxTaskWorkGroupInvocations;
+       uint32_t                maxTaskWorkGroupSize[3];
+       uint32_t                maxTaskPayloadSize;
+       uint32_t                maxTaskSharedMemorySize;
+       uint32_t                maxTaskPayloadAndSharedMemorySize;
+       uint32_t                maxMeshWorkGroupTotalCount;
+       uint32_t                maxMeshWorkGroupCount[3];
+       uint32_t                maxMeshWorkGroupInvocations;
+       uint32_t                maxMeshWorkGroupSize[3];
+       uint32_t                maxMeshSharedMemorySize;
+       uint32_t                maxMeshPayloadAndSharedMemorySize;
+       uint32_t                maxMeshOutputMemorySize;
+       uint32_t                maxMeshPayloadAndOutputMemorySize;
+       uint32_t                maxMeshOutputComponents;
+       uint32_t                maxMeshOutputVertices;
+       uint32_t                maxMeshOutputPrimitives;
+       uint32_t                maxMeshOutputLayers;
+       uint32_t                maxMeshMultiviewViewCount;
+       uint32_t                meshOutputPerVertexGranularity;
+       uint32_t                meshOutputPerPrimitiveGranularity;
+       uint32_t                maxPreferredTaskWorkGroupInvocations;
+       uint32_t                maxPreferredMeshWorkGroupInvocations;
+       VkBool32                prefersLocalInvocationVertexOutput;
+       VkBool32                prefersLocalInvocationPrimitiveOutput;
+       VkBool32                prefersCompactVertexOutput;
+       VkBool32                prefersCompactPrimitiveOutput;
 };
 
 struct VkDrawMeshTasksIndirectCommandEXT
index 0eb70c8..d255570 100644 (file)
@@ -2612,6 +2612,7 @@ typedef enum VkQueryType {
 #ifdef VK_ENABLE_BETA_EXTENSIONS
     VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR = 1000299000,
 #endif
+    VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT = 1000328000,
     VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT = 1000382000,
     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR = 1000386000,
     VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR = 1000386001,
@@ -3282,6 +3283,8 @@ typedef enum VkQueryPipelineStatisticFlagBits {
     VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
     VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
     VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
+    VK_QUERY_PIPELINE_STATISTIC_TASK_SHADER_INVOCATIONS_BIT_EXT = 0x00000800,
+    VK_QUERY_PIPELINE_STATISTIC_MESH_SHADER_INVOCATIONS_BIT_EXT = 0x00001000,
     VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueryPipelineStatisticFlagBits;
 typedef VkFlags VkQueryPipelineStatisticFlags;
@@ -15684,40 +15687,40 @@ typedef struct VkPhysicalDeviceMeshShaderFeaturesEXT {
     VkBool32           meshShader;
     VkBool32           multiviewMeshShader;
     VkBool32           primitiveFragmentShadingRateMeshShader;
+    VkBool32           meshShaderQueries;
 } VkPhysicalDeviceMeshShaderFeaturesEXT;
 
 typedef struct VkPhysicalDeviceMeshShaderPropertiesEXT {
-    VkStructureType                  sType;
-    void*                            pNext;
-    deUint32                         maxTaskWorkGroupTotalCount;
-    deUint32                         maxTaskWorkGroupCount[3];
-    deUint32                         maxTaskWorkGroupInvocations;
-    deUint32                         maxTaskWorkGroupSize[3];
-    deUint32                         maxTaskPayloadSize;
-    deUint32                         maxTaskSharedMemorySize;
-    deUint32                         maxTaskPayloadAndSharedMemorySize;
-    deUint32                         maxMeshWorkGroupTotalCount;
-    deUint32                         maxMeshWorkGroupCount[3];
-    deUint32                         maxMeshWorkGroupInvocations;
-    deUint32                         maxMeshWorkGroupSize[3];
-    deUint32                         maxMeshSharedMemorySize;
-    deUint32                         maxMeshPayloadAndSharedMemorySize;
-    deUint32                         maxMeshOutputMemorySize;
-    deUint32                         maxMeshPayloadAndOutputMemorySize;
-    deUint32                         maxMeshOutputComponents;
-    deUint32                         maxMeshOutputVertices;
-    deUint32                         maxMeshOutputPrimitives;
-    deUint32                         maxMeshOutputLayers;
-    deUint32                         maxMeshMultiviewViewCount;
-    deUint32                         meshOutputPerVertexGranularity;
-    deUint32                         meshOutputPerPrimitiveGranularity;
-    deUint32                         maxPreferredTaskWorkGroupInvocations;
-    deUint32                         maxPreferredMeshWorkGroupInvocations;
-    VkBool32                         prefersLocalInvocationVertexOutput;
-    VkBool32                         prefersLocalInvocationPrimitiveOutput;
-    VkBool32                         prefersCompactVertexOutput;
-    VkBool32                         prefersCompactPrimitiveOutput;
-    VkQueryPipelineStatisticFlags    meshShadingAffectedPipelineStatistics;
+    VkStructureType    sType;
+    void*              pNext;
+    deUint32           maxTaskWorkGroupTotalCount;
+    deUint32           maxTaskWorkGroupCount[3];
+    deUint32           maxTaskWorkGroupInvocations;
+    deUint32           maxTaskWorkGroupSize[3];
+    deUint32           maxTaskPayloadSize;
+    deUint32           maxTaskSharedMemorySize;
+    deUint32           maxTaskPayloadAndSharedMemorySize;
+    deUint32           maxMeshWorkGroupTotalCount;
+    deUint32           maxMeshWorkGroupCount[3];
+    deUint32           maxMeshWorkGroupInvocations;
+    deUint32           maxMeshWorkGroupSize[3];
+    deUint32           maxMeshSharedMemorySize;
+    deUint32           maxMeshPayloadAndSharedMemorySize;
+    deUint32           maxMeshOutputMemorySize;
+    deUint32           maxMeshPayloadAndOutputMemorySize;
+    deUint32           maxMeshOutputComponents;
+    deUint32           maxMeshOutputVertices;
+    deUint32           maxMeshOutputPrimitives;
+    deUint32           maxMeshOutputLayers;
+    deUint32           maxMeshMultiviewViewCount;
+    deUint32           meshOutputPerVertexGranularity;
+    deUint32           meshOutputPerPrimitiveGranularity;
+    deUint32           maxPreferredTaskWorkGroupInvocations;
+    deUint32           maxPreferredMeshWorkGroupInvocations;
+    VkBool32           prefersLocalInvocationVertexOutput;
+    VkBool32           prefersLocalInvocationPrimitiveOutput;
+    VkBool32           prefersCompactVertexOutput;
+    VkBool32           prefersCompactPrimitiveOutput;
 } VkPhysicalDeviceMeshShaderPropertiesEXT;
 
 typedef struct VkDrawMeshTasksIndirectCommandEXT {
index 3548c84..c72f6c4 100644 (file)
@@ -2709,9 +2709,18 @@ void FSRTestInstance::drawCommands(VkCommandBuffer                                                                       cmdBuffer,
        const VkDevice                  device  = m_context.getDevice();
        const bool                              useMesh = (meshShader != DE_NULL);
 
-       VkFlags allShaderStages = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
-       if (m_data.geometryShader)
-               allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
+       VkFlags allShaderStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
+
+       if (useMesh)
+       {
+               allShaderStages |= VK_SHADER_STAGE_MESH_BIT_EXT;
+       }
+       else
+       {
+               allShaderStages |= VK_SHADER_STAGE_VERTEX_BIT;
+               if (m_data.geometryShader)
+                       allShaderStages |= VK_SHADER_STAGE_GEOMETRY_BIT;
+       }
 
        VkPipelineCreateFlags pipelineCreateFlags = (VkPipelineCreateFlags)0;
        if (m_data.groupParams->useDynamicRendering)
@@ -2771,6 +2780,7 @@ void FSRTestInstance::drawCommands(VkCommandBuffer                                                                        cmdBuffer,
                                                                          multisampleState,
                                                                          shadingRateState)
                        .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
+                       .setMonolithicPipelineLayout(pipelineLayout)
                        .buildPipeline();
 
                vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
@@ -2856,6 +2866,7 @@ void FSRTestInstance::drawCommands(VkCommandBuffer                                                                        cmdBuffer,
                                                                                  multisampleState,
                                                                                  shadingRateState)
                                .setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
+                               .setMonolithicPipelineLayout(pipelineLayout)
                                .buildPipeline();
 
                        vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
index 9a3eec7..d7d248a 100644 (file)
@@ -34,6 +34,8 @@ set(DEQP_VK_MESH_SHADER_SRCS
        vktMeshShaderPropertyTestsEXT.hpp
        vktMeshShaderConditionalRenderingTestsEXT.cpp
        vktMeshShaderConditionalRenderingTestsEXT.hpp
+       vktMeshShaderProvokingVertexTestsEXT.cpp
+       vktMeshShaderProvokingVertexTestsEXT.hpp
        vktMeshShaderUtil.cpp
        vktMeshShaderUtil.hpp
        )
index 51edbbd..489c693 100644 (file)
@@ -1966,14 +1966,15 @@ MaxMeshOutputSizeCase::ParamsFromContext MaxMeshOutputSizeCase::getParamsFromCon
        }
 
        // This uses the equation in "Mesh Shader Output" spec section. Note per-vertex data already has gl_Position and gl_PointSize.
+       // Also note gl_PointSize uses 1 effective location (4 scalar components) despite being a float.
        const auto granularity                  = ((m_params.locationType == LocationType::PER_PRIMITIVE)
                                                                        ? meshProperties.meshOutputPerPrimitiveGranularity
                                                                        : meshProperties.meshOutputPerVertexGranularity);
        const auto actualPoints                 = de::roundUp(kMaxPoints, granularity);
        const auto sizeMultiplier               = actualPoints * kUvec4Size;
-       const auto builtinDataSize              = (16u/*gl_Position*/ + 4u/*gl_PointSize*/) * actualPoints;
+       const auto builtinDataSize              = (16u/*gl_Position*/ + 16u/*gl_PointSize*/) * actualPoints;
        const auto locationsDataSize    = (outSize - builtinDataSize) / numViewFactor;
-       const auto maxTotalLocations    = meshProperties.maxMeshOutputComponents / kUvec4Comp;
+       const auto maxTotalLocations    = meshProperties.maxMeshOutputComponents / kUvec4Comp - 2u; // gl_Position and gl_PointSize use 1 location each.
        const auto locationCount                = std::min(locationsDataSize / sizeMultiplier, maxTotalLocations);
 
        ParamsFromContext params;
diff --git a/external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.cpp b/external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.cpp
new file mode 100644 (file)
index 0000000..e12e769
--- /dev/null
@@ -0,0 +1,485 @@
+/*------------------------------------------------------------------------
+ * 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 Tests mixing VK_EXT_mesh_shader and VK_EXT_provoking_vertex
+ *//*--------------------------------------------------------------------*/
+
+#include "vktMeshShaderProvokingVertexTestsEXT.hpp"
+#include "vktTestCase.hpp"
+#include "vktMeshShaderUtil.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkObjUtil.hpp"
+#include "vkBufferWithMemory.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkBarrierUtil.hpp"
+
+#include "deUniquePtr.hpp"
+
+#include <sstream>
+#include <vector>
+#include <string>
+
+namespace vkt
+{
+namespace MeshShader
+{
+
+namespace
+{
+
+using namespace vk;
+
+enum class Geometry
+{
+       LINES = 0,
+       TRIANGLES,
+};
+
+using ProvokingVertexModeVec = std::vector<VkProvokingVertexModeEXT>;
+
+std::vector<tcu::UVec4>        getLineColors                   (void)
+{
+       return std::vector<tcu::UVec4>{
+               tcu::UVec4(1, 1, 0, 1),
+               tcu::UVec4(1, 0, 1, 1),
+       };
+}
+
+std::vector<tcu::UVec4>        getTriangleColors               (void)
+{
+       return std::vector<tcu::UVec4>{
+               tcu::UVec4(1, 1, 0, 1),
+               tcu::UVec4(0, 1, 1, 1),
+               tcu::UVec4(1, 0, 1, 1),
+       };
+}
+
+std::vector<tcu::Vec4> getLinePositions                (void)
+{
+       return std::vector<tcu::Vec4>{
+               tcu::Vec4(-1.0, 0.0, 0.0, 1.0),
+               tcu::Vec4( 1.0, 0.0, 0.0, 1.0),
+       };
+}
+
+std::vector<tcu::Vec4> getTrianglePositions    (void)
+{
+       return std::vector<tcu::Vec4>{
+               tcu::Vec4(-1.0, -1.0, 0.0, 1.0),
+               tcu::Vec4(-1.0,  1.0, 0.0, 1.0),
+               tcu::Vec4( 3.0, -1.0, 0.0, 1.0),
+       };
+}
+
+tcu::Vec4                              getClearColor                   (void)
+{
+       return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+std::string getCaseName (Geometry geometry)
+{
+       switch (geometry)
+       {
+       case Geometry::LINES:           return "lines";
+       case Geometry::TRIANGLES:       return "triangles";
+       default:
+               DE_ASSERT(false);
+               break;
+       }
+       // Unreachable.
+       return "";
+}
+
+std::string getCaseName (const ProvokingVertexModeVec& modes)
+{
+       std::string caseName;
+
+       for (const auto& mode : modes)
+       {
+               caseName += (caseName.empty() ? "" : "_");
+               switch (mode)
+               {
+               case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT:         caseName += "first";    break;
+               case VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT:          caseName += "last";             break;
+               default:
+                       DE_ASSERT(false);
+                       break;
+               }
+       }
+
+       return caseName;
+}
+
+struct TestParams
+{
+       ProvokingVertexModeVec  provokingVertices;      // In the same render pass. In practice 1 or 2 elements.
+       Geometry                                geometryType;
+};
+
+class ProvokingVertexCase : public vkt::TestCase
+{
+public:
+                                       ProvokingVertexCase             (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
+                                               : vkt::TestCase (testCtx, name, description)
+                                               , m_params              (params)
+                                               {
+                                                       DE_ASSERT(m_params.provokingVertices.size() <= 2);
+                                               }
+
+       virtual                 ~ProvokingVertexCase    (void) {}
+
+       void                    initPrograms                    (vk::SourceCollections& programCollection) const override;
+       TestInstance*   createInstance                  (Context& context) const override;
+       void                    checkSupport                    (Context& context) const override;
+
+protected:
+       TestParams              m_params;
+};
+
+class ProvokingVertexInstance : public vkt::TestInstance
+{
+public:
+                                               ProvokingVertexInstance         (Context& context, const TestParams& params)
+                                                       : vkt::TestInstance     (context)
+                                                       , m_params                      (&params)
+                                                       {}
+       virtual                         ~ProvokingVertexInstance        (void) {}
+
+       tcu::TestStatus         iterate                                         (void) override;
+
+protected:
+       const TestParams*       m_params;
+};
+
+TestInstance* ProvokingVertexCase::createInstance (Context& context) const
+{
+       return new ProvokingVertexInstance(context, m_params);
+}
+
+void ProvokingVertexCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+       const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
+
+       std::ostringstream frag;
+       frag
+               << "#version 460\n"
+               << "layout (location=0) flat in uvec4 inColor;\n"
+               << "layout (location=0) out vec4 outColor;\n"
+               << "void main ()\n"
+               << "{\n"
+               << "    outColor = vec4(inColor);\n"
+               << "}\n"
+               ;
+       programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+
+       const auto isLines              = (m_params.geometryType == Geometry::LINES);
+       const auto vertCount    = (isLines ? 2u : 3u);
+       const auto geometryName = (isLines ? "lines" : "triangles");
+       const auto primIndices  = (isLines
+                                                       ? "gl_PrimitiveLineIndicesEXT[0] = uvec2(0, 1);"
+                                                       : "gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);");
+       const auto colors               = (isLines ? getLineColors() : getTriangleColors());
+       const auto positions    = (isLines ? getLinePositions() : getTrianglePositions());
+
+       std::ostringstream mesh;
+       mesh
+               << "#version 460\n"
+               << "#extension GL_EXT_mesh_shader : enable\n"
+               << "\n"
+               << "layout (local_size_x=" << vertCount << ", local_size_y=1, local_size_z=1) in;\n"
+               << "layout (" << geometryName << ") out;\n"
+               << "layout (max_vertices=" << vertCount << ", max_primitives=1) out;\n"
+               << "\n"
+               << "layout (push_constant, std430) uniform PushConstantBlock {\n"
+               << "    int layer;\n"
+               << "} pc;\n"
+               << "\n"
+               << "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
+               << "   int gl_Layer;\n"
+               << "} gl_MeshPrimitivesEXT[];\n"
+               << "\n"
+               << "uvec4 colors[] = uvec4[](\n"
+               ;
+
+       for (size_t i = 0; i < colors.size(); ++i)
+               mesh << "    uvec4" << colors[i] << ((i < colors.size() - 1) ? "," : "") << "\n";
+
+       mesh
+               << ");\n"
+               << "\n"
+               << "vec4 vertices[] = vec4[](\n"
+               ;
+
+       for (size_t i = 0; i < positions.size(); ++i)
+               mesh << "    vec4" << positions[i] << ((i < positions.size() - 1) ? "," : "") << "\n";
+
+       mesh
+               << ");\n"
+               << "\n"
+               << "layout (location=0) flat out uvec4 vtxColor[];\n"
+               << "\n"
+               << "void main ()\n"
+               << "{\n"
+               << "    SetMeshOutputsEXT(" << vertCount << ", 1);\n"
+               << "    gl_MeshVerticesEXT[gl_LocalInvocationIndex].gl_Position = vertices[gl_LocalInvocationIndex];\n"
+               << "    vtxColor[gl_LocalInvocationIndex] = colors[gl_LocalInvocationIndex];\n"
+               << "\n"
+               << "    if (gl_LocalInvocationIndex == 0u) {\n"
+               << "        " << primIndices << "\n"
+               << "        gl_MeshPrimitivesEXT[0].gl_Layer = pc.layer;\n"
+               << "    }\n"
+               << "}\n"
+               ;
+       programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << buildOptions;
+}
+
+void ProvokingVertexCase::checkSupport (Context& context) const
+{
+       checkTaskMeshShaderSupportEXT(context, false/*requireTask*/, true/*requireMesh*/);
+
+       context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
+
+       if (m_params.provokingVertices.size() > 1)
+       {
+               const auto& pvProperties = context.getProvokingVertexPropertiesEXT();
+               if (!pvProperties.provokingVertexModePerPipeline)
+                       TCU_THROW(NotSupportedError, "Switching provoking vertex modes in the same render pass not supported");
+       }
+}
+
+tcu::TestStatus ProvokingVertexInstance::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                      colorExtent             = makeExtent3D(1u, 1u, 1u);
+       const auto                      colorLayers             = static_cast<uint32_t>(m_params->provokingVertices.size());
+       const auto                      colorFormat             = VK_FORMAT_R8G8B8A8_UNORM;
+       const auto                      colorUsage              = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+       const auto                      tcuFormat               = mapVkFormat(colorFormat);
+       const auto                      pixelSize               = static_cast<uint32_t>(tcu::getPixelSize(tcuFormat));
+       const auto                      viewType                = ((colorLayers > 1u) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
+       const auto                      clearColor              = getClearColor();
+
+       // Color attachment.
+       const VkImageCreateInfo colorBufferInfo =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //      VkStructureType                 sType;
+               nullptr,                                                                //      const void*                             pNext;
+               0u,                                                                             //      VkImageCreateFlags              flags;
+               VK_IMAGE_TYPE_2D,                                               //      VkImageType                             imageType;
+               colorFormat,                                                    //      VkFormat                                format;
+               colorExtent,                                                    //      VkExtent3D                              extent;
+               1u,                                                                             //      uint32_t                                mipLevels;
+               colorLayers,                                                                            //      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;
+       };
+       ImageWithMemory colorBuffer     (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
+       const auto              colorSRR        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, colorLayers);
+       const auto              colorSRL        = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, colorLayers);
+       const auto              colorView       = makeImageView(vkd, device, colorBuffer.get(), viewType, colorFormat, colorSRR);
+
+       // Verification buffer.
+       const auto                      verificationBufferSize  = (pixelSize * colorExtent.width * colorExtent.height * colorLayers);
+       const auto                      verificationBufferInfo  = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       BufferWithMemory        verificationBuffer              (vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
+
+       // Push constant range.
+       const auto pcSize       = static_cast<uint32_t>(sizeof(int32_t));
+       const auto pcStages     = VK_SHADER_STAGE_MESH_BIT_EXT;
+       const auto pcRange      = makePushConstantRange(pcStages, 0u, pcSize);
+
+       // Pipeline layout.
+       const auto pipelineLayout = makePipelineLayout(vkd, device, DE_NULL, &pcRange);
+
+       // Modules.
+       const auto&     binaries        = m_context.getBinaryCollection();
+       const auto      meshModule      = createShaderModule(vkd, device, binaries.get("mesh"));
+       const auto      fragModule      = createShaderModule(vkd, device, binaries.get("frag"));
+
+       // Render pass and framebuffer.
+       const auto renderPass   = makeRenderPass(vkd, device, colorFormat);
+       const auto framebuffer  = makeFramebuffer(vkd, device, renderPass.get(), colorView.get(), colorExtent.width, colorExtent.height, colorLayers);
+
+       // Viewports and scissors.
+       const std::vector<VkViewport>   viewports       (1u, makeViewport(colorExtent));
+       const std::vector<VkRect2D>             scissors        (1u, makeRect2D(colorExtent));
+
+       // Pipelines with different provoking vertex modes.
+       std::vector<Move<VkPipeline>>   pipelines;
+
+       VkPipelineRasterizationProvokingVertexStateCreateInfoEXT pvInfo = initVulkanStructure();
+
+       const VkPipelineRasterizationStateCreateInfo rasterState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //      VkStructureType                                                 sType;
+               &pvInfo,                                                                                                                //      const void*                                                             pNext;
+               0u,                                                                                                                             //      VkPipelineRasterizationStateCreateFlags flags;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthClampEnable;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                rasterizerDiscardEnable;
+               VK_POLYGON_MODE_FILL,                                                                                   //      VkPolygonMode                                                   polygonMode;
+               VK_CULL_MODE_BACK_BIT,                                                                                  //      VkCullModeFlags                                                 cullMode;
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //      VkFrontFace                                                             frontFace;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthBiasEnable;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasConstantFactor;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasClamp;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasSlopeFactor;
+               1.0f,                                                                                                                   //      float                                                                   lineWidth;
+       };
+
+       for (const auto& pvMode : m_params->provokingVertices)
+       {
+               pvInfo.provokingVertexMode = pvMode;
+
+               pipelines.push_back(makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
+                       DE_NULL, meshModule.get(), fragModule.get(),
+                       renderPass.get(), viewports, scissors, 0u, &rasterState));
+       }
+
+       // 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);
+       beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
+       for (int32_t layer = 0; layer < static_cast<int32_t>(pipelines.size()); ++layer)
+       {
+               const auto& pipeline = pipelines.at(static_cast<size_t>(layer));
+               vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+               vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &layer);
+               vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
+       }
+       endRenderPass(vkd, cmdBuffer);
+       {
+               // Copy data to verification buffer.
+               const auto preTransferBarrier = makeImageMemoryBarrier(
+                       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);
+
+               cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preTransferBarrier);
+
+               const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
+               vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
+
+               const auto postTransferBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+
+               cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postTransferBarrier);
+       }
+       endCommandBuffer(vkd, cmdBuffer);
+       submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+       // Verify colors.
+       auto& verificationBufferAlloc   = verificationBuffer.getAllocation();
+       void* verificationBufferData    = verificationBufferAlloc.getHostPtr();
+       invalidateAlloc(vkd, device, verificationBufferAlloc);
+
+       const tcu::IVec3                                        iExtent                 (static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorLayers));
+       const tcu::ConstPixelBufferAccess       resultAccess    (tcuFormat, iExtent, verificationBufferData);
+
+       const auto isLines              = (m_params->geometryType == Geometry::LINES);
+       const auto colors               = (isLines ? getLineColors() : getTriangleColors());
+
+       bool    fail    = false;
+       auto&   log             = m_context.getTestContext().getLog();
+
+       for (int z = 0; z < iExtent.z(); ++z)
+       {
+               const auto              pvMode                          = m_params->provokingVertices.at(static_cast<size_t>(z));
+               const auto              expectedIntColor        = (pvMode == VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT ? colors.front() : colors.back());
+               const tcu::Vec4 expectedColor           (static_cast<float>(expectedIntColor.x()),
+                                                                                        static_cast<float>(expectedIntColor.y()),
+                                                                                        static_cast<float>(expectedIntColor.z()),
+                                                                                        static_cast<float>(expectedIntColor.w()));
+
+               for (int y = 0; y < iExtent.y(); ++y)
+                       for (int x = 0; x < iExtent.x(); ++x)
+                       {
+                               const auto resultColor = resultAccess.getPixel(x, y, z);
+                               if (resultColor != expectedColor)
+                               {
+                                       fail = true;
+                                       std::ostringstream msg;
+                                       msg << "Unexpected color found at layer " << z << " coordinates (" << x << ", " << y << "): expected " << expectedColor << " found " << resultColor;
+                                       log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
+                               }
+                       }
+       }
+
+       if (fail)
+               return tcu::TestStatus::fail("Failed -- check log for details");
+       return tcu::TestStatus::pass("Pass");
+}
+
+using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
+
+} // anonymous namespace
+
+tcu::TestCaseGroup* createMeshShaderProvokingVertexTestsEXT (tcu::TestContext& testCtx)
+{
+       const std::vector<Geometry> geometries { Geometry::LINES, Geometry::TRIANGLES };
+
+       const std::vector<ProvokingVertexModeVec> testModeCases
+       {
+               ProvokingVertexModeVec{VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT},
+               ProvokingVertexModeVec{VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT},
+               ProvokingVertexModeVec{VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT},
+               ProvokingVertexModeVec{VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT},
+       };
+
+       GroupPtr provokingVertexGroup (new tcu::TestCaseGroup(testCtx, "provoking_vertex", ""));
+
+       for (const auto& geometry : geometries)
+       {
+               const auto      geometryName    = getCaseName(geometry);
+               GroupPtr        geometryGroup   (new tcu::TestCaseGroup(testCtx, geometryName.c_str(), ""));
+
+               for (const auto& testModes : testModeCases)
+               {
+                       const auto      modeName = getCaseName(testModes);
+                       TestParams      params
+                       {
+                               testModes,      //      ProvokingVertexModeVec  provokingVertices;
+                               geometry,       //      Geometry                                geometryType;
+                       };
+
+                       geometryGroup->addChild(new ProvokingVertexCase(testCtx, modeName, "", params));
+               }
+
+               provokingVertexGroup->addChild(geometryGroup.release());
+       }
+
+       return provokingVertexGroup.release();
+}
+
+} // MeshShader
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.hpp b/external/vulkancts/modules/vulkan/mesh_shader/vktMeshShaderProvokingVertexTestsEXT.hpp
new file mode 100644 (file)
index 0000000..3c4c79c
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _VKTMESHSHADERPROVOKINGVERTEXTESTSEXT_HPP
+#define _VKTMESHSHADERPROVOKINGVERTEXTESTSEXT_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 Tests mixing VK_EXT_mesh_shader and VK_EXT_provoking_vertex
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace MeshShader
+{
+tcu::TestCaseGroup* createMeshShaderProvokingVertexTestsEXT (tcu::TestContext& testCtx);
+} // MeshShader
+} // vkt
+
+#endif // _VKTMESHSHADERPROVOKINGVERTEXTESTSEXT_HPP
index 54d2793..60ecc11 100644 (file)
@@ -35,6 +35,7 @@
 #include "vkCmdUtil.hpp"
 #include "vkImageUtil.hpp"
 #include "vkBarrierUtil.hpp"
+#include "vkPipelineConstructionUtil.hpp"
 
 #include "tcuImageCompare.hpp"
 #include "tcuTestLog.hpp"
@@ -83,16 +84,62 @@ tcu::Vec4 getClearColor ()
        return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
 }
 
+void makeMeshGraphicsPipeline (        GraphicsPipelineWrapper&                                                        maker,
+                                                               const VkPipelineLayout                                                          pipelineLayout,
+                                                               const VkShaderModule                                                            taskShader,
+                                                               const VkShaderModule                                                            meshShader,
+                                                               const VkShaderModule                                                            fragShader,
+                                                               const VkRenderPass                                                                      renderPass,
+                                                               const std::vector<VkViewport>&                                          viewports,
+                                                               const std::vector<VkRect2D>&                                            scissors,
+                                                               const uint32_t                                                                          subpass = 0u,
+                                                               const VkPipelineDepthStencilStateCreateInfo*            depthStencilStateCreateInfo = nullptr,
+                                                               VkPipelineFragmentShadingRateStateCreateInfoKHR*        fragmentShadingRateStateCreateInfo = nullptr)
+{
+#ifndef CTS_USES_VULKANSC
+       maker.setDefaultMultisampleState()
+                .setDefaultColorBlendState()
+                .setDefaultRasterizationState()
+                .setDefaultDepthStencilState()
+                .setupPreRasterizationMeshShaderState(viewports,
+                                                                                          scissors,
+                                                                                          pipelineLayout,
+                                                                                          renderPass,
+                                                                                          subpass,
+                                                                                          taskShader,
+                                                                                          meshShader)
+                .setupFragmentShaderState(pipelineLayout,
+                                                                  renderPass,
+                                                                  subpass,
+                                                                  fragShader,
+                                                                  depthStencilStateCreateInfo,
+                                                                  nullptr,
+                                                                  fragmentShadingRateStateCreateInfo)
+                .setupFragmentOutputState(renderPass, subpass)
+                .setMonolithicPipelineLayout(pipelineLayout)
+                .buildPipeline();
+#else
+       DE_ASSERT(false);
+#endif // CTS_USES_VULKANSC
+}
+
 struct MeshTriangleRendererParams
 {
-       std::vector<tcu::Vec4>  vertexCoords;
-       std::vector<uint32_t>   vertexIndices;
-       uint32_t                                taskCount;
-       tcu::Vec4                               expectedColor;
-       bool                                    rasterizationDisabled;
-
-       MeshTriangleRendererParams (std::vector<tcu::Vec4> vertexCoords_, std::vector<uint32_t> vertexIndices_, uint32_t taskCount_, const tcu::Vec4& expectedColor_, bool rasterizationDisabled_ = false)
-               : vertexCoords                  (std::move(vertexCoords_))
+       PipelineConstructionType        constructionType;
+       std::vector<tcu::Vec4>          vertexCoords;
+       std::vector<uint32_t>           vertexIndices;
+       uint32_t                                        taskCount;
+       tcu::Vec4                                       expectedColor;
+       bool                                            rasterizationDisabled;
+
+       MeshTriangleRendererParams (PipelineConstructionType    constructionType_,
+                                                               std::vector<tcu::Vec4>          vertexCoords_,
+                                                               std::vector<uint32_t>           vertexIndices_,
+                                                               uint32_t                                        taskCount_,
+                                                               const tcu::Vec4&                        expectedColor_,
+                                                               bool                                            rasterizationDisabled_ = false)
+               : constructionType              (constructionType_)
+               , vertexCoords                  (std::move(vertexCoords_))
                , vertexIndices                 (std::move(vertexIndices_))
                , taskCount                             (taskCount_)
                , expectedColor                 (expectedColor_)
@@ -100,15 +147,22 @@ struct MeshTriangleRendererParams
        {}
 
        MeshTriangleRendererParams (MeshTriangleRendererParams&& other)
-               : MeshTriangleRendererParams (std::move(other.vertexCoords), std::move(other.vertexIndices), other.taskCount, other.expectedColor, other.rasterizationDisabled)
+               : MeshTriangleRendererParams (other.constructionType,
+                                                                         std::move(other.vertexCoords),
+                                                                         std::move(other.vertexIndices),
+                                                                         other.taskCount,
+                                                                         other.expectedColor,
+                                                                         other.rasterizationDisabled)
        {}
 };
 
 class MeshOnlyTriangleCase : public vkt::TestCase
 {
 public:
-                                       MeshOnlyTriangleCase                    (tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool rasterizationDisabled = false)
+                                       MeshOnlyTriangleCase                    (tcu::TestContext& testCtx, const std::string& name, const std::string& description,
+                                                                                                        PipelineConstructionType constructionType, bool rasterizationDisabled = false)
                                                : vkt::TestCase                         (testCtx, name, description)
+                                               , m_constructionType            (constructionType)
                                                , m_rasterizationDisabled       (rasterizationDisabled)
                                                {}
        virtual                 ~MeshOnlyTriangleCase   (void) {}
@@ -118,30 +172,43 @@ public:
        void                    checkSupport                    (Context& context) const override;
 
 protected:
-       const bool              m_rasterizationDisabled;
+       const PipelineConstructionType  m_constructionType;
+       const bool                                              m_rasterizationDisabled;
 };
 
 class MeshTaskTriangleCase : public vkt::TestCase
 {
 public:
-                                       MeshTaskTriangleCase    (tcu::TestContext& testCtx, const std::string& name, const std::string& description) : vkt::TestCase (testCtx, name, description) {}
+                                       MeshTaskTriangleCase    (tcu::TestContext& testCtx, const std::string& name, const std::string& description, PipelineConstructionType constructionType)
+                                               : vkt::TestCase                 (testCtx, name, description)
+                                               , m_constructionType    (constructionType)
+                                               {}
        virtual                 ~MeshTaskTriangleCase   (void) {}
 
        void                    initPrograms                    (vk::SourceCollections& programCollection) const override;
        TestInstance*   createInstance                  (Context& context) const override;
        void                    checkSupport                    (Context& context) const override;
+
+protected:
+       const PipelineConstructionType m_constructionType;
 };
 
 // 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) {}
+                                       TaskOnlyTriangleCase    (tcu::TestContext& testCtx, const std::string& name, const std::string& description, PipelineConstructionType constructionType)
+                                               : vkt::TestCase                 (testCtx, name, description)
+                                               , m_constructionType    (constructionType)
+                                               {}
        virtual                 ~TaskOnlyTriangleCase   (void) {}
 
        void                    initPrograms                    (vk::SourceCollections& programCollection) const override;
        TestInstance*   createInstance                  (Context& context) const override;
        void                    checkSupport                    (Context& context) const override;
+
+protected:
+       const PipelineConstructionType m_constructionType;
 };
 
 class MeshTriangleRenderer : public vkt::TestInstance
@@ -159,16 +226,19 @@ protected:
 void MeshOnlyTriangleCase::checkSupport (Context& context) const
 {
        checkTaskMeshShaderSupportEXT(context, false, true);
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
 }
 
 void MeshTaskTriangleCase::checkSupport (Context& context) const
 {
        checkTaskMeshShaderSupportEXT(context, true, true);
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
 }
 
 void TaskOnlyTriangleCase::checkSupport (Context& context) const
 {
        checkTaskMeshShaderSupportEXT(context, true, true);
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
 }
 
 void MeshOnlyTriangleCase::initPrograms (SourceCollections& dst) const
@@ -374,7 +444,7 @@ TestInstance* MeshOnlyTriangleCase::createInstance (Context& context) const
        };
        const std::vector<uint32_t>             vertexIndices   = { 0u, 1u, 2u };
        const auto                                              expectedColor   = (m_rasterizationDisabled ? getClearColor() : tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
-       MeshTriangleRendererParams              params                  (std::move(vertexCoords), std::move(vertexIndices), 1u, expectedColor, m_rasterizationDisabled);
+       MeshTriangleRendererParams              params                  (m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 1u, expectedColor, m_rasterizationDisabled);
 
        return new MeshTriangleRenderer(context, std::move(params));
 }
@@ -389,7 +459,7 @@ TestInstance* MeshTaskTriangleCase::createInstance (Context& context) const
                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));
+       MeshTriangleRendererParams              params                  (m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 2u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
 
        return new MeshTriangleRenderer(context, std::move(params));
 }
@@ -404,7 +474,7 @@ TestInstance* TaskOnlyTriangleCase::createInstance (Context& context) const
        };
        const std::vector<uint32_t>             vertexIndices   = { 0u, 1u, 2u };
        // Note we expect the clear color.
-       MeshTriangleRendererParams              params                  (std::move(vertexCoords), std::move(vertexIndices), 1u, getClearColor());
+       MeshTriangleRendererParams              params                  (m_constructionType, std::move(vertexCoords), std::move(vertexIndices), 1u, getClearColor());
 
        return new MeshTriangleRenderer(context, std::move(params));
 }
@@ -519,9 +589,12 @@ tcu::TestStatus MeshTriangleRenderer::iterate ()
        const auto meshModule = createShaderModule(vkd, device, binaries.get("mesh"), 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);
+       std::vector<VkViewport> viewports               (1u, makeViewport(colorBufferExtent));
+       std::vector<VkRect2D>   scissors                (1u, makeRect2D(colorBufferExtent));
+       GraphicsPipelineWrapper pipelineMaker   (vkd, device, m_params.constructionType);
+
+       makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout.get(), taskModule.get(), meshModule.get(), fragModule.get(), renderPass.get(), viewports, scissors);
+       const auto                              pipeline                = pipelineMaker.getPipeline();
 
        // Command pool and buffer.
        const auto cmdPool                      = makeCommandPool(vkd, device, qIndex);
@@ -541,7 +614,7 @@ tcu::TestStatus MeshTriangleRenderer::iterate ()
        beginCommandBuffer(vkd, cmdBuffer);
        beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), getClearColor());
        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.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
        vkd.cmdDrawMeshTasksEXT(cmdBuffer, m_params.taskCount, 1u, 1u);
        endRenderPass(vkd, cmdBuffer);
 
@@ -571,19 +644,32 @@ VkExtent3D gradientImageExtent ()
        return makeExtent3D(256u, 256u, 1u);
 }
 
-void checkMeshSupport (Context& context, tcu::Maybe<FragmentSize> fragmentSize)
+struct GradientParams
+{
+       tcu::Maybe<FragmentSize> fragmentSize;
+       PipelineConstructionType constructionType;
+
+       GradientParams (const tcu::Maybe<FragmentSize>& fragmentSize_, PipelineConstructionType constructionType_)
+               : fragmentSize          (fragmentSize_)
+               , constructionType      (constructionType_)
+               {}
+};
+
+void checkMeshSupport (Context& context, GradientParams params)
 {
        checkTaskMeshShaderSupportEXT(context, false, true);
 
-       if (static_cast<bool>(fragmentSize))
+       if (static_cast<bool>(params.fragmentSize))
        {
                const auto& features = context.getMeshShaderFeaturesEXT();
                if (!features.primitiveFragmentShadingRateMeshShader)
                        TCU_THROW(NotSupportedError, "Primitive fragment shading rate not supported in mesh shaders");
        }
+
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.constructionType);
 }
 
-void initGradientPrograms (vk::SourceCollections& programCollection, tcu::Maybe<FragmentSize> fragmentSize)
+void initGradientPrograms (vk::SourceCollections& programCollection, GradientParams params)
 {
        const auto buildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
        const auto extent               = gradientImageExtent();
@@ -603,11 +689,11 @@ void initGradientPrograms (vk::SourceCollections& programCollection, tcu::Maybe<
        programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
 
        std::string fragmentSizeStr;
-       const auto useFragmentSize      = static_cast<bool>(fragmentSize);
+       const auto useFragmentSize      = static_cast<bool>(params.fragmentSize);
 
        if (useFragmentSize)
        {
-               const auto& fragSize = fragmentSize.get();
+               const auto& fragSize = params.fragmentSize.get();
                fragmentSizeStr = getGLSLShadingRateMask(fragSize);
 
                const auto val  = getSPVShadingRateValue(fragSize);
@@ -712,16 +798,16 @@ std::string coordColorFormat (int x, int y, const tcu::Vec4& color)
        return msg.str();
 }
 
-tcu::TestStatus testFullscreenGradient (Context& context, tcu::Maybe<FragmentSize> fragmentSize)
+tcu::TestStatus testFullscreenGradient (Context& context, GradientParams params)
 {
        const auto&             vkd                                     = context.getDeviceInterface();
        const auto              device                          = context.getDevice();
        auto&                   alloc                           = context.getDefaultAllocator();
        const auto              qIndex                          = context.getUniversalQueueFamilyIndex();
        const auto              queue                           = context.getUniversalQueue();
-       const auto              useFragmentSize         = static_cast<bool>(fragmentSize);
+       const auto              useFragmentSize         = static_cast<bool>(params.fragmentSize);
        const auto              defaultFragmentSize     = FragmentSize::SIZE_1X1;
-       const auto              rateSize                        = getShadingRateSize(useFragmentSize ? fragmentSize.get() : defaultFragmentSize);
+       const auto              rateSize                        = getShadingRateSize(useFragmentSize ? params.fragmentSize.get() : defaultFragmentSize);
 
        // Color buffer.
        const auto      colorBufferFormat       = VK_FORMAT_R8G8B8A8_UNORM;
@@ -784,11 +870,14 @@ tcu::TestStatus testFullscreenGradient (Context& context, tcu::Maybe<FragmentSiz
        }
 
        // 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, 0u, nullptr, nullptr, nullptr, nullptr, nullptr, pNext.get());
+       std::vector<VkViewport> viewports               (1u, makeViewport(colorBufferExtent));
+       std::vector<VkRect2D>   scissors                (1u, makeRect2D(colorBufferExtent));
+       GraphicsPipelineWrapper pipelineMaker   (vkd, device, params.constructionType);
+
+       makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout.get(),
+                                                        taskModule.get(), meshModule.get(), fragModule.get(),
+                                                        renderPass.get(), viewports, scissors, 0u, nullptr, pNext.get());
+       const auto pipeline = pipelineMaker.getPipeline();
 
        // Command pool and buffer.
        const auto cmdPool                      = makeCommandPool(vkd, device, qIndex);
@@ -807,7 +896,7 @@ tcu::TestStatus testFullscreenGradient (Context& context, tcu::Maybe<FragmentSiz
        // Draw triangles.
        beginCommandBuffer(vkd, cmdBuffer);
        beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), getClearColor());
-       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
        vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
        endRenderPass(vkd, cmdBuffer);
 
@@ -913,7 +1002,8 @@ tcu::TestStatus testFullscreenGradient (Context& context, tcu::Maybe<FragmentSiz
 // draws half the front triangles. It gets information from a mix of vertex buffers, per primitive buffers and push constants.
 struct PartialUsageParams
 {
-       bool compactVertices;
+       PipelineConstructionType        constructionType;
+       bool                                            compactVertices;
 };
 
 class PartialUsageCase : public vkt::TestCase
@@ -957,20 +1047,27 @@ protected:
 class PartialUsageInstance : public vkt::TestInstance
 {
 public:
-                                               PartialUsageInstance    (Context& context) : vkt::TestInstance(context) {}
+                                               PartialUsageInstance    (Context& context, PipelineConstructionType constructionType)
+                                                       : vkt::TestInstance             (context)
+                                                       , m_constructionType    (constructionType)
+                                                       {}
        virtual                         ~PartialUsageInstance   (void) {}
 
        tcu::TestStatus         iterate                                 (void) override;
+
+protected:
+       const PipelineConstructionType m_constructionType;
 };
 
 void PartialUsageCase::checkSupport (Context& context) const
 {
        checkTaskMeshShaderSupportEXT(context, true, true);
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.constructionType);
 }
 
 TestInstance* PartialUsageCase::createInstance (Context &context) const
 {
-       return new PartialUsageInstance(context);
+       return new PartialUsageInstance(context, m_params.constructionType);
 }
 
 void PartialUsageCase::initPrograms (vk::SourceCollections &programCollection) const
@@ -1072,9 +1169,7 @@ void PartialUsageCase::initPrograms (vk::SourceCollections &programCollection) c
        }
 
        mesh
-               << "    if (gl_LocalInvocationIndex == 0u) {\n"
-               << "        SetMeshOutputsEXT(wgVertexCount, wgTriangleCount);\n"
-               << "    }\n"
+               << "    SetMeshOutputsEXT(wgVertexCount, wgTriangleCount);\n"
                << "\n"
                // Calculate global invocation primitive id, and use it to access the per-primitive buffer. From there, get the primitive index in the
                // vertex buffer and the blue color component.
@@ -1373,10 +1468,11 @@ tcu::TestStatus PartialUsageInstance::iterate ()
                1.0f,                                                                                                                   //      float                                                                   maxDepthBounds;
        };
 
-       const auto pipeline = makeGraphicsPipeline(
-               vkd, device, pipelineLayout.get(),
-               taskShader.get(), meshShader.get(), fragShader.get(),
-               renderPass.get(), viewports, scissors, 0u, nullptr, nullptr, &dsInfo);
+       GraphicsPipelineWrapper pipelineMaker(vkd, device, m_constructionType);
+       makeMeshGraphicsPipeline(pipelineMaker, pipelineLayout.get(),
+                                                        taskShader.get(), meshShader.get(), fragShader.get(),
+                                                        renderPass.get(), viewports, scissors, 0u, &dsInfo);
+       const auto pipeline = pipelineMaker.getPipeline();
 
        // Command pool and buffer.
        const auto cmdPool              = makeCommandPool(vkd, device, queueIndex);
@@ -1393,7 +1489,7 @@ tcu::TestStatus PartialUsageInstance::iterate ()
 
        beginCommandBuffer(vkd, cmdBuffer);
        beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor, clearDepth, clearStencil);
-       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
+       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
 
        // Front triangles.
        vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &setFront.get(), 0u, nullptr);
@@ -1435,29 +1531,548 @@ tcu::TestStatus PartialUsageInstance::iterate ()
        return tcu::TestStatus::pass("Pass");
 }
 
+// Create a classic and a mesh shading pipeline using graphics pipeline libraries. Both pipelines will use the same fragment shader
+// pipeline library, and the fragment shader will use the gl_Layer built-in, which is per-primitive in mesh shaders and per-vertex
+// in vertex shaders.
+class SharedFragLibraryCase : public vkt::TestCase
+{
+public:
+                                       SharedFragLibraryCase   (tcu::TestContext& testCtx, const std::string& name, const std::string& description, PipelineConstructionType constructionType)
+                                               : vkt::TestCase                 (testCtx, name, description)
+                                               , m_constructionType    (constructionType)
+                                               {}
+       virtual                 ~SharedFragLibraryCase  (void) {}
+
+       void                    checkSupport                    (Context& context) const override;
+       void                    initPrograms                    (vk::SourceCollections& programCollection) const override;
+       TestInstance*   createInstance                  (Context& context) const override;
+
+       static std::vector<tcu::Vec4> getLayerColors (void);
+
+protected:
+       PipelineConstructionType m_constructionType;
+};
+
+class SharedFragLibraryInstance : public vkt::TestInstance
+{
+public:
+                                               SharedFragLibraryInstance       (Context& context, PipelineConstructionType constructionType)
+                                                       : vkt::TestInstance             (context)
+                                                       , m_constructionType    (constructionType)
+                                                       {}
+       virtual                         ~SharedFragLibraryInstance      (void) {}
+
+       tcu::TestStatus         iterate                                         (void) override;
+
+protected:
+       PipelineConstructionType m_constructionType;
+};
+
+std::vector<tcu::Vec4> SharedFragLibraryCase::getLayerColors (void)
+{
+       std::vector<tcu::Vec4> layerColors
+       {
+               tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
+               tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
+               tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
+       };
+
+       return layerColors;
+}
+
+void SharedFragLibraryCase::checkSupport (Context& context) const
+{
+       checkTaskMeshShaderSupportEXT(context, false/*requireTask*/, true/*requireMesh*/);
+
+       if (context.getUsedApiVersion() < VK_API_VERSION_1_2)
+               context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
+       else
+       {
+               // More fine-grained: we do not need shaderViewportIndex.
+               const auto& vk12Features = context.getDeviceVulkan12Features();
+               if (!vk12Features.shaderOutputLayer)
+                       TCU_THROW(NotSupportedError, "shaderOutputLayer not supported");
+       }
+
+       checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_constructionType);
+}
+
+void SharedFragLibraryCase::initPrograms (vk::SourceCollections &programCollection) const
+{
+       const auto meshBuildOptions = getMinMeshEXTBuildOptions(programCollection.usedVulkanVersion);
+
+       const std::string vtxPositions =
+               "vec2 positions[3] = vec2[](\n"
+               "    vec2(-1.0, -1.0),\n"
+               "    vec2(-1.0, 3.0),\n"
+               "    vec2(3.0, -1.0)\n"
+               ");\n"
+               ;
+
+       // The vertex shader emits geometry to layer 1.
+       std::ostringstream vert;
+       vert
+               << "#version 450\n"
+               << "#extension GL_ARB_shader_viewport_layer_array : enable\n"
+               << "\n"
+               << vtxPositions
+               << "void main ()\n"
+               << "{\n"
+               << "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
+               << "    gl_Layer = 1;\n"
+               << "}\n"
+               ;
+       programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
+
+       // The mesh shader emits geometry to layer 2.
+       std::ostringstream mesh;
+       mesh
+               << "#version 450\n"
+               << "#extension GL_EXT_mesh_shader : enable\n"
+               << "\n"
+               << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
+               << "layout (triangles) out;\n"
+               << "layout (max_vertices=3, max_primitives=1) out;\n"
+               << "\n"
+               << "perprimitiveEXT out gl_MeshPerPrimitiveEXT {\n"
+               << "   int gl_Layer;\n"
+               << "} gl_MeshPrimitivesEXT[];\n"
+               << "\n"
+               << vtxPositions
+               << "void main ()\n"
+               << "{\n"
+               << "    SetMeshOutputsEXT(3u, 1u);\n"
+               << "    for (uint i = 0; i < 3; ++i)\n"
+               << "        gl_MeshVerticesEXT[i].gl_Position = vec4(positions[i], 0.0, 1.0);\n"
+               << "    gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0, 1, 2);\n"
+               << "    gl_MeshPrimitivesEXT[0].gl_Layer = 2;\n"
+               << "}\n"
+               ;
+       programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << meshBuildOptions;
+
+       // The frag shader uses the gl_Layer built-in to choose an output color.
+       const auto outColors = getLayerColors();
+       DE_ASSERT(outColors.size() == 3);
+
+       std::ostringstream frag;
+       frag
+               << "#version 450\n"
+               << "\n"
+               << "layout (location=0) out vec4 outColor;\n"
+               << "\n"
+               << "vec4 outColors[3] = vec4[](\n"
+               << "    vec4" << outColors.at(0) << ",\n"
+               << "    vec4" << outColors.at(1) << ",\n"
+               << "    vec4" << outColors.at(2) << "\n"
+               << ");\n"
+               << "\n"
+               << "void main ()\n"
+               << "{\n"
+               << "    outColor = outColors[gl_Layer];\n"
+               << "}\n"
+               ;
+       programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
+}
+
+TestInstance* SharedFragLibraryCase::createInstance (Context& context) const
+{
+       return new SharedFragLibraryInstance(context, m_constructionType);
+}
+
+VkGraphicsPipelineLibraryCreateInfoEXT makeLibCreateInfo (VkGraphicsPipelineLibraryFlagsEXT flags, void* pNext = nullptr)
+{
+       const VkGraphicsPipelineLibraryCreateInfoEXT createInfo =
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT,    //      VkStructureType                                         sType;
+               pNext,                                                                                                                  //      void*                                                           pNext;
+               flags,                                                                                                                  //      VkGraphicsPipelineLibraryFlagsEXT       flags;
+       };
+
+       return createInfo;
+}
+
+tcu::TestStatus SharedFragLibraryInstance::iterate (void)
+{
+       const auto&                     vkd                                     = m_context.getDeviceInterface();
+       const auto&                     device                          = m_context.getDevice();
+       const auto                      queueIndex                      = m_context.getUniversalQueueFamilyIndex();
+       const auto                      queue                           = m_context.getUniversalQueue();
+       auto&                           alloc                           = m_context.getDefaultAllocator();
+       const auto                      layerColors                     = SharedFragLibraryCase::getLayerColors();
+       const auto&                     clearColor                      = layerColors.front();
+       const auto                      layerCount                      = static_cast<uint32_t>(layerColors.size());
+       const auto                      fbExtent                        = makeExtent3D(1u, 1u, 1u);
+       const tcu::IVec3        iExtent                         (static_cast<int>(fbExtent.width), static_cast<int>(fbExtent.height), static_cast<int>(layerCount));
+       const auto                      fbFormat                        = VK_FORMAT_R8G8B8A8_UNORM;
+       const auto                      tcuFormat                       = mapVkFormat(fbFormat);
+       const auto                      pixelSize                       = tcu::getPixelSize(tcuFormat);
+       const auto                      pixelCount                      = fbExtent.width * fbExtent.height * layerCount;
+       const auto                      fbUsage                         = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+       const bool                      optimized                       = (m_constructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
+       const auto                      libExtraFlags           = (optimized ? VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT : 0);
+       const auto                      libCompileFlags         = (VK_PIPELINE_CREATE_LIBRARY_BIT_KHR | libExtraFlags);
+       const auto                      pipelineLinkFlags       = (optimized ? VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT : 0);
+
+       // 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;
+               fbFormat,                                                               //      VkFormat                                format;
+               fbExtent,                                                               //      VkExtent3D                              extent;
+               1u,                                                                             //      uint32_t                                mipLevels;
+               layerCount,                                                             //      uint32_t                                arrayLayers;
+               VK_SAMPLE_COUNT_1_BIT,                                  //      VkSampleCountFlagBits   samples;
+               VK_IMAGE_TILING_OPTIMAL,                                //      VkImageTiling                   tiling;
+               fbUsage,                                                                //      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              colorBufferSRR  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, layerCount);
+       const auto              colorBufferSRL  = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, layerCount);
+       const auto              colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D_ARRAY, fbFormat, colorBufferSRR);
+
+       // Render pass.
+       const auto renderPass = makeRenderPass(vkd, device, fbFormat);
+
+       // Framebuffer.
+       const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), fbExtent.width, fbExtent.height, layerCount);
+
+       // Verification buffer.
+       const auto                      verificationBufferSize  = static_cast<VkDeviceSize>(static_cast<int>(pixelCount) * pixelSize);
+       const auto                      verificationBufferInfo  = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       BufferWithMemory        verificationBuffer              (vkd, device, alloc, verificationBufferInfo, MemoryRequirement::HostVisible);
+       auto&                           verificationBufferAlloc = verificationBuffer.getAllocation();
+       void*                           verificationBufferData  = verificationBufferAlloc.getHostPtr();
+
+       // Pipeline layout (common).
+       const auto pipelineLayout = makePipelineLayout(vkd, device);
+
+       // Shader modules.
+       const auto&     binaries        = m_context.getBinaryCollection();
+       const auto      vertModule      = createShaderModule(vkd, device, binaries.get("vert"));
+       const auto      meshModule      = createShaderModule(vkd, device, binaries.get("mesh"));
+       const auto      fragModule      = createShaderModule(vkd, device, binaries.get("frag"));
+
+       // Fragment output state library (common).
+       const VkColorComponentFlags                                     colorComponentFlags                     = (     VK_COLOR_COMPONENT_R_BIT
+                                                                                                                                                       |       VK_COLOR_COMPONENT_G_BIT
+                                                                                                                                                       |       VK_COLOR_COMPONENT_B_BIT
+                                                                                                                                                       |       VK_COLOR_COMPONENT_A_BIT);
+       const VkPipelineColorBlendAttachmentState       colorBlendAttachmentState       =
+       {
+               VK_FALSE,                               // VkBool32                                     blendEnable
+               VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        srcColorBlendFactor
+               VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstColorBlendFactor
+               VK_BLEND_OP_ADD,                // VkBlendOp                            colorBlendOp
+               VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        srcAlphaBlendFactor
+               VK_BLEND_FACTOR_ZERO,   // VkBlendFactor                        dstAlphaBlendFactor
+               VK_BLEND_OP_ADD,                // VkBlendOp                            alphaBlendOp
+               colorComponentFlags,    // VkColorComponentFlags        colorWriteMask
+       };
+
+       const VkPipelineColorBlendStateCreateInfo colorBlendState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       //      VkStructureType                                                         sType;
+               nullptr,                                                                                                        //      const void*                                                                     pNext;
+               0u,                                                                                                                     //      VkPipelineColorBlendStateCreateFlags            flags;
+               VK_FALSE,                                                                                                       //      VkBool32                                                                        logicOpEnable;
+               VK_LOGIC_OP_CLEAR,                                                                                      //      VkLogicOp                                                                       logicOp;
+               1u,                                                                                                                     //      uint32_t                                                                        attachmentCount;
+               &colorBlendAttachmentState,                                                                     //      const VkPipelineColorBlendAttachmentState*      pAttachments;
+               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     //      float                                                                           blendConstants[4];
+       };
+
+       const VkPipelineMultisampleStateCreateInfo multisampleState =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                              sType
+               nullptr,                                                                                                        // const void*                                                                  pNext
+               0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags                flags
+               VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                                rasterizationSamples
+               VK_FALSE,                                                                                                       // VkBool32                                                                             sampleShadingEnable
+               1.0f,                                                                                                           // float                                                                                minSampleShading
+               nullptr,                                                                                                        // const VkSampleMask*                                                  pSampleMask
+               VK_FALSE,                                                                                                       // VkBool32                                                                             alphaToCoverageEnable
+               VK_FALSE                                                                                                        // VkBool32                                                                             alphaToOneEnable
+       };
+
+       const auto fragOutputLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT);
+
+       VkGraphicsPipelineCreateInfo fragOutputInfo     = initVulkanStructure();
+       fragOutputInfo.layout                                           = pipelineLayout.get();
+       fragOutputInfo.renderPass                                       = renderPass.get();
+       fragOutputInfo.pColorBlendState                         = &colorBlendState;
+       fragOutputInfo.pMultisampleState                        = &multisampleState;
+       fragOutputInfo.flags                                            = libCompileFlags;
+       fragOutputInfo.pNext                                            = &fragOutputLibInfo;
+
+       const auto fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputInfo);
+
+       // Fragment shader lib (shared among the classic and mesh pipelines).
+       const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = initVulkanStructure();
+
+       const VkPipelineShaderStageCreateInfo fragShaderStageCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineShaderStageCreateFlags        flags;
+               VK_SHADER_STAGE_FRAGMENT_BIT,                                                   //      VkShaderStageFlagBits                           stage;
+               fragModule.get(),                                                                               //      VkShaderModule                                          module;
+               "main",                                                                                                 //      const char*                                                     pName;
+               nullptr,                                                                                                //      const VkSpecializationInfo*                     pSpecializationInfo;
+       };
+
+       const auto fragShaderLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT);
+
+       VkGraphicsPipelineCreateInfo fragShaderInfo     = initVulkanStructure();
+       fragShaderInfo.layout                                           = pipelineLayout.get();
+       fragShaderInfo.renderPass                                       = renderPass.get();
+       fragShaderInfo.pMultisampleState                        = &multisampleState;
+       fragShaderInfo.pDepthStencilState                       = &depthStencilStateCreateInfo;
+       fragShaderInfo.stageCount                                       = 1u;
+       fragShaderInfo.pStages                                          = &fragShaderStageCreateInfo;
+       fragShaderInfo.flags                                            = libCompileFlags;
+       fragShaderInfo.pNext                                            = &fragShaderLibInfo;
+
+       const auto fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderInfo);
+
+       // Vertex input state (common, but should be unused by the mesh shading pipeline).
+       const VkPipelineVertexInputStateCreateInfo      vertexInputStateCreateInfo              = initVulkanStructure();
+       VkPipelineInputAssemblyStateCreateInfo          inputAssemblyStateCreateInfo    = initVulkanStructure();
+       inputAssemblyStateCreateInfo.topology                                                                           = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+       const auto                                                                      vertexInputLibInfo                              = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT);
+
+       VkGraphicsPipelineCreateInfo vertexInputInfo    = initVulkanStructure();
+       vertexInputInfo.layout                                                  = pipelineLayout.get();
+       vertexInputInfo.pVertexInputState                               = &vertexInputStateCreateInfo;
+       vertexInputInfo.pInputAssemblyState                             = &inputAssemblyStateCreateInfo;
+       vertexInputInfo.flags                                                   = libCompileFlags;
+       vertexInputInfo.pNext                                                   = &vertexInputLibInfo;
+
+       const auto vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputInfo);
+
+       // Pre-rasterization shader state: common pieces.
+       const std::vector<VkViewport>   viewports       (1u, makeViewport(fbExtent));
+       const std::vector<VkRect2D>             scissors        (1u, makeRect2D(fbExtent));
+
+       const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineViewportStateCreateFlags      flags;
+               static_cast<uint32_t>(viewports.size()),                                //      uint32_t                                                        viewportCount;
+               de::dataOrNull(viewports),                                                              //      const VkViewport*                                       pViewports;
+               static_cast<uint32_t>(scissors.size()),                                 //      uint32_t                                                        scissorCount;
+               de::dataOrNull(scissors),                                                               //      const VkRect2D*                                         pScissors;
+       };
+
+       const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             //      VkStructureType                                                 sType;
+               nullptr,                                                                                                                //      const void*                                                             pNext;
+               0u,                                                                                                                             //      VkPipelineRasterizationStateCreateFlags flags;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthClampEnable;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                rasterizerDiscardEnable;
+               VK_POLYGON_MODE_FILL,                                                                                   //      VkPolygonMode                                                   polygonMode;
+               VK_CULL_MODE_NONE,                                                                                              //      VkCullModeFlags                                                 cullMode;
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                //      VkFrontFace                                                             frontFace;
+               VK_FALSE,                                                                                                               //      VkBool32                                                                depthBiasEnable;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasConstantFactor;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasClamp;
+               0.0f,                                                                                                                   //      float                                                                   depthBiasSlopeFactor;
+               1.0f,                                                                                                                   //      float                                                                   lineWidth;
+       };
+
+       const auto preRastLibInfo = makeLibCreateInfo(VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
+
+       VkGraphicsPipelineCreateInfo preRastShaderInfo  = initVulkanStructure();
+       preRastShaderInfo.layout                                                = pipelineLayout.get();
+       preRastShaderInfo.pViewportState                                = &viewportStateCreateInfo;
+       preRastShaderInfo.pRasterizationState                   = &rasterizationStateCreateInfo;
+       preRastShaderInfo.renderPass                                    = renderPass.get();
+       preRastShaderInfo.flags                                                 = libCompileFlags;
+       preRastShaderInfo.pNext                                                 = &preRastLibInfo;
+       preRastShaderInfo.stageCount                                    = 1u;
+
+       // Vertex stage info.
+       const VkPipelineShaderStageCreateInfo vertShaderStageCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineShaderStageCreateFlags        flags;
+               VK_SHADER_STAGE_VERTEX_BIT,                                                             //      VkShaderStageFlagBits                           stage;
+               vertModule.get(),                                                                               //      VkShaderModule                                          module;
+               "main",                                                                                                 //      const char*                                                     pName;
+               nullptr,                                                                                                //      const VkSpecializationInfo*                     pSpecializationInfo;
+       };
+
+       // Mesh stage info.
+       const VkPipelineShaderStageCreateInfo meshShaderStageCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    //      VkStructureType                                         sType;
+               nullptr,                                                                                                //      const void*                                                     pNext;
+               0u,                                                                                                             //      VkPipelineShaderStageCreateFlags        flags;
+               VK_SHADER_STAGE_MESH_BIT_EXT,                                                   //      VkShaderStageFlagBits                           stage;
+               meshModule.get(),                                                                               //      VkShaderModule                                          module;
+               "main",                                                                                                 //      const char*                                                     pName;
+               nullptr,                                                                                                //      const VkSpecializationInfo*                     pSpecializationInfo;
+       };
+
+       // Pre-rasterization shader libs.
+       preRastShaderInfo.pStages = &vertShaderStageCreateInfo;
+       const auto preRastClassicLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRastShaderInfo);
+
+       preRastShaderInfo.pStages = &meshShaderStageCreateInfo;
+       const auto preRastMeshLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRastShaderInfo);
+
+       // Pipelines.
+       const std::vector<VkPipeline> classicLibs       { vertexInputLib.get(), preRastClassicLib.get(),        fragShaderLib.get(), fragOutputLib.get() };
+       const std::vector<VkPipeline> meshLibs          { vertexInputLib.get(), preRastMeshLib.get(),           fragShaderLib.get(), fragOutputLib.get() };
+
+       const VkPipelineLibraryCreateInfoKHR classicLinkInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,     //      VkStructureType         sType;
+               nullptr,                                                                                        //      const void*                     pNext;
+               static_cast<uint32_t>(classicLibs.size()),                      //      uint32_t                        libraryCount;
+               de::dataOrNull(classicLibs),                                            //      const VkPipeline*       pLibraries;
+       };
+
+       const VkPipelineLibraryCreateInfoKHR meshLinkInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR,     //      VkStructureType         sType;
+               nullptr,                                                                                        //      const void*                     pNext;
+               static_cast<uint32_t>(meshLibs.size()),                         //      uint32_t                        libraryCount;
+               de::dataOrNull(meshLibs),                                                       //      const VkPipeline*       pLibraries;
+       };
+
+       VkGraphicsPipelineCreateInfo classicPipelineCreateInfo = initVulkanStructure();
+       classicPipelineCreateInfo.flags         = pipelineLinkFlags;
+       classicPipelineCreateInfo.layout        = pipelineLayout.get();
+       classicPipelineCreateInfo.pNext         = &classicLinkInfo;
+
+       VkGraphicsPipelineCreateInfo meshPipelineCreateInfo = initVulkanStructure();
+       meshPipelineCreateInfo.flags    = pipelineLinkFlags;
+       meshPipelineCreateInfo.layout   = pipelineLayout.get();
+       meshPipelineCreateInfo.pNext    = &meshLinkInfo;
+
+       const auto classicPipeline      = createGraphicsPipeline(vkd, device, DE_NULL, &classicPipelineCreateInfo);
+       const auto meshPipeline         = createGraphicsPipeline(vkd, device, DE_NULL, &meshPipelineCreateInfo);
+
+       // Record commands with both pipelines.
+       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);
+
+       // Draw using both pipelines.
+       beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
+       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, classicPipeline.get());
+       vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
+       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, meshPipeline.get());
+       vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
+       endRenderPass(vkd, cmdBuffer);
+
+       // Copy color buffer to verification buffer.
+       const auto preTransferBarrier = makeImageMemoryBarrier(
+               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(), colorBufferSRR);
+
+       const auto postTransferBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
+
+       const auto copyRegion = makeBufferImageCopy(fbExtent, colorBufferSRL);
+
+       cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preTransferBarrier);
+       vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, &copyRegion);
+       cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postTransferBarrier);
+
+       endCommandBuffer(vkd, cmdBuffer);
+       submitCommandsAndWait(vkd, device, queue, cmdBuffer);
+
+       // Validate color buffer.
+       invalidateAlloc(vkd, device, verificationBufferAlloc);
+
+       tcu::ConstPixelBufferAccess     resultAccess    (tcuFormat, iExtent, verificationBufferData);
+       auto&                                           log                             = m_context.getTestContext().getLog();
+       bool                                            fail                    = false;
+
+       for (int z = 0; z < iExtent.z(); ++z)
+       {
+               const auto& expectedColor = layerColors.at(z);
+               for (int y = 0; y < iExtent.y(); ++y)
+                       for (int x = 0; x < iExtent.x(); ++x)
+                       {
+                               const auto resultColor = resultAccess.getPixel(x, y, z);
+                               if (resultColor != expectedColor)
+                               {
+                                       std::ostringstream msg;
+                                       msg << "Unexpected color at coordinates (x=" << x << ", y=" << y << ", layer=" << z << "): expected " << expectedColor << " but found " << resultColor;
+                                       log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
+                                       fail = true;
+                               }
+                       }
+       }
+
+       if (fail)
+               return tcu::TestStatus::fail("Failed; check log for details");
+       return tcu::TestStatus::pass("Pass");
+}
+
 } // anonymous namespace
 
 tcu::TestCaseGroup* createMeshShaderSmokeTestsEXT (tcu::TestContext& testCtx)
 {
-       GroupPtr smokeTests (new tcu::TestCaseGroup(testCtx, "smoke", "Mesh Shader Smoke Tests"));
+       struct
+       {
+               PipelineConstructionType        constructionType;
+               const char*                                     name;
+       } constructionTypes[] =
+       {
+               { PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC,                                        "monolithic"            },
+               { PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY,       "optimized_lib"         },
+               { PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY,                       "fast_lib"                      },
+       };
 
-       smokeTests->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle", ""));
-       smokeTests->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle_rasterization_disabled", "", true/*rasterizationDisabled*/));
-       smokeTests->addChild(new MeshTaskTriangleCase(testCtx, "mesh_task_shader_triangle", ""));
-       smokeTests->addChild(new TaskOnlyTriangleCase(testCtx, "task_only_shader_triangle", ""));
+       GroupPtr smokeTests (new tcu::TestCaseGroup(testCtx, "smoke", "Mesh Shader Smoke Tests"));
 
-       for (int i = 0; i < 2; ++i)
+       for (const auto& constructionCase : constructionTypes)
        {
-               const bool                                      compaction      = (i == 0);
-               const std::string                       nameSuffix      = (compaction ? "" : "_without_compaction");
-               const PartialUsageParams        params          { compaction };
+               GroupPtr constructionGroup(new tcu::TestCaseGroup(testCtx, constructionCase.name, ""));
 
-               smokeTests->addChild(new PartialUsageCase(testCtx, "partial_usage" + nameSuffix, "", params));
-       }
+               const auto& cType = constructionCase.constructionType;
+
+               constructionGroup->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle", "", cType));
+               constructionGroup->addChild(new MeshOnlyTriangleCase(testCtx, "mesh_shader_triangle_rasterization_disabled", "", cType, true/*rasterizationDisabled*/));
+               constructionGroup->addChild(new MeshTaskTriangleCase(testCtx, "mesh_task_shader_triangle", "", cType));
+               constructionGroup->addChild(new TaskOnlyTriangleCase(testCtx, "task_only_shader_triangle", "", cType));
+
+               for (int i = 0; i < 2; ++i)
+               {
+                       const bool                                      compaction      = (i == 0);
+                       const std::string                       nameSuffix      = (compaction ? "" : "_without_compaction");
+                       const PartialUsageParams        params          { cType, compaction };
 
-       addFunctionCaseWithPrograms(smokeTests.get(), "fullscreen_gradient",            "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, tcu::nothing<FragmentSize>());
-       addFunctionCaseWithPrograms(smokeTests.get(), "fullscreen_gradient_fs2x2",      "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, tcu::just(FragmentSize::SIZE_2X2));
-       addFunctionCaseWithPrograms(smokeTests.get(), "fullscreen_gradient_fs2x1",      "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, tcu::just(FragmentSize::SIZE_2X1));
+                       constructionGroup->addChild(new PartialUsageCase(testCtx, "partial_usage" + nameSuffix, "", params));
+               }
+
+               addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient",                     "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::nothing<FragmentSize>(), cType));
+               addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient_fs2x2",       "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::just(FragmentSize::SIZE_2X2), cType));
+               addFunctionCaseWithPrograms(constructionGroup.get(), "fullscreen_gradient_fs2x1",       "", checkMeshSupport, initGradientPrograms, testFullscreenGradient, GradientParams(tcu::just(FragmentSize::SIZE_2X1), cType));
+
+               if (cType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
+               {
+                       constructionGroup->addChild(new SharedFragLibraryCase(testCtx, "shared_frag_library", "", cType));
+               }
+
+               smokeTests->addChild(constructionGroup.release());
+       }
 
        return smokeTests.release();
 }
index c5657d1..a227fd2 100644 (file)
@@ -141,7 +141,6 @@ enum class BarrierType
 {
        GENERAL = 0,
        SPECIFIC,
-       DEPENDENCY,
 };
 
 // Types of writes we will use.
@@ -341,8 +340,8 @@ VkBufferUsageFlags resourceBufferUsageFlags (ResourceType resourceType)
        return flags;
 }
 
-// A subpass dependency is needed if both the source and destination stages are shader stages.
-bool needsSubpassDependency (Stage fromStage, Stage toStage)
+// Is the resource written to and read from a shader stage?
+bool readAndWriteFromShaders (Stage fromStage, Stage toStage)
 {
        return (isShaderStage(fromStage) && isShaderStage(toStage));
 }
@@ -395,10 +394,29 @@ public:
                return decl.str();
        }
 
+       struct PushConstantStruct
+       {
+               uint32_t writeVal;
+               uint32_t readVal;
+       };
+
+       // Get declaration for the "pc" push constant block. Must match the structure above.
+       std::string getPushConstantDecl () const
+       {
+               std::ostringstream pc;
+               pc
+                       << "layout (push_constant, std430) uniform PushConstantBlock {\n"
+                       << "    uint writeVal;\n"
+                       << "    uint readVal;\n"
+                       << "} pc;\n"
+                       ;
+               return pc.str();
+       }
+
        std::string getReadStatement (const std::string& outName) const
        {
                std::ostringstream statement;
-               statement << "    " << outName << " = ";
+               statement << "    if (pc.readVal > 0u) { " << outName << " = ";
 
                switch (resourceType)
                {
@@ -409,14 +427,14 @@ public:
                default:                                                        DE_ASSERT(false); break;
                }
 
-               statement << ";\n";
+               statement << "; }\n";
                return statement.str();
        }
 
        std::string getWriteStatement (const std::string& valueName) const
        {
                std::ostringstream statement;
-               statement << "    ";
+               statement << "    if (pc.writeVal > 0u) { ";
 
                switch (resourceType)
                {
@@ -427,7 +445,7 @@ public:
                default:                                                        DE_ASSERT(false); break;
                }
 
-               statement << ";\n";
+               statement << "; }\n";
                return statement.str();
        }
 
@@ -449,6 +467,12 @@ public:
        {
                return (isShaderStage(fromStage) || (barrierType == BarrierType::GENERAL) || (resourceType == ResourceType::STORAGE_IMAGE));
        }
+
+       // A subpass dependency is needed if both the source and destination stages are shader stages.
+       bool needsSubpassDependency () const
+       {
+               return readAndWriteFromShaders(fromStage, toStage);
+       }
 };
 
 class MeshShaderSyncCase : public vkt::TestCase
@@ -495,6 +519,7 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
        const bool      needsTaskShader = m_params.needsTask();
        const auto      valueStr                = de::toString(m_params.testValue);
        const auto      resourceDecl    = m_params.getResourceDecl();
+       const auto      pcDecl                  = m_params.getPushConstantDecl();
 
        if (needsTaskShader)
        {
@@ -509,6 +534,7 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << "out taskNV TaskData { uint value; } td;\n"
                        << "\n"
                        << resourceDecl
+                       << pcDecl
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
@@ -522,6 +548,8 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
        }
 
        {
+               const bool rwInMesh = m_params.readsOrWritesInMesh();
+
                std::ostringstream mesh;
                mesh
                        << "#version 450\n"
@@ -534,7 +562,8 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << (needsTaskShader ? "in taskNV TaskData { uint value; } td;\n" : "")
                        << "layout (location=0) out perprimitiveNV uint primitiveValue[];\n"
                        << "\n"
-                       << (m_params.readsOrWritesInMesh() ? resourceDecl : "")
+                       << (rwInMesh ? resourceDecl : "")
+                       << (rwInMesh ? pcDecl : "")
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
@@ -566,11 +595,13 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << "layout (location=0) out uvec4 outColor;\n"
                        << "\n"
                        << (readFromFrag ? resourceDecl : "")
+                       << (readFromFrag ? pcDecl : "")
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
-                       << "    outColor = uvec4(primitiveValue, 0, 0, 0);\n"
-                       << (readFromFrag ? m_params.getReadStatement("const uint readVal")      : "")
+                       << "    outColor = uvec4(primitiveValue, 0, 0, 0);\n"
+                       << "    uint readVal = 0u;\n"
+                       << (readFromFrag ? m_params.getReadStatement("readVal") : "")
                        << (readFromFrag ? "    outColor = uvec4(readVal, 0, 0, 0);\n"          : "")
                        << "}\n"
                        ;
@@ -637,7 +668,7 @@ Move<VkRenderPass> createCustomRenderPass (const DeviceInterface& vkd, VkDevice
 
        // 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))
+       if (params.needsSubpassDependency())
        {
                const VkSubpassDependency dependency =
                {
@@ -698,6 +729,7 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
        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 bool      needsTwoDrawCalls               = m_params.needsSubpassDependency();
 
        const auto      writeAccessFlags                = writeAccessToFlags(m_params.writeAccess);
        const auto      readAccessFlags                 = readAccessToFlags(m_params.readAccess);
@@ -885,8 +917,12 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
        meshShader = createShaderModule(vkd, device, binaries.get("mesh"), 0u);
        fragShader = createShaderModule(vkd, device, binaries.get("frag"), 0u);
 
+       using PushConstantStruct = TestParams::PushConstantStruct;
+
        // Pipeline layout, render pass, framebuffer.
-       const auto pipelineLayout       = makePipelineLayout(vkd, device, setLayout.get());
+       const auto pcSize                       = static_cast<uint32_t>(sizeof(PushConstantStruct));
+       const auto pcRange                      = makePushConstantRange(resourceStages, 0u, pcSize);
+       const auto pipelineLayout       = makePipelineLayout(vkd, device, setLayout.get(), &pcRange);
        const auto renderPass           = createCustomRenderPass(vkd, device, imageFormat, m_params);
        const auto framebuffer          = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), imageExtent.width, imageExtent.height);
 
@@ -958,7 +994,7 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
        }
 
        // 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 (isShaderStage(m_params.toStage) && !needsTwoDrawCalls)
        {
                if (m_params.barrierType == BarrierType::GENERAL)
                {
@@ -981,18 +1017,73 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
                                currentLayout = newLayout;
                        }
                }
-               // For subpass dependencies, they have already been included in the render pass.
+               else
+               {
+                       DE_ASSERT(false);
+               }
+       }
+
+       if (needsTwoDrawCalls)
+       {
+               // Transition image to the general layout before writing to it. When we need two draw calls (because the image will be
+               // written to and read from a shader stage), the layout will always be general.
+               if (useImageResource)
+               {
+                       const auto newLayout    = VK_IMAGE_LAYOUT_GENERAL;
+                       const auto imageBarrier = makeImageMemoryBarrier(0u, writeAccessFlags, currentLayout, newLayout, imageResource->get(), colorSRR);
+
+                       vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, fromStageFlags, 0u, 0u, nullptr, 0u, nullptr, 1u, &imageBarrier);
+                       currentLayout = newLayout;
+               }
        }
 
        // 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);
+       if (needsTwoDrawCalls)
+       {
+               // The first draw call will write to the resource and the second one will read from the resource.
+               PushConstantStruct pcData;
+
+               pcData.writeVal = 1u;
+               pcData.readVal  = 0u;
+
+               vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), resourceStages, 0u, pcSize, &pcData);
+               vkd.cmdDrawMeshTasksNV(cmdBuffer, 1u, 0u);
+
+               // Use a barrier between both draw calls. The barrier must be generic because:
+               //    * VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178 forbids using buffer barriers inside render passes.
+               //    * VUID-vkCmdPipelineBarrier-image-04073 forbids using image memory barriers inside render passes with resources that are not attachments.
+               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
+               {
+                       DE_ASSERT(false);
+               }
+
+               pcData.writeVal = 0u;
+               pcData.readVal  = 1u;
+
+               vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), resourceStages, 0u, pcSize, &pcData);
+               vkd.cmdDrawMeshTasksNV(cmdBuffer, 1u, 0u);
+       }
+       else
+       {
+               PushConstantStruct pcData;
+               pcData.writeVal = 1u;
+               pcData.readVal  = 1u;
+
+               vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), resourceStages, 0u, pcSize, &pcData);
+               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 (isShaderStage(m_params.fromStage) && !needsTwoDrawCalls)
        {
                if (m_params.barrierType == BarrierType::GENERAL)
                {
@@ -1159,7 +1250,6 @@ tcu::TestCaseGroup* createMeshShaderSyncTests (tcu::TestContext& testCtx)
        {
                {       BarrierType::GENERAL,           "memory_barrier"                },
                {       BarrierType::SPECIFIC,          "specific_barrier"              },
-               {       BarrierType::DEPENDENCY,        "subpass_dependency"    },
        };
 
        const struct
@@ -1206,11 +1296,8 @@ tcu::TestCaseGroup* createMeshShaderSyncTests (tcu::TestContext& testCtx)
 
                        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)
+                               // See note above about VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178 and VUID-vkCmdPipelineBarrier-image-04073.
+                               if (readAndWriteFromShaders(stageCombination.fromStage, stageCombination.toStage) && barrierCase.barrierType == BarrierType::SPECIFIC)
                                        continue;
 
                                GroupPtr barrierGroup (new tcu::TestCaseGroup(testCtx, barrierCase.name, ""));
index 26d9e7c..526cb5a 100644 (file)
@@ -420,10 +420,29 @@ public:
                return decl.str();
        }
 
+       struct PushConstantStruct
+       {
+               uint32_t writeVal;
+               uint32_t readVal;
+       };
+
+       // Get declaration for the "pc" push constant block. Must match the structure above.
+       std::string getPushConstantDecl () const
+       {
+               std::ostringstream pc;
+               pc
+                       << "layout (push_constant, std430) uniform PushConstantBlock {\n"
+                       << "    uint writeVal;\n"
+                       << "    uint readVal;\n"
+                       << "} pc;\n"
+                       ;
+               return pc.str();
+       }
+
        std::string getReadStatement (const std::string& outName) const
        {
                std::ostringstream statement;
-               statement << "    " << outName << " = ";
+               statement << "    if (pc.readVal > 0u) { " << outName << " = ";
 
                switch (resourceType)
                {
@@ -434,14 +453,14 @@ public:
                default:                                                        DE_ASSERT(false); break;
                }
 
-               statement << ";\n";
+               statement << "; }\n";
                return statement.str();
        }
 
        std::string getWriteStatement (const std::string& valueName) const
        {
                std::ostringstream statement;
-               statement << "    ";
+               statement << "    if (pc.writeVal > 0u) { ";
 
                switch (resourceType)
                {
@@ -452,7 +471,7 @@ public:
                default:                                                        DE_ASSERT(false); break;
                }
 
-               statement << ";\n";
+               statement << "; }\n";
                return statement.str();
        }
 
@@ -485,6 +504,13 @@ public:
                                barrierType != BarrierType::DEPENDENCY));
        }
 
+       // We need to use generic barriers when using subpass self-dependencies (single subpass and pipeline).
+       // Note: barrierType == BarrierType::DEPENDENCY is technically redundant with !needsTwoPipelines().
+       bool subpassSelfDependency () const
+       {
+               return (fromShaderToShader(fromStage, toStage) && barrierType == BarrierType::DEPENDENCY && !needsTwoPipelines());
+       }
+
 };
 
 class MeshShaderSyncCase : public vkt::TestCase
@@ -532,6 +558,7 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
        const bool                      needsTaskShader = m_params.needsTask();
        const auto                      valueStr                = de::toString(m_params.testValue);
        const auto                      resourceDecl    = m_params.getResourceDecl();
+       const auto                      pcDecl                  = m_params.getPushConstantDecl();
        const std::string       tdDecl                  = "struct TaskData { uint value; }; taskPayloadSharedEXT TaskData td;\n";
 
        if (needsTaskShader)
@@ -546,6 +573,7 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << tdDecl
                        << "\n"
                        << resourceDecl
+                       << pcDecl
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
@@ -560,7 +588,11 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
 
        {
                // In the mesh-to-task case, we need non-passthrough mesh and task shaders but the mesh shader doesn't have a previous task shader.
-               const bool prevTaskInMainMesh = (needsTaskShader && !(m_params.fromStage == Stage::MESH && m_params.toStage == Stage::TASK));
+               // In the task-to-mesh case, the second pipeline will have the main mesh shader but no previous task shader either.
+               const bool prevTaskInMainMesh   = (needsTaskShader
+                                                                                       && !(m_params.fromStage == Stage::MESH && m_params.toStage == Stage::TASK)
+                                                                                       && !(m_params.fromStage == Stage::TASK && m_params.toStage == Stage::MESH));
+               const bool rwInMeshStage                = m_params.readsOrWritesInMesh();
 
                std::ostringstream mesh;
                mesh
@@ -574,7 +606,8 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << (prevTaskInMainMesh ? tdDecl : "")
                        << "layout (location=0) out perprimitiveEXT uint primitiveValue[];\n"
                        << "\n"
-                       << (m_params.readsOrWritesInMesh() ? resourceDecl : "")
+                       << (rwInMeshStage ? resourceDecl : "")
+                       << (rwInMeshStage ? pcDecl : "")
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
@@ -595,6 +628,7 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
        {
                const bool                      readFromFrag    = (m_params.toStage == Stage::FRAG);
                const bool                      writeFromFrag   = (m_params.fromStage == Stage::FRAG);
+               const bool                      rwInFragStage   = (readFromFrag || writeFromFrag);
                std::ostringstream      frag;
 
                frag
@@ -604,12 +638,14 @@ void MeshShaderSyncCase::initPrograms (vk::SourceCollections& programCollection)
                        << "layout (location=0) in perprimitiveEXT flat uint primitiveValue;\n"
                        << "layout (location=0) out uvec4 outColor;\n"
                        << "\n"
-                       << ((readFromFrag || writeFromFrag) ? resourceDecl : "")
+                       << (rwInFragStage ? resourceDecl : "")
+                       << (rwInFragStage ? pcDecl : "")
                        << "\n"
                        << "void main ()\n"
                        << "{\n"
-                       << "    outColor = uvec4(primitiveValue, 0, 0, 0);\n"
-                       << (readFromFrag ?      m_params.getReadStatement("const uint readVal") : "")
+                       << "    outColor = uvec4(primitiveValue, 0, 0, 0);\n"
+                       << "    uint readVal = 0u;\n"
+                       << (readFromFrag ?      m_params.getReadStatement("readVal")    : "")
                        << (readFromFrag ?      "    outColor = uvec4(readVal, 0, 0, 0);\n"             : "")
                        << (writeFromFrag ?     m_params.getWriteStatement(valueStr)                    : "")
                        << "}\n"
@@ -1011,11 +1047,24 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
        std::vector<VkViewport> viewports       (1u, makeViewport(imageExtent));
        std::vector<VkRect2D>   scissors        (1u, makeRect2D(imageExtent));
 
+       using PushConstantStruct = TestParams::PushConstantStruct;
+
        // Pipeline layout.
-       const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
+       const auto pcSize                       = static_cast<uint32_t>(sizeof(PushConstantStruct));
+       const auto pcRange                      = makePushConstantRange(resourceStages, 0u, pcSize);
+       const auto pipelineLayout       = makePipelineLayout(vkd, device, setLayout.get(), &pcRange);
 
        // Shader modules, pipelines and pipeline layouts.
-       const auto                                              pipelineCount   = (m_params.needsTwoPipelines() ? 2u : 1u);
+       const auto                                              twoPipelines    = m_params.needsTwoPipelines();
+       const auto                                              selfDeps                = m_params.subpassSelfDependency();
+
+       // Both at the same time does not make sense.
+       DE_ASSERT(!(twoPipelines && selfDeps));
+
+       const auto                                              pipelineCount   = (twoPipelines ? 2u : 1u);
+       const auto                                              drawCount               = (selfDeps ? 2u : 1u);
+       const auto                                              iterationCount  = std::max(pipelineCount, drawCount);
+
        std::vector<Move<VkPipeline>>   pipelines;
        pipelines.reserve(pipelineCount);
 
@@ -1171,7 +1220,7 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
                                currentLayout = newLayout;
                        }
                }
-               // For subpass dependencies, they have already been included in the render pass.
+               // For subpass dependencies, they have already been included in the render pass or loop below.
        }
 
        // Run the pipeline.
@@ -1180,24 +1229,43 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
 
        vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
 
-       for (uint32_t pipelineIdx = 0u; pipelineIdx < pipelineCount; ++pipelineIdx)
+       for (uint32_t iterationIdx = 0u; iterationIdx < iterationCount; ++iterationIdx)
        {
-               if (pipelineIdx > 0u && !multiRenderPass)
+               if (iterationIdx > 0u && !multiRenderPass && twoPipelines)
                        vkd.cmdNextSubpass(cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
 
                if (multiRenderPass)
-                       beginRenderPass(vkd, cmdBuffer, renderPasses.at(pipelineIdx).get(), framebuffers.at(pipelineIdx).get(), scissors.at(0), tcu::UVec4(0u));
+                       beginRenderPass(vkd, cmdBuffer, renderPasses.at(iterationIdx).get(), framebuffers.at(iterationIdx).get(), scissors.at(0), tcu::UVec4(0u));
 
-               vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.at(pipelineIdx).get());
+               if (twoPipelines || iterationIdx == 0u)
+                       vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.at(iterationIdx).get());
+
+               PushConstantStruct pcData;
+               if (selfDeps)
+               {
+                       // First draw writes, second draw reads.
+                       pcData.writeVal = 1u - iterationIdx;
+                       pcData.readVal  = iterationIdx;
+               }
+               else
+               {
+                       // Otherwise reads and writes freely according to the pipeline shaders.
+                       pcData.writeVal = 1u;
+                       pcData.readVal  = 1u;
+               }
+               vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), resourceStages, 0u, pcSize, &pcData);
                vkd.cmdDrawMeshTasksEXT(cmdBuffer, 1u, 1u, 1u);
 
                if (multiRenderPass)
                        endRenderPass(vkd, cmdBuffer);
 
-               // If there are multiple render passes, synchronize resource between them.
-               if (multiRenderPass && pipelineIdx < pipelineCount - 1u)
+               // If there are self-dependencies or multiple render passes, synchronize resource between draw calls.
+               if ((multiRenderPass || selfDeps) && iterationIdx == 0u)
                {
-                       if (m_params.barrierType == BarrierType::GENERAL)
+                       // In the case of self-dependencies, the barrier type is BarrierType::DEPENDENCY and we'll insert a general barrier because:
+                       //    * VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178 forbids using buffer barriers inside render passes.
+                       //    * VUID-vkCmdPipelineBarrier-image-04073 forbids using image memory barriers inside render passes with resources that are not attachments.
+                       if (m_params.barrierType == BarrierType::GENERAL || m_params.barrierType == BarrierType::DEPENDENCY)
                        {
                                const auto memoryBarrier = makeMemoryBarrier(writeAccessFlags, readAccessFlags);
                                cmdPipelineMemoryBarrier(vkd, cmdBuffer, fromStageFlags, toStageFlags, &memoryBarrier);
@@ -1222,20 +1290,22 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
                        }
                        else
                        {
-                               // Subpass dependencies cannot be used with multiple render passes.
                                DE_ASSERT(false);
                        }
 
-                       // Sync color attachment writes.
-                       const auto colorWritesBarrier = makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
-                       cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &colorWritesBarrier);
+                       if (multiRenderPass)
+                       {
+                               // Sync color attachment writes.
+                               const auto colorWritesBarrier = makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
+                               cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &colorWritesBarrier);
+                       }
                }
        }
 
        if (!multiRenderPass)
                endRenderPass(vkd, cmdBuffer);
 
-       // If the resource was written to from the shaders and will be read from a non-shader stage, insert the main barrier after running the pipeline.
+       // If the resource was written to from shaders and will be read from a non-shader stage, insert the main barrier after running the pipeline.
        if (isShaderStage(m_params.fromStage) && !isShaderStage(m_params.toStage))
        {
                if (m_params.barrierType == BarrierType::GENERAL)
@@ -1260,7 +1330,7 @@ tcu::TestStatus MeshShaderSyncInstance::iterate (void)
                                currentLayout = newLayout;
                        }
                }
-               // For subpass dependencies, they have already been included in the render pass.
+               // For subpass dependencies, they have already been included in the render pass and loop.
        }
 
        // Read resource from the destination stage if needed.
@@ -1682,7 +1752,7 @@ tcu::TestCaseGroup* createMeshShaderSyncTestsEXT (tcu::TestContext& testCtx)
                                const auto shaderToShader      = fromShaderToShader(stageCombination.fromStage, stageCombination.toStage);
                                const auto barrierIsDependency = (barrierCase.barrierType == BarrierType::DEPENDENCY);
 
-                               // Subpass can only be used in shader to shader situations.
+                               // Subpass dependencies can only be used in shader to shader situations.
                                if (barrierIsDependency && !shaderToShader)
                                                continue;
 
index 31a64ad..d8fb95d 100644 (file)
@@ -37,6 +37,7 @@
 #include "vktMeshShaderInOutTestsEXT.hpp"
 #include "vktMeshShaderPropertyTestsEXT.hpp"
 #include "vktMeshShaderConditionalRenderingTestsEXT.hpp"
+#include "vktMeshShaderProvokingVertexTestsEXT.hpp"
 
 #include "deUniquePtr.hpp"
 
@@ -72,6 +73,7 @@ tcu::TestCaseGroup*   createTests     (tcu::TestContext& testCtx)
        extGroup->addChild(createMeshShaderInOutTestsEXT(testCtx));
        extGroup->addChild(createMeshShaderPropertyTestsEXT(testCtx));
        extGroup->addChild(createMeshShaderConditionalRenderingTestsEXT(testCtx));
+       extGroup->addChild(createMeshShaderProvokingVertexTestsEXT(testCtx));
 
        mainGroup->addChild(nvGroup.release());
        mainGroup->addChild(extGroup.release());
index cc38064..ed3e2fd 100644 (file)
@@ -472,18 +472,18 @@ dEQP-VK.mesh_shader.nv.synchronization.transfer_to_mesh.storage_image.memory_bar
 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_mesh.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_mesh.storage_image.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.task_to_frag.storage_image.memory_barrier.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_frag.storage_buffer.memory_barrier.shader_write_shader_read
+dEQP-VK.mesh_shader.nv.synchronization.mesh_to_frag.storage_image.memory_barrier.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
@@ -1121,15 +1121,35 @@ dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_38.task_mesh
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.mesh_only
 dEQP-VK.mesh_shader.nv.in_out.all_types.permutation_39.task_mesh
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.mesh_shader_triangle_rasterization_disabled
-dEQP-VK.mesh_shader.ext.smoke.mesh_task_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.task_only_shader_triangle
-dEQP-VK.mesh_shader.ext.smoke.partial_usage
-dEQP-VK.mesh_shader.ext.smoke.partial_usage_without_compaction
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x2
-dEQP-VK.mesh_shader.ext.smoke.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.monolithic.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.monolithic.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.monolithic.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.optimized_lib.shared_frag_library
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_shader_triangle_rasterization_disabled
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.mesh_task_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.task_only_shader_triangle
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.partial_usage_without_compaction
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x2
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.fullscreen_gradient_fs2x1
+dEQP-VK.mesh_shader.ext.smoke.fast_lib.shared_frag_library
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.no_task_shader_secondary_cmd
 dEQP-VK.mesh_shader.ext.api.draw.draw_count_0.no_indirect_args.no_count_limit.no_count_offset.with_task_shader
@@ -3036,3 +3056,11 @@ dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000100
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000001
 dEQP-VK.mesh_shader.ext.conditional_rendering.draw_indirect_count.secondary_cmd_buffer_inheritance.bind_with_offset.cond_with_offset.inverted_cond.mesh_and_task.value_0x00000000
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.lines.last_first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.first_last
+dEQP-VK.mesh_shader.ext.provoking_vertex.triangles.last_first