[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