[PATCH 4/5] wined3d: Implement raw blits in the Vulkan GPU blitter.
Henri Verbeet
hverbeet at codeweavers.com
Thu Apr 23 16:51:25 CDT 2020
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
dlls/wined3d/texture.c | 183 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 407c1078c4e..3e9c350aa96 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -5760,13 +5760,93 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev
clear_rects, draw_rect, flags, colour, depth, stencil);
}
+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_format *src_format = src_resource->format;
+ const struct wined3d_format *dst_format = dst_resource->format;
+
+ if (!(dst_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
+ {
+ TRACE("Destination resource does not have GPU access.\n");
+ return false;
+ }
+
+ if (!(src_resource->access & WINED3D_RESOURCE_ACCESS_GPU))
+ {
+ TRACE("Source resource does not have GPU access.\n");
+ return false;
+ }
+
+ if (dst_format->id != src_format->id)
+ {
+ if (!is_identity_fixup(dst_format->color_fixup))
+ {
+ TRACE("Destination fixups are not supported.\n");
+ return false;
+ }
+
+ if (!is_identity_fixup(src_format->color_fixup))
+ {
+ TRACE("Source fixups are not supported.\n");
+ return false;
+ }
+
+ if (op != WINED3D_BLIT_OP_RAW_BLIT
+ && wined3d_format_vk(src_format)->vk_format != wined3d_format_vk(dst_format)->vk_format)
+ {
+ TRACE("Format conversion not supported.\n");
+ return false;
+ }
+ }
+
+ if (wined3d_resource_get_sample_count(dst_resource) > 1)
+ {
+ TRACE("Multi-sample destination resource not supported.\n");
+ return false;
+ }
+
+ if (wined3d_resource_get_sample_count(src_resource) > 1)
+ {
+ TRACE("Multi-sample source resource not supported.\n");
+ return false;
+ }
+
+ if (op == WINED3D_BLIT_OP_RAW_BLIT)
+ return true;
+
+ if (op != WINED3D_BLIT_OP_COLOR_BLIT)
+ {
+ TRACE("Unsupported blit operation %#x.\n", op);
+ 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 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,
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)
{
+ 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);
+ const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+ unsigned int src_level, src_layer, dst_level, dst_layer;
+ VkImageAspectFlags src_aspect, dst_aspect;
+ VkCommandBuffer vk_command_buffer;
struct wined3d_blitter *next;
+ VkImageCopy region;
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",
@@ -5774,6 +5854,109 @@ static DWORD vk_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_blit_
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));
+ if (!vk_blitter_blit_supported(op, context, &src_texture->resource, src_rect, &dst_texture->resource, dst_rect))
+ 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 ((src_aspect | dst_aspect) & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
+ {
+ TRACE("Depth/stencil blits not supported.\n");
+ goto next;
+ }
+
+ src_level = src_sub_resource_idx % src_texture->level_count;
+ src_layer = src_sub_resource_idx / src_texture->level_count;
+
+ dst_level = dst_sub_resource_idx % dst_texture->level_count;
+ dst_layer = dst_sub_resource_idx / dst_texture->level_count;
+
+ if (!wined3d_texture_load_location(src_texture, src_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB))
+ ERR("Failed to load the source sub-resource.\n");
+
+ if (texture2d_is_full_rect(dst_texture, dst_level, dst_rect))
+ {
+ if (!wined3d_texture_prepare_location(dst_texture,
+ dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB))
+ {
+ ERR("Failed to prepare the destination sub-resource.\n");
+ goto next;
+ }
+ }
+ else
+ {
+ if (!wined3d_texture_load_location(dst_texture,
+ dst_sub_resource_idx, context, WINED3D_LOCATION_TEXTURE_RGB))
+ {
+ ERR("Failed to load the destination sub-resource.\n");
+ goto next;
+ }
+ }
+
+ if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
+ {
+ ERR("Failed to get command buffer.\n");
+ goto next;
+ }
+
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ vk_access_mask_from_bind_flags(src_texture_vk->t.resource.bind_flags),
+ VK_ACCESS_TRANSFER_READ_BIT,
+ src_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ src_texture_vk->vk_image, src_aspect);
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ vk_access_mask_from_bind_flags(dst_texture_vk->t.resource.bind_flags),
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ dst_texture_vk->layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ dst_texture_vk->vk_image, dst_aspect);
+
+ 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;
+
+ VK_CALL(vkCmdCopyImage(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));
+
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ vk_access_mask_from_bind_flags(dst_texture_vk->t.resource.bind_flags),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_texture_vk->layout,
+ dst_texture_vk->vk_image, dst_aspect);
+ wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ VK_ACCESS_TRANSFER_READ_BIT,
+ vk_access_mask_from_bind_flags(src_texture_vk->t.resource.bind_flags),
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, src_texture_vk->layout,
+ src_texture_vk->vk_image, src_aspect);
+
+ wined3d_texture_validate_location(dst_texture, dst_sub_resource_idx, WINED3D_LOCATION_TEXTURE_RGB);
+ wined3d_texture_invalidate_location(dst_texture, dst_sub_resource_idx, ~WINED3D_LOCATION_TEXTURE_RGB);
+ if (!wined3d_texture_load_location(dst_texture, dst_sub_resource_idx, context, dst_location))
+ ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location));
+
+ wined3d_context_vk_reference_texture(context_vk, src_texture_vk);
+ wined3d_context_vk_reference_texture(context_vk, dst_texture_vk);
+
+ return dst_location | WINED3D_LOCATION_TEXTURE_RGB;
+
+next:
if (!(next = blitter->next))
{
ERR("No blitter to handle blit op %#x.\n", op);
--
2.20.1
More information about the wine-devel
mailing list