[PATCH v3 0/2] MR10292: wined3d: Implement format conversion in the Vulkan blitter.
-- v3: wined3d: Implement format conversion in the Vulkan blitter. d3d9/tests: Test format conversion in StretchRect(). https://gitlab.winehq.org/wine/wine/-/merge_requests/10292
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/d3d9/tests/visual.c | 91 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 9e588b0768e..29f7a45637f 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -4470,8 +4470,6 @@ static void stretchrect_test(void) ok(hr == test->allowed ? D3D_OK : D3DERR_INVALIDCALL, "Test %u, got unexpected hr %#lx.\n", i, hr); } - /* TODO: Test format conversions. */ - for (i = 0; i < ARRAY_SIZE(surfaces); ++i) { IDirect3DSurface9_Release(surfaces[i]); @@ -29141,6 +29139,94 @@ static void test_generated_texcoords(void) release_test_context(&context); } +static void test_blit_format_conversion(void) +{ + IDirect3DSurface9 *src_surface, *dst_surface; + struct d3d9_test_context context; + IDirect3DTexture9 *src, *dst; + struct surface_readback rb; + IDirect3DDevice9 *device; + HRESULT hr; + + static const struct + { + D3DFORMAT src_format; + uint32_t src_colour; + D3DFORMAT dst_format; + unsigned int dst_size; + union + { + float f[4]; + uint32_t u; + } dst_data; + } + tests[] = + { + {D3DFMT_A8R8G8B8, 0x12345678, D3DFMT_X8R8G8B8, 3, {.u = 0x12345678}}, + {D3DFMT_X8R8G8B8, 0x12345678, D3DFMT_A8R8G8B8, 3, {.u = 0x12345678}}, + {D3DFMT_A8R8G8B8, 0x12345678, D3DFMT_R5G6B5, 2, {.u = 0x32af}}, + {D3DFMT_A8R8G8B8, 0x12345678, D3DFMT_A32B32G32R32F, 16, {.f = {0x34/255.0f, 0x56/255.0f, 0x78/255.0f, 0x12/255.0f}}}, + {D3DFMT_A32B32G32R32F, 0x12345678, D3DFMT_A8R8G8B8, 4, {.u = 0x12345678}}, + }; + + if (!init_test_context(&context)) + return; + device = context.device; + + for (unsigned int i = 0; i < ARRAY_SIZE(tests); ++i) + { + /* Use a nontrivial clear rect to defeat a wined3d optimization and + * ensure that we are actually testing format conversion blits. */ + static const RECT rect = {0, 0, 2, 2}; + + winetest_push_context("Test %u", i); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, D3DUSAGE_RENDERTARGET, + tests[i].src_format, D3DPOOL_DEFAULT, &src, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, D3DUSAGE_RENDERTARGET, + tests[i].dst_format, D3DPOOL_DEFAULT, &dst, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DTexture9_GetSurfaceLevel(src, 0, &src_surface); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirect3DTexture9_GetSurfaceLevel(dst, 0, &dst_surface); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9_ColorFill(device, src_surface, &rect, tests[i].src_colour); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_surface, NULL, D3DTEXF_LINEAR); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + get_rt_readback(dst_surface, &rb); + if (tests[i].dst_format == D3DFMT_A32B32G32R32F) + { + const struct vec4 *data = rb.locked_rect.pBits; + + ok(compare_vec4(data, tests[i].dst_data.f[0], tests[i].dst_data.f[1], + tests[i].dst_data.f[2], tests[i].dst_data.f[3], 1), + "Got %.8e, %.8e, %.8e, %.8e.\n", data->x, data->y, data->z, data->w); + } + else + { + ok(!memcmp(rb.locked_rect.pBits, &tests[i].dst_data, tests[i].dst_size), + "Got data %08x.\n", *(uint32_t *)rb.locked_rect.pBits); + } + release_surface_readback(&rb); + + IDirect3DSurface9_Release(src_surface); + IDirect3DSurface9_Release(dst_surface); + IDirect3DTexture9_Release(src); + IDirect3DTexture9_Release(dst); + + winetest_pop_context(); + } + + release_test_context(&context); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER9 identifier; @@ -29302,4 +29388,5 @@ START_TEST(visual) test_texture_transform_flags(); test_lighting_matrices(); test_generated_texcoords(); + test_blit_format_conversion(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10292
From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/wined3d/sampler.c | 2 +- dlls/wined3d/texture_vk.c | 56 +++++++++++++++++++++++++++++----- dlls/wined3d/utils.c | 2 ++ dlls/wined3d/wined3d_private.h | 1 + dlls/wined3d/wined3d_vk.h | 1 + 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/dlls/wined3d/sampler.c b/dlls/wined3d/sampler.c index 2f269f06df5..066e92ccd89 100644 --- a/dlls/wined3d/sampler.c +++ b/dlls/wined3d/sampler.c @@ -145,7 +145,7 @@ void wined3d_sampler_gl_init(struct wined3d_sampler_gl *sampler_gl, struct wined wined3d_cs_init_object(device->cs, wined3d_sampler_gl_cs_init, sampler_gl); } -static VkFilter vk_filter_from_wined3d(enum wined3d_texture_filter_type f) +VkFilter vk_filter_from_wined3d(enum wined3d_texture_filter_type f) { switch (f) { diff --git a/dlls/wined3d/texture_vk.c b/dlls/wined3d/texture_vk.c index 88d83e3f7f4..a11606303c1 100644 --- a/dlls/wined3d/texture_vk.c +++ b/dlls/wined3d/texture_vk.c @@ -1500,6 +1500,12 @@ static bool vk_blitter_conversion_supported(enum wined3d_blit_op op, const struc if (resolve_format) return true; + if (!((src_format->attrs | dst_format->attrs) & WINED3D_FORMAT_ATTR_INTEGER)) + return true; + + if ((src_format->attrs & WINED3D_FORMAT_ATTR_UNSIGNED) == (dst_format->attrs & WINED3D_FORMAT_ATTR_UNSIGNED)) + return true; + return false; } @@ -1565,16 +1571,20 @@ static bool vk_blitter_blit_supported(enum wined3d_blit_op op, const struct wine return false; } - if ((src_rect->right - src_rect->left != dst_rect->right - dst_rect->left) - || (src_rect->bottom - src_rect->top != dst_rect->bottom - dst_rect->top)) - { - TRACE("Scaling not supported.\n"); - return false; - } - return true; } +static bool use_raw_blit(enum wined3d_blit_op op, const struct wined3d_format_vk *src_format_vk, + const struct wined3d_format_vk *dst_format_vk, const RECT *src_rect, const RECT *dst_rect) +{ + if (op == WINED3D_BLIT_OP_RAW_BLIT) + return true; + + return src_format_vk->vk_format == dst_format_vk->vk_format + && src_rect->right - src_rect->left == dst_rect->right - dst_rect->left + && src_rect->bottom - src_rect->top == dst_rect->bottom - dst_rect->top; +} + 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, @@ -1582,6 +1592,8 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ const struct wined3d_color_key *colour_key, enum wined3d_texture_filter_type filter, const struct wined3d_format *resolve_format) { + 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); struct wined3d_texture_vk *src_texture_vk = wined3d_texture_vk(src_texture); struct wined3d_texture_vk *dst_texture_vk = wined3d_texture_vk(dst_texture); struct wined3d_context_vk *context_vk = wined3d_context_vk(context); @@ -1867,7 +1879,7 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ dst_texture_vk->image.vk_image, dst_layout, 1, ©_region)); } } - else + else if (use_raw_blit(op, src_format_vk, dst_format_vk, src_rect, dst_rect)) { const struct wined3d_format *src_format = src_texture_vk->t.resource.format; VkImageCopy region; @@ -1913,6 +1925,34 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ dst_texture_vk->image.vk_image, dst_layout, 1, ®ion)); } } + else + { + VkImageBlit region; + + region.srcSubresource.aspectMask = vk_src_range.aspectMask; + region.srcSubresource.mipLevel = vk_src_range.baseMipLevel; + region.srcSubresource.baseArrayLayer = vk_src_range.baseArrayLayer; + region.srcSubresource.layerCount = vk_src_range.layerCount; + region.srcOffsets[0].x = src_rect->left; + region.srcOffsets[0].y = src_rect->top; + region.srcOffsets[0].z = 0; + region.srcOffsets[1].x = src_rect->right; + region.srcOffsets[1].y = src_rect->bottom; + region.srcOffsets[1].z = 1; + region.dstSubresource.aspectMask = vk_dst_range.aspectMask; + region.dstSubresource.mipLevel = vk_dst_range.baseMipLevel; + region.dstSubresource.baseArrayLayer = vk_dst_range.baseArrayLayer; + region.dstSubresource.layerCount = vk_dst_range.layerCount; + region.dstOffsets[0].x = dst_rect->left; + region.dstOffsets[0].y = dst_rect->top; + region.dstOffsets[0].z = 0; + region.dstOffsets[1].x = dst_rect->right; + region.dstOffsets[1].y = dst_rect->bottom; + region.dstOffsets[1].z = 1; + + VK_CALL(vkCmdBlitImage(vk_command_buffer, src_texture_vk->image.vk_image, src_layout, + dst_texture_vk->image.vk_image, dst_layout, 1, ®ion, vk_filter_from_wined3d(filter))); + } wined3d_context_vk_image_barrier(context_vk, vk_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 6091f6bd820..0fb90ba3f18 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -1928,6 +1928,8 @@ static void parse_channel_desc(struct wined3d_format *format, const char *channe attrs |= WINED3D_FORMAT_ATTR_NORMALISED; if (channel_type == WINED3D_CHANNEL_TYPE_UINT || channel_type == WINED3D_CHANNEL_TYPE_SINT) attrs |= WINED3D_FORMAT_ATTR_INTEGER; + if (channel_type == WINED3D_CHANNEL_TYPE_UINT || channel_type == WINED3D_CHANNEL_TYPE_UNORM) + attrs |= WINED3D_FORMAT_ATTR_UNSIGNED; if (channel_type == WINED3D_CHANNEL_TYPE_FLOAT) attrs |= WINED3D_FORMAT_ATTR_FLOAT; if (channel_type == WINED3D_CHANNEL_TYPE_DEPTH) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9998b29ccf1..fa758c53cc1 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4541,6 +4541,7 @@ extern enum wined3d_format_id pixelformat_for_depth(DWORD depth); #define WINED3D_FORMAT_ATTR_CAST_TO_BLOCK 0x00000800 #define WINED3D_FORMAT_ATTR_PLANAR 0x00001000 #define WINED3D_FORMAT_ATTR_SHADOW 0x00002000 +#define WINED3D_FORMAT_ATTR_UNSIGNED 0x00004000 /* Pixel format capabilities */ #define WINED3D_FORMAT_CAP_POSTPIXELSHADER_BLENDING 0x00000001 diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index a0f167ea17a..aa5976bb730 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -299,6 +299,7 @@ static const VkAccessFlags WINED3D_READ_ONLY_ACCESS_FLAGS = VK_ACCESS_INDIRECT_C VkAccessFlags vk_access_mask_from_bind_flags(uint32_t bind_flags); VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op); +VkFilter vk_filter_from_wined3d(enum wined3d_texture_filter_type f); VkImageViewType vk_image_view_type_from_wined3d(enum wined3d_resource_type type, uint32_t flags); VkPipelineStageFlags vk_pipeline_stage_mask_from_bind_flags(uint32_t bind_flags); VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10292
participants (2)
-
Elizabeth Figura -
Elizabeth Figura (@zfigura)