vkd3d: Implement sampler min/max reduction filtering.

This commit is contained in:
Conor McCarthy
2023-08-18 00:17:02 +10:00
committed by Henri Verbeet
parent dc7cdec9a5
commit cb8da3125b
Notes: Henri Verbeet 2025-11-26 17:14:34 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1846
4 changed files with 62 additions and 14 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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)