From: Henri Verbeet <hverbeet(a)locutus.nl> --- dlls/d3d11/device.c | 11 ++++++++- dlls/d3d11/state.c | 6 ++--- dlls/wined3d/adapter_gl.c | 1 + dlls/wined3d/adapter_vk.c | 26 +++++++++++++++++++++ dlls/wined3d/device.c | 2 +- dlls/wined3d/directx.c | 1 + dlls/wined3d/sampler.c | 41 +++++++++++++++++++++++++++++++--- dlls/wined3d/stateblock.c | 5 ++++- dlls/wined3d/texture_gl.c | 15 +++++++++---- dlls/wined3d/wined3d_private.h | 1 + dlls/wined3d/wined3d_vk.h | 1 + include/wine/wined3d.h | 11 ++++++++- 12 files changed, 107 insertions(+), 14 deletions(-) diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 1053dace677..60ce120c254 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -4899,9 +4899,18 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CheckFeatureSupport(ID3D11Device5 return E_INVALIDARG; } + wined3d_mutex_lock(); + hr = wined3d_device_get_device_caps(device->wined3d_device, &wined3d_caps); + wined3d_mutex_unlock(); + if (FAILED(hr)) + { + WARN("Failed to get device caps, hr %#lx.\n", hr); + return hr; + } + FIXME("Returning fake Options1 support data.\n"); options->TiledResourcesTier = D3D11_TILED_RESOURCES_NOT_SUPPORTED; - options->MinMaxFiltering = FALSE; + options->MinMaxFiltering = wined3d_caps.min_max_filtering; options->ClearViewAlsoSupportsDepthOnlyFormats = FALSE; options->MapOnDefaultBuffers = FALSE; return S_OK; diff --git a/dlls/d3d11/state.c b/dlls/d3d11/state.c index 8818cb6a827..d86ff72732f 100644 --- a/dlls/d3d11/state.c +++ b/dlls/d3d11/state.c @@ -1588,9 +1588,9 @@ static enum wined3d_texture_filter_type wined3d_texture_filter_min_from_d3d11(en return WINED3D_TEXF_POINT; } -static BOOL wined3d_texture_compare_from_d3d11(enum D3D11_FILTER f) +static enum wined3d_filter_reduction_mode wined3d_filter_reduction_mode_from_d3d11(enum D3D11_FILTER f) { - return D3D11_DECODE_IS_COMPARISON_FILTER(f); + return (enum wined3d_filter_reduction_mode)D3D11_DECODE_FILTER_REDUCTION(f); } static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3d_device *device, @@ -1620,7 +1620,7 @@ static HRESULT d3d_sampler_state_init(struct d3d_sampler_state *state, struct d3 wined3d_desc.max_anisotropy = desc->MaxAnisotropy; else wined3d_desc.max_anisotropy = 1; - wined3d_desc.compare = wined3d_texture_compare_from_d3d11(desc->Filter); + wined3d_desc.reduction_mode = wined3d_filter_reduction_mode_from_d3d11(desc->Filter); wined3d_desc.comparison_func = wined3d_cmp_func_from_d3d11(desc->ComparisonFunc); wined3d_desc.srgb_decode = TRUE; diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index d0008a35a3e..9d97ebda371 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4944,6 +4944,7 @@ static void wined3d_adapter_gl_init_d3d_info(struct wined3d_adapter_gl *adapter_ d3d_info->viewport_array_index_any_shader = !!gl_info->supported[ARB_SHADER_VIEWPORT_LAYER_ARRAY]; d3d_info->stencil_export = !!gl_info->supported[ARB_SHADER_STENCIL_EXPORT]; d3d_info->simple_instancing = !!gl_info->supported[ARB_INSTANCED_ARRAYS]; + d3d_info->min_max_filtering = false; d3d_info->unconditional_npot = !!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]; d3d_info->draw_base_vertex_offset = !!gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX]; d3d_info->vertex_bgra = !!gl_info->supported[ARB_VERTEX_ARRAY_BGRA]; diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index ca11ec480d2..86f7971fda7 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2338,6 +2338,7 @@ static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk *adapter_ d3d_info->viewport_array_index_any_shader = false; /* VK_EXT_shader_viewport_index_layer */ d3d_info->stencil_export = vk_info->supported[WINED3D_VK_EXT_SHADER_STENCIL_EXPORT]; d3d_info->simple_instancing = true; + d3d_info->min_max_filtering = !!vk_info->supported[WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX]; d3d_info->unconditional_npot = true; d3d_info->draw_base_vertex_offset = true; d3d_info->vertex_bgra = true; @@ -2406,6 +2407,7 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME, VK_API_VERSION_1_3}, {VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME, ~0u}, {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, VK_API_VERSION_1_2}, + {VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, VK_API_VERSION_1_2}, {VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, ~0u}, {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, ~0u}, {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, ~0u}, @@ -2433,6 +2435,7 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME, WINED3D_VK_EXT_EXTENDED_DYNAMIC_STATE2}, {VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME, WINED3D_VK_EXT_EXTENDED_DYNAMIC_STATE3}, {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, WINED3D_VK_EXT_HOST_QUERY_RESET}, + {VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX}, {VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, WINED3D_VK_EXT_SHADER_STENCIL_EXPORT}, {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, WINED3D_VK_EXT_TRANSFORM_FEEDBACK}, {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, WINED3D_VK_EXT_VERTEX_ATTRIBUTE_DIVISOR}, @@ -2531,6 +2534,7 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, unsigned int ordinal, unsigned int wined3d_creation_flags) { struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; + VkPhysicalDeviceSamplerFilterMinmaxProperties *minmax; struct wined3d_adapter *adapter = &adapter_vk->a; VkPhysicalDeviceIDProperties id_properties; VkPhysicalDeviceProperties2 properties2; @@ -2556,6 +2560,16 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; properties2.pNext = &id_properties; + minmax = &(VkPhysicalDeviceSamplerFilterMinmaxProperties) + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, + .pNext = properties2.pNext, + }; + if (vk_info->supported[WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX]) + properties2.pNext = minmax; + else + minmax = NULL; + if (vk_info->vk_ops.vkGetPhysicalDeviceProperties2) VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk->physical_device, &properties2)); else @@ -2569,6 +2583,18 @@ static BOOL wined3d_adapter_vk_init(struct wined3d_adapter_vk *adapter_vk, else if (ordinal == 0 && wined3d_get_primary_adapter_luid(&primary_luid)) luid = &primary_luid; + if (minmax) + { + TRACE(" VkPhysicalDeviceSamplerFilterMinmaxProperties:\n"); + TRACE(" filterMinmaxSingleComponentFormats: %#x.\n", minmax->filterMinmaxSingleComponentFormats); + TRACE(" filterMinmaxImageComponentMapping: %#x.\n", minmax->filterMinmaxImageComponentMapping); + if (!minmax->filterMinmaxSingleComponentFormats || !minmax->filterMinmaxImageComponentMapping) + { + WARN("Sampler min/max reduction filtering is only partially supported; disabling."); + vk_info->supported[WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX] = false; + } + } + if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_vk_ops)) { free(adapter_vk->device_extensions); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 443bf10ab76..974c195f76b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -751,7 +751,7 @@ void wined3d_device_create_default_samplers(struct wined3d_device *device, struc desc.max_lod = 1000.0f; desc.mip_base_level = 0; desc.max_anisotropy = 1; - desc.compare = FALSE; + desc.reduction_mode = WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE; desc.comparison_func = WINED3D_CMP_NEVER; desc.srgb_decode = TRUE; diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index c3f381a611d..2b673123bb2 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2770,6 +2770,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d_adapter *adapter, caps->viewport_array_index_any_shader = d3d_info->viewport_array_index_any_shader; caps->stencil_export = d3d_info->stencil_export; caps->simple_instancing = d3d_info->simple_instancing; + caps->min_max_filtering = d3d_info->min_max_filtering; caps->max_feature_level = d3d_info->feature_level; diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c index afd26a527f9..56b9ff2e642 100644 --- a/dlls/wined3d/sampler.c +++ b/dlls/wined3d/sampler.c @@ -70,7 +70,7 @@ static void wined3d_sampler_init(struct wined3d_sampler *sampler, struct wined3d TRACE(" Maximum LOD: %.8e.\n", desc->max_lod); TRACE(" Base mip level: %u.\n", desc->mip_base_level); TRACE(" Maximum anisotropy: %u.\n", desc->max_anisotropy); - TRACE(" Comparison: %d.\n", desc->compare); + TRACE(" Reduction mode: %#x.\n", desc->reduction_mode); TRACE(" Comparison func: %#x.\n", desc->comparison_func); TRACE(" SRGB decode: %d.\n", desc->srgb_decode); @@ -112,8 +112,10 @@ static void wined3d_sampler_gl_cs_init(void *object) GL_EXTCALL(glSamplerParameterf(name, GL_TEXTURE_MAX_LOD, desc->max_lod)); if (gl_info->supported[ARB_TEXTURE_FILTER_ANISOTROPIC]) GL_EXTCALL(glSamplerParameteri(name, GL_TEXTURE_MAX_ANISOTROPY, desc->max_anisotropy)); - if (desc->compare) + if (desc->reduction_mode == WINED3D_FILTER_REDUCTION_COMPARISON) GL_EXTCALL(glSamplerParameteri(name, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE)); + else if (desc->reduction_mode != WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE) + WARN("Sampler min/max reduction filtering is not supported.\n"); GL_EXTCALL(glSamplerParameteri(name, GL_TEXTURE_COMPARE_FUNC, wined3d_gl_compare_func(desc->comparison_func))); if ((context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) @@ -212,8 +214,26 @@ static VkBorderColor vk_border_colour_from_wined3d(const struct wined3d_color *c return VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; } +static VkSamplerReductionMode vk_reduction_mode_from_wined3d(enum wined3d_filter_reduction_mode mode) +{ + switch (mode) + { + case WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE: + case WINED3D_FILTER_REDUCTION_COMPARISON: + return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + case WINED3D_FILTER_REDUCTION_MINIMUM: + return VK_SAMPLER_REDUCTION_MODE_MIN; + case WINED3D_FILTER_REDUCTION_MAXIMUM: + return VK_SAMPLER_REDUCTION_MODE_MAX; + default: + FIXME("Unhandled reduction mode %#x.\n", mode); + return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; + } +} + static void wined3d_sampler_vk_cs_init(void *object) { + VkSamplerReductionModeCreateInfo reduction_desc; struct wined3d_sampler_vk *sampler_vk = object; const struct wined3d_sampler_desc *desc; const struct wined3d_d3d_info *d3d_info; @@ -244,7 +264,7 @@ static void wined3d_sampler_vk_cs_init(void *object) sampler_desc.mipLodBias = desc->lod_bias; sampler_desc.anisotropyEnable = desc->max_anisotropy != 1; sampler_desc.maxAnisotropy = desc->max_anisotropy; - sampler_desc.compareEnable = !!desc->compare; + sampler_desc.compareEnable = desc->reduction_mode == WINED3D_FILTER_REDUCTION_COMPARISON; sampler_desc.compareOp = vk_compare_op_from_wined3d(desc->comparison_func); sampler_desc.minLod = desc->min_lod; sampler_desc.maxLod = desc->max_lod; @@ -259,6 +279,21 @@ static void wined3d_sampler_vk_cs_init(void *object) if ((d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) && !desc->srgb_decode) FIXME("Unhandled srgb_decode %#x.\n", desc->srgb_decode); + reduction_desc.reductionMode = vk_reduction_mode_from_wined3d(desc->reduction_mode); + if (reduction_desc.reductionMode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE) + { + if (vk_info->supported[WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX]) + { + reduction_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO; + reduction_desc.pNext = sampler_desc.pNext; + sampler_desc.pNext = &reduction_desc; + } + else + { + FIXME("Sampler min/max reduction filtering is not supported.\n"); + } + } + vr = VK_CALL(vkCreateSampler(device_vk->vk_device, &sampler_desc, NULL, &vk_sampler)); context_release(&context_vk->c); if (vr < 0) diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index af192cff669..958d8bb5a29 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -2889,7 +2889,10 @@ static void sampler_desc_from_sampler_states(struct wined3d_sampler_desc *desc, && sampler_states[WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_ANISOTROPIC) || (texture->flags & WINED3D_TEXTURE_COND_NP2)) desc->max_anisotropy = 1; - desc->compare = texture->resource.format_attrs & WINED3D_FORMAT_ATTR_SHADOW; + if (texture->resource.format_attrs & WINED3D_FORMAT_ATTR_SHADOW) + desc->reduction_mode = WINED3D_FILTER_REDUCTION_COMPARISON; + else + desc->reduction_mode = WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE; desc->comparison_func = WINED3D_CMP_LESSEQUAL; /* Only use the LSB of the WINED3D_SAMP_SRGB_TEXTURE value. This matches diff --git a/dlls/wined3d/texture_gl.c b/dlls/wined3d/texture_gl.c index 993ff7c0383..7a097f85f30 100644 --- a/dlls/wined3d/texture_gl.c +++ b/dlls/wined3d/texture_gl.c @@ -2731,7 +2731,7 @@ void wined3d_texture_gl_bind(struct wined3d_texture_gl *texture_gl, gl_tex->sampler_desc.min_lod = -1000.0f; gl_tex->sampler_desc.max_lod = 1000.0f; gl_tex->sampler_desc.max_anisotropy = 1; - gl_tex->sampler_desc.compare = FALSE; + gl_tex->sampler_desc.reduction_mode = WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE; gl_tex->sampler_desc.comparison_func = WINED3D_CMP_LESSEQUAL; if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) gl_tex->sampler_desc.srgb_decode = TRUE; @@ -2888,13 +2888,20 @@ void wined3d_texture_gl_apply_sampler_desc(struct wined3d_texture_gl *texture_gl gl_tex->sampler_desc.srgb_decode = sampler_desc->srgb_decode; } - if (!sampler_desc->compare != !gl_tex->sampler_desc.compare) + if (!sampler_desc->reduction_mode != !gl_tex->sampler_desc.reduction_mode) { - if (sampler_desc->compare) + if (sampler_desc->reduction_mode == WINED3D_FILTER_REDUCTION_COMPARISON) + { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + } else + { gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); - gl_tex->sampler_desc.compare = sampler_desc->compare; + if (sampler_desc->reduction_mode != WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE) + WARN("Sampler min/max reduction filtering is not supported.\n"); + } + + gl_tex->sampler_desc.reduction_mode = sampler_desc->reduction_mode; } checkGLcall("Texture parameter application"); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 7b955d798f8..498ac5628fb 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -227,6 +227,7 @@ struct wined3d_d3d_info uint32_t shader_output_interpolation : 1; uint32_t viewport_array_index_any_shader : 1; uint32_t simple_instancing : 1; + uint32_t min_max_filtering : 1; uint32_t stencil_export : 1; /* If zero, only conditional NPOT textures are supported, via * WINED3D_GL_NORMALIZED_TEXRECT. */ diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index 55f40d5a831..6fcfe2afbf2 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -255,6 +255,7 @@ enum wined3d_vk_extension WINED3D_VK_EXT_EXTENDED_DYNAMIC_STATE2, WINED3D_VK_EXT_EXTENDED_DYNAMIC_STATE3, WINED3D_VK_EXT_HOST_QUERY_RESET, + WINED3D_VK_EXT_SAMPLER_FILTER_MINMAX, WINED3D_VK_EXT_SHADER_STENCIL_EXPORT, WINED3D_VK_EXT_TRANSFORM_FEEDBACK, WINED3D_VK_EXT_VERTEX_ATTRIBUTE_DIVISOR, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 2c57b55cb1a..9918ac68838 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -469,6 +469,14 @@ enum wined3d_cmp_func WINED3D_CMP_ALWAYS = 8, }; +enum wined3d_filter_reduction_mode +{ + WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE = 0x0, + WINED3D_FILTER_REDUCTION_COMPARISON = 0x1, + WINED3D_FILTER_REDUCTION_MINIMUM = 0x2, + WINED3D_FILTER_REDUCTION_MAXIMUM = 0x3, +}; + enum wined3d_depth_buffer_type { WINED3D_ZB_FALSE = 0, @@ -2014,6 +2022,7 @@ struct wined3d_caps bool viewport_array_index_any_shader; bool stencil_export; bool simple_instancing; + bool min_max_filtering; enum wined3d_feature_level max_feature_level; }; @@ -2116,7 +2125,7 @@ struct wined3d_sampler_desc float max_lod; unsigned int mip_base_level; unsigned int max_anisotropy; - BOOL compare; + enum wined3d_filter_reduction_mode reduction_mode; enum wined3d_cmp_func comparison_func; BOOL srgb_decode; }; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9683