diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/freedreno/registers/a6xx.xml | 4 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a6xx/fd6_blitter.c | 101 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a6xx/fd6_blitter.h | 5 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a6xx/fd6_format.h | 9 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 67 |
5 files changed, 171 insertions, 15 deletions
diff --git a/src/freedreno/registers/a6xx.xml b/src/freedreno/registers/a6xx.xml index 858f2f3c94c..4763c47b7d1 100644 --- a/src/freedreno/registers/a6xx.xml +++ b/src/freedreno/registers/a6xx.xml @@ -963,6 +963,7 @@ to upconvert to 32b float internally? <value value="0x4" name="R2D_FLOAT32"/> <value value="0x3" name="R2D_FLOAT16"/> <value value="0x1" name="R2D_UNORM8_SRGB"/> + <value value="0x0" name="R2D_RAW"/> </enum> <domain name="A6XX" width="32"> @@ -2009,6 +2010,9 @@ to upconvert to 32b float internally? <bitfield name="SOLID_COLOR" pos="7" type="boolean"/> <bitfield name="COLOR_FORMAT" low="8" high="15" type="a6xx_color_fmt"/> <bitfield name="SCISSOR" pos="16" type="boolean"/> + + <bitfield name="UNK" low="17" high="18" type="uint"/> + <!-- required when blitting D24S8/D24X8 --> <bitfield name="D24S8" pos="19" type="boolean"/> <!-- some sort of channel mask, disabled channels are set to zero ? --> diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c index 67924a8185f..79541e5cb54 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.c @@ -26,6 +26,7 @@ */ #include "util/u_dump.h" +#include "util/half_float.h" #include "freedreno_blitter.h" #include "freedreno_fence.h" @@ -341,8 +342,8 @@ emit_blit_buffer(struct fd_context *ctx, struct fd_ringbuffer *ring, } static void -emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, - const struct pipe_blit_info *info) +emit_blit_or_clear_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, + const struct pipe_blit_info *info, union pipe_color_union *color) { const struct pipe_box *sbox = &info->src.box; const struct pipe_box *dbox = &info->dst.box; @@ -393,7 +394,7 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, nelements = blocksize; } else { debug_assert(!util_format_is_compressed(info->dst.format)); - nelements = 1; + nelements = (dst->base.nr_samples ? dst->base.nr_samples : 1); } spitch = DIV_ROUND_UP(sslice->pitch, blockwidth) * src->cpp; @@ -417,6 +418,68 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, uint32_t blit_cntl = blit_control(dfmt); + if (color) { + blit_cntl |= A6XX_RB_2D_BLIT_CNTL_SOLID_COLOR; + + switch (info->dst.format) { + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + case PIPE_FORMAT_X24S8_UINT: { + uint32_t depth_unorm24 = color->f[0] * ((1u << 24) - 1); + uint8_t stencil = color->ui[1]; + color->ui[0] = depth_unorm24 & 0xff; + color->ui[1] = (depth_unorm24 >> 8) & 0xff; + color->ui[2] = (depth_unorm24 >> 16) & 0xff; + color->ui[3] = stencil; + + dfmt = RB6_Z24_UNORM_S8_UINT; + break; + } + case PIPE_FORMAT_B5G6R5_UNORM: + case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: + case PIPE_FORMAT_B4G4R4A4_UNORM: + color->ui[0] = float_to_ubyte(color->f[0]); + color->ui[1] = float_to_ubyte(color->f[1]); + color->ui[2] = float_to_ubyte(color->f[2]); + color->ui[3] = float_to_ubyte(color->f[3]); + break; + default: + break; + } + + OUT_PKT4(ring, REG_A6XX_RB_2D_SRC_SOLID_C0, 4); + + switch (fd6_ifmt(dfmt)) { + case R2D_UNORM8: + case R2D_UNORM8_SRGB: + OUT_RING(ring, float_to_ubyte(color->f[0])); + OUT_RING(ring, float_to_ubyte(color->f[1])); + OUT_RING(ring, float_to_ubyte(color->f[2])); + OUT_RING(ring, float_to_ubyte(color->f[3])); + break; + case R2D_FLOAT16: + OUT_RING(ring, _mesa_float_to_half(color->f[0])); + OUT_RING(ring, _mesa_float_to_half(color->f[1])); + OUT_RING(ring, _mesa_float_to_half(color->f[2])); + OUT_RING(ring, _mesa_float_to_half(color->f[3])); + sfmt = RB6_R16G16B16A16_FLOAT; + break; + + case R2D_FLOAT32: + case R2D_INT32: + case R2D_INT16: + case R2D_INT8: + case R2D_RAW: + default: + OUT_RING(ring, color->ui[0]); + OUT_RING(ring, color->ui[1]); + OUT_RING(ring, color->ui[2]); + OUT_RING(ring, color->ui[3]); + break; + } + } + if (dtile != stile) blit_cntl |= 0x20000000; @@ -452,6 +515,9 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, enum a3xx_msaa_samples samples = fd_msaa_samples(src->base.nr_samples); + if (sfmt == RB6_R10G10B10A2_UNORM) + sfmt = RB6_R10G10B10A2_FLOAT16; + OUT_PKT4(ring, REG_A6XX_SP_PS_2D_SRC_INFO, 10); OUT_RING(ring, A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT(sfmt) | A6XX_SP_PS_2D_SRC_INFO_TILE_MODE(stile) | @@ -526,6 +592,9 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_PKT4(ring, REG_A6XX_RB_UNKNOWN_8C01, 1); OUT_RING(ring, 0); + if (dfmt == RB6_R10G10B10A2_UNORM) + sfmt = RB6_R16G16B16A16_FLOAT; + OUT_PKT4(ring, REG_A6XX_SP_2D_SRC_FORMAT, 1); OUT_RING(ring, A6XX_SP_2D_SRC_FORMAT_COLOR_FORMAT(sfmt) | COND(util_format_is_pure_sint(info->src.format), @@ -554,6 +623,30 @@ emit_blit_texture(struct fd_context *ctx, struct fd_ringbuffer *ring, } } +void +fd6_clear_surface(struct fd_context *ctx, + struct fd_ringbuffer *ring, struct pipe_surface *psurf, + uint32_t width, uint32_t height, union pipe_color_union *color) +{ + struct pipe_blit_info info = {}; + + info.dst.resource = psurf->texture; + info.dst.level = psurf->u.tex.level; + info.dst.box.x = 0; + info.dst.box.y = 0; + info.dst.box.z = psurf->u.tex.first_layer; + info.dst.box.width = width; + info.dst.box.height = height; + info.dst.box.depth = psurf->u.tex.last_layer + 1 - psurf->u.tex.first_layer; + info.dst.format = psurf->format; + info.src = info.dst; + info.mask = util_format_get_mask(psurf->format); + info.filter = PIPE_TEX_FILTER_NEAREST; + info.scissor_enable = 0; + + emit_blit_or_clear_texture(ctx, ring, &info, color); +} + static bool handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info); /** @@ -683,7 +776,7 @@ handle_rgba_blit(struct fd_context *ctx, const struct pipe_blit_info *info) /* I don't *think* we need to handle blits between buffer <-> !buffer */ debug_assert(info->src.resource->target != PIPE_BUFFER); debug_assert(info->dst.resource->target != PIPE_BUFFER); - emit_blit_texture(ctx, batch->draw, info); + emit_blit_or_clear_texture(ctx, batch->draw, info, NULL); } fd6_event_write(batch, batch->draw, 0x1d, true); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h index c1609b57936..b75013c6d04 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_blitter.h @@ -35,4 +35,9 @@ void fd6_blitter_init(struct pipe_context *pctx); unsigned fd6_tile_mode(const struct pipe_resource *tmpl); +void +fd6_clear_surface(struct fd_context *ctx, + struct fd_ringbuffer *ring, struct pipe_surface *psurf, + uint32_t width, uint32_t height, union pipe_color_union *color); + #endif /* FD6_BLIT_H_ */ diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_format.h b/src/gallium/drivers/freedreno/a6xx/fd6_format.h index 388de5b48c0..3c1e0a0e5d4 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_format.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_format.h @@ -102,21 +102,20 @@ fd6_ifmt(enum a6xx_color_fmt fmt) case RB6_R16_FLOAT: case RB6_R16G16_FLOAT: case RB6_R16G16B16A16_FLOAT: + case RB6_R11G11B10_FLOAT: return R2D_FLOAT16; + case RB6_R10G10B10A2_UNORM: case RB6_R4G4B4A4_UNORM: case RB6_R5G5B5A1_UNORM: case RB6_R5G6B5_UNORM: - case RB6_R10G10B10A2_UNORM: case RB6_R10G10B10A2_UINT: - case RB6_R11G11B10_FLOAT: case RB6_X8Z24_UNORM: - // ??? - return 0; + case RB6_Z24_UNORM_S8_UINT: + return R2D_RAW; default: unreachable("bad format"); return 0; } } - #endif /* FD6_UTIL_H_ */ diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index d9fabcbaa23..5799e6b0d3f 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -37,6 +37,7 @@ #include "freedreno_state.h" #include "freedreno_resource.h" +#include "fd6_blitter.h" #include "fd6_gmem.h" #include "fd6_context.h" #include "fd6_draw.h" @@ -1446,6 +1447,58 @@ fd6_emit_tile_fini(struct fd_batch *batch) } static void +emit_sysmem_clears(struct fd_batch *batch, struct fd_ringbuffer *ring) +{ + struct fd_context *ctx = batch->ctx; + struct pipe_framebuffer_state *pfb = &batch->framebuffer; + + uint32_t buffers = batch->fast_cleared; + + if (buffers & PIPE_CLEAR_COLOR) { + for (int i = 0; i < pfb->nr_cbufs; i++) { + union pipe_color_union *color = &batch->clear_color[i]; + + if (!pfb->cbufs[i]) + continue; + + if (!(buffers & (PIPE_CLEAR_COLOR0 << i))) + continue; + + fd6_clear_surface(ctx, ring, + pfb->cbufs[i], pfb->width, pfb->height, color); + } + } + if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) { + union pipe_color_union value = {}; + + const bool has_depth = pfb->zsbuf; + struct pipe_resource *separate_stencil = + has_depth && fd_resource(pfb->zsbuf->texture)->stencil ? + &fd_resource(pfb->zsbuf->texture)->stencil->base : NULL; + + if ((has_depth && (buffers & PIPE_CLEAR_DEPTH)) || + (!separate_stencil && (buffers & PIPE_CLEAR_STENCIL))) { + value.f[0] = batch->clear_depth; + value.ui[1] = batch->clear_stencil; + fd6_clear_surface(ctx, ring, + pfb->zsbuf, pfb->width, pfb->height, &value); + } + + if (separate_stencil && (buffers & PIPE_CLEAR_STENCIL)) { + value.ui[0] = batch->clear_stencil; + + struct pipe_surface stencil_surf = *pfb->zsbuf; + stencil_surf.texture = separate_stencil; + + fd6_clear_surface(ctx, ring, + &stencil_surf, pfb->width, pfb->height, &value); + } + } + + fd6_event_write(batch, ring, 0x1d, true); +} + +static void fd6_emit_sysmem_prep(struct fd_batch *batch) { struct pipe_framebuffer_state *pfb = &batch->framebuffer; @@ -1453,6 +1506,14 @@ fd6_emit_sysmem_prep(struct fd_batch *batch) fd6_emit_restore(batch, ring); + set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1); + + set_window_offset(ring, 0, 0); + + set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */ + + emit_sysmem_clears(batch, ring); + fd6_emit_lrz_flush(ring); emit_marker6(ring, 7); @@ -1474,12 +1535,6 @@ fd6_emit_sysmem_prep(struct fd_batch *batch) OUT_PKT4(ring, REG_A6XX_VPC_SO_OVERRIDE, 1); OUT_RING(ring, 0); - set_scissor(ring, 0, 0, pfb->width - 1, pfb->height - 1); - - set_window_offset(ring, 0, 0); - - set_bin_size(ring, 0, 0, 0xc00000); /* 0xc00000 = BYPASS? */ - OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1); OUT_RING(ring, 0x1); |