[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, &region));
+
+    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