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 \
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
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
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
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
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
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
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",
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,
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;
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>()))
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";
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));
s << "\tmeshShader = " << value.meshShader << '\n';
s << "\tmultiviewMeshShader = " << value.multiviewMeshShader << '\n';
s << "\tprimitiveFragmentShadingRateMeshShader = " << value.primitiveFragmentShadingRateMeshShader << '\n';
+ s << "\tmeshShaderQueries = " << value.meshShaderQueries << '\n';
s << '}';
return s;
}
s << "\tprefersLocalInvocationPrimitiveOutput = " << value.prefersLocalInvocationPrimitiveOutput << '\n';
s << "\tprefersCompactVertexOutput = " << value.prefersCompactVertexOutput << '\n';
s << "\tprefersCompactPrimitiveOutput = " << value.prefersCompactPrimitiveOutput << '\n';
- s << "\tmeshShadingAffectedPipelineStatistics = " << getQueryPipelineStatisticFlagsStr(value.meshShadingAffectedPipelineStatistics) << '\n';
s << '}';
return s;
}
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
#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,
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;
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 {
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)
multisampleState,
shadingRateState)
.setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
+ .setMonolithicPipelineLayout(pipelineLayout)
.buildPipeline();
vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
multisampleState,
shadingRateState)
.setupFragmentOutputState(renderPass, 0u, DE_NULL, multisampleState)
+ .setMonolithicPipelineLayout(pipelineLayout)
.buildPipeline();
vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
vktMeshShaderPropertyTestsEXT.hpp
vktMeshShaderConditionalRenderingTestsEXT.cpp
vktMeshShaderConditionalRenderingTestsEXT.hpp
+ vktMeshShaderProvokingVertexTestsEXT.cpp
+ vktMeshShaderProvokingVertexTestsEXT.hpp
vktMeshShaderUtil.cpp
vktMeshShaderUtil.hpp
)
}
// 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;
--- /dev/null
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2021 The Khronos Group Inc.
+ * Copyright (c) 2021 Valve Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief 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 (¶ms)
+ {}
+ 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, ©Region);
+
+ 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
--- /dev/null
+#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
#include "vkCmdUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkBarrierUtil.hpp"
+#include "vkPipelineConstructionUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"
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_)
{}
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) {}
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
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
};
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));
}
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));
}
};
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));
}
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);
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);
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();
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);
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;
}
// 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);
// 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);
// 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
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
}
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.
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);
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);
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, ©Region);
+ 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();
}
{
GENERAL = 0,
SPECIFIC,
- DEPENDENCY,
};
// Types of writes we will use.
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));
}
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)
{
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)
{
default: DE_ASSERT(false); break;
}
- statement << ";\n";
+ statement << "; }\n";
return statement.str();
}
{
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
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)
{
<< "out taskNV TaskData { uint value; } td;\n"
<< "\n"
<< resourceDecl
+ << pcDecl
<< "\n"
<< "void main ()\n"
<< "{\n"
}
{
+ const bool rwInMesh = m_params.readsOrWritesInMesh();
+
std::ostringstream mesh;
mesh
<< "#version 450\n"
<< (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"
<< "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"
;
// 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 =
{
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);
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);
}
// 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)
{
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)
{
{
{ BarrierType::GENERAL, "memory_barrier" },
{ BarrierType::SPECIFIC, "specific_barrier" },
- { BarrierType::DEPENDENCY, "subpass_dependency" },
};
const struct
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, ""));
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)
{
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)
{
default: DE_ASSERT(false); break;
}
- statement << ";\n";
+ statement << "; }\n";
return statement.str();
}
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
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)
<< tdDecl
<< "\n"
<< resourceDecl
+ << pcDecl
<< "\n"
<< "void main ()\n"
<< "{\n"
{
// 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
<< (prevTaskInMainMesh ? tdDecl : "")
<< "layout (location=0) out perprimitiveEXT uint primitiveValue[];\n"
<< "\n"
- << (m_params.readsOrWritesInMesh() ? resourceDecl : "")
+ << (rwInMeshStage ? resourceDecl : "")
+ << (rwInMeshStage ? pcDecl : "")
<< "\n"
<< "void main ()\n"
<< "{\n"
{
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
<< "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"
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);
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.
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);
}
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)
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.
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;
#include "vktMeshShaderInOutTestsEXT.hpp"
#include "vktMeshShaderPropertyTestsEXT.hpp"
#include "vktMeshShaderConditionalRenderingTestsEXT.hpp"
+#include "vktMeshShaderProvokingVertexTestsEXT.hpp"
#include "deUniquePtr.hpp"
extGroup->addChild(createMeshShaderInOutTestsEXT(testCtx));
extGroup->addChild(createMeshShaderPropertyTestsEXT(testCtx));
extGroup->addChild(createMeshShaderConditionalRenderingTestsEXT(testCtx));
+ extGroup->addChild(createMeshShaderProvokingVertexTestsEXT(testCtx));
mainGroup->addChild(nvGroup.release());
mainGroup->addChild(extGroup.release());
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
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
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