From 06274621927a624ab1f8c88d159ac054ee625efe Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Thu, 24 Mar 2022 14:36:09 +1000 Subject: [PATCH] vkd3d: Use Vulkan null descriptors if EXT_robustness2 is available. This implements all remaining unsupported image view dimensions and saves a small amount of resources because null buffers and images are no longer needed. It matches the D3D12 requirement that all reads return zero, which is not strictly true of the existing implementation using resources of small but non-zero size. Warnings on null view creation are silenced because there should no longer be a difference from D3D12 behaviour. Signed-off-by: Conor McCarthy Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- README | 2 +- configure.ac | 2 +- libs/vkd3d/device.c | 8 +++++ libs/vkd3d/resource.c | 74 +++++++++++++++++++++++++------------- libs/vkd3d/vkd3d_private.h | 1 + 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/README b/README index 066a24bc..465d5f91 100644 --- a/README +++ b/README @@ -9,7 +9,7 @@ similar, but not identical, to Direct3D 12. Building vkd3d ============== -Vkd3d depends on SPIRV-Headers and Vulkan-Headers (>= 1.1.113). +Vkd3d depends on SPIRV-Headers and Vulkan-Headers (>= 1.2.139). Vkd3d generates some of its headers from IDL files. If you are using the release tarballs, then these headers are pre-generated and are included. If diff --git a/configure.ac b/configure.ac index 53029d2c..308bdda1 100644 --- a/configure.ac +++ b/configure.ac @@ -81,7 +81,7 @@ AS_IF([test "x$ac_cv_header_spirv_unified1_GLSL_std_450_h" != "xyes" \ -a "x$ac_cv_header_vulkan_GLSL_std_450_h" != "xyes"], [AC_MSG_ERROR([GLSL.std.450.h not found.])]) -VKD3D_CHECK_VULKAN_HEADER_VERSION([113], [AC_MSG_ERROR([Vulkan headers are too old, 1.1.113 is required.])]) +VKD3D_CHECK_VULKAN_HEADER_VERSION([139], [AC_MSG_ERROR([Vulkan headers are too old, 1.2.139 is required.])]) AC_CHECK_DECL([SpvCapabilityDemoteToHelperInvocationEXT],, [AC_MSG_ERROR([SPIR-V headers are too old.])], [ #ifdef HAVE_SPIRV_UNIFIED1_SPIRV_H diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index d1629284..eb470c12 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -135,6 +135,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_DEBUG_MARKER, EXT_debug_marker), VK_EXTENSION(EXT_DEPTH_CLIP_ENABLE, EXT_depth_clip_enable), VK_EXTENSION(EXT_DESCRIPTOR_INDEXING, EXT_descriptor_indexing), + VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), VK_EXTENSION(EXT_TEXEL_BUFFER_ALIGNMENT, EXT_texel_buffer_alignment), @@ -797,6 +798,7 @@ struct vkd3d_physical_device_info VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features; VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_features; VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features; + VkPhysicalDeviceRobustness2FeaturesEXT robustness2_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT texel_buffer_alignment_features; VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features; @@ -813,6 +815,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *vertex_divisor_properties; VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment_properties; VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features; + VkPhysicalDeviceRobustness2FeaturesEXT *robustness2_features; VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *vertex_divisor_features; VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT *buffer_alignment_features; VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *demote_features; @@ -827,6 +830,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i conditional_rendering_features = &info->conditional_rendering_features; depth_clip_features = &info->depth_clip_features; descriptor_indexing_features = &info->descriptor_indexing_features; + robustness2_features = &info->robustness2_features; descriptor_indexing_properties = &info->descriptor_indexing_properties; maintenance3_properties = &info->maintenance3_properties; demote_features = &info->demote_features; @@ -845,6 +849,8 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i vk_prepend_struct(&info->features2, depth_clip_features); descriptor_indexing_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; vk_prepend_struct(&info->features2, descriptor_indexing_features); + robustness2_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + vk_prepend_struct(&info->features2, robustness2_features); demote_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; vk_prepend_struct(&info->features2, demote_features); buffer_alignment_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT; @@ -1577,6 +1583,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, vulkan_info->EXT_conditional_rendering = false; if (!physical_device_info->depth_clip_features.depthClipEnable) vulkan_info->EXT_depth_clip_enable = false; + if (!physical_device_info->robustness2_features.nullDescriptor) + vulkan_info->EXT_robustness2 = false; if (!physical_device_info->demote_features.shaderDemoteToHelperInvocation) vulkan_info->EXT_shader_demote_to_helper_invocation = false; if (!physical_device_info->texel_buffer_alignment_features.texelBufferAlignment) diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index cbbd4170..38fd632b 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -2423,10 +2423,10 @@ bool vkd3d_create_buffer_view(struct d3d12_device *device, VkBuffer vk_buffer, c VkDeviceSize offset, VkDeviceSize size, struct vkd3d_view **view) { const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; + VkBufferView vk_view = VK_NULL_HANDLE; struct vkd3d_view *object; - VkBufferView vk_view; - if (!vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view)) + if (vk_buffer && !vkd3d_create_vk_buffer_view(device, vk_buffer, format, offset, size, &vk_view)) return false; if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_BUFFER))) @@ -2711,28 +2711,31 @@ bool vkd3d_create_texture_view(struct d3d12_device *device, VkImage vk_image, const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; const struct vkd3d_format *format = desc->format; struct VkImageViewCreateInfo view_desc; + VkImageView vk_view = VK_NULL_HANDLE; struct vkd3d_view *object; - VkImageView vk_view; VkResult vr; - view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_desc.pNext = NULL; - view_desc.flags = 0; - view_desc.image = vk_image; - view_desc.viewType = desc->view_type; - view_desc.format = format->vk_format; - vkd3d_set_view_swizzle_for_format(&view_desc.components, format, desc->allowed_swizzle); - if (desc->allowed_swizzle) - vk_component_mapping_compose(&view_desc.components, &desc->components); - view_desc.subresourceRange.aspectMask = desc->vk_image_aspect; - view_desc.subresourceRange.baseMipLevel = desc->miplevel_idx; - view_desc.subresourceRange.levelCount = desc->miplevel_count; - view_desc.subresourceRange.baseArrayLayer = desc->layer_idx; - view_desc.subresourceRange.layerCount = desc->layer_count; - if ((vr = VK_CALL(vkCreateImageView(device->vk_device, &view_desc, NULL, &vk_view))) < 0) + if (vk_image) { - WARN("Failed to create Vulkan image view, vr %d.\n", vr); - return false; + view_desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_desc.pNext = NULL; + view_desc.flags = 0; + view_desc.image = vk_image; + view_desc.viewType = desc->view_type; + view_desc.format = format->vk_format; + vkd3d_set_view_swizzle_for_format(&view_desc.components, format, desc->allowed_swizzle); + if (desc->allowed_swizzle) + vk_component_mapping_compose(&view_desc.components, &desc->components); + view_desc.subresourceRange.aspectMask = desc->vk_image_aspect; + view_desc.subresourceRange.baseMipLevel = desc->miplevel_idx; + view_desc.subresourceRange.levelCount = desc->miplevel_count; + view_desc.subresourceRange.baseArrayLayer = desc->layer_idx; + view_desc.subresourceRange.layerCount = desc->layer_count; + if ((vr = VK_CALL(vkCreateImageView(device->vk_device, &view_desc, NULL, &vk_view))) < 0) + { + WARN("Failed to create Vulkan image view, vr %d.\n", vr); + return false; + } } if (!(object = vkd3d_view_create(VKD3D_VIEW_TYPE_IMAGE))) @@ -2782,7 +2785,7 @@ void d3d12_desc_create_cbv(struct d3d12_desc *descriptor, /* NULL descriptor */ buffer_info->buffer = device->null_resources.vk_buffer; buffer_info->offset = 0; - buffer_info->range = VKD3D_NULL_BUFFER_SIZE; + buffer_info->range = VK_WHOLE_SIZE; } descriptor->magic = VKD3D_DESCRIPTOR_MAGIC_CBV; @@ -2815,7 +2818,8 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor, switch (desc->ViewDimension) { case D3D12_SRV_DIMENSION_BUFFER: - WARN("Creating NULL buffer SRV %#x.\n", desc->Format); + if (!device->vk_info.EXT_robustness2) + WARN("Creating NULL buffer SRV %#x.\n", desc->Format); if (vkd3d_create_buffer_view(device, null_resources->vk_buffer, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false), @@ -2838,11 +2842,19 @@ static void vkd3d_create_null_srv(struct d3d12_desc *descriptor, break; default: + if (device->vk_info.EXT_robustness2) + { + vk_image = VK_NULL_HANDLE; + /* view_type is not used for Vulkan null descriptors, but make it valid. */ + vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D; + break; + } FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); return; } - WARN("Creating NULL SRV %#x.\n", desc->ViewDimension); + if (!device->vk_info.EXT_robustness2) + WARN("Creating NULL SRV %#x.\n", desc->ViewDimension); vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false); vkd3d_desc.miplevel_idx = 0; @@ -3052,7 +3064,8 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, switch (desc->ViewDimension) { case D3D12_UAV_DIMENSION_BUFFER: - WARN("Creating NULL buffer UAV %#x.\n", desc->Format); + if (!device->vk_info.EXT_robustness2) + WARN("Creating NULL buffer UAV %#x.\n", desc->Format); if (vkd3d_create_buffer_view(device, null_resources->vk_storage_buffer, vkd3d_get_format(device, DXGI_FORMAT_R32_UINT, false), @@ -3075,11 +3088,19 @@ static void vkd3d_create_null_uav(struct d3d12_desc *descriptor, break; default: + if (device->vk_info.EXT_robustness2) + { + vk_image = VK_NULL_HANDLE; + /* view_type is not used for Vulkan null descriptors, but make it valid. */ + vkd3d_desc.view_type = VK_IMAGE_VIEW_TYPE_2D; + break; + } FIXME("Unhandled view dimension %#x.\n", desc->ViewDimension); return; } - WARN("Creating NULL UAV %#x.\n", desc->ViewDimension); + if (!device->vk_info.EXT_robustness2) + WARN("Creating NULL UAV %#x.\n", desc->ViewDimension); vkd3d_desc.format = vkd3d_get_format(device, VKD3D_NULL_VIEW_FORMAT, false); vkd3d_desc.miplevel_idx = 0; @@ -4421,6 +4442,9 @@ HRESULT vkd3d_init_null_resources(struct vkd3d_null_resources *null_resources, memset(null_resources, 0, sizeof(*null_resources)); + if (device->vk_info.EXT_robustness2) + return S_OK; + memset(&heap_properties, 0, sizeof(heap_properties)); heap_properties.Type = D3D12_HEAP_TYPE_DEFAULT; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index c28eb234..796dfefd 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -131,6 +131,7 @@ struct vkd3d_vulkan_info bool EXT_debug_marker; bool EXT_depth_clip_enable; bool EXT_descriptor_indexing; + bool EXT_robustness2; bool EXT_shader_demote_to_helper_invocation; bool EXT_shader_stencil_export; bool EXT_texel_buffer_alignment;