From 7411264ca6758293349ba8730165eade8b8235b0 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 2 Mar 2023 12:12:32 -0500 Subject: [PATCH] zink: add a dynamic render version of clear_texture hook this avoids the (sizable) overhead of going through the previous path with set_frame_buffer state et al, instead just firing off a quick begin+end rendering with a clear it's also easily reorderable Part-of: --- src/gallium/drivers/zink/zink_clear.c | 81 +++++++++++++++++++++++++++++++++ src/gallium/drivers/zink/zink_clear.h | 6 +++ src/gallium/drivers/zink/zink_context.c | 2 +- 3 files changed, 88 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/zink/zink_clear.c b/src/gallium/drivers/zink/zink_clear.c index 8d67577..39ac5c4 100644 --- a/src/gallium/drivers/zink/zink_clear.c +++ b/src/gallium/drivers/zink/zink_clear.c @@ -437,6 +437,87 @@ set_clear_fb(struct pipe_context *pctx, struct pipe_surface *psurf, struct pipe_ } void +zink_clear_texture_dynamic(struct pipe_context *pctx, + struct pipe_resource *pres, + unsigned level, + const struct pipe_box *box, + const void *data) +{ + struct zink_context *ctx = zink_context(pctx); + struct zink_resource *res = zink_resource(pres); + + bool full_clear = 0 <= box->x && u_minify(pres->width0, level) >= box->x + box->width && + 0 <= box->y && u_minify(pres->height0, level) >= box->y + box->height && + 0 <= box->z && u_minify(pres->target == PIPE_TEXTURE_3D ? pres->depth0 : pres->array_size, level) >= box->z + box->depth; + + struct pipe_surface *surf = create_clear_surface(pctx, pres, level, box); + + VkRenderingAttachmentInfo att = {0}; + att.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; + att.imageView = zink_csurface(surf)->image_view; + att.imageLayout = res->aspect & VK_IMAGE_ASPECT_COLOR_BIT ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + att.loadOp = full_clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; + att.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + VkRenderingInfo info = {0}; + info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO; + info.renderArea.offset.x = box->x; + info.renderArea.offset.y = box->y; + info.renderArea.extent.width = box->width; + info.renderArea.extent.height = box->height; + info.layerCount = MAX2(box->depth, 1); + + union pipe_color_union color; + float depth = 0.0; + uint8_t stencil = 0; + if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + util_format_unpack_rgba(pres->format, color.ui, data, 1); + } else { + if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + util_format_unpack_z_float(pres->format, &depth, data, 1); + + if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) + util_format_unpack_s_8uint(pres->format, &stencil, data, 1); + } + + zink_blit_barriers(ctx, NULL, res, full_clear); + VkCommandBuffer cmdbuf = zink_get_cmdbuf(ctx, NULL, res); + if (cmdbuf == ctx->batch.state->cmdbuf && ctx->batch.in_rp) + zink_batch_no_rp(ctx); + + if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + memcpy(&att.clearValue, &color, sizeof(float) * 4); + info.colorAttachmentCount = 1; + info.pColorAttachments = &att; + } else { + att.clearValue.depthStencil.depth = depth; + att.clearValue.depthStencil.stencil = stencil; + if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + info.pDepthAttachment = &att; + if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) + info.pStencilAttachment = &att; + } + VKCTX(CmdBeginRendering)(cmdbuf, &info); + if (!full_clear) { + VkClearRect rect; + rect.rect = info.renderArea; + rect.baseArrayLayer = box->z; + rect.layerCount = box->depth; + + VkClearAttachment clear_att; + clear_att.aspectMask = res->aspect; + clear_att.colorAttachment = 0; + clear_att.clearValue = att.clearValue; + + VKCTX(CmdClearAttachments)(cmdbuf, 1, &clear_att, 1, &rect); + } + VKCTX(CmdEndRendering)(cmdbuf); + zink_batch_reference_resource_rw(&ctx->batch, res, true); + /* this will never destroy the surface */ + pipe_surface_reference(&surf, NULL); +} + +void zink_clear_texture(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, diff --git a/src/gallium/drivers/zink/zink_clear.h b/src/gallium/drivers/zink/zink_clear.h index b1f4b18..eb17f15 100644 --- a/src/gallium/drivers/zink/zink_clear.h +++ b/src/gallium/drivers/zink/zink_clear.h @@ -40,6 +40,12 @@ zink_clear_texture(struct pipe_context *ctx, const struct pipe_box *box, const void *data); void +zink_clear_texture_dynamic(struct pipe_context *ctx, + struct pipe_resource *p_res, + unsigned level, + const struct pipe_box *box, + const void *data); +void zink_clear_buffer(struct pipe_context *pctx, struct pipe_resource *pres, unsigned offset, diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index b59bd10..552b8ef 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -5316,7 +5316,7 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->gfx_pipeline_state.sample_mask = UINT32_MAX; ctx->base.clear = zink_clear; - ctx->base.clear_texture = zink_clear_texture; + ctx->base.clear_texture = screen->info.have_KHR_dynamic_rendering ? zink_clear_texture_dynamic : zink_clear_texture; ctx->base.clear_buffer = zink_clear_buffer; ctx->base.clear_render_target = zink_clear_render_target; ctx->base.clear_depth_stencil = zink_clear_depth_stencil; -- 2.7.4