From 7598db41ae8ee47aca414fa415f5736492b22f7d Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 29 Oct 2022 12:41:01 -0700 Subject: [PATCH] freedreno/a6xx: Implement ARB_clear_texture Signed-off-by: Rob Clark Part-of: --- docs/features.txt | 2 +- .../drivers/freedreno/a6xx/fd6_blitter.c | 107 ++++++++++++++++++ .../drivers/freedreno/freedreno_screen.c | 1 + 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/docs/features.txt b/docs/features.txt index 45fbb6eb989..953983611ed 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -196,7 +196,7 @@ GL 4.4, GLSL 4.40 -- all DONE: i965/gen8+, nvc0, r600, radeonsi, llvmpipe, zink GL_MAX_VERTEX_ATTRIB_STRIDE DONE (all drivers) GL_ARB_buffer_storage DONE (freedreno, i965, nv50, v3d, vc4, lima, panfrost, asahi, d3d12, softpipe, etnaviv) - GL_ARB_clear_texture DONE (i965, nv50, softpipe, virgl) + GL_ARB_clear_texture DONE (freedreno/a6xx, i965, nv50, softpipe, virgl) GL_ARB_enhanced_layouts DONE (freedreno/a3xx+, i965, nv50, softpipe, virgl) - compile-time constant expressions DONE - explicit byte offsets for blocks DONE diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index a113d90f160..9bbedce25a8 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -31,6 +31,7 @@ #include "util/half_float.h" #include "util/u_dump.h" #include "util/u_log.h" +#include "util/u_surface.h" #include "freedreno_blitter.h" #include "freedreno_fence.h" @@ -233,6 +234,16 @@ can_do_blit(const struct pipe_blit_info *info) return true; } +static bool +can_do_clear(const struct pipe_resource *prsc, unsigned level, + const struct pipe_box *box) +{ + return ok_format(prsc->format) && + ok_dims(prsc, box, level); + + return true; +} + static void emit_setup(struct fd_batch *batch) { @@ -829,6 +840,101 @@ fd6_clear_surface(struct fd_context *ctx, struct fd_ringbuffer *ring, } } +static void +fd6_clear_texture(struct pipe_context *pctx, struct pipe_resource *prsc, + unsigned level, const struct pipe_box *box, const void *data) + assert_dt +{ + struct fd_context *ctx = fd_context(pctx); + struct fd_resource *rsc = fd_resource(prsc); + + if (DEBUG_BLIT) { + fprintf(stderr, "surface texture:\ndst resource: "); + util_dump_resource(stderr, prsc); + fprintf(stderr, "\n"); + } + + if (!can_do_clear(prsc, level, box)) + goto fallback; + + union pipe_color_union color; + + if (util_format_is_depth_or_stencil(prsc->format)) { + const struct util_format_description *desc = + util_format_description(prsc->format); + float depth = 0.0f; + uint8_t stencil = 0; + + if (util_format_has_depth(desc)) + util_format_unpack_z_float(prsc->format, &depth, data, 1); + + if (util_format_has_stencil(desc)) + util_format_unpack_s_8uint(prsc->format, &stencil, data, 1); + + if (rsc->stencil) + fd6_clear_texture(pctx, &rsc->stencil->b.b, level, box, &stencil); + + color.f[0] = depth; + color.ui[1] = stencil; + } else { + util_format_unpack_rgba(prsc->format, color.ui, data, 1); + } + + struct fd_batch *batch = fd_bc_alloc_batch(ctx, true); + + fd_screen_lock(ctx->screen); + fd_batch_resource_write(batch, rsc); + fd_screen_unlock(ctx->screen); + + ASSERTED bool ret = fd_batch_lock_submit(batch); + assert(ret); + + /* Marking the batch as needing flush must come after the batch + * dependency tracking (resource_read()/resource_write()), as that + * can trigger a flush + */ + fd_batch_needs_flush(batch); + + fd_batch_update_queries(batch); + + emit_setup(batch); + + struct pipe_surface surf = { + .format = prsc->format, + .texture = prsc, + .u = { + .tex = { + .level = level, + .first_layer = box->z, + .last_layer = box->depth + box->z - 1, + }, + }, + }; + + fd6_clear_surface(ctx, batch->draw, &surf, box, &color, 0); + + fd6_event_write(batch, batch->draw, PC_CCU_FLUSH_COLOR_TS, true); + fd6_event_write(batch, batch->draw, PC_CCU_FLUSH_DEPTH_TS, true); + fd6_event_write(batch, batch->draw, CACHE_FLUSH_TS, true); + fd_wfi(batch, batch->draw); + fd6_cache_inv(batch, batch->draw); + + fd_batch_unlock_submit(batch); + + fd_batch_flush(batch); + fd_batch_reference(&batch, NULL); + + /* Acc query state will have been dirtied by our fd_batch_update_queries, so + * the ctx->batch may need to turn its queries back on. + */ + ctx->update_active_queries = true; + + return; + +fallback: + util_clear_texture(pctx, prsc, level, box, data); +} + void fd6_resolve_tile(struct fd_batch *batch, struct fd_ringbuffer *ring, uint32_t base, struct pipe_surface *psurf, uint32_t unknown_8c01) @@ -1190,6 +1296,7 @@ fd6_blitter_init(struct pipe_context *pctx) disable_thread_safety_analysis if (FD_DBG(NOBLIT)) return; + pctx->clear_texture = fd6_clear_texture; ctx->blit = fd6_blit; } diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 0b2dbea9586..d3bdb477051 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -210,6 +210,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 1; case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: + case PIPE_CAP_CLEAR_TEXTURE: return is_a6xx(screen); case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: