This one checks results of blending of background and foreground samples, and a wider variety of pixel formats.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d11/tests/d3d11.c | 325 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 6cdac34c0cd..f0bdd26a948 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -260,6 +260,13 @@ static BOOL compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned && compare_float(v1->w, v2->w, ulps); }
+static BOOL compare_int(int x, int y, int max_diff) +{ + int diff = x > y ? x - y : y - x; + + return diff <= max_diff; +} + static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { unsigned int diff = x > y ? x - y : y - x; @@ -280,6 +287,15 @@ static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); }
+static BOOL compare_scolor(DWORD c1, DWORD c2, BYTE max_diff) +{ + signed char c1x = c1, c1y = (c1 >> 8), c1z = (c1 >> 16), c1w = (c1 >> 24); + signed char c2x = c2, c2y = (c2 >> 8), c2z = (c2 >> 16), c2w = (c2 >> 24); + + return compare_int(c1x, c2x, max_diff) && compare_int(c1y, c2y, max_diff) + && compare_int(c1z, c2z, max_diff) && compare_int(c1w, c2w, max_diff); +} + static char const *debugstr_viewport(D3D11_VIEWPORT *vp) { if (!vp) return "(null)"; @@ -30057,6 +30073,314 @@ done: release_test_context(&test_context); }
+static void test_multisample_resolve_blended(void) +{ + static const D3D11_VIEWPORT viewport = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + static const float clear_color[4] = {0.2f, 0.2f, 0.2f, 1.0f}; + unsigned int vertex_buffer_stride = 6 * sizeof(float); + ID3D11PixelShader *pixel_shader, *pixel_shader_uint; + ID3D11Texture2D *resolve_target, *render_target; + D3D11_RENDER_TARGET_VIEW_DESC render_view_desc; + ID3D11RenderTargetView *render_target_view; + unsigned int vertex_buffer_offset = 0; + ID3D11DeviceContext *device_context; + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11VertexShader *vertex_shader; + ID3D11InputLayout *input_layout; + unsigned int i, quality_levels; + struct resource_readback rb; + ID3D11Buffer *vertex_buffer; + unsigned char *result; + ID3D11Device *device; + BOOL compare_ok; + HRESULT hr; + + static const DWORD vs_code[] = + { +#if 0 + struct VS_Input + { + float2 pos : TEXCOORD0; + float4 color : COLOR; + }; + + struct VS_Output + { + float4 position : SV_POSITION; + float4 color : COLOR; + }; + + VS_Output vs_main(VS_Input input) + { + VS_Output output; + output.position = float4(input.pos, 0.0f, 1.0f); + output.color = input.color; + + return output; + } +#endif + 0x43425844, 0x3fbe97c7, 0x2cdce39d, 0xa8d3bf48, 0xe0d872e3, 0x00000001, 0x00000160, 0x00000003, + 0x0000002c, 0x0000007c, 0x000000d0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, + 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, + 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, + 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000088, 0x00010040, 0x00000022, + 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, + 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x00102032, 0x00000000, + 0x00101046, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, + }; + + static const DWORD ps_code[] = + { +#if 0 + float4 ps_main(VS_Output input) : SV_TARGET + { + return input.color; + } +#endif + 0x43425844, 0xe2087fa6, 0xa35fbd95, 0x8e585b3f, 0x67890f54, 0x00000001, 0x000000f4, 0x00000003, + 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, + 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, + 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e + }; + + static const DWORD ps_uint_code[] = + { +#if 0 + uint4 ps_main_uint(VS_Output input) : SV_TARGET + { + return 255 * input.color; + } +#endif + 0x43425844, 0x9c2c834b, 0x37ca7b30, 0x01b4b43e, 0x713b001e, 0x00000001, 0x00000124, 0x00000003, + 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000068, 0x00000040, + 0x0000001a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, + 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x00004002, 0x437f0000, + 0x437f0000, 0x437f0000, 0x437f0000, 0x0500001c, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, + 0x0100003e + }; + + static const struct + { + struct vec2 xy; + struct vec4 rgba; + } + vertex_data[] = + { + {{ 1.0f, 1.0f }, { .8f, 0.f, 0.f, 1.f }}, + {{ 1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }}, + {{-1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }}, + }; + + static const D3D11_INPUT_ELEMENT_DESC input_elements[] = + { + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + static const struct + { + BOOL use_uint_shader; + DXGI_FORMAT render_target_view_format; + DXGI_FORMAT source_format; + DXGI_FORMAT destination_format; + DXGI_FORMAT resolve_format; + unsigned int byte_count; + unsigned char expected[4]; + BOOL todo; + } + tests[] = + { + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f } }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, + 2, { 0, 0x80 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + 2, { 0xff, 0x37 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, + 2, { 0xff, 0x37 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, + 2, { 0x66, 0x36 }, TRUE }, + { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, + 2, { 0xbd, 0xc8 } }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x80, 0x19, 0x19, 0xff } }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, + 4, { 0, 0x19, 0x19, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x3f, 0xc, 0xc, 0x7f }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x3f, 0, 0, 0x40 }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, + 4, { 0x40, 0, 0, 0x40 }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x66, 0, 0, 0x80 }, TRUE }, + }; + + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.MiscFlags = 0; + + render_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + + if (!(device = create_device(NULL))) + { + skip("Failed to create device.\n"); + return; + } + + ID3D11Device_GetImmediateContext(device, &device_context); + + hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), + NULL, &vertex_shader); + ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), + NULL, &pixel_shader); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreatePixelShader(device, ps_uint_code, sizeof(ps_uint_code), + NULL, &pixel_shader_uint); + ok(SUCCEEDED(hr),"Failed to create uint pixel shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreateInputLayout(device, input_elements, + ARRAY_SIZE(input_elements), vs_code, sizeof(vs_code), &input_layout); + ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); + + vertex_buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, + sizeof(vertex_data), vertex_data); + + ID3D11DeviceContext_IASetVertexBuffers(device_context, 0, 1, &vertex_buffer, + &vertex_buffer_stride, &vertex_buffer_offset); + ID3D11DeviceContext_IASetPrimitiveTopology(device_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D11DeviceContext_IASetInputLayout(device_context, input_layout); + ID3D11DeviceContext_VSSetShader(device_context, vertex_shader, NULL, 0); + ID3D11DeviceContext_RSSetViewports(device_context, 1, &viewport); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + hr = ID3D11Device_CheckMultisampleQualityLevels(device, tests[i].source_format, 2, &quality_levels); + ok(SUCCEEDED(hr), "Failed to check multisample quality levels, hr %#x.\n", hr); + if (!quality_levels) + { + skip("Test %3u: 2xMSAA not supported.\n", i); + continue; + } + + texture_desc.Format = tests[i].source_format; + texture_desc.SampleDesc.Count = 2; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; + texture_desc.CPUAccessFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); + ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr); + + texture_desc.Format = tests[i].destination_format; + texture_desc.SampleDesc.Count = 1; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &resolve_target); + ok(SUCCEEDED(hr), "Failed to create resolve texture, hr %#x.\n", hr); + + render_view_desc.Format = tests[i].render_target_view_format; + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, + &render_view_desc, &render_target_view); + ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); + + ID3D11DeviceContext_RSSetViewports(device_context, 1, &viewport); + ID3D11DeviceContext_OMSetRenderTargets(device_context, 1, &render_target_view, NULL); + ID3D11DeviceContext_PSSetShader(device_context, tests[i].use_uint_shader ? pixel_shader_uint : pixel_shader, NULL, 0); + ID3D11DeviceContext_ClearRenderTargetView(device_context, render_target_view, clear_color); + ID3D11DeviceContext_Draw(device_context, 3, 0); + ID3D11DeviceContext_ResolveSubresource(device_context, (ID3D11Resource *)resolve_target, + 0, (ID3D11Resource *)render_target, 0, tests[i].resolve_format); + + get_texture_readback(resolve_target, 0, &rb); + result = get_readback_data(&rb, 0, 0, 0, tests[i].byte_count); + + switch (tests[i].resolve_format) + { + case DXGI_FORMAT_R32_FLOAT: + compare_ok = compare_float(*(float *)result, *(float *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_FLOAT: + compare_ok = compare_uint(*(WORD *)result, *(WORD *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + compare_ok = compare_color(*(DWORD *)result, *(DWORD *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R8G8B8A8_SNORM: + compare_ok = compare_scolor(*(DWORD *)result, *(DWORD *)tests[i].expected, 2); + break; + default: + trace("Test %3u: unhandled format.\n", i); + compare_ok = FALSE; + break; + } + + todo_wine_if(tests[i].todo) + ok(compare_ok, "Test %3u: expected: %2x %2x %2x %2x, got: %2x %2x %2x %2x.\n", i, + tests[i].expected[0], tests[i].expected[1], tests[i].expected[2], tests[i].expected[3], + result[0], result[1], result[2], result[3]); + + release_resource_readback(&rb); + ID3D11RenderTargetView_Release(render_target_view); + ID3D11Texture2D_Release(render_target); + ID3D11Texture2D_Release(resolve_target); + } + + ID3D11Buffer_Release(vertex_buffer); + ID3D11InputLayout_Release(input_layout); + ID3D11PixelShader_Release(pixel_shader_uint); + ID3D11PixelShader_Release(pixel_shader); + ID3D11VertexShader_Release(vertex_shader); + ID3D11DeviceContext_Release(device_context); + ID3D11Device_Release(device); +} + static void test_multisample_resolve(void) { struct d3d11_test_context test_context; @@ -32284,6 +32608,7 @@ START_TEST(d3d11) queue_test(test_unbound_multisample_texture); queue_test(test_multiple_viewports); queue_test(test_multisample_resolve); + queue_test(test_multisample_resolve_blended); queue_test(test_sample_shading); queue_test(test_sample_mask); queue_test(test_depth_clip);
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/device.c | 5 ++++- dlls/wined3d/surface.c | 3 +++ include/wine/wined3d.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 06329293261..d17d923af08 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4984,6 +4984,7 @@ void CDECL wined3d_device_resolve_sub_resource(struct wined3d_device *device, { struct wined3d_texture *dst_texture, *src_texture; unsigned int dst_level, src_level; + struct wined3d_blt_fx fx = {0}; RECT dst_rect, src_rect;
TRACE("device %p, dst_resource %p, dst_sub_resource_idx %u, " @@ -5010,6 +5011,8 @@ void CDECL wined3d_device_resolve_sub_resource(struct wined3d_device *device, return; }
+ fx.resolve_format_id = format_id; + dst_texture = texture_from_resource(dst_resource); src_texture = texture_from_resource(src_resource);
@@ -5020,7 +5023,7 @@ void CDECL wined3d_device_resolve_sub_resource(struct wined3d_device *device, SetRect(&src_rect, 0, 0, wined3d_texture_get_level_width(src_texture, src_level), wined3d_texture_get_level_height(src_texture, src_level)); wined3d_texture_blt(dst_texture, dst_sub_resource_idx, &dst_rect, - src_texture, src_sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); + src_texture, src_sub_resource_idx, &src_rect, 0, &fx, WINED3D_TEXF_POINT); }
HRESULT CDECL wined3d_device_clear_rendertarget_view(struct wined3d_device *device, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d5d07d8c401..d25516defc8 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1479,6 +1479,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ enum wined3d_texture_filter_type filter) { struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource; + enum wined3d_format_id resolve_format_id = WINED3DFMT_UNKNOWN; struct wined3d_device *device = dst_texture->resource.device; struct wined3d_swapchain *src_swapchain, *dst_swapchain; const struct wined3d_color_key *colour_key = NULL; @@ -1509,6 +1510,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ TRACE("src_color_key {0x%08x, 0x%08x}.\n", fx->src_color_key.color_space_low_value, fx->src_color_key.color_space_high_value); + TRACE("resolve_format_id %s.\n", debug_d3dformat(fx->resolve_format_id)); + resolve_format_id = fx->resolve_format_id; }
dst_sub_resource = &dst_texture->sub_resources[dst_sub_resource_idx]; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 030e3fdcb67..29028fa6450 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2007,6 +2007,7 @@ struct wined3d_blt_fx DWORD fx; struct wined3d_color_key dst_color_key; struct wined3d_color_key src_color_key; + enum wined3d_format_id resolve_format_id; };
struct wined3d_buffer_desc
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
dlls/wined3d/device.c | 5 ++++- dlls/wined3d/surface.c | 3 +++ include/wine/wined3d.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-)
This is largely fine, but you should adjust existing usage of wined3d_blt_fx as well. In particular, after this change, ddraw_surface1_Blt() leaves the "resolve_format_id" field uninitialised. That kind of works as long as wined3d doesn't access the field, but note that we trace it's value in texture2d_blt().
@@ -1479,6 +1479,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ enum wined3d_texture_filter_type filter) { struct wined3d_texture_sub_resource *src_sub_resource, *dst_sub_resource;
- enum wined3d_format_id resolve_format_id = WINED3DFMT_UNKNOWN; struct wined3d_device *device = dst_texture->resource.device; struct wined3d_swapchain *src_swapchain, *dst_swapchain; const struct wined3d_color_key *colour_key = NULL;
@@ -1509,6 +1510,8 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ TRACE("src_color_key {0x%08x, 0x%08x}.\n", fx->src_color_key.color_space_low_value, fx->src_color_key.color_space_high_value);
TRACE("resolve_format_id %s.\n", debug_d3dformat(fx->resolve_format_id));
}resolve_format_id = fx->resolve_format_id;
"resolve_format_id" is set, but not used.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/arb_program_shader.c | 8 ++++---- dlls/wined3d/glsl_shader.c | 8 ++++---- dlls/wined3d/surface.c | 6 +++--- dlls/wined3d/swapchain.c | 2 +- dlls/wined3d/texture.c | 22 +++++++++++----------- dlls/wined3d/wined3d_private.h | 2 +- 6 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index af8f2a508fa..bd23f0830b4 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -7792,7 +7792,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_context_gl *context_gl = wined3d_context_gl(context); @@ -7805,10 +7805,10 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl RECT s, d;
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), color_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id));
if (!arbfp_blit_supported(op, context, &src_texture->resource, src_location, &dst_texture->resource, dst_location)) @@ -7821,7 +7821,7 @@ static DWORD arbfp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bl
TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, color_key, filter, format_id); }
arbfp_blitter = CONTAINING_RECORD(blitter, struct wined3d_arbfp_blitter, blitter); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 45eebcc2c20..4567370f3fc 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -13061,7 +13061,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_texture_gl *dst_texture_gl = wined3d_texture_gl(dst_texture); @@ -13078,10 +13078,10 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli RECT s, d;
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id));
if (!glsl_blitter_supported(op, context, src_texture_gl, src_location, dst_texture_gl, dst_location)) { @@ -13093,7 +13093,7 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); }
glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d25516defc8..7e2b7c542ce 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1400,7 +1400,7 @@ static DWORD cpu_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *color_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_box dst_box = {dst_rect->left, dst_rect->top, dst_rect->right, dst_rect->bottom, 0, 1}; struct wined3d_box src_box = {src_rect->left, src_rect->top, src_rect->right, src_rect->bottom, 0, 1}; @@ -1584,7 +1584,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_ context = context_acquire(device, dst_texture, dst_sub_resource_idx); valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context, src_texture, src_sub_resource_idx, src_texture->resource.draw_binding, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter); + dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, NULL, filter, resolve_format_id); context_release(context);
wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, valid_locations); @@ -1718,7 +1718,7 @@ HRESULT texture2d_blt(struct wined3d_texture *dst_texture, unsigned int dst_sub_
valid_locations = device->blitter->ops->blitter_blit(device->blitter, blit_op, context, src_texture, src_sub_resource_idx, src_location, &src_rect, - dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter); + dst_texture, dst_sub_resource_idx, dst_location, &dst_rect, colour_key, filter, resolve_format_id);
context_release(context);
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 72e17a6f833..e7f9fa83512 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -492,7 +492,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, 0, - location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter); + location, src_rect, texture, 0, WINED3D_LOCATION_DRAWABLE, dst_rect, NULL, filter, WINED3DFMT_UNKNOWN); wined3d_texture_invalidate_location(texture, 0, WINED3D_LOCATION_DRAWABLE); }
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index a4148b166f2..6969de46952 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -2933,7 +2933,7 @@ static BOOL wined3d_texture_load_drawable(struct wined3d_texture *texture, device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_COLOR_BLIT, context, texture, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &r, texture, sub_resource_idx, WINED3D_LOCATION_DRAWABLE, &r, - NULL, WINED3D_TEXF_POINT); + NULL, WINED3D_TEXF_POINT, WINED3DFMT_UNKNOWN);
return TRUE; } @@ -5650,7 +5650,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_context_gl *context_gl = wined3d_context_gl(context); @@ -5671,7 +5671,7 @@ static DWORD ffp_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { if ((next = blitter->next)) return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); }
TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n", @@ -5859,7 +5859,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_context_gl *context_gl = wined3d_context_gl(context); struct wined3d_resource *src_resource, *dst_resource; @@ -5868,10 +5868,10 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_blitter *next;
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id));
src_resource = &src_texture->resource; dst_resource = &dst_texture->resource; @@ -5897,7 +5897,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); }
if (blit_op == WINED3D_BLIT_OP_COLOR_BLIT) @@ -5975,7 +5975,7 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_gl *src_texture_gl = wined3d_texture_gl(src_texture); struct wined3d_texture_gl *dst_texture_gl = wined3d_texture_gl(dst_texture); @@ -6002,7 +6002,7 @@ static DWORD raw_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit
TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); }
TRACE("Blit using ARB_copy_image.\n"); @@ -6444,7 +6444,7 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, - const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter) + const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id) { struct wined3d_texture_vk *src_texture_vk = wined3d_texture_vk(src_texture); struct wined3d_texture_vk *dst_texture_vk = wined3d_texture_vk(dst_texture); @@ -6601,7 +6601,7 @@ next:
TRACE("Forwarding to blitter %p.\n", next); return next->ops->blitter_blit(next, op, context, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, colour_key, filter, format_id); }
static const struct wined3d_blitter_ops vk_blitter_ops = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index ee00530981c..d625ef403aa 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2756,7 +2756,7 @@ struct wined3d_blitter_ops struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key, - enum wined3d_texture_filter_type filter); + enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id); };
void wined3d_arbfp_blitter_create(struct wined3d_blitter **next,
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
@@ -2756,7 +2756,7 @@ struct wined3d_blitter_ops struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, const RECT *dst_rect, const struct wined3d_color_key *colour_key,
enum wined3d_texture_filter_type filter);
enum wined3d_texture_filter_type filter, enum wined3d_format_id format_id);
};
"resolve_format_id" is probably clearer. It's perhaps also nicer to look up the actual format in the caller (i.e., texture2d_blt()), and pass a wined3d_format structure here.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 160 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 142 insertions(+), 18 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 6969de46952..7d85413fc5d 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -320,9 +320,13 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont enum wined3d_texture_filter_type filter, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, DWORD dst_location, - const RECT *dst_rect) + const RECT *dst_rect, enum wined3d_format_id resolve_format_id) { + unsigned int dst_save_sub_resource_idx = dst_sub_resource_idx; struct wined3d_texture *required_texture, *restore_texture; + struct wined3d_texture *dst_save_texture = dst_texture; + struct wined3d_texture *src_staging_texture = NULL; + struct wined3d_texture *dst_staging_texture = NULL; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; unsigned int restore_idx; @@ -332,10 +336,10 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont RECT s, d;
TRACE("device %p, context %p, filter %s, src_texture %p, src_sub_resource_idx %u, src_location %s, " - "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s.\n", + "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, resolve_format_id %s.\n", device, context, debug_d3dtexturefiltertype(filter), src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, - dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect)); + dst_sub_resource_idx, wined3d_debug_location(dst_location), wine_dbgstr_rect(dst_rect), debug_d3dformat(resolve_format_id));
scaled_resolve = wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture), src_location) && (abs(src_rect->bottom - src_rect->top) != abs(dst_rect->bottom - dst_rect->top) @@ -346,6 +350,124 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont else gl_filter = scaled_resolve ? GL_SCALED_RESOLVE_FASTEST_EXT : GL_NEAREST;
+ context_gl = wined3d_context_gl(context); + if (!context_gl->valid) + { + context_release(context); + WARN("Invalid context, skipping blit.\n"); + return; + } + + gl_info = context_gl->gl_info; + + if (resolve_format_id != WINED3DFMT_UNKNOWN) + { + const struct wined3d_format_gl *resolve_format_gl = wined3d_format_gl(wined3d_get_format(device->adapter, resolve_format_id, 0)); + const struct wined3d_format_gl *src_format_gl = wined3d_format_gl(src_texture->resource.format); + const struct wined3d_format_gl *dst_format_gl = wined3d_format_gl(dst_texture->resource.format); + GLint src_internal, dst_internal, resolve_internal; + + switch (resolve_format_id) + { + case WINED3DFMT_R8G8B8A8_UNORM_SRGB: + case WINED3DFMT_B8G8R8A8_UNORM_SRGB: + case WINED3DFMT_B8G8R8X8_UNORM_SRGB: + gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB); + context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE)); + resolve_internal = resolve_format_gl->srgb_internal; + break; + default: + resolve_internal = resolve_format_gl->internal; + break; + } + + if (src_location == WINED3D_LOCATION_TEXTURE_SRGB) + src_internal = src_format_gl->srgb_internal; + else if (src_texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET && wined3d_resource_is_offscreen(&src_texture->resource)) + src_internal = src_format_gl->rt_internal; + else + src_internal = src_format_gl->internal; + + if (dst_location == WINED3D_LOCATION_TEXTURE_SRGB) + dst_internal = dst_format_gl->srgb_internal; + else if (dst_texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET && wined3d_resource_is_offscreen(&dst_texture->resource)) + dst_internal = dst_format_gl->rt_internal; + else + dst_internal = dst_format_gl->internal; + + /* In case of typeless resolve the texture type may not match the resolve type. + * To handle that, allocate intermediate texture(s) to resolve from/to. + * A possible performance improvement would be to resolve using a shader instead. */ + if (src_internal != resolve_internal) + { + struct wined3d_resource_desc desc; + unsigned src_level; + HRESULT hr; + + src_level = src_sub_resource_idx % src_texture->level_count; + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = resolve_format_id; + desc.multisample_type = src_texture->resource.multisample_type; + desc.multisample_quality = src_texture->resource.multisample_quality; + desc.usage = WINED3DUSAGE_PRIVATE; + desc.bind_flags = 0; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + desc.width = wined3d_texture_get_level_width(src_texture, src_level); + desc.height = wined3d_texture_get_level_height(src_texture, src_level); + desc.depth = 1; + desc.size = 0; + + hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &src_staging_texture); + if (FAILED(hr)) + { + ERR("Failed to create staging texture, hr %#x.\n", hr); + return; + } + + device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_RAW_BLIT, context, + src_texture, src_sub_resource_idx, src_location, src_rect, + src_staging_texture, 0, src_location, src_rect, + NULL, WINED3D_TEXF_NONE, WINED3DFMT_UNKNOWN); + + src_texture = src_staging_texture; + src_sub_resource_idx = 0; + } + + if (dst_internal != resolve_internal) + { + struct wined3d_resource_desc desc; + unsigned dst_level; + HRESULT hr; + + dst_level = dst_sub_resource_idx % dst_texture->level_count; + desc.resource_type = WINED3D_RTYPE_TEXTURE_2D; + desc.format = resolve_format_id; + desc.multisample_type = dst_texture->resource.multisample_type; + desc.multisample_quality = dst_texture->resource.multisample_quality; + desc.usage = WINED3DUSAGE_PRIVATE; + desc.bind_flags = 0; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + desc.width = wined3d_texture_get_level_width(dst_texture, dst_level); + desc.height = wined3d_texture_get_level_height(dst_texture, dst_level); + desc.depth = 1; + desc.size = 0; + + hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &dst_staging_texture); + if (FAILED(hr)) + { + ERR("Failed to create staging texture, hr %#x.\n", hr); + if (src_staging_texture) + wined3d_texture_decref(src_staging_texture); + return; + } + + wined3d_texture_load_location(dst_staging_texture, 0, context, dst_location); + + dst_texture = dst_staging_texture; + dst_sub_resource_idx = 0; + } + } + /* Make sure the locations are up-to-date. Loading the destination * surface isn't required if the entire surface is overwritten. (And is * in fact harmful if we're being called by surface_load_location() with @@ -374,16 +496,6 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont else restore_texture = NULL;
- context_gl = wined3d_context_gl(context); - if (!context_gl->valid) - { - context_release(context); - WARN("Invalid context, skipping blit.\n"); - return; - } - - gl_info = context_gl->gl_info; - if (src_location == WINED3D_LOCATION_DRAWABLE) { TRACE("Source texture %p is onscreen.\n", src_texture); @@ -437,6 +549,18 @@ static void texture2d_blt_fbo(struct wined3d_device *device, struct wined3d_cont if (dst_location == WINED3D_LOCATION_DRAWABLE && dst_texture->swapchain->front_buffer == dst_texture) gl_info->gl_ops.gl.p_glFlush();
+ if (dst_staging_texture) + { + device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_RAW_BLIT, context, + dst_texture, 0, dst_location, dst_rect, + dst_save_texture, dst_save_sub_resource_idx, dst_location, dst_rect, + NULL, WINED3D_TEXF_NONE, WINED3DFMT_UNKNOWN); + wined3d_texture_decref(dst_texture); + } + + if (src_staging_texture) + wined3d_texture_decref(src_staging_texture); + if (restore_texture) context_restore(context, restore_texture, restore_idx); } @@ -2971,7 +3095,7 @@ static BOOL wined3d_texture_load_renderbuffer(struct wined3d_texture *texture, src_location = WINED3D_LOCATION_TEXTURE_RGB;
texture2d_blt_fbo(texture->resource.device, context, WINED3D_TEXF_POINT, texture, - sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect); + sub_resource_idx, src_location, &rect, texture, sub_resource_idx, dst_location, &rect, WINED3DFMT_UNKNOWN);
return TRUE; } @@ -3018,11 +3142,11 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g if (srgb) texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect, - &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect); + &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect, WINED3DFMT_UNKNOWN); else texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_SRGB, &src_rect, - &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect); + &texture_gl->t, sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB, &src_rect, WINED3DFMT_UNKNOWN);
return TRUE; } @@ -3039,7 +3163,7 @@ static BOOL wined3d_texture_gl_load_texture(struct wined3d_texture_gl *texture_g if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT, gl_info, &texture_gl->t.resource, src_location, &texture_gl->t.resource, dst_location)) texture2d_blt_fbo(device, &context_gl->c, WINED3D_TEXF_POINT, &texture_gl->t, sub_resource_idx, - src_location, &src_rect, &texture_gl->t, sub_resource_idx, dst_location, &src_rect); + src_location, &src_rect, &texture_gl->t, sub_resource_idx, dst_location, &src_rect, WINED3DFMT_UNKNOWN);
return TRUE; } @@ -5904,7 +6028,7 @@ static DWORD fbo_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit { TRACE("Colour blit.\n"); texture2d_blt_fbo(device, context, filter, src_texture, src_sub_resource_idx, src_location, - src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect); + src_rect, dst_texture, dst_sub_resource_idx, dst_location, dst_rect, format_id); return dst_location; }
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
- if (resolve_format_id != WINED3DFMT_UNKNOWN)
- {
I think we only care about the resolve format if we're doing a resolve operation.
switch (resolve_format_id)
{
case WINED3DFMT_R8G8B8A8_UNORM_SRGB:
case WINED3DFMT_B8G8R8A8_UNORM_SRGB:
case WINED3DFMT_B8G8R8X8_UNORM_SRGB:
gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
resolve_internal = resolve_format_gl->srgb_internal;
break;
default:
resolve_internal = resolve_format_gl->internal;
break;
}
Don't hardcode formats like that, it's very fragile. You'll probably want to do something similar to needs_srgb_write(). Should we enable GL_FRAMEBUFFER_SRGB for blits more broadly instead of only for typeless resolves? If yes, this belongs in a separate commit, and something like wined3d_context_gl_apply_fbo_state_blit() may be a more appropriate place.
if (src_location == WINED3D_LOCATION_TEXTURE_SRGB)
src_internal = src_format_gl->srgb_internal;
else if (src_texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET && wined3d_resource_is_offscreen(&src_texture->resource))
src_internal = src_format_gl->rt_internal;
else
src_internal = src_format_gl->internal;
if (dst_location == WINED3D_LOCATION_TEXTURE_SRGB)
dst_internal = dst_format_gl->srgb_internal;
else if (dst_texture->resource.bind_flags & WINED3D_BIND_RENDER_TARGET && wined3d_resource_is_offscreen(&dst_texture->resource))
dst_internal = dst_format_gl->rt_internal;
else
dst_internal = dst_format_gl->internal;
That could use a helper function.
/* In case of typeless resolve the texture type may not match the resolve type.
* To handle that, allocate intermediate texture(s) to resolve from/to.
* A possible performance improvement would be to resolve using a shader instead. */
if (src_internal != resolve_internal)
{
struct wined3d_resource_desc desc;
unsigned src_level;
HRESULT hr;
src_level = src_sub_resource_idx % src_texture->level_count;
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
desc.format = resolve_format_id;
desc.multisample_type = src_texture->resource.multisample_type;
desc.multisample_quality = src_texture->resource.multisample_quality;
desc.usage = WINED3DUSAGE_PRIVATE;
desc.bind_flags = 0;
desc.access = WINED3D_RESOURCE_ACCESS_GPU;
desc.width = wined3d_texture_get_level_width(src_texture, src_level);
desc.height = wined3d_texture_get_level_height(src_texture, src_level);
desc.depth = 1;
desc.size = 0;
hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &src_staging_texture);
if (FAILED(hr))
{
ERR("Failed to create staging texture, hr %#x.\n", hr);
return;
}
device->blitter->ops->blitter_blit(device->blitter, WINED3D_BLIT_OP_RAW_BLIT, context,
src_texture, src_sub_resource_idx, src_location, src_rect,
src_staging_texture, 0, src_location, src_rect,
NULL, WINED3D_TEXF_NONE, WINED3DFMT_UNKNOWN);
src_texture = src_staging_texture;
src_sub_resource_idx = 0;
}
Note that that only works if the source location isn't WINED3D_LOCATION_DRAWABLE. That should always hold in practice, but we may want to be explicit about that.
if (dst_internal != resolve_internal)
{
struct wined3d_resource_desc desc;
unsigned dst_level;
HRESULT hr;
dst_level = dst_sub_resource_idx % dst_texture->level_count;
desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
desc.format = resolve_format_id;
desc.multisample_type = dst_texture->resource.multisample_type;
desc.multisample_quality = dst_texture->resource.multisample_quality;
desc.usage = WINED3DUSAGE_PRIVATE;
desc.bind_flags = 0;
desc.access = WINED3D_RESOURCE_ACCESS_GPU;
desc.width = wined3d_texture_get_level_width(dst_texture, dst_level);
desc.height = wined3d_texture_get_level_height(dst_texture, dst_level);
desc.depth = 1;
desc.size = 0;
hr = wined3d_texture_create(device, &desc, 1, 1, 0, NULL, NULL, &wined3d_null_parent_ops, &dst_staging_texture);
if (FAILED(hr))
{
ERR("Failed to create staging texture, hr %#x.\n", hr);
if (src_staging_texture)
wined3d_texture_decref(src_staging_texture);
return;
}
wined3d_texture_load_location(dst_staging_texture, 0, context, dst_location);
dst_texture = dst_staging_texture;
dst_sub_resource_idx = 0;
}
- }
Likewise.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/texture.c | 274 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 248 insertions(+), 26 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 7d85413fc5d..fa78cddc69b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -6500,7 +6500,7 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev
static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wined3d_context *context, const struct wined3d_resource *src_resource, const RECT *src_rect, - const struct wined3d_resource *dst_resource, const RECT *dst_rect) + const struct wined3d_resource *dst_resource, const RECT *dst_rect, enum wined3d_format_id format_id) { const struct wined3d_format *src_format = src_resource->format; const struct wined3d_format *dst_format = dst_resource->format; @@ -6532,7 +6532,9 @@ static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wine }
if (op != WINED3D_BLIT_OP_RAW_BLIT - && wined3d_format_vk(src_format)->vk_format != wined3d_format_vk(dst_format)->vk_format) + && wined3d_format_vk(src_format)->vk_format != wined3d_format_vk(dst_format)->vk_format + && ((!wined3d_format_is_typeless(src_format) && !wined3d_format_is_typeless(dst_format)) + || (format_id == WINED3DFMT_UNKNOWN))) { TRACE("Format conversion not supported.\n"); return false; @@ -6564,6 +6566,74 @@ static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wine return true; }
+static VkResult create_staging_image_for_resolve(struct wined3d_context_vk *context_vk, + VkImageType vk_image_type, VkFormat vk_format, unsigned width, unsigned height, unsigned depth, + unsigned sample_count, VkImage *image) +{ + struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + VkMemoryAllocateInfo allocate_info = {0}; + VkMemoryRequirements memory_requirements; + VkImageCreateInfo create_info; + VkDeviceMemory device_memory; + VkResult vr; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + create_info.pNext = NULL; + create_info.flags = 0; + create_info.imageType = vk_image_type; + create_info.format = vk_format; + create_info.extent.width = width; + create_info.extent.height = height; + create_info.extent.depth = depth; + create_info.mipLevels = 1; + create_info.arrayLayers = 1; + create_info.samples = sample_count; + create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + create_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.queueFamilyIndexCount = 0; + create_info.pQueueFamilyIndices = NULL; + create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, image)); + if (vr != VK_SUCCESS) + { + ERR("Failed to create image, vr %#x.\n", vr); + return vr; + } + + wined3d_context_vk_destroy_image(context_vk, *image, context_vk->current_command_buffer.id); + + VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, *image, &memory_requirements)); + + allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocate_info.allocationSize = memory_requirements.size; + allocate_info.memoryTypeIndex = wined3d_adapter_vk_get_memory_type_index(adapter_vk, + memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &device_memory)); + if (vr != VK_SUCCESS) + { + ERR("Failed to allocate memory, vr %#x.\n", vr); + return vr; + } + + wined3d_context_vk_destroy_memory(context_vk, device_memory, context_vk->current_command_buffer.id); + + vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, *image, device_memory, 0)); + if (vr != VK_SUCCESS) + { + ERR("Failed to bind image memory, vr %#x.\n", vr); + return vr; + } + + return VK_SUCCESS; +} + static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_op op, struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, DWORD src_location, const RECT *src_rect, struct wined3d_texture *dst_texture, @@ -6578,21 +6648,23 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ VkImageAspectFlags src_aspect, dst_aspect; VkCommandBuffer vk_command_buffer; struct wined3d_blitter *next; + unsigned src_sample_count; bool resolve = false;
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s.\n", + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, colour_key %p, filter %s, format_id %s.\n", blitter, op, context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), wine_dbgstr_rect(src_rect), dst_texture, dst_sub_resource_idx, wined3d_debug_location(dst_location), - wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter)); + wine_dbgstr_rect(dst_rect), colour_key, debug_d3dtexturefiltertype(filter), debug_d3dformat(format_id));
- if (!vk_blitter_blit_supported(op, context, &src_texture->resource, src_rect, &dst_texture->resource, dst_rect)) + if (!vk_blitter_blit_supported(op, context, &src_texture->resource, src_rect, &dst_texture->resource, dst_rect, format_id)) goto next;
src_aspect = vk_aspect_mask_from_format(src_texture_vk->t.resource.format); dst_aspect = vk_aspect_mask_from_format(dst_texture_vk->t.resource.format);
- if (wined3d_resource_get_sample_count(&src_texture_vk->t.resource) > 1) + src_sample_count = wined3d_resource_get_sample_count(&src_texture_vk->t.resource); + if (src_sample_count > 1) resolve = true;
src_level = src_sub_resource_idx % src_texture->level_count; @@ -6642,30 +6714,180 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ dst_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->vk_image, dst_aspect);
+ if (resolve) { - VkImageResolve region; + const struct wined3d_format_vk *src_format_vk = wined3d_format_vk(src_texture->resource.format); + const struct wined3d_format_vk *dst_format_vk = wined3d_format_vk(dst_texture->resource.format); + const struct wined3d_format_vk *resolve_format_vk; + VkImage src_vk_image, dst_vk_image; + VkImageResolve resolve_region; + VkImageType vk_image_type; + VkImageCopy copy_region; + VkFormat vk_format; + VkResult vr;
- region.srcSubresource.aspectMask = src_aspect; - region.srcSubresource.mipLevel = src_level; - region.srcSubresource.baseArrayLayer = src_layer; - region.srcSubresource.layerCount = 1; - region.srcOffset.x = src_rect->left; - region.srcOffset.y = src_rect->top; - region.srcOffset.z = 0; - region.dstSubresource.aspectMask = dst_aspect; - region.dstSubresource.mipLevel = dst_level; - region.dstSubresource.baseArrayLayer = dst_layer; - region.dstSubresource.layerCount = 1; - region.dstOffset.x = dst_rect->left; - region.dstOffset.y = dst_rect->top; - region.dstOffset.z = 0; - region.extent.width = src_rect->right - src_rect->left; - region.extent.height = src_rect->bottom - src_rect->top; - region.extent.depth = 1; + resolve_format_vk = wined3d_format_vk(wined3d_get_format(context->device->adapter, format_id, 0));
- VK_CALL(vkCmdResolveImage(vk_command_buffer, src_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dst_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion)); + if (!wined3d_format_is_typeless(&src_format_vk->f)) + { + vk_format = src_format_vk->vk_format; + } + else if (!wined3d_format_is_typeless(&dst_format_vk->f)) + { + vk_format = dst_format_vk->vk_format; + } + else + { + vk_format = resolve_format_vk->vk_format; + } + + switch (src_texture->resource.type) + { + case WINED3D_RTYPE_TEXTURE_1D: + vk_image_type = VK_IMAGE_TYPE_1D; + break; + case WINED3D_RTYPE_TEXTURE_2D: + vk_image_type = VK_IMAGE_TYPE_2D; + break; + case WINED3D_RTYPE_TEXTURE_3D: + vk_image_type = VK_IMAGE_TYPE_3D; + break; + default: + ERR("Unexpected resource type: %s\n", debug_d3dresourcetype(src_texture->resource.type)); + goto next; + } + + resolve_region.dstSubresource.aspectMask = dst_aspect; + resolve_region.extent.width = src_rect->right - src_rect->left; + resolve_region.extent.height = src_rect->bottom - src_rect->top; + resolve_region.extent.depth = 1; + + /* In case of typeless resolve the texture type may not match the resolve type. + * To handle that, allocate intermediate texture(s) to resolve from/to. + * A possible performance improvement would be to resolve using a shader instead. */ + if (src_format_vk->vk_format != vk_format) + { + vr = create_staging_image_for_resolve(context_vk, vk_image_type, vk_format, + resolve_region.extent.width, resolve_region.extent.height, 1, src_sample_count, &src_vk_image); + if (vr != VK_SUCCESS) + goto next; + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, src_vk_image, src_aspect); + + copy_region.srcSubresource.aspectMask = src_aspect; + copy_region.srcSubresource.mipLevel = src_level; + copy_region.srcSubresource.baseArrayLayer = src_layer; + copy_region.srcSubresource.layerCount = 1; + copy_region.srcOffset.x = src_rect->left; + copy_region.srcOffset.y = src_rect->top; + copy_region.srcOffset.z = 0; + copy_region.dstSubresource.aspectMask = src_aspect; + copy_region.dstSubresource.mipLevel = 0; + copy_region.dstSubresource.baseArrayLayer = 0; + copy_region.dstSubresource.layerCount = 1; + copy_region.dstOffset.x = 0; + copy_region.dstOffset.y = 0; + copy_region.dstOffset.z = 0; + copy_region.extent.width = resolve_region.extent.width; + copy_region.extent.height = resolve_region.extent.height; + copy_region.extent.depth = 1; + + VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + src_vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region)); + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + src_vk_image, src_aspect); + + resolve_region.srcSubresource.aspectMask = src_aspect; + resolve_region.srcSubresource.mipLevel = 0; + resolve_region.srcSubresource.baseArrayLayer = 0; + resolve_region.srcSubresource.layerCount = 1; + resolve_region.srcOffset.x = 0; + resolve_region.srcOffset.y = 0; + resolve_region.srcOffset.z = 0; + } + else + { + src_vk_image = src_texture_vk->vk_image; + + resolve_region.srcSubresource.aspectMask = src_aspect; + resolve_region.srcSubresource.mipLevel = src_level; + resolve_region.srcSubresource.baseArrayLayer = src_layer; + resolve_region.srcSubresource.layerCount = 1; + resolve_region.srcOffset.x = src_rect->left; + resolve_region.srcOffset.y = src_rect->top; + resolve_region.srcOffset.z = 0; + } + + if (dst_format_vk->vk_format != vk_format) + { + vr = create_staging_image_for_resolve(context_vk, vk_image_type, vk_format, + resolve_region.extent.width, resolve_region.extent.height, 1, VK_SAMPLE_COUNT_1_BIT, &dst_vk_image); + if (vr != VK_SUCCESS) + goto next; + + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_vk_image, dst_aspect); + + resolve_region.dstSubresource.mipLevel = 0; + resolve_region.dstSubresource.baseArrayLayer = 0; + resolve_region.dstSubresource.layerCount = 1; + resolve_region.dstOffset.x = 0; + resolve_region.dstOffset.y = 0; + resolve_region.dstOffset.z = 0; + } + else + { + dst_vk_image = dst_texture_vk->vk_image; + + resolve_region.dstSubresource.mipLevel = dst_level; + resolve_region.dstSubresource.baseArrayLayer = dst_layer; + resolve_region.dstSubresource.layerCount = 1; + resolve_region.dstOffset.x = dst_rect->left; + resolve_region.dstOffset.y = dst_rect->top; + resolve_region.dstOffset.z = 0; + } + + VK_CALL(vkCmdResolveImage(vk_command_buffer, src_vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &resolve_region)); + + if (dst_vk_image != dst_texture_vk->vk_image) + { + wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_vk_image, dst_aspect); + + copy_region.srcSubresource.aspectMask = dst_aspect; + copy_region.srcSubresource.mipLevel = 0; + copy_region.srcSubresource.baseArrayLayer = 0; + copy_region.srcSubresource.layerCount = 1; + copy_region.srcOffset.x = 0; + copy_region.srcOffset.y = 0; + copy_region.srcOffset.z = 0; + copy_region.dstSubresource.aspectMask = dst_aspect; + copy_region.dstSubresource.mipLevel = dst_level; + copy_region.dstSubresource.baseArrayLayer = dst_layer; + copy_region.dstSubresource.layerCount = 1; + copy_region.dstOffset.x = dst_rect->left; + copy_region.dstOffset.y = dst_rect->top; + copy_region.dstOffset.z = 0; + copy_region.extent.width = resolve_region.extent.width; + copy_region.extent.height = resolve_region.extent.height; + copy_region.extent.depth = 1; + + VK_CALL(vkCmdCopyImage(vk_command_buffer, dst_vk_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dst_texture_vk->vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region)); + } } else {
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
- vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &device_memory));
- if (vr != VK_SUCCESS)
- {
ERR("Failed to allocate memory, vr %#x.\n", vr);
return vr;
- }
wined3d_context_vk_allocate_memory(). More broadly, we may want to introduce a helper for creating Vulkan images, analogous to wined3d_context_vk_create_bo().
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d10core/tests/d3d10core.c | 2 +- dlls/d3d11/tests/d3d11.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c index b2a2e2028f2..f1b4c012086 100644 --- a/dlls/d3d10core/tests/d3d10core.c +++ b/dlls/d3d10core/tests/d3d10core.c @@ -18046,7 +18046,7 @@ static void test_multisample_resolve(void) DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - &color, 0xffe1bc89, TRUE}, + &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index f0bdd26a948..e59383aa6d5 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -30206,13 +30206,13 @@ static void test_multisample_resolve_blended(void) 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, - 4, { 0, 0, 0, 0x3f }, TRUE }, + 4, { 0, 0, 0, 0x3f } }, { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, 2, { 0, 0x80 } }, @@ -30224,7 +30224,7 @@ static void test_multisample_resolve_blended(void) 2, { 0xff, 0x37 } }, { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, - 2, { 0x66, 0x36 }, TRUE }, + 2, { 0x66, 0x36 } }, { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, 2, { 0xbd, 0xc8 } }, @@ -30233,16 +30233,16 @@ static void test_multisample_resolve_blended(void) 4, { 0x80, 0x19, 0x19, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + 4, { 0x99, 0x23, 0x23, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + 4, { 0x99, 0x23, 0x23, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, - 4, { 0, 0x19, 0x19, 0xff }, TRUE }, + 4, { 0, 0x19, 0x19, 0xff } }, { FALSE, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, - 4, { 0x3f, 0xc, 0xc, 0x7f }, TRUE }, + 4, { 0x3f, 0xc, 0xc, 0x7f } }, { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, 4, { 0x3f, 0, 0, 0x40 }, TRUE }, @@ -30446,7 +30446,7 @@ static void test_multisample_resolve(void) DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, - &color, 0xffe1bc89, TRUE}, + &color, 0xffe1bc89}, {DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86664
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:5827: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5828: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5829: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5832: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5833: Test failed: Got unexpected CPrimitives count: 0.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:5827: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5828: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5829: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5832: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5833: Test failed: Got unexpected CPrimitives count: 0.
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
dlls/d3d10core/tests/d3d10core.c | 2 +- dlls/d3d11/tests/d3d11.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-)
These belong in the patches that make the tests in question pass.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=86659
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:5827: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5828: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5829: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5832: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5833: Test failed: Got unexpected CPrimitives count: 0.
=== w1064 (32 bit report) ===
d3d11: d3d11.c:5827: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5828: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5829: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5832: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5833: Test failed: Got unexpected CPrimitives count: 0. d3d11.c:5674: Test failed: Got unexpected query result 0x0000000000000000.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:5827: Test failed: Got unexpected IAVertices count: 0. d3d11.c:5828: Test failed: Got unexpected IAPrimitives count: 0. d3d11.c:5829: Test failed: Got unexpected VSInvocations count: 0. d3d11.c:5832: Test failed: Got unexpected CInvocations count: 0. d3d11.c:5833: Test failed: Got unexpected CPrimitives count: 0.
=== debiant2 (32 bit Japanese:Japan report) ===
d3d11: d3d11.c:19454: Test failed: d3d11.c:16083: Test marked todo: Got 0xdeadbeef, expected 0x4030201 or 0x4030201 at 1, uvec4 0x1, 0x2, 0x3, 0x4.
On Tue, 9 Mar 2021 at 10:26, Jan Sikorski jsikorski@codeweavers.com wrote:
+static BOOL compare_scolor(DWORD c1, DWORD c2, BYTE max_diff) +{
- signed char c1x = c1, c1y = (c1 >> 8), c1z = (c1 >> 16), c1w = (c1 >> 24);
- signed char c2x = c2, c2y = (c2 >> 8), c2z = (c2 >> 16), c2w = (c2 >> 24);
- return compare_int(c1x, c2x, max_diff) && compare_int(c1y, c2y, max_diff)
&& compare_int(c1z, c2z, max_diff) && compare_int(c1w, c2w, max_diff);
+}
Truncating to a signed integer type is implementation-defined.
+static void test_multisample_resolve_blended(void) +{
- static const D3D11_VIEWPORT viewport = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
- static const float clear_color[4] = {0.2f, 0.2f, 0.2f, 1.0f};
- unsigned int vertex_buffer_stride = 6 * sizeof(float);
- ID3D11PixelShader *pixel_shader, *pixel_shader_uint;
- ID3D11Texture2D *resolve_target, *render_target;
- D3D11_RENDER_TARGET_VIEW_DESC render_view_desc;
- ID3D11RenderTargetView *render_target_view;
- unsigned int vertex_buffer_offset = 0;
- ID3D11DeviceContext *device_context;
- D3D11_TEXTURE2D_DESC texture_desc;
- ID3D11VertexShader *vertex_shader;
- ID3D11InputLayout *input_layout;
- unsigned int i, quality_levels;
- struct resource_readback rb;
- ID3D11Buffer *vertex_buffer;
- unsigned char *result;
- ID3D11Device *device;
- BOOL compare_ok;
- HRESULT hr;
- static const DWORD vs_code[] =
- {
+#if 0
struct VS_Input
{
float2 pos : TEXCOORD0;
float4 color : COLOR;
};
struct VS_Output
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VS_Output vs_main(VS_Input input)
{
VS_Output output;
output.position = float4(input.pos, 0.0f, 1.0f);
output.color = input.color;
return output;
}
+#endif
0x43425844, 0x3fbe97c7, 0x2cdce39d, 0xa8d3bf48, 0xe0d872e3, 0x00000001, 0x00000160, 0x00000003,
0x0000002c, 0x0000007c, 0x000000d0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038,
0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
0x00000003, 0x00000001, 0x00000f0f, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f,
0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000,
0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653,
0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000088, 0x00010040, 0x00000022,
0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2,
0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x00102032, 0x00000000,
0x00101046, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000,
0x00000000, 0x3f800000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e,
- };
- static const DWORD ps_code[] =
- {
+#if 0
float4 ps_main(VS_Output input) : SV_TARGET
{
return input.color;
}
+#endif
0x43425844, 0xe2087fa6, 0xa35fbd95, 0x8e585b3f, 0x67890f54, 0x00000001, 0x000000f4, 0x00000003,
0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040,
0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036,
0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e
- };
- static const DWORD ps_uint_code[] =
- {
+#if 0
uint4 ps_main_uint(VS_Output input) : SV_TARGET
{
return 255 * input.color;
}
+#endif
0x43425844, 0x9c2c834b, 0x37ca7b30, 0x01b4b43e, 0x713b001e, 0x00000001, 0x00000124, 0x00000003,
0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001,
0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000068, 0x00000040,
0x0000001a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068,
0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x00004002, 0x437f0000,
0x437f0000, 0x437f0000, 0x437f0000, 0x0500001c, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000,
0x0100003e
- };
- static const struct
- {
struct vec2 xy;
struct vec4 rgba;
- }
- vertex_data[] =
- {
{{ 1.0f, 1.0f }, { .8f, 0.f, 0.f, 1.f }},
{{ 1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }},
{{-1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }},
- };
- static const D3D11_INPUT_ELEMENT_DESC input_elements[] =
- {
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
- };
Do we really need all that? It seems that most of the reason for not using draw_color_quad() is that you're drawing a triangle over half a pixel, in order to get partial coverage for testing how the resolve operation blends. If that's the case, it would seem simpler (and more robust) to pass an appropriate sample mask to OMSetBlendState() instead. That would also allow you to trivially integrate this with the existing test_multisample_resolve() test.
- static const struct
- {
BOOL use_uint_shader;
DXGI_FORMAT render_target_view_format;
DXGI_FORMAT source_format;
DXGI_FORMAT destination_format;
DXGI_FORMAT resolve_format;
unsigned int byte_count;
unsigned char expected[4];
BOOL todo;
- }
- tests[] =
- {
{ FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT,
DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT,
4, { 0, 0, 0, 0x3f } },
It's perhaps somewhat moot in light of the comment above, but at least personally, I think "0x3f000000" is much more recognisable as "0.5f" than the "{0, 0, 0, 0x3f}" above.
ok(compare_ok, "Test %3u: expected: %2x %2x %2x %2x, got: %2x %2x %2x %2x.\n", i,
tests[i].expected[0], tests[i].expected[1], tests[i].expected[2], tests[i].expected[3],
result[0], result[1], result[2], result[3]);
Likewise.