[PATCH 0/4] MR9683: wined3d: Implement sampler min/max reduction filtering.
From: Henri Verbeet <hverbeet(a)locutus.nl> --- include/d3d11.idl | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/include/d3d11.idl b/include/d3d11.idl index 9a246fa7cec..d13a7ad85bd 100644 --- a/include/d3d11.idl +++ b/include/d3d11.idl @@ -855,23 +855,34 @@ typedef enum D3D11_FILTER_TYPE D3D11_FILTER_TYPE_LINEAR = 1 } D3D11_FILTER_TYPE; +typedef enum D3D11_FILTER_REDUCTION_TYPE +{ + D3D11_FILTER_REDUCTION_TYPE_STANDARD = 0x0, + D3D11_FILTER_REDUCTION_TYPE_COMPARISON = 0x1, + D3D11_FILTER_REDUCTION_TYPE_MINIMUM = 0x2, + D3D11_FILTER_REDUCTION_TYPE_MAXIMUM = 0x3, +} D3D11_FILTER_REDUCTION_TYPE; + +const UINT D3D11_FILTER_REDUCTION_TYPE_SHIFT = 7; const UINT D3D11_MIN_FILTER_SHIFT = 4; const UINT D3D11_MAG_FILTER_SHIFT = 2; const UINT D3D11_MIP_FILTER_SHIFT = 0; -const UINT D3D11_FILTER_TYPE_MASK = 0x00000003; -const UINT D3D11_COMPARISON_FILTERING_BIT = 0x00000080; -const UINT D3D11_ANISOTROPIC_FILTERING_BIT = 0x00000040; -cpp_quote("#define D3D11_ENCODE_BASIC_FILTER(min, mag, mip, bComparison) \\") -cpp_quote(" ((D3D11_FILTER)(((bComparison) ? D3D11_COMPARISON_FILTERING_BIT : 0 ) | \\") -cpp_quote(" (((min)&D3D11_FILTER_TYPE_MASK) << D3D11_MIN_FILTER_SHIFT) | \\") +const UINT D3D11_FILTER_REDUCTION_TYPE_MASK = 0x00000003; +const UINT D3D11_FILTER_TYPE_MASK = 0x00000003; +const UINT D3D11_COMPARISON_FILTERING_BIT = 0x00000080; +const UINT D3D11_ANISOTROPIC_FILTERING_BIT = 0x00000040; + +cpp_quote("#define D3D11_ENCODE_BASIC_FILTER(min, mag, mip, reduction_mode) \\") +cpp_quote(" ((D3D11_FILTER)((((min)&D3D11_FILTER_TYPE_MASK) << D3D11_MIN_FILTER_SHIFT) | \\") cpp_quote(" (((mag)&D3D11_FILTER_TYPE_MASK) << D3D11_MAG_FILTER_SHIFT) | \\") -cpp_quote(" (((mip)&D3D11_FILTER_TYPE_MASK) << D3D11_MIP_FILTER_SHIFT)))") +cpp_quote(" (((mip)&D3D11_FILTER_TYPE_MASK) << D3D11_MIP_FILTER_SHIFT) | \\") +cpp_quote(" (((reduction_mode)&D3D11_FILTER_REDUCTION_TYPE_MASK) << D3D11_FILTER_REDUCTION_TYPE_SHIFT)))") -cpp_quote("#define D3D11_ENCODE_ANISOTROPIC_FILTER(bComparison) \\") +cpp_quote("#define D3D11_ENCODE_ANISOTROPIC_FILTER(reduction_mode) \\") cpp_quote(" ((D3D11_FILTER)(D3D11_ANISOTROPIC_FILTERING_BIT | \\" ) cpp_quote(" D3D11_ENCODE_BASIC_FILTER(D3D11_FILTER_TYPE_LINEAR,D3D11_FILTER_TYPE_LINEAR, \\" ) -cpp_quote(" D3D11_FILTER_TYPE_LINEAR,bComparison)))" ) +cpp_quote(" D3D11_FILTER_TYPE_LINEAR,reduction_mode)))" ) cpp_quote("#define D3D11_DECODE_MIN_FILTER(d3d11Filter) \\") cpp_quote(" ((D3D11_FILTER_TYPE)(((d3d11Filter) >> D3D11_MIN_FILTER_SHIFT) & D3D11_FILTER_TYPE_MASK))") @@ -882,7 +893,11 @@ cpp_quote(" ((D3D11_FILTER_TYPE)(((d3d11Filter) >> D3D11_MAG_FILTER_SHIFT) & cpp_quote("#define D3D11_DECODE_MIP_FILTER(d3d11Filter) \\") cpp_quote(" ((D3D11_FILTER_TYPE)(((d3d11Filter) >> D3D11_MIP_FILTER_SHIFT) & D3D11_FILTER_TYPE_MASK))") -cpp_quote("#define D3D11_DECODE_IS_COMPARISON_FILTER(d3d11Filter) ((d3d11Filter) & D3D11_COMPARISON_FILTERING_BIT)") +cpp_quote("#define D3D11_DECODE_FILTER_REDUCTION(filter) \\") +cpp_quote(" ((D3D11_FILTER_REDUCTION_TYPE)(((filter) >> D3D11_FILTER_REDUCTION_TYPE_SHIFT) & D3D11_FILTER_REDUCTION_TYPE_MASK))") + +cpp_quote("#define D3D11_DECODE_IS_COMPARISON_FILTER(filter) \\") +cpp_quote(" (D3D11_DECODE_FILTER_REDUCTION(filter) == D3D11_FILTER_REDUCTION_TYPE_COMPARISON)") cpp_quote("#define D3D11_DECODE_IS_ANISOTROPIC_FILTER(d3d11Filter) \\") cpp_quote(" (((d3d11Filter) & D3D11_ANISOTROPIC_FILTERING_BIT ) \\" ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9683
From: Henri Verbeet <hverbeet(a)locutus.nl> --- dlls/d3d11/tests/d3d11.c | 195 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index af90fa2a7aa..05b1134bfdf 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -37322,6 +37322,200 @@ static void test_h264_decoder(void) release_test_context(&test_context); } +static void test_filter_minmax(void) +{ + ID3D11Resource *srv_resource, *rtv_resource; + D3D11_FEATURE_DATA_D3D11_OPTIONS1 options1; + struct d3d11_test_context test_context; + ID3D10Blob *bytecode, *vs_blob; + ID3D11ShaderResourceView *srv; + ID3D11DeviceContext *context; + struct resource_readback rb; + ID3D11RenderTargetView *rtv; + D3D11_SUBRESOURCE_DATA data; + ID3D11SamplerState *sampler; + ID3D11PixelShader *ps; + const struct vec4 *c; + ID3D11Device *device; + size_t i, j; + HRESULT hr; + + static const struct resource_desc srv_resource_desc = + { + .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, + .width = 4, + .height = 4, + .depth_or_array_size = 1, + .level_count = 1, + .format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .sample_desc.Count = 1, + .usage = D3D11_USAGE_DEFAULT, + .bind_flags = D3D11_BIND_SHADER_RESOURCE, + }, + rtv_resource_desc = + { + .dimension = D3D11_RESOURCE_DIMENSION_TEXTURE2D, + .width = 64, + .height = 64, + .depth_or_array_size = 1, + .level_count = 1, + .format = DXGI_FORMAT_R32G32B32A32_FLOAT, + .sample_desc.Count = 1, + .usage = D3D11_USAGE_DEFAULT, + .bind_flags = D3D11_BIND_RENDER_TARGET, + }; + + static const struct vec4 srv_data[] = + { + {.00, .00, .00, 1.0}, {.25, .00, .00, 1.0}, {.50, .00, .00, 1.0}, {.75, .00, .00, 1.0}, + {.00, .25, .00, 1.0}, {.25, .25, .00, 1.0}, {.50, .25, .00, 1.0}, {.75, .25, .00, 1.0}, + {.00, .50, .00, 1.0}, {.25, .50, .00, 1.0}, {.50, .50, .00, 1.0}, {.75, .50, .00, 1.0}, + {.00, .75, .00, 1.0}, {.25, .75, .00, 1.0}, {.50, .75, .00, 1.0}, {.75, .75, .00, 1.0}, + }; + + static const struct expected + { + unsigned int x, y; + struct vec4 c; + } + avg_expected[] = + { + {36, 20, {.375, .125, 0, 1}}, + {20, 36, {.125, .375, 0, 1}}, + {36, 36, {.375, .375, 0, 1}}, + {52, 36, {.625, .375, 0, 1}}, + {36, 52, {.375, .625, 0, 1}}, + }, + minimum_expected[] = + { + {36, 20, {.25, .00, 0, 1}}, + {20, 36, {.00, .25, 0, 1}}, + {36, 36, {.25, .25, 0, 1}}, + {52, 36, {.50, .25, 0, 1}}, + {36, 52, {.25, .50, 0, 1}}, + }, + maximum_expected[] = + { + {36, 20, {.50, .25, 0, 1}}, + {20, 36, {.25, .50, 0, 1}}, + {36, 36, {.50, .50, 0, 1}}, + {52, 36, {.75, .50, 0, 1}}, + {36, 52, {.50, .75, 0, 1}}, + }; + + static const struct + { + D3D11_FILTER filter; + const struct expected *expected; + size_t expected_count; + } + tests[] = + { + {D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT, avg_expected, ARRAY_SIZE(avg_expected)}, + {D3D11_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT, minimum_expected, ARRAY_SIZE(minimum_expected)}, + {D3D11_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT, maximum_expected, ARRAY_SIZE(maximum_expected)}, + }; + + static const char vs_code[] = + "void main(float4 p : POSITION, out float2 t : TEXCOORD, out float4 position : SV_Position)\n" + "{\n" + " t.x = (p.x + 1.0) / 2.0;\n" + " t.y = (-p.y + 1.0) / 2.0;\n" + " position = p;\n" + "}\n"; + static const char ps_code[] = + "Texture2D t;\n" + "sampler s;\n" + "\n" + "float4 main(float2 p : TEXCOORD) : SV_Target\n" + "{\n" + " return t.Sample(s, floor(p * 8.0) / 8.0);\n" + "}\n"; + + static const float white_color[] = {1.0f, 1.0f, 1.0f, 1.0f}; + + if (!init_test_context(&test_context, NULL)) + return; + + device = test_context.device; + context = test_context.immediate_context; + + if (FAILED(hr = ID3D11Device_CheckFeatureSupport(device, D3D11_FEATURE_D3D11_OPTIONS1, + &options1, sizeof(options1))) || !options1.MinMaxFiltering) + { + skip("Min/max reduction filtering is not supported.\n"); + release_test_context(&test_context); + return; + } + + vs_blob = compile_shader(vs_code, strlen(vs_code), "vs_4_0"); + + bytecode = compile_shader(ps_code, strlen(ps_code), "ps_4_0"); + hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(bytecode), + ID3D10Blob_GetBufferSize(bytecode), NULL, &ps); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D10Blob_Release(bytecode); + ID3D11DeviceContext_PSSetShader(context, ps, NULL, 0); + + data.pSysMem = srv_data; + data.SysMemPitch = srv_resource_desc.width * sizeof(*srv_data); + data.SysMemSlicePitch = srv_resource_desc.height * data.SysMemPitch; + hr = create_resource(device, &srv_resource_desc, &data, &srv_resource); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D11Device_CreateShaderResourceView(device, srv_resource, NULL, &srv); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &srv); + + hr = create_resource(device, &rtv_resource_desc, NULL, &rtv_resource); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID3D11Device_CreateRenderTargetView(device, rtv_resource, NULL, &rtv); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rtv, NULL); + set_viewport(context, 0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const D3D11_SAMPLER_DESC sampler_desc = + { + .Filter = tests[i].filter, + .AddressU = D3D11_TEXTURE_ADDRESS_CLAMP, + .AddressV = D3D11_TEXTURE_ADDRESS_CLAMP, + .AddressW = D3D11_TEXTURE_ADDRESS_CLAMP, + }; + + winetest_push_context("Test %Iu", i); + + ID3D11DeviceContext_ClearRenderTargetView(context, rtv, white_color); + + hr = ID3D11Device_CreateSamplerState(device, &sampler_desc, &sampler); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &sampler); + draw_quad_vs(&test_context, ID3D10Blob_GetBufferPointer(vs_blob), ID3D10Blob_GetBufferSize(vs_blob)); + ID3D11SamplerState_Release(sampler); + + get_resource_readback(rtv_resource, 0, &rb); + for (j = 0; j < tests[i].expected_count; ++j) + { + const struct expected *e = &tests[i].expected[j]; + + c = get_readback_vec4(&rb, e->x, e->y); + ok(compare_vec4(c, &e->c, 0), "Got {%.8e, %.8e, %.8e, %.8e} at %u, %u.\n", + c->x, c->y, c->z, c->w, e->x, e->y); + } + release_resource_readback(&rb); + + winetest_pop_context(); + } + + ID3D11RenderTargetView_Release(rtv); + ID3D11Resource_Release(rtv_resource); + ID3D11ShaderResourceView_Release(srv); + ID3D11Resource_Release(srv_resource); + ID3D11PixelShader_Release(ps); + ID3D10Blob_Release(vs_blob); + release_test_context(&test_context); +} + START_TEST(d3d11) { unsigned int argc, i; @@ -37529,6 +37723,7 @@ START_TEST(d3d11) queue_test(test_high_resource_count); queue_test(test_nv12); queue_test(test_h264_decoder); + queue_test(test_filter_minmax); run_queued_tests(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9683
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
From: Henri Verbeet <hverbeet(a)locutus.nl> --- dlls/wined3d/adapter_gl.c | 3 ++- dlls/wined3d/ffp_gl.c | 17 +++++++++++++++++ dlls/wined3d/sampler.c | 6 +++++- dlls/wined3d/texture_gl.c | 13 +++++++------ dlls/wined3d/wined3d_gl.h | 2 ++ 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 9d97ebda371..e33e27b4cc3 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -138,6 +138,7 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE }, {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3 }, {"GL_ARB_texture_filter_anisotropic", ARB_TEXTURE_FILTER_ANISOTROPIC}, + {"GL_ARB_texture_filter_minmax", ARB_TEXTURE_FILTER_MINMAX }, {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT }, {"GL_ARB_texture_gather", ARB_TEXTURE_GATHER }, {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT }, @@ -4944,7 +4945,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->min_max_filtering = !!gl_info->supported[ARB_TEXTURE_FILTER_MINMAX]; 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/ffp_gl.c b/dlls/wined3d/ffp_gl.c index 04c6310013c..8bba21cb7f8 100644 --- a/dlls/wined3d/ffp_gl.c +++ b/dlls/wined3d/ffp_gl.c @@ -157,6 +157,23 @@ GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f) } } +GLenum wined3d_gl_filter_reduction_mode(enum wined3d_filter_reduction_mode m) +{ + switch (m) + { + case WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE: + case WINED3D_FILTER_REDUCTION_COMPARISON: + return GL_WEIGHTED_AVERAGE_ARB; + case WINED3D_FILTER_REDUCTION_MINIMUM: + return GL_MIN; + case WINED3D_FILTER_REDUCTION_MAXIMUM: + return GL_MAX; + default: + FIXME("Unhandled reduction mode %#x.\n", m); + return GL_WEIGHTED_AVERAGE_ARB; + } +} + static GLenum gl_blend_op(const struct wined3d_gl_info *gl_info, enum wined3d_blend_op op) { switch (op) diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c index 56b9ff2e642..2f269f06df5 100644 --- a/dlls/wined3d/sampler.c +++ b/dlls/wined3d/sampler.c @@ -87,6 +87,7 @@ static void wined3d_sampler_gl_cs_init(void *object) const struct wined3d_sampler_desc *desc; const struct wined3d_gl_info *gl_info; struct wined3d_context *context; + GLenum reduction_mode; GLuint name; TRACE("sampler_gl %p.\n", sampler_gl); @@ -114,7 +115,10 @@ static void wined3d_sampler_gl_cs_init(void *object) GL_EXTCALL(glSamplerParameteri(name, GL_TEXTURE_MAX_ANISOTROPY, desc->max_anisotropy)); 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) + reduction_mode = wined3d_gl_filter_reduction_mode(desc->reduction_mode); + if (gl_info->supported[ARB_TEXTURE_FILTER_MINMAX]) + GL_EXTCALL(glSamplerParameteri(name, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_mode)); + else if (reduction_mode != GL_WEIGHTED_AVERAGE_ARB) 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))); diff --git a/dlls/wined3d/texture_gl.c b/dlls/wined3d/texture_gl.c index 7a097f85f30..97e40d46601 100644 --- a/dlls/wined3d/texture_gl.c +++ b/dlls/wined3d/texture_gl.c @@ -2890,16 +2890,17 @@ void wined3d_texture_gl_apply_sampler_desc(struct wined3d_texture_gl *texture_gl if (!sampler_desc->reduction_mode != !gl_tex->sampler_desc.reduction_mode) { + GLenum reduction_mode = wined3d_gl_filter_reduction_mode(sampler_desc->reduction_mode); + 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); - if (sampler_desc->reduction_mode != WINED3D_FILTER_REDUCTION_WEIGHTED_AVERAGE) - WARN("Sampler min/max reduction filtering is not supported.\n"); - } + + if (gl_info->supported[ARB_TEXTURE_FILTER_MINMAX]) + gl_info->gl_ops.gl.p_glTexParameteri(target, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_mode); + else if (reduction_mode != GL_WEIGHTED_AVERAGE_ARB) + WARN("Sampler min/max reduction filtering is not supported.\n"); gl_tex->sampler_desc.reduction_mode = sampler_desc->reduction_mode; } diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index ed537686007..0cb36eadafe 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -131,6 +131,7 @@ enum wined3d_gl_extension ARB_TEXTURE_ENV_COMBINE, ARB_TEXTURE_ENV_DOT3, ARB_TEXTURE_FILTER_ANISOTROPIC, + ARB_TEXTURE_FILTER_MINMAX, ARB_TEXTURE_FLOAT, ARB_TEXTURE_GATHER, ARB_TEXTURE_MIRRORED_REPEAT, @@ -404,6 +405,7 @@ static inline GLenum wined3d_gl_min_mip_filter(enum wined3d_texture_filter_type } GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f); +GLenum wined3d_gl_filter_reduction_mode(enum wined3d_filter_reduction_mode m); const char *debug_fboattachment(GLenum attachment); const char *debug_fbostatus(GLenum status); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9683
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9683
participants (3)
-
Elizabeth Figura (@zfigura) -
Henri Verbeet -
Henri Verbeet (@hverbeet)