Stefan Dösinger : wined3d: Set WINED3D_LOCATION_CLEARED for full-subresource clears to black.

Alexandre Julliard julliard at winehq.org
Tue Apr 26 16:25:26 CDT 2022


Module: wine
Branch: master
Commit: b46cb0346c0eea67895f9e2b60a66d153a05b8a2
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b46cb0346c0eea67895f9e2b60a66d153a05b8a2

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Tue Apr 26 14:46:09 2022 +0300

wined3d: Set WINED3D_LOCATION_CLEARED for full-subresource clears to black.

Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wined3d/texture.c | 80 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 62 insertions(+), 18 deletions(-)

diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index 18a60ecbf52..213a04fb496 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -6560,13 +6560,13 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
 {
     VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
     VkImageView views[WINED3D_MAX_RENDER_TARGETS + 1];
+    unsigned int i, attachment_count, delay_count = 0;
     struct wined3d_rendertarget_view_vk *rtv_vk;
     struct wined3d_rendertarget_view *view;
     const struct wined3d_vk_info *vk_info;
     struct wined3d_device_vk *device_vk;
     VkCommandBuffer vk_command_buffer;
     VkRenderPassBeginInfo begin_desc;
-    unsigned int i, attachment_count;
     VkFramebufferCreateInfo fb_desc;
     VkFramebuffer vk_framebuffer;
     VkRenderPass vk_render_pass;
@@ -6592,10 +6592,25 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         if (!(view = fb->render_targets[i]))
             continue;
 
-        if (!is_full_clear(view, draw_rect, clear_rects))
-            wined3d_rendertarget_view_load_location(view, &context_vk->c, view->resource->draw_binding);
+        if (is_full_clear(view, draw_rect, clear_rects))
+        {
+            if (!colour->r && !colour->g && !colour->b && !colour->a)
+            {
+                wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED);
+                wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED);
+                delay_count++;
+                continue;
+            }
+            else
+            {
+                TRACE_(d3d_perf)("non-zero clear\n");
+                wined3d_rendertarget_view_prepare_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_load_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);
 
@@ -6625,31 +6640,60 @@ static void vk_blitter_clear_rendertargets(struct wined3d_context_vk *context_vk
         ++attachment_count;
     }
 
+    if (!attachment_count)
+        flags &= ~WINED3DCLEAR_TARGET;
+
     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && (view = fb->depth_stencil))
     {
-        if (!is_full_clear(view, draw_rect, clear_rects))
+        DWORD full_flags = 0;
+
+        /* Vulkan can clear only depth or stencil, but at the moment we can't put the depth and
+         * stencil parts in separate locations. It isn't easy to do either, as such a half-cleared
+         * texture would need to be handled not just as a DS target but also when used as a shader
+         * resource or accessed on sysmem. */
+        if (view->format->depth_size)
+            full_flags = WINED3DCLEAR_ZBUFFER;
+        if (view->format->stencil_size)
+            full_flags |= WINED3DCLEAR_STENCIL;
+
+        if (!is_full_clear(view, draw_rect, clear_rects)
+                || depth || stencil || (flags & full_flags) != full_flags)
+        {
             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);
+            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);
-        wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
+            rtv_vk = wined3d_rendertarget_view_vk(view);
+            views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
+            wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
 
-        clear_values[attachment_count].depthStencil.depth = depth;
-        clear_values[attachment_count].depthStencil.stencil = stencil;
+            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;
+            if (view->layer_count > layer_count)
+                layer_count = view->layer_count;
 
-        depth_stencil = true;
-        ++attachment_count;
+            depth_stencil = true;
+            ++attachment_count;
+        }
+        else
+        {
+            wined3d_rendertarget_view_validate_location(view, WINED3D_LOCATION_CLEARED);
+            wined3d_rendertarget_view_invalidate_location(view, ~WINED3D_LOCATION_CLEARED);
+            flags &= ~(WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL);
+            delay_count++;
+        }
     }
 
     if (!attachment_count)
+    {
+        TRACE("The clear has been delayed until draw time.\n");
         return;
+    }
+
+    TRACE("Doing an immediate clear of %u attachments.\n", attachment_count);
+    if (delay_count)
+        TRACE_(d3d_perf)("Partial clear: %u immediate, %u delayed.\n", attachment_count, delay_count);
 
     if (!(vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, fb,
             rt_count, flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL), flags)))




More information about the wine-cvs mailing list