From 1e3a732603a4a4d5b3e7102cf0d7840f79ecf5c4 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 5 Dec 2014 11:43:03 -0500 Subject: [PATCH] freedreno/a4xx: texture fixes Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a4xx/fd4_emit.c | 23 ++++++++++++++----- .../drivers/freedreno/a4xx/fd4_format.c | 17 ++++++++++++++ .../drivers/freedreno/a4xx/fd4_format.h | 1 + .../drivers/freedreno/a4xx/fd4_texture.c | 12 ++++++++++ .../drivers/freedreno/a4xx/fd4_texture.h | 2 +- .../drivers/freedreno/freedreno_resource.c | 6 +++++ 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index c7be161a073..5b471584ee0 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -162,12 +162,20 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, unsigned i; if (tex->num_samplers > 0) { + int num_samplers; + + /* not sure if this is an a420.0 workaround, but we seem + * to need to emit these in pairs.. emit a final dummy + * entry if odd # of samplers: + */ + num_samplers = align(tex->num_samplers, 2); + /* output sampler state: */ - OUT_PKT3(ring, CP_LOAD_STATE, 2 + 2 + (2 * tex->num_samplers)); + OUT_PKT3(ring, CP_LOAD_STATE, 2 + (2 * num_samplers)); OUT_RING(ring, CP_LOAD_STATE_0_DST_OFF(0) | CP_LOAD_STATE_0_STATE_SRC(SS_DIRECT) | CP_LOAD_STATE_0_STATE_BLOCK(sb) | - CP_LOAD_STATE_0_NUM_UNIT(tex->num_samplers)); + CP_LOAD_STATE_0_NUM_UNIT(num_samplers)); OUT_RING(ring, CP_LOAD_STATE_1_STATE_TYPE(ST_SHADER) | CP_LOAD_STATE_1_EXT_SRC_ADDR(0)); for (i = 0; i < tex->num_samplers; i++) { @@ -178,9 +186,11 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, sampler->texsamp0); OUT_RING(ring, sampler->texsamp1); } - /* maybe an a420.0 (or a4xx.0) workaround?? or just driver bug? */ - OUT_RING(ring, 0x00000000); - OUT_RING(ring, 0x00000000); + + for (; i < num_samplers; i++) { + OUT_RING(ring, 0x00000000); + OUT_RING(ring, 0x00000000); + } } if (tex->num_textures > 0) { @@ -203,7 +213,8 @@ emit_textures(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, view->texconst1); OUT_RING(ring, view->texconst2); OUT_RING(ring, view->texconst3); - OUT_RELOC(ring, rsc->bo, slice->offset, 0, 0); + OUT_RELOC(ring, rsc->bo, slice->offset, + view->textconst4, 0); OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_format.c b/src/gallium/drivers/freedreno/a4xx/fd4_format.c index bbece83d109..9cff1340ee7 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_format.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_format.c @@ -232,6 +232,23 @@ fd4_pipe2swap(enum pipe_format format) return formats[format].swap; } +enum a4xx_tex_fetchsize +fd4_pipe2fetchsize(enum pipe_format format) +{ + switch (util_format_get_blocksizebits(format)) { + case 8: return TFETCH4_1_BYTE; + case 16: return TFETCH4_2_BYTE; + case 32: return TFETCH4_4_BYTE; + case 64: return TFETCH4_8_BYTE; + case 128: return TFETCH4_16_BYTE; + default: + debug_printf("Unknown block size for format %s: %d\n", + util_format_name(format), + util_format_get_blocksizebits(format)); + return TFETCH4_1_BYTE; + } +} + /* we need to special case a bit the depth/stencil restore, because we are * using the texture sampler to blit into the depth/stencil buffer, *not* * into a color buffer. Otherwise fd4_tex_swiz() will do the wrong thing, diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_format.h b/src/gallium/drivers/freedreno/a4xx/fd4_format.h index 5d6d1ae9e85..04837da650b 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_format.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_format.h @@ -38,6 +38,7 @@ enum a4xx_tex_fmt fd4_pipe2tex(enum pipe_format format); enum a4xx_color_fmt fd4_pipe2color(enum pipe_format format); enum pipe_format fd4_gmem_restore_format(enum pipe_format format); enum a3xx_color_swap fd4_pipe2swap(enum pipe_format format); +enum a4xx_tex_fetchsize fd4_pipe2fetchsize(enum pipe_format format); enum a4xx_depth_format fd4_pipe2depth(enum pipe_format format); uint32_t fd4_tex_swiz(enum pipe_format format, unsigned swizzle_r, diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c index 2b826d6325d..849113d80cc 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.c @@ -165,13 +165,25 @@ fd4_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, A4XX_TEX_CONST_1_WIDTH(prsc->width0) | A4XX_TEX_CONST_1_HEIGHT(prsc->height0); so->texconst2 = + A4XX_TEX_CONST_2_FETCHSIZE(fd4_pipe2fetchsize(cso->format)) | A4XX_TEX_CONST_2_PITCH(rsc->slices[lvl].pitch * rsc->cpp); switch (prsc->target) { case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: + so->texconst3 = + A4XX_TEX_CONST_3_DEPTH(prsc->array_size) | + A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0); + break; + case PIPE_TEXTURE_CUBE: + case PIPE_TEXTURE_CUBE_ARRAY: /* ?? not sure about _CUBE_ARRAY */ + so->texconst3 = + A4XX_TEX_CONST_3_DEPTH(1) | + A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0); + break; case PIPE_TEXTURE_3D: so->texconst3 = + A4XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) | A4XX_TEX_CONST_3_LAYERSZ(rsc->slices[0].size0); break; default: diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_texture.h b/src/gallium/drivers/freedreno/a4xx/fd4_texture.h index 07eb961eb8f..975dfe5157d 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_texture.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_texture.h @@ -51,7 +51,7 @@ fd4_sampler_stateobj(struct pipe_sampler_state *samp) struct fd4_pipe_sampler_view { struct pipe_sampler_view base; struct fd_resource *tex_resource; - uint32_t texconst0, texconst1, texconst2, texconst3; + uint32_t texconst0, texconst1, texconst2, texconst3, textconst4; }; static INLINE struct fd4_pipe_sampler_view * diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 461e378c89e..d604aa3f1f8 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -216,6 +216,12 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment) static uint32_t slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) { + struct fd_screen *screen = fd_screen(pscreen); + + /* on a4xx, seems like everything is aligned to page: */ + if ((screen->gpu_id >= 400) && (screen->gpu_id < 500)) + return 4096; + /* on a3xx, 2d array and 3d textures seem to want their * layers aligned to page boundaries: */ -- 2.30.2