-- v3: d3d11/tests: Extend NV12 tests. wined3d: Implement planar NV12 in the Vulkan renderer. wined3d: Enable KHR_sampler_ycbcr_conversion. wined3d: Implement planar Vulkan blits. wined3d: Implement planar Vulkan downloads. wined3d: Implement planar Vulkan uploads. wined3d: Separate a wined3d_texture_vk_download_plane() helper. wined3d: Separate a wined3d_texture_vk_upload_plane() helper. wined3d: Use a separate format value for d3d10+ NV12.
From: Elizabeth Figura zfigura@codeweavers.com
d3d9 and d3d10 YUV formats generally have completely different behaviour, even after accounting for the fundamental differences between the APIs. d3d9 can blit between YUV and RGB formats, with associated format conversion, and can use the entire resource in blits and clears, whereas d3d10 cannot do either of these things, and must use views of individual planes.
This causes some friction given that we implement d3d9 APIs using views internally. In particular, 4caa93a369b51a9bd8922a3f2cdd02a632b52543 inadvertently breaks clears of d3d1-9 YUV surfaces.
The two formats have almost no actual functionality in common, so address this by using two different format enumerants.
Fixes: 4caa93a369b51a9bd8922a3f2cdd02a632b52543 --- dlls/d3d11/tests/d3d11.c | 2 +- dlls/d3d11/utils.c | 4 ++-- dlls/d3d9/tests/visual.c | 7 +++++++ dlls/dxgi/utils.c | 4 ++-- dlls/wined3d/utils.c | 4 +++- include/wine/wined3d.h | 1 + 6 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 8436e2a1ef5..4adad271fc8 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -36300,7 +36300,7 @@ static void test_nv12(void) device_context = test_context.immediate_context;
hr = ID3D11Device_CheckFormatSupport(device, DXGI_FORMAT_NV12, &support); - ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr);
if (!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D)) { diff --git a/dlls/d3d11/utils.c b/dlls/d3d11/utils.c index 1a0be470f38..de5e08b8e7a 100644 --- a/dlls/d3d11/utils.c +++ b/dlls/d3d11/utils.c @@ -311,7 +311,7 @@ DXGI_FORMAT dxgi_format_from_wined3dformat(enum wined3d_format_id format) case WINED3DFMT_BC7_TYPELESS: return DXGI_FORMAT_BC7_TYPELESS; case WINED3DFMT_BC7_UNORM: return DXGI_FORMAT_BC7_UNORM; case WINED3DFMT_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_UNORM_SRGB; - case WINED3DFMT_NV12: return DXGI_FORMAT_NV12; + case WINED3DFMT_NV12_PLANAR: return DXGI_FORMAT_NV12; case WINED3DFMT_YUY2: return DXGI_FORMAT_YUY2; case WINED3DFMT_B4G4R4A4_UNORM: return DXGI_FORMAT_B4G4R4A4_UNORM; default: @@ -424,7 +424,7 @@ enum wined3d_format_id wined3dformat_from_dxgi_format(DXGI_FORMAT format) case DXGI_FORMAT_BC7_TYPELESS: return WINED3DFMT_BC7_TYPELESS; case DXGI_FORMAT_BC7_UNORM: return WINED3DFMT_BC7_UNORM; case DXGI_FORMAT_BC7_UNORM_SRGB: return WINED3DFMT_BC7_UNORM_SRGB; - case DXGI_FORMAT_NV12: return WINED3DFMT_NV12; + case DXGI_FORMAT_NV12: return WINED3DFMT_NV12_PLANAR; case DXGI_FORMAT_YUY2: return WINED3DFMT_YUY2; case DXGI_FORMAT_B4G4R4A4_UNORM: return WINED3DFMT_B4G4R4A4_UNORM; default: diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index bcf14631a8d..0c511f495b3 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -13919,6 +13919,13 @@ static void yuv_layout_test(void) hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == S_OK, "Got hr %#lx.\n", hr); } + + for (i = 0; i < ARRAY_SIZE(test_data); i++) + { + hr = IDirect3DDevice9_ColorFill(device, surface, NULL, test_data[i].color1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + IDirect3DSurface9_Release(surface); }
diff --git a/dlls/dxgi/utils.c b/dlls/dxgi/utils.c index 6ae60a79f9a..8ab1ace3c43 100644 --- a/dlls/dxgi/utils.c +++ b/dlls/dxgi/utils.c @@ -263,7 +263,7 @@ DXGI_FORMAT dxgi_format_from_wined3dformat(enum wined3d_format_id format) case WINED3DFMT_BC7_TYPELESS: return DXGI_FORMAT_BC7_TYPELESS; case WINED3DFMT_BC7_UNORM: return DXGI_FORMAT_BC7_UNORM; case WINED3DFMT_BC7_UNORM_SRGB: return DXGI_FORMAT_BC7_UNORM_SRGB; - case WINED3DFMT_NV12: return DXGI_FORMAT_NV12; + case WINED3DFMT_NV12_PLANAR: return DXGI_FORMAT_NV12; case WINED3DFMT_YUY2: return DXGI_FORMAT_YUY2; case WINED3DFMT_B4G4R4A4_UNORM: return DXGI_FORMAT_B4G4R4A4_UNORM; default: @@ -376,7 +376,7 @@ enum wined3d_format_id wined3dformat_from_dxgi_format(DXGI_FORMAT format) case DXGI_FORMAT_BC7_TYPELESS: return WINED3DFMT_BC7_TYPELESS; case DXGI_FORMAT_BC7_UNORM: return WINED3DFMT_BC7_UNORM; case DXGI_FORMAT_BC7_UNORM_SRGB: return WINED3DFMT_BC7_UNORM_SRGB; - case DXGI_FORMAT_NV12: return WINED3DFMT_NV12; + case DXGI_FORMAT_NV12: return WINED3DFMT_NV12_PLANAR; case DXGI_FORMAT_YUY2: return WINED3DFMT_YUY2; case DXGI_FORMAT_B4G4R4A4_UNORM: return WINED3DFMT_B4G4R4A4_UNORM; default: diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index e5969daa527..58ca1fcca5e 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -89,6 +89,7 @@ static const struct wined3d_format_channels formats[] = {WINED3DFMT_YUY2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0}, {WINED3DFMT_YV12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_NV12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {WINED3DFMT_NV12_PLANAR, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_DXT1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_DXT2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_DXT3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, @@ -718,7 +719,7 @@ static const struct } format_plane_info[] = { - {WINED3DFMT_NV12, {WINED3DFMT_R8_UINT, WINED3DFMT_R8G8_UINT}, 2, 2}, + {WINED3DFMT_NV12_PLANAR, {WINED3DFMT_R8_UINT, WINED3DFMT_R8G8_UINT}, 2, 2}, };
struct wined3d_format_vertex_info @@ -4757,6 +4758,7 @@ const char *debug_d3dformat(enum wined3d_format_id format_id) FMT_TO_STR(WINED3DFMT_R9G9B9E5_SHAREDEXP); FMT_TO_STR(WINED3DFMT_R8G8_B8G8_UNORM); FMT_TO_STR(WINED3DFMT_G8R8_G8B8_UNORM); + FMT_TO_STR(WINED3DFMT_NV12_PLANAR); FMT_TO_STR(WINED3DFMT_BC1_TYPELESS); FMT_TO_STR(WINED3DFMT_BC1_UNORM); FMT_TO_STR(WINED3DFMT_BC1_UNORM_SRGB); diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 871d61fcde3..85e12f8e621 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -224,6 +224,7 @@ enum wined3d_format_id WINED3DFMT_R9G9B9E5_SHAREDEXP, WINED3DFMT_R8G8_B8G8_UNORM, WINED3DFMT_G8R8_G8B8_UNORM, + WINED3DFMT_NV12_PLANAR, WINED3DFMT_BC1_TYPELESS, WINED3DFMT_BC1_UNORM, WINED3DFMT_BC1_UNORM_SRGB,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 102 ++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 43 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index b26b1221e7a..2c13e7fee10 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4677,10 +4677,10 @@ const VkDescriptorImageInfo *wined3d_texture_vk_get_default_image_info(struct wi return &texture_vk->default_image_info; }
-static void wined3d_texture_vk_upload_data(struct wined3d_context *context, - const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format, +static void wined3d_texture_vk_upload_plane(struct wined3d_context *context, VkImageAspectFlags vk_aspect, + const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *plane_format, const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch, - struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_location, + struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) { struct wined3d_texture_vk *dst_texture_vk = wined3d_texture_vk(dst_texture); @@ -4695,26 +4695,16 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, VkBufferMemoryBarrier vk_barrier; VkImageSubresourceRange vk_range; struct wined3d_bo_vk staging_bo; - VkImageAspectFlags aspect_mask; struct wined3d_bo_vk *src_bo; struct wined3d_range range; VkBufferImageCopy region; size_t src_offset; void *map_ptr;
- TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, " - "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n", - context, debug_const_bo_address(src_bo_addr), debug_d3dformat(src_format->id), debug_box(src_box), - src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, - wined3d_debug_location(dst_location), dst_x, dst_y, dst_z); - - if (src_format->id != dst_texture->resource.format->id) - { - FIXME("Unhandled format conversion (%s -> %s).\n", - debug_d3dformat(src_format->id), - debug_d3dformat(dst_texture->resource.format->id)); - return; - } + TRACE("context %p, vk_aspect %#x, src_bo_addr %s, plane_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, " + "dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u.\n", + context, vk_aspect, debug_const_bo_address(src_bo_addr), debug_d3dformat(plane_format->id), debug_box(src_box), + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z);
dst_level = dst_sub_resource_idx % dst_texture->level_count; wined3d_texture_get_pitch(dst_texture, dst_level, &dst_row_pitch, &dst_slice_pitch); @@ -4723,25 +4713,6 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, if (dst_texture->resource.type != WINED3D_RTYPE_TEXTURE_3D) src_slice_pitch = dst_slice_pitch = 0;
- if (dst_location != WINED3D_LOCATION_TEXTURE_RGB) - { - FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location)); - return; - } - - if (wined3d_resource_get_sample_count(&dst_texture_vk->t.resource) > 1) - { - FIXME("Not supported for multisample textures.\n"); - return; - } - - aspect_mask = vk_aspect_mask_from_format(dst_texture->resource.format); - if (wined3d_popcount(aspect_mask) > 1) - { - FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(dst_texture->resource.format->id)); - return; - } - sub_resource = &dst_texture_vk->t.sub_resources[dst_sub_resource_idx]; vk_info = context_vk->vk_info;
@@ -4750,8 +4721,8 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, src_depth = src_box->back - src_box->front;
src_offset = src_box->front * src_slice_pitch - + (src_box->top / src_format->block_height) * src_row_pitch - + (src_box->left / src_format->block_width) * src_format->block_byte_count; + + (src_box->top / plane_format->block_height) * src_row_pitch + + (src_box->left / plane_format->block_width) * plane_format->block_byte_count;
if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) { @@ -4765,7 +4736,7 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, { unsigned int staging_row_pitch, staging_slice_pitch, staging_size;
- wined3d_format_calculate_pitch(src_format, context->device->surface_alignment, src_width, src_height, + wined3d_format_calculate_pitch(plane_format, context->device->surface_alignment, src_width, src_height, &staging_row_pitch, &staging_slice_pitch); staging_size = staging_slice_pitch * src_depth;
@@ -4786,7 +4757,7 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, return; }
- wined3d_format_copy_data(src_format, src_bo_addr->addr + src_offset, src_row_pitch, src_slice_pitch, + wined3d_format_copy_data(plane_format, src_bo_addr->addr + src_offset, src_row_pitch, src_slice_pitch, map_ptr, staging_row_pitch, staging_slice_pitch, src_width, src_height, src_depth);
range.offset = 0; @@ -4821,7 +4792,7 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); }
- vk_range.aspectMask = aspect_mask; + vk_range.aspectMask = vk_aspect; vk_range.baseMipLevel = dst_level; vk_range.levelCount = 1; vk_range.baseArrayLayer = dst_sub_resource_idx / dst_texture_vk->t.level_count; @@ -4835,9 +4806,9 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, dst_texture_vk->image.vk_image, &vk_range);
region.bufferOffset = src_bo->b.buffer_offset + src_offset; - region.bufferRowLength = (src_row_pitch / src_format->block_byte_count) * src_format->block_width; + region.bufferRowLength = (src_row_pitch / plane_format->block_byte_count) * plane_format->block_width; if (src_row_pitch) - region.bufferImageHeight = (src_slice_pitch / src_row_pitch) * src_format->block_height; + region.bufferImageHeight = (src_slice_pitch / src_row_pitch) * plane_format->block_height; else region.bufferImageHeight = 1; region.imageSubresource.aspectMask = vk_range.aspectMask; @@ -4874,6 +4845,51 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, } }
+static void wined3d_texture_vk_upload_data(struct wined3d_context *context, + const struct wined3d_const_bo_address *src_bo_addr, const struct wined3d_format *src_format, + const struct wined3d_box *src_box, unsigned int src_row_pitch, unsigned int src_slice_pitch, + struct wined3d_texture *dst_texture, unsigned int dst_sub_resource_idx, unsigned int dst_location, + unsigned int dst_x, unsigned int dst_y, unsigned int dst_z) +{ + VkImageAspectFlags aspect_mask; + + TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, " + "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n", + context, debug_const_bo_address(src_bo_addr), debug_d3dformat(src_format->id), debug_box(src_box), + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, + wined3d_debug_location(dst_location), dst_x, dst_y, dst_z); + + if (src_format->id != dst_texture->resource.format->id) + { + FIXME("Unhandled format conversion (%s -> %s).\n", + debug_d3dformat(src_format->id), + debug_d3dformat(dst_texture->resource.format->id)); + return; + } + + if (dst_location != WINED3D_LOCATION_TEXTURE_RGB) + { + FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location)); + return; + } + + if (wined3d_resource_get_sample_count(&dst_texture->resource) > 1) + { + FIXME("Not supported for multisample textures.\n"); + return; + } + + aspect_mask = vk_aspect_mask_from_format(dst_texture->resource.format); + if (wined3d_popcount(aspect_mask) > 1) + { + FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(dst_texture->resource.format->id)); + return; + } + + wined3d_texture_vk_upload_plane(context, aspect_mask, src_bo_addr, src_format, src_box, + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); +} + static void wined3d_texture_vk_download_data(struct wined3d_context *context, struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, unsigned int src_location, const struct wined3d_box *src_box, const struct wined3d_bo_address *dst_bo_addr,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 157 +++++++++++++++++++++++++---------------- 1 file changed, 96 insertions(+), 61 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 2c13e7fee10..1ab4db200d2 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4890,10 +4890,10 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); }
-static void wined3d_texture_vk_download_data(struct wined3d_context *context, - struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, unsigned int src_location, +static void wined3d_texture_vk_download_plane(struct wined3d_context *context, VkImageAspectFlags vk_aspect, + struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, const struct wined3d_box *src_box, const struct wined3d_bo_address *dst_bo_addr, - const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, + const struct wined3d_format *plane_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, unsigned int dst_row_pitch, unsigned int dst_slice_pitch) { struct wined3d_texture_vk *src_texture_vk = wined3d_texture_vk(src_texture); @@ -4908,62 +4908,18 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, VkImageSubresourceRange vk_range; VkBufferMemoryBarrier vk_barrier; struct wined3d_bo_vk staging_bo; - VkImageAspectFlags aspect_mask; struct wined3d_bo_vk *dst_bo; VkBufferImageCopy region; size_t dst_offset = 0; void *map_ptr;
- TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, " - "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n", - context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), - debug_box(src_box), debug_bo_address(dst_bo_addr), debug_d3dformat(dst_format->id), + TRACE("context %p, vk_aspect %#x, src_texture %p, src_sub_resource_idx %u, src_box %s, dst_bo_addr %s, " + "plane_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n", + context, vk_aspect, src_texture, src_sub_resource_idx, + debug_box(src_box), debug_bo_address(dst_bo_addr), debug_d3dformat(plane_format->id), dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch);
- if (src_location != WINED3D_LOCATION_TEXTURE_RGB) - { - FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location)); - return; - } - src_level = src_sub_resource_idx % src_texture->level_count; - src_width = wined3d_texture_get_level_width(src_texture, src_level); - src_height = wined3d_texture_get_level_height(src_texture, src_level); - src_depth = wined3d_texture_get_level_depth(src_texture, src_level); - if (src_box->left || src_box->top || src_box->right != src_width || src_box->bottom != src_height - || src_box->front || src_box->back != src_depth) - { - FIXME("Unhandled source box %s.\n", debug_box(src_box)); - return; - } - - if (dst_format->id != src_texture->resource.format->id) - { - FIXME("Unhandled format conversion (%s -> %s).\n", - debug_d3dformat(src_texture->resource.format->id), - debug_d3dformat(dst_format->id)); - return; - } - - if (dst_x || dst_y || dst_z) - { - FIXME("Unhandled destination (%u, %u, %u).\n", dst_x, dst_y, dst_z); - return; - } - - if (wined3d_resource_get_sample_count(&src_texture_vk->t.resource) > 1) - { - FIXME("Not supported for multisample textures.\n"); - return; - } - - aspect_mask = vk_aspect_mask_from_format(src_texture->resource.format); - if (wined3d_popcount(aspect_mask) > 1) - { - FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(src_texture->resource.format->id)); - return; - } - wined3d_texture_get_pitch(src_texture, src_level, &src_row_pitch, &src_slice_pitch); if (src_texture->resource.type == WINED3D_RTYPE_TEXTURE_1D) src_row_pitch = dst_row_pitch = 0; @@ -4972,6 +4928,11 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context,
sub_resource = &src_texture_vk->t.sub_resources[src_sub_resource_idx]; vk_info = context_vk->vk_info; + + src_width = src_box->right - src_box->left; + src_height = src_box->bottom - src_box->top; + src_depth = src_box->back - src_box->front; + if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk))) { ERR("Failed to get command buffer.\n"); @@ -4992,15 +4953,15 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context,
dst_bo = &staging_bo;
- region.bufferRowLength = (src_row_pitch / dst_format->block_byte_count) * dst_format->block_width; + region.bufferRowLength = (src_row_pitch / plane_format->block_byte_count) * plane_format->block_width; if (src_row_pitch) - region.bufferImageHeight = (src_slice_pitch / src_row_pitch) * dst_format->block_height; + region.bufferImageHeight = (src_slice_pitch / src_row_pitch) * plane_format->block_height; else region.bufferImageHeight = 1;
- if (src_row_pitch % dst_format->byte_count) + if (src_row_pitch % plane_format->byte_count) { - FIXME("Row pitch %u is not a multiple of byte count %u.\n", src_row_pitch, dst_format->byte_count); + FIXME("Row pitch %u is not a multiple of byte count %u.\n", src_row_pitch, plane_format->byte_count); return; } if (src_row_pitch && src_slice_pitch % src_row_pitch) @@ -5013,15 +4974,15 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, { dst_bo = wined3d_bo_vk(dst_bo_addr->buffer_object);
- region.bufferRowLength = (dst_row_pitch / dst_format->block_byte_count) * dst_format->block_width; + region.bufferRowLength = (dst_row_pitch / plane_format->block_byte_count) * plane_format->block_width; if (dst_row_pitch) - region.bufferImageHeight = (dst_slice_pitch / dst_row_pitch) * dst_format->block_height; + region.bufferImageHeight = (dst_slice_pitch / dst_row_pitch) * plane_format->block_height; else region.bufferImageHeight = 1;
- if (dst_row_pitch % dst_format->byte_count) + if (dst_row_pitch % plane_format->byte_count) { - FIXME("Row pitch %u is not a multiple of byte count %u.\n", dst_row_pitch, dst_format->byte_count); + FIXME("Row pitch %u is not a multiple of byte count %u.\n", dst_row_pitch, plane_format->byte_count); return; } if (dst_row_pitch && dst_slice_pitch % dst_row_pitch) @@ -5047,7 +5008,7 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &vk_barrier, 0, NULL)); }
- vk_range.aspectMask = aspect_mask; + vk_range.aspectMask = vk_aspect; vk_range.baseMipLevel = src_level; vk_range.levelCount = 1; vk_range.baseArrayLayer = src_sub_resource_idx / src_texture_vk->t.level_count; @@ -5100,7 +5061,7 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, return; }
- wined3d_format_copy_data(dst_format, map_ptr, src_row_pitch, src_slice_pitch, + wined3d_format_copy_data(plane_format, map_ptr, src_row_pitch, src_slice_pitch, dst_bo_addr->addr, dst_row_pitch, dst_slice_pitch, src_box->right - src_box->left, src_box->bottom - src_box->top, src_box->back - src_box->front);
@@ -5125,6 +5086,80 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, } }
+static void wined3d_texture_vk_download_data(struct wined3d_context *context, + struct wined3d_texture *src_texture, unsigned int src_sub_resource_idx, unsigned int src_location, + const struct wined3d_box *src_box, const struct wined3d_bo_address *dst_bo_addr, + const struct wined3d_format *dst_format, unsigned int dst_x, unsigned int dst_y, unsigned int dst_z, + unsigned int dst_row_pitch, unsigned int dst_slice_pitch) +{ + unsigned int src_level, src_width, src_height, src_depth; + VkImageAspectFlags aspect_mask; + + TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, " + "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n", + context, src_texture, src_sub_resource_idx, wined3d_debug_location(src_location), + debug_box(src_box), debug_bo_address(dst_bo_addr), debug_d3dformat(dst_format->id), + dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); + + if (src_location != WINED3D_LOCATION_TEXTURE_RGB) + { + FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location)); + return; + } + + src_level = src_sub_resource_idx % src_texture->level_count; + src_width = wined3d_texture_get_level_width(src_texture, src_level); + src_height = wined3d_texture_get_level_height(src_texture, src_level); + src_depth = wined3d_texture_get_level_depth(src_texture, src_level); + if (src_box->left || src_box->top || src_box->right != src_width || src_box->bottom != src_height + || src_box->front || src_box->back != src_depth) + { + FIXME("Unhandled source box %s.\n", debug_box(src_box)); + return; + } + + src_level = src_sub_resource_idx % src_texture->level_count; + src_width = wined3d_texture_get_level_width(src_texture, src_level); + src_height = wined3d_texture_get_level_height(src_texture, src_level); + src_depth = wined3d_texture_get_level_depth(src_texture, src_level); + if (src_box->left || src_box->top || src_box->right != src_width || src_box->bottom != src_height + || src_box->front || src_box->back != src_depth) + { + FIXME("Unhandled source box %s.\n", debug_box(src_box)); + return; + } + + if (dst_format->id != src_texture->resource.format->id) + { + FIXME("Unhandled format conversion (%s -> %s).\n", + debug_d3dformat(src_texture->resource.format->id), + debug_d3dformat(dst_format->id)); + return; + } + + if (dst_x || dst_y || dst_z) + { + FIXME("Unhandled destination (%u, %u, %u).\n", dst_x, dst_y, dst_z); + return; + } + + if (wined3d_resource_get_sample_count(&src_texture->resource) > 1) + { + FIXME("Not supported for multisample textures.\n"); + return; + } + + aspect_mask = vk_aspect_mask_from_format(src_texture->resource.format); + if (wined3d_popcount(aspect_mask) > 1) + { + FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(src_texture->resource.format->id)); + return; + } + + wined3d_texture_vk_download_plane(context, aspect_mask, src_texture, src_sub_resource_idx, + src_box, dst_bo_addr, dst_format, dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); +} + static bool wined3d_texture_vk_clear(struct wined3d_texture_vk *texture_vk, unsigned int sub_resource_idx, struct wined3d_context *context) {
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 1ab4db200d2..2f773978f9b 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4886,8 +4886,37 @@ static void wined3d_texture_vk_upload_data(struct wined3d_context *context, return; }
- wined3d_texture_vk_upload_plane(context, aspect_mask, src_bo_addr, src_format, src_box, - src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); + if (src_format->attrs & WINED3D_FORMAT_ATTR_PLANAR) + { + struct wined3d_const_bo_address uv_bo_addr; + const struct wined3d_format *plane_format; + struct wined3d_box uv_box; + + plane_format = wined3d_get_format(context->device->adapter, src_format->plane_formats[0], 0); + wined3d_texture_vk_upload_plane(context, VK_IMAGE_ASPECT_PLANE_0_BIT, src_bo_addr, plane_format, src_box, + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); + + uv_bo_addr = *src_bo_addr; + uv_bo_addr.addr += src_slice_pitch; + uv_box = *src_box; + uv_box.left /= src_format->uv_width; + uv_box.right /= src_format->uv_width; + uv_box.top /= src_format->uv_height; + uv_box.bottom /= src_format->uv_height; + dst_x /= src_format->uv_width; + dst_y /= src_format->uv_height; + src_row_pitch = src_row_pitch * 2 / src_format->uv_width; + src_slice_pitch = src_slice_pitch * 2 / src_format->uv_width / src_format->uv_height; + + plane_format = wined3d_get_format(context->device->adapter, src_format->plane_formats[1], 0); + wined3d_texture_vk_upload_plane(context, VK_IMAGE_ASPECT_PLANE_1_BIT, &uv_bo_addr, plane_format, &uv_box, + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); + } + else + { + wined3d_texture_vk_upload_plane(context, aspect_mask, src_bo_addr, src_format, src_box, + src_row_pitch, src_slice_pitch, dst_texture, dst_sub_resource_idx, dst_x, dst_y, dst_z); + } }
static void wined3d_texture_vk_download_plane(struct wined3d_context *context, VkImageAspectFlags vk_aspect,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 2f773978f9b..5a98ec6cd90 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5185,8 +5185,37 @@ static void wined3d_texture_vk_download_data(struct wined3d_context *context, return; }
- wined3d_texture_vk_download_plane(context, aspect_mask, src_texture, src_sub_resource_idx, - src_box, dst_bo_addr, dst_format, dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); + if (dst_format->attrs & WINED3D_FORMAT_ATTR_PLANAR) + { + const struct wined3d_format *plane_format; + struct wined3d_bo_address uv_bo_addr; + struct wined3d_box uv_box; + + plane_format = wined3d_get_format(context->device->adapter, dst_format->plane_formats[0], 0); + wined3d_texture_vk_download_plane(context, VK_IMAGE_ASPECT_PLANE_0_BIT, src_texture, src_sub_resource_idx, + src_box, dst_bo_addr, plane_format, dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); + + uv_bo_addr = *dst_bo_addr; + uv_bo_addr.addr += dst_slice_pitch; + uv_box = *src_box; + uv_box.left /= dst_format->uv_width; + uv_box.right /= dst_format->uv_width; + uv_box.top /= dst_format->uv_height; + uv_box.bottom /= dst_format->uv_height; + dst_x /= dst_format->uv_width; + dst_y /= dst_format->uv_height; + dst_row_pitch = dst_row_pitch * 2 / dst_format->uv_width; + dst_slice_pitch = dst_slice_pitch * 2 / dst_format->uv_width / dst_format->uv_height; + + plane_format = wined3d_get_format(context->device->adapter, dst_format->plane_formats[1], 0); + wined3d_texture_vk_download_plane(context, VK_IMAGE_ASPECT_PLANE_1_BIT, src_texture, src_sub_resource_idx, + &uv_box, &uv_bo_addr, plane_format, dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); + } + else + { + wined3d_texture_vk_download_plane(context, aspect_mask, src_texture, src_sub_resource_idx, + src_box, dst_bo_addr, dst_format, dst_x, dst_y, dst_z, dst_row_pitch, dst_slice_pitch); + } }
static bool wined3d_texture_vk_clear(struct wined3d_texture_vk *texture_vk,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/texture.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 5a98ec6cd90..14c3aa419a8 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -7090,6 +7090,7 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ } else { + const struct wined3d_format *src_format = src_texture_vk->t.resource.format; VkImageCopy region;
region.srcSubresource.aspectMask = vk_src_range.aspectMask; @@ -7110,8 +7111,28 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_ region.extent.height = src_rect->bottom - src_rect->top; region.extent.depth = 1;
- VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->image.vk_image, src_layout, - dst_texture_vk->image.vk_image, dst_layout, 1, ®ion)); + if (src_format->attrs & WINED3D_FORMAT_ATTR_PLANAR) + { + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT; + VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->image.vk_image, src_layout, + dst_texture_vk->image.vk_image, dst_layout, 1, ®ion)); + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_PLANE_1_BIT; + region.srcOffset.x /= src_format->uv_width; + region.srcOffset.y /= src_format->uv_height; + region.dstOffset.x /= src_format->uv_width; + region.dstOffset.y /= src_format->uv_height; + region.extent.width /= src_format->uv_width; + region.extent.height /= src_format->uv_height; + VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->image.vk_image, src_layout, + dst_texture_vk->image.vk_image, dst_layout, 1, ®ion)); + } + else + { + VK_CALL(vkCmdCopyImage(vk_command_buffer, src_texture_vk->image.vk_image, src_layout, + dst_texture_vk->image.vk_image, dst_layout, 1, ®ion)); + } }
wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/wined3d/adapter_vk.c | 2 ++ dlls/wined3d/wined3d_vk.h | 1 + 2 files changed, 3 insertions(+)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 851f5415b7a..8dc944fafb6 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -2368,6 +2368,7 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_KHR_MAINTENANCE1_EXTENSION_NAME, VK_API_VERSION_1_1, true}, {VK_KHR_MAINTENANCE2_EXTENSION_NAME, VK_API_VERSION_1_1}, {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,VK_API_VERSION_1_2}, + {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_API_VERSION_1_1}, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_API_VERSION_1_1}, {VK_KHR_SWAPCHAIN_EXTENSION_NAME, ~0u, true}, }; @@ -2388,6 +2389,7 @@ static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, WINED3D_VK_EXT_VERTEX_ATTRIBUTE_DIVISOR}, {VK_KHR_MAINTENANCE2_EXTENSION_NAME, WINED3D_VK_KHR_MAINTENANCE2}, {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE}, + {VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, WINED3D_VK_KHR_SAMPLER_YCBCR_CONVERSION}, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, WINED3D_VK_KHR_SHADER_DRAW_PARAMETERS}, };
diff --git a/dlls/wined3d/wined3d_vk.h b/dlls/wined3d/wined3d_vk.h index a9f535fa1bd..1bc40223af6 100644 --- a/dlls/wined3d/wined3d_vk.h +++ b/dlls/wined3d/wined3d_vk.h @@ -246,6 +246,7 @@ enum wined3d_vk_extension WINED3D_VK_EXT_VERTEX_ATTRIBUTE_DIVISOR, WINED3D_VK_KHR_MAINTENANCE2, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, + WINED3D_VK_KHR_SAMPLER_YCBCR_CONVERSION, WINED3D_VK_KHR_SHADER_DRAW_PARAMETERS,
WINED3D_VK_EXT_COUNT,
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/tests/d3d11.c | 3 +-- dlls/wined3d/texture.c | 3 ++- dlls/wined3d/utils.c | 53 ++++++++++++++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 13 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 4adad271fc8..27378cc6e01 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -36300,7 +36300,7 @@ static void test_nv12(void) device_context = test_context.immediate_context;
hr = ID3D11Device_CheckFormatSupport(device, DXGI_FORMAT_NV12, &support); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine_if (!damavand) ok(hr == S_OK, "Got hr %#lx.\n", hr);
if (!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D)) { @@ -36398,7 +36398,6 @@ static void test_nv12(void)
expected_hr = (width & 1 || height & 1) ? E_INVALIDARG : S_OK; hr = ID3D11Device_CreateTexture2D(device, &desc, &subresource_data, &texture); - todo_wine_if(SUCCEEDED(expected_hr)) ok(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
if (FAILED(hr)) diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 14c3aa419a8..d12cadd71fc 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -5380,7 +5380,8 @@ BOOL wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk *texture_vk, format_vk = wined3d_format_vk(resource->format);
if (wined3d_format_is_typeless(&format_vk->f) || texture_vk->t.swapchain - || (texture_vk->t.resource.bind_flags & WINED3D_BIND_UNORDERED_ACCESS)) + || (texture_vk->t.resource.bind_flags & WINED3D_BIND_UNORDERED_ACCESS) + || (format_vk->f.attrs & WINED3D_FORMAT_ATTR_PLANAR)) { /* For UAVs, we need this in case a clear necessitates creation of a new view * with a different format. */ diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 58ca1fcca5e..c75516aac5a 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4243,7 +4243,7 @@ fail: return FALSE; }
-static void init_vulkan_format_info(struct wined3d_format_vk *format, +static void init_vulkan_format_info(struct wined3d_adapter *adapter, struct wined3d_format_vk *format, const struct wined3d_vk_info *vk_info, VkPhysicalDevice vk_physical_device) { static const struct @@ -4330,6 +4330,7 @@ static void init_vulkan_format_info(struct wined3d_format_vk *format, {WINED3DFMT_R32_FLOAT_X8X24_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT, }, {WINED3DFMT_X32_TYPELESS_G8X24_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, }, {WINED3DFMT_D24_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, }, + {WINED3DFMT_NV12_PLANAR, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,}, }; VkFormat vk_format = VK_FORMAT_UNDEFINED; VkImageFormatProperties image_properties; @@ -4357,6 +4358,10 @@ static void init_vulkan_format_info(struct wined3d_format_vk *format, return; }
+ if ((format->f.attrs & WINED3D_FORMAT_ATTR_PLANAR) && !vk_info->supported[WINED3D_VK_KHR_SAMPLER_YCBCR_CONVERSION] + && vk_info->api_version < VK_API_VERSION_1_1) + return; + format->vk_format = vk_format; if (fixup) format->f.color_fixup = create_color_fixup_desc_from_string(fixup); @@ -4376,13 +4381,45 @@ static void init_vulkan_format_info(struct wined3d_format_vk *format, } }
+ caps = 0; + texture_flags = properties.linearTilingFeatures | properties.optimalTilingFeatures; + if ((texture_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) + && (texture_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) + caps |= WINED3D_FORMAT_CAP_BLIT; + + if (format->f.attrs & WINED3D_FORMAT_ATTR_PLANAR) + { + /* Direct3D only does planar views, without YCbCr conversion. + * In order to query whether this is supported on the Vulkan side, + * we need to ignore the feature flags for the planar image, + * and instead combine the feature flags for the corresponding format + * for each plane. + * + * Somewhat oddly, Vulkan doesn't distinguish "R8_UNORM (e.g.) views of + * a planar image are supported" from "R8_UNORM views are supported in + * general", which means that we don't really know through querying if + * a given YUV format is supported. Fortunately we need blit support + * anyway, and it seems fair to assume that if blit is supported for a + * format, then we can also create planar views. */ + if (!caps) + { + TRACE("Unsupported format %s (no blit support).\n", debug_d3dformat(format->f.id)); + return; + } + + caps = ~0u; + for (unsigned int i = 0; i < 2; ++i) + caps &= get_format_internal(adapter, format->f.plane_formats[i])->caps[WINED3D_GL_RES_TYPE_TEX_2D]; + format->f.caps[WINED3D_GL_RES_TYPE_TEX_2D] |= caps; + TRACE("Caps %#08x are supported for format %s.\n", caps, debug_d3dformat(format->f.id)); + return; + } + if (properties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) format->f.caps[WINED3D_GL_RES_TYPE_BUFFER] |= WINED3D_FORMAT_CAP_VERTEX_ATTRIBUTE; if (properties.bufferFeatures & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) format->f.caps[WINED3D_GL_RES_TYPE_BUFFER] |= WINED3D_FORMAT_CAP_TEXTURE;
- caps = 0; - texture_flags = properties.linearTilingFeatures | properties.optimalTilingFeatures; if (texture_flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) { caps |= WINED3D_FORMAT_CAP_TEXTURE | WINED3D_FORMAT_CAP_VTF; @@ -4407,15 +4444,11 @@ static void init_vulkan_format_info(struct wined3d_format_vk *format, { caps |= WINED3D_FORMAT_CAP_UNORDERED_ACCESS; } - if ((texture_flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) - && (texture_flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) - { - caps |= WINED3D_FORMAT_CAP_BLIT; - } - if (!(~caps & (WINED3D_FORMAT_CAP_RENDERTARGET | WINED3D_FORMAT_CAP_FILTERING))) caps |= WINED3D_FORMAT_CAP_GEN_MIPMAP;
+ TRACE("Caps %#08x are supported for format %s.\n", caps, debug_d3dformat(format->f.id)); + format->f.caps[WINED3D_GL_RES_TYPE_TEX_1D] |= caps; format->f.caps[WINED3D_GL_RES_TYPE_TEX_2D] |= caps; format->f.caps[WINED3D_GL_RES_TYPE_TEX_3D] |= caps; @@ -4460,7 +4493,7 @@ BOOL wined3d_adapter_vk_init_format_info(struct wined3d_adapter_vk *adapter_vk, format = wined3d_format_vk_mutable(get_format_by_idx(adapter, i));
if (format->f.id) - init_vulkan_format_info(format, vk_info, vk_physical_device); + init_vulkan_format_info(adapter, format, vk_info, vk_physical_device); }
if (!init_typeless_formats(adapter)) goto fail;
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/d3d11/tests/d3d11.c | 153 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 3 deletions(-)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 27378cc6e01..32e92a170da 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -22,6 +22,7 @@ #include <limits.h> #include <math.h> #include <stdbool.h> +#include <stdint.h> #include <stdlib.h> #define COBJMACROS #include "initguid.h" @@ -36330,21 +36331,22 @@ static void test_nv12(void) for (test_idx = 0; test_idx < ARRAY_SIZE(tests); ++test_idx) { /* I need only two uints in the cbuffer, but the size must be a multiple of 16. */ + ID3D11Texture2D *texture, *texture2, *check_texture, *staging_texture; + unsigned int i, j, image_size, broken_warp_pitch; D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {0}; D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {0}; D3D11_SUBRESOURCE_DATA subresource_data = {0}; D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {0}; - ID3D11Texture2D *texture, *check_texture; char *content, *content2, *copy_source; ID3D11UnorderedAccessView *check_uav; ID3D11RenderTargetView *rtv1, *rtv2; ID3D11ShaderResourceView *srvs[2]; + D3D11_MAPPED_SUBRESOURCE map_desc; D3D11_TEXTURE2D_DESC desc = {0}; struct resource_readback rb; uint32_t cbuffer_data[4]; ID3D11Buffer *cbuffer; HRESULT expected_hr; - unsigned int i, j; D3D11_BOX box;
const uint32_t width = tests[test_idx].width; @@ -36406,6 +36408,9 @@ static void test_nv12(void) continue; }
+ hr = ID3D11Device_CreateTexture2D(device, &desc, &subresource_data, &texture2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + desc.Height += height / 2; desc.Format = DXGI_FORMAT_R8_UINT; desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; @@ -36490,12 +36495,13 @@ static void test_nv12(void) } }
+ set_box(&box, copy_x, copy_y, 0, copy_x + copy_width, copy_y + copy_height, 1); + /* UpdateSubresource() copies the specified box on the luma plane and also the corresponding * box on the chroma plane. It does nothing as soon as any coordinate of the box is not a * multiple of 2. AMD seems to have a bug and copies data with the wrong pitch. */ if (!is_amd_device(device)) { - set_box(&box, copy_x, copy_y, 0, copy_x + copy_width, copy_y + copy_height, 1); ID3D11DeviceContext_UpdateSubresource(device_context, (ID3D11Resource *)texture, 0, &box, copy_source, copy_width, 0);
@@ -36558,13 +36564,154 @@ static void test_nv12(void) check_readback_data_u8_with_buffer(&rb, content, width, 0); release_resource_readback(&rb);
+ /* Staging upload, GPU blit, and staging download tests. */ + desc.Height = height; + desc.Format = DXGI_FORMAT_NV12; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Usage = D3D11_USAGE_STAGING; + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &staging_texture); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = ID3D11DeviceContext_Map(device_context, (ID3D11Resource *)staging_texture, 0, + D3D11_MAP_WRITE, 0, &map_desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + /* Row pitch isn't consistent across drivers. Of the machines tested, + * row pitch may be aligned to a multiple of 4 (WARP), 128 (NVidia), or + * 256 (AMD). + * + * In all cases it seems to signify both the pitch of the Y plane, and + * the pitch of the U/V plane (which is 2x2 subsampled but has 2 bytes + * per sample, so has the same number of content bytes in a row). + * + * Slice pitch is either the size of the Y plane alone (WARP) or the + * size of the entire image (AMD, NVidia). + * + * Older versions of WARP (Windows 10) also calculate the size of the Y + * plane incorrectly, by taking the size of the entire image and + * multiplying by 2/3. This ends up being incorrect because said + * versions apparently add *vertical* alignment to 4 to only one plane, + * so the UV plane is not exactly half the size of the Y plane. */ + ok(map_desc.RowPitch >= width, "Got row pitch %u.\n", map_desc.RowPitch); + image_size = (map_desc.RowPitch * (height * 3 / 2)); + broken_warp_pitch = (map_desc.RowPitch * height) + (map_desc.RowPitch * ((height + 3) & ~3) / 2); + broken_warp_pitch = broken_warp_pitch / 3 * 2; + ok(map_desc.DepthPitch == image_size + || (is_warp_device(device) && map_desc.DepthPitch == (map_desc.RowPitch * height)) + || broken(is_warp_device(device) && map_desc.DepthPitch == broken_warp_pitch), + "Got row pitch %u, slice pitch %u.\n", map_desc.RowPitch, map_desc.DepthPitch); + + for (i = 0; i < height; ++i) + { + for (j = 0; j < width; ++j) + { + unsigned int idx = i * map_desc.RowPitch + j; + ((uint8_t *)map_desc.pData)[idx] = (j & 7) << 3 | (i & 7); + idx = i * width + j; + content2[idx] = (j & 7) << 3 | (i & 7); + } + } + + for (i = 0; i < height / 2; ++i) + { + for (j = 0; j < width / 2; ++j) + { + unsigned int idx = map_desc.RowPitch * (height + i) + j * 2; + ((uint8_t *)map_desc.pData)[idx] = 1u << 6 | (j & 7) << 3 | (i & 7); + ((uint8_t *)map_desc.pData)[idx + 1] = 1u << 7 | (j & 7) << 3 | (i & 7); + idx = width * (height + i) + j * 2; + content2[idx] = 1u << 6 | (j & 7) << 3 | (i & 7); + content2[idx + 1] = 1u << 7 | (j & 7) << 3 | (i & 7); + } + } + + ID3D11DeviceContext_Unmap(device_context, (ID3D11Resource *)staging_texture, 0); + + ID3D11DeviceContext_CopyResource(device_context, (ID3D11Resource *)texture2, (ID3D11Resource *)staging_texture); + ID3D11DeviceContext_CopyResource(device_context, (ID3D11Resource *)texture, (ID3D11Resource *)texture2); + + hr = ID3D11DeviceContext_Map(device_context, (ID3D11Resource *)staging_texture, 0, + D3D11_MAP_WRITE, 0, &map_desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + memset(map_desc.pData, 0xfe, map_desc.RowPitch * height); + memset((uint8_t *)map_desc.pData + map_desc.RowPitch * height, 0xdc, map_desc.RowPitch * height / 2); + + /* Similarly CopySubresourceRegion() ignores boxes not aligned to 2. */ + if (copy_x % 2 == 0 && copy_y % 2 == 0 && copy_width % 2 == 0 && copy_height % 2 == 0) + { + for (i = copy_y; i < copy_y + copy_height; ++i) + { + memset(content2 + i * width + copy_x, 0xfe, copy_width); + if (i % 2 == 0) + memset(content2 + width * (height + i / 2) + copy_x, 0xdc, copy_width); + } + } + + ID3D11DeviceContext_Unmap(device_context, (ID3D11Resource *)staging_texture, 0); + + ID3D11DeviceContext_CopyResource(device_context, (ID3D11Resource *)texture2, (ID3D11Resource *)staging_texture); + ID3D11DeviceContext_CopySubresourceRegion(device_context, (ID3D11Resource *)texture, 0, + copy_x, copy_y, 0, (ID3D11Resource *)texture2, 0, &box); + + ID3D11DeviceContext_ClearUnorderedAccessViewUint(device_context, check_uav, clear_values); + ID3D11DeviceContext_CSSetShader(device_context, cs, NULL, 0); + ID3D11DeviceContext_CSSetShaderResources(device_context, 0, ARRAY_SIZE(srvs), srvs); + ID3D11DeviceContext_CSSetUnorderedAccessViews(device_context, 1, 1, &check_uav, NULL); + ID3D11DeviceContext_CSSetConstantBuffers(device_context, 0, 1, &cbuffer); + ID3D11DeviceContext_Dispatch(device_context, width, height, 1); + + get_texture_readback(check_texture, 0, &rb); + check_readback_data_u8_with_buffer(&rb, content2, width, 0); + release_resource_readback(&rb); + + ID3D11DeviceContext_CopyResource(device_context, (ID3D11Resource *)staging_texture, (ID3D11Resource *)texture); + + hr = ID3D11DeviceContext_Map(device_context, (ID3D11Resource *)staging_texture, 0, + D3D11_MAP_READ, 0, &map_desc); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (i = 0; i < height; ++i) + { + for (j = 0; j < width; ++j) + { + uint8_t value = ((uint8_t *)map_desc.pData)[i * map_desc.RowPitch + j]; + uint8_t expect = content2[i * width + j]; + ok(value == expect, "Got Y %02x, expected %02x at (%u, %u).\n", value, expect, i, j); + if (value != expect) + goto fail_match; + } + } + + for (i = 0; i < height / 2; ++i) + { + for (j = 0; j < width / 2; ++j) + { + uint8_t value = ((uint8_t *)map_desc.pData)[map_desc.RowPitch * (height + i) + j * 2]; + uint8_t expect = content2[width * (height + i) + j * 2]; + ok(value == expect, "Got U %02x, expected %02x at (%u, %u).\n", value, expect, i, j); + if (value != expect) + goto fail_match; + value = ((uint8_t *)map_desc.pData)[map_desc.RowPitch * (height + i) + j * 2 + 1]; + expect = content2[width * (height + i) + j * 2 + 1]; + ok(value == expect, "Got V %02x, expected %02x at (%u, %u).\n", value, expect, i, j); + if (value != expect) + goto fail_match; + } + } + +fail_match: + ID3D11DeviceContext_Unmap(device_context, (ID3D11Resource *)staging_texture, 0); + ID3D11RenderTargetView_Release(rtv2); ID3D11RenderTargetView_Release(rtv1); ID3D11Buffer_Release(cbuffer); ID3D11UnorderedAccessView_Release(check_uav); ID3D11ShaderResourceView_Release(srvs[1]); ID3D11ShaderResourceView_Release(srvs[0]); + ID3D11Texture2D_Release(staging_texture); ID3D11Texture2D_Release(check_texture); + ID3D11Texture2D_Release(texture2); ID3D11Texture2D_Release(texture); free(content);
I'm getting a new failure in d3d11 tests (with GL): `d3d11.c:36304: Test failed: Got hr 0x80004005`.
Oops, yes, I was not nearly careful enough with my testing. Fixed now.
Other than that it LGTM. Maybe NV12_D3D9 and NV12 would be another naming option to consider?
I don't hate it, although I'd reverse it and use NV12_D3D10 so that the other FOURCC formats remain consistent.
Not sure I like it better than NV12_PLANAR though, so I left it alone for now...
This merge request was approved by Jan Sikorski.