[PATCH 1/5] wined3d: Implement depth/stencil clears in the Vulkan blitter.

Henri Verbeet hverbeet at codeweavers.com
Mon Apr 27 16:58:23 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/context_vk.c      | 54 ++++++++++++++++++++++++---
 dlls/wined3d/texture.c         | 68 ++++++++++++++++++++++++++++++++--
 dlls/wined3d/wined3d_private.h |  5 ++-
 3 files changed, 117 insertions(+), 10 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 427dc064055..e8fcc391782 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -630,7 +630,7 @@ static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void
 }
 
 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
-        const struct wined3d_fb_state *fb, unsigned int rt_count)
+        const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
 {
     struct wined3d_render_pass_attachment_vk *a;
     struct wined3d_rendertarget_view *view;
@@ -649,6 +649,17 @@ static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *k
         a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
         key->rt_mask |= 1u << i;
     }
+
+    if (depth_stencil && (view = fb->depth_stencil))
+    {
+        a = &key->ds;
+        a->vk_format = wined3d_format_vk(view->format)->vk_format;
+        a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
+        a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
+        key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
+    }
+
+    key->clear_flags = clear_flags;
 }
 
 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
@@ -668,6 +679,8 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
     VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
     const struct wined3d_render_pass_attachment_vk *a;
+    VkAttachmentReference ds_attachment_reference;
+    VkAttachmentReference *ds_reference = NULL;
     unsigned int attachment_count, rt_count, i;
     VkAttachmentDescription *attachment;
     VkSubpassDescription sub_pass_desc;
@@ -687,7 +700,10 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
         attachment->flags = 0;
         attachment->format = a->vk_format;
         attachment->samples = a->vk_samples;
-        attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        if (key->clear_flags & WINED3DCLEAR_TARGET)
+            attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        else
+            attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
         attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
         attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
         attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -709,6 +725,34 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
         attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
     }
 
+    if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
+    {
+        a = &key->ds;
+
+        attachment = &attachments[attachment_count];
+        attachment->flags = 0;
+        attachment->format = a->vk_format;
+        attachment->samples = a->vk_samples;
+        if (key->clear_flags & WINED3DCLEAR_ZBUFFER)
+            attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        else
+            attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+        attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+        if (key->clear_flags & WINED3DCLEAR_STENCIL)
+            attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+        else
+            attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+        attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
+        attachment->initialLayout = a->vk_layout;
+        attachment->finalLayout = a->vk_layout;
+
+        ds_reference = &ds_attachment_reference;
+        ds_reference->attachment = attachment_count;
+        ds_reference->layout = a->vk_layout;
+
+        ++attachment_count;
+    }
+
     sub_pass_desc.flags = 0;
     sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
     sub_pass_desc.inputAttachmentCount = 0;
@@ -716,7 +760,7 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
     sub_pass_desc.colorAttachmentCount = rt_count;
     sub_pass_desc.pColorAttachments = attachment_references;
     sub_pass_desc.pResolveAttachments = NULL;
-    sub_pass_desc.pDepthStencilAttachment = NULL;
+    sub_pass_desc.pDepthStencilAttachment = ds_reference;
     sub_pass_desc.preserveAttachmentCount = 0;
     sub_pass_desc.pPreserveAttachments = NULL;
 
@@ -742,13 +786,13 @@ static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
 }
 
 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
-        const struct wined3d_fb_state *fb, unsigned int rt_count)
+        const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
 {
     struct wined3d_render_pass_key_vk key;
     struct wined3d_render_pass_vk *pass;
     struct wine_rb_entry *entry;
 
-    wined3d_render_pass_key_vk_init(&key, fb, rt_count);
+    wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
     if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
         return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index ef5f3cd48e5..4f55abb5e2b 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -6052,8 +6052,8 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rects, const RECT *draw_rect,
         uint32_t flags, const struct wined3d_color *colour, float depth, unsigned int stencil)
 {
-    VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS];
-    VkImageView views[WINED3D_MAX_RENDER_TARGETS];
+    VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
+    VkImageView views[WINED3D_MAX_RENDER_TARGETS + 1];
     struct wined3d_rendertarget_view_vk *rtv_vk;
     struct wined3d_rendertarget_view *view;
     const struct wined3d_vk_info *vk_info;
@@ -6065,6 +6065,7 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
     VkFramebufferCreateInfo fb_desc;
     VkFramebuffer vk_framebuffer;
     VkRenderPass vk_render_pass;
+    bool depth_stencil = false;
     unsigned int layer_count;
     VkClearColorValue *c;
     VkResult vr;
@@ -6078,6 +6079,9 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
     device_vk = wined3d_device_vk(context_vk->c.device);
     vk_info = context_vk->vk_info;
 
+    if (!(flags & WINED3DCLEAR_TARGET))
+        rt_count = 0;
+
     for (i = 0, attachment_count = 0, layer_count = 1; i < rt_count; ++i)
     {
         if (!(view = fb->render_targets[i]))
@@ -6115,7 +6119,33 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         ++attachment_count;
     }
 
-    if (!(vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, fb, rt_count)))
+    if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && (view = fb->depth_stencil))
+    {
+        if (!is_full_clear(view, draw_rect, clear_rects))
+            wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding);
+        else
+            wined3d_rendertarget_view_prepare_location(view, &context_vk->c, view->resource->draw_binding);
+        wined3d_rendertarget_view_validate_location(view, view->resource->draw_binding);
+        wined3d_rendertarget_view_invalidate_location(view, ~view->resource->draw_binding);
+
+        rtv_vk = wined3d_rendertarget_view_vk(view);
+        views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
+
+        clear_values[attachment_count].depthStencil.depth = depth;
+        clear_values[attachment_count].depthStencil.stencil = stencil;
+
+        if (view->layer_count > layer_count)
+            layer_count = view->layer_count;
+
+        depth_stencil = true;
+        ++attachment_count;
+    }
+
+    if (!attachment_count)
+        return;
+
+    if (!(vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, fb,
+            rt_count, flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL), flags)))
     {
         ERR("Failed to get render pass.\n");
         return;
@@ -6183,6 +6213,19 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
                 texture_vk->layout, texture_vk->layout,
                 texture_vk->vk_image, VK_IMAGE_ASPECT_COLOR_BIT);
     }
+
+    if (depth_stencil)
+    {
+        view = fb->depth_stencil;
+        wined3d_context_vk_reference_rendertarget_view(context_vk, wined3d_rendertarget_view_vk(view));
+        texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(view->resource));
+        wined3d_context_vk_image_barrier(context_vk, vk_command_buffer,
+                VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                vk_access_mask_from_bind_flags(texture_vk->t.resource.bind_flags),
+                texture_vk->layout, texture_vk->layout,
+                texture_vk->vk_image, vk_aspect_mask_from_format(texture_vk->t.resource.format));
+    }
 }
 
 static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_device *device,
@@ -6228,7 +6271,10 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev
         }
     }
 
-    if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && fb->depth_stencil)
+    if ((flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)) && (view = fb->depth_stencil)
+            && (!view->format->depth_size || (flags & WINED3DCLEAR_ZBUFFER))
+            && (!view->format->stencil_size || (flags & WINED3DCLEAR_STENCIL))
+            && blitter_use_cpu_clear(view))
     {
         next_flags |= flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
         flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
@@ -6247,6 +6293,13 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev
                 have_identical_size = false;
             previous = view;
         }
+        if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
+        {
+            view = fb->depth_stencil;
+
+            if (previous && (previous->width != view->width || previous->height != view->height))
+                have_identical_size = false;
+        }
 
         if (have_identical_size)
         {
@@ -6265,6 +6318,13 @@ static void vk_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_dev
                 vk_blitter_clear_rendertargets(context_vk, 1, &tmp_fb, rect_count,
                         clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil);
             }
+            if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
+            {
+                tmp_fb.render_targets[0] = NULL;
+                tmp_fb.depth_stencil = fb->depth_stencil;
+                vk_blitter_clear_rendertargets(context_vk, 0, &tmp_fb, rect_count,
+                        clear_rects, draw_rect, flags & ~WINED3DCLEAR_TARGET, colour, depth, stencil);
+            }
         }
 
         context_release(&context_vk->c);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index dd8e03d35d9..db86d746b5f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2272,7 +2272,9 @@ struct wined3d_render_pass_attachment_vk
 struct wined3d_render_pass_key_vk
 {
     struct wined3d_render_pass_attachment_vk rt[WINED3D_MAX_RENDER_TARGETS];
+    struct wined3d_render_pass_attachment_vk ds;
     uint32_t rt_mask;
+    uint32_t clear_flags;
 };
 
 struct wined3d_render_pass_vk
@@ -2330,7 +2332,8 @@ void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
         VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
-        const struct wined3d_fb_state *fb, unsigned int rt_count) DECLSPEC_HIDDEN;
+        const struct wined3d_fb_state *fb, unsigned int rt_count,
+        bool depth_stencil, uint32_t clear_flags) DECLSPEC_HIDDEN;
 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
         VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
         VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
-- 
2.20.1




More information about the wine-devel mailing list