wined3d: Implement depth/stencil clears in the Vulkan blitter.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Henri Verbeet 2020-04-28 02:28:23 +04:30 committed by Alexandre Julliard
parent 28ec279518
commit f793f4446c
3 changed files with 117 additions and 10 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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,