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