From 622f8f6ed57bb32cb6b1014e4f8c7be2a58a5bd3 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 13 Aug 2020 17:23:51 -0400 Subject: [PATCH] zink: add a pipe_context::clear_texture hook there's a lot going on here, but the gist of it is: * if we're not in a renderpass, use the no_rp clear helpers * if we're in a renderpass, use our lord and savior u_blitter with a temporary surface that we create just for the blit Reviewed-by: Adam Jackson Part-of: --- src/gallium/drivers/zink/zink_clear.c | 73 ++++++++++++++++++++++++- src/gallium/drivers/zink/zink_context.c | 2 + src/gallium/drivers/zink/zink_context.h | 6 ++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/zink/zink_clear.c b/src/gallium/drivers/zink/zink_clear.c index ad85a7079ee..daa60558e00 100644 --- a/src/gallium/drivers/zink/zink_clear.c +++ b/src/gallium/drivers/zink/zink_clear.c @@ -23,10 +23,15 @@ #include "zink_context.h" #include "zink_resource.h" +#include "zink_screen.h" + +#include "util/u_blitter.h" #include "util/format/u_format.h" -#include "util/u_framebuffer.h" #include "util/format_srgb.h" +#include "util/u_framebuffer.h" +#include "util/u_inlines.h" #include "util/u_rect.h" +#include "util/u_surface.h" static inline bool check_3d_layers(struct pipe_surface *psurf) @@ -230,3 +235,69 @@ zink_clear(struct pipe_context *pctx, fb->zsbuf->u.tex.last_layer - fb->zsbuf->u.tex.first_layer + 1); } } + +static struct pipe_surface * +create_clear_surface(struct pipe_context *pctx, struct pipe_resource *pres, unsigned level, const struct pipe_box *box) +{ + struct pipe_surface tmpl = {{0}}; + + tmpl.format = pres->format; + tmpl.u.tex.first_layer = box->z; + tmpl.u.tex.last_layer = box->z + box->depth - 1; + tmpl.u.tex.level = level; + return pctx->create_surface(pctx, pres, &tmpl); +} + +void +zink_clear_texture(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); + struct pipe_screen *pscreen = pctx->screen; + struct u_rect region = {box->x, box->x + box->width, box->y, box->y + box->height}; + bool needs_rp = clear_needs_rp(pres->width0, pres->height0, ®ion) || ctx->render_condition_active; + struct zink_batch *batch = zink_curr_batch(ctx); + struct pipe_surface *surf = NULL; + + if (res->aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + union pipe_color_union color; + + util_format_unpack_rgba(pres->format, color.ui, data, 1); + + if (pscreen->is_format_supported(pscreen, pres->format, pres->target, 0, 0, + PIPE_BIND_RENDER_TARGET) && !needs_rp && !batch->in_rp) { + clear_color_no_rp(batch, res, &color, level, box->z, box->depth); + } else { + surf = create_clear_surface(pctx, pres, level, box); + zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS); + util_clear_render_target(pctx, surf, &color, box->x, box->y, box->width, box->height); + } + } else { + float depth = 0.0; + uint8_t stencil = 0; + + 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); + + if (!needs_rp && !batch->in_rp) + clear_zs_no_rp(batch, res, res->aspect, depth, stencil, level, box->z, box->depth); + else { + unsigned flags = 0; + if (res->aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + flags |= PIPE_CLEAR_DEPTH; + if (res->aspect & VK_IMAGE_ASPECT_STENCIL_BIT) + flags |= PIPE_CLEAR_STENCIL; + surf = create_clear_surface(pctx, pres, level, box); + zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS); + util_blitter_clear_depth_stencil(ctx->blitter, surf, flags, depth, stencil, box->x, box->y, box->width, box->height); + } + } + pipe_surface_reference(&surf, NULL); +} diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 340b77b2315..4e938d1c369 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -1293,6 +1293,8 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) ctx->base.set_sample_mask = zink_set_sample_mask; ctx->base.clear = zink_clear; + ctx->base.clear_texture = zink_clear_texture; + ctx->base.draw_vbo = zink_draw_vbo; ctx->base.flush = zink_flush; diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 273b223a955..7b83aa147af 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -210,6 +210,12 @@ zink_clear(struct pipe_context *pctx, const struct pipe_scissor_state *scissor_state, const union pipe_color_union *pcolor, double depth, unsigned stencil); +void +zink_clear_texture(struct pipe_context *ctx, + struct pipe_resource *p_res, + unsigned level, + const struct pipe_box *box, + const void *data); void zink_draw_vbo(struct pipe_context *pctx,