From cb8da3125b080b23136c3d1ee1b9e271701d1835 Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Fri, 18 Aug 2023 00:17:02 +1000 Subject: [PATCH] vkd3d: Implement sampler min/max reduction filtering. --- libs/vkd3d/device.c | 17 +++++++++++++ libs/vkd3d/resource.c | 38 +++++++++++++++++++++++++--- libs/vkd3d/vkd3d_private.h | 1 + tests/hlsl/sample-minmax.shader_test | 20 +++++++-------- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 6af5e2a5c..33628d486 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -109,6 +109,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), + VK_EXTENSION(EXT_SAMPLER_FILTER_MINMAX, EXT_sampler_filter_minmax), 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_SHADER_VIEWPORT_INDEX_LAYER, EXT_shader_viewport_index_layer), @@ -835,6 +836,7 @@ struct vkd3d_physical_device_info /* properties */ VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_properties; VkPhysicalDeviceMaintenance3Properties maintenance3_properties; + VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT filter_minmax_properties; VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties; VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties; VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties; @@ -900,6 +902,8 @@ static void vkd3d_chain_physical_device_info_structures(struct vkd3d_physical_de vk_prepend_struct(&info->properties2, &info->maintenance3_properties); if (vulkan_info->EXT_descriptor_indexing) vk_prepend_struct(&info->properties2, &info->descriptor_indexing_properties); + if (vulkan_info->EXT_sampler_filter_minmax) + vk_prepend_struct(&info->properties2, &info->filter_minmax_properties); if (vulkan_info->EXT_texel_buffer_alignment) vk_prepend_struct(&info->properties2, &info->texel_buffer_alignment_properties); if (vulkan_info->EXT_transform_feedback) @@ -936,6 +940,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i info->properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; info->maintenance3_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; info->descriptor_indexing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; + info->filter_minmax_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT; info->texel_buffer_alignment_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; info->xfb_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; info->vertex_divisor_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; @@ -1017,6 +1022,7 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic const VkPhysicalDeviceLimits *limits = &info->properties2.properties.limits; const VkPhysicalDeviceDescriptorIndexingPropertiesEXT *descriptor_indexing; const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment; + const VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *minmax; const VkPhysicalDeviceMaintenance3Properties *maintenance3; const VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb; @@ -1196,6 +1202,11 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic TRACE(" maxPerSetDescriptors: %u.\n", maintenance3->maxPerSetDescriptors); TRACE(" maxMemoryAllocationSize: %#"PRIx64".\n", maintenance3->maxMemoryAllocationSize); + minmax = &info->filter_minmax_properties; + TRACE(" VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT:\n"); + TRACE(" filterMinmaxSingleComponentFormats: %#x.\n", minmax->filterMinmaxSingleComponentFormats); + TRACE(" filterMinmaxImageComponentMapping: %#x.\n", minmax->filterMinmaxImageComponentMapping); + buffer_alignment = &info->texel_buffer_alignment_properties; TRACE(" VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT:\n"); TRACE(" storageTexelBufferOffsetAlignmentBytes: %#"PRIx64".\n", @@ -1866,6 +1877,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, physical_device_info->formats4444_features.formatA4B4G4R4 = VK_FALSE; + if (!vulkan_info->EXT_sampler_filter_minmax) + WARN("Sampler min/max reduction filtering is not supported.\n"); + else if (!physical_device_info->filter_minmax_properties.filterMinmaxSingleComponentFormats + || !physical_device_info->filter_minmax_properties.filterMinmaxImageComponentMapping) + WARN("Sampler min/max reduction filtering is only partially supported."); + vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties; if (get_spec_version(vk_extensions, vk_extension_count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) diff --git a/libs/vkd3d/resource.c b/libs/vkd3d/resource.c index 7946445ad..f1491cbc2 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -3661,6 +3661,24 @@ bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, } /* samplers */ + +static VkSamplerReductionModeEXT vk_reduction_mode_from_d3d12(D3D12_FILTER_REDUCTION_TYPE mode) +{ + switch (mode) + { + case D3D12_FILTER_REDUCTION_TYPE_STANDARD: + case D3D12_FILTER_REDUCTION_TYPE_COMPARISON: + return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + case D3D12_FILTER_REDUCTION_TYPE_MINIMUM: + return VK_SAMPLER_REDUCTION_MODE_MIN; + case D3D12_FILTER_REDUCTION_TYPE_MAXIMUM: + return VK_SAMPLER_REDUCTION_MODE_MAX; + default: + FIXME("Unhandled reduction mode %#x.\n", mode); + return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + } +} + static VkFilter vk_filter_from_d3d12(D3D12_FILTER_TYPE type) { switch (type) @@ -3734,16 +3752,13 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, float min_lod, float max_lod, VkSampler *vk_sampler) { + VkSamplerReductionModeCreateInfoEXT reduction_desc; const struct vkd3d_vk_device_procs *vk_procs; struct VkSamplerCreateInfo sampler_desc; VkResult vr; vk_procs = &device->vk_procs; - if (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MINIMUM - || D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MAXIMUM) - FIXME("Min/max reduction mode not supported.\n"); - sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; sampler_desc.pNext = NULL; sampler_desc.flags = 0; @@ -3767,6 +3782,21 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); + reduction_desc.reductionMode = vk_reduction_mode_from_d3d12(D3D12_DECODE_FILTER_REDUCTION(filter)); + if (reduction_desc.reductionMode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE) + { + if (device->vk_info.EXT_sampler_filter_minmax) + { + reduction_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT; + reduction_desc.pNext = NULL; + vk_prepend_struct(&sampler_desc, &reduction_desc); + } + else + { + FIXME("Sampler min/max reduction filtering is not supported by the device.\n"); + } + } + if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) WARN("Failed to create Vulkan sampler, vr %d.\n", vr); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 7a2fd010a..a6b4ffcd3 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -144,6 +144,7 @@ struct vkd3d_vulkan_info bool EXT_fragment_shader_interlock; bool EXT_mutable_descriptor_type; bool EXT_robustness2; + bool EXT_sampler_filter_minmax; bool EXT_shader_demote_to_helper_invocation; bool EXT_shader_stencil_export; bool EXT_shader_viewport_index_layer; diff --git a/tests/hlsl/sample-minmax.shader_test b/tests/hlsl/sample-minmax.shader_test index 0fe88670f..77c390160 100644 --- a/tests/hlsl/sample-minmax.shader_test +++ b/tests/hlsl/sample-minmax.shader_test @@ -45,19 +45,19 @@ filter minimum linear linear point [test] draw quad -todo(d3d12) probe (36, 20) f32(.25, .00, 0, 1) -todo(d3d12) probe (20, 36) f32(.00, .25, 0, 1) -todo(d3d12) probe (36, 36) f32(.25, .25, 0, 1) -todo(d3d12) probe (52, 36) f32(.50, .25, 0, 1) -todo(d3d12) probe (36, 52) f32(.25, .50, 0, 1) +todo(mvk) probe (36, 20) f32(.25, .00, 0, 1) +todo(mvk) probe (20, 36) f32(.00, .25, 0, 1) +todo(mvk) probe (36, 36) f32(.25, .25, 0, 1) +todo(mvk) probe (52, 36) f32(.50, .25, 0, 1) +todo(mvk) probe (36, 52) f32(.25, .50, 0, 1) [sampler 0] filter maximum linear linear point [test] draw quad -todo(d3d12) probe (36, 20) f32(.50, .25, 0, 1) -todo(d3d12) probe (20, 36) f32(.25, .50, 0, 1) -todo(d3d12) probe (36, 36) f32(.50, .50, 0, 1) -todo(d3d12) probe (52, 36) f32(.75, .50, 0, 1) -todo(d3d12) probe (36, 52) f32(.50, .75, 0, 1) +todo(mvk) probe (36, 20) f32(.50, .25, 0, 1) +todo(mvk) probe (20, 36) f32(.25, .50, 0, 1) +todo(mvk) probe (36, 36) f32(.50, .50, 0, 1) +todo(mvk) probe (52, 36) f32(.75, .50, 0, 1) +todo(mvk) probe (36, 52) f32(.50, .75, 0, 1)