From c1e9cca6965cb0b7dcb6fa14b08f42e98b25b322 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 3 Dec 2016 12:34:10 -0500 Subject: [PATCH] freedreno: pitch alignment should match gmem alignment Deal w/ differing gmem tile size alignment between generations, and make sure texture pitch matches. Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a5xx/fd5_gmem.c | 1 + src/gallium/drivers/freedreno/freedreno_gmem.c | 17 +++++++++-------- src/gallium/drivers/freedreno/freedreno_resource.c | 11 +++++++---- src/gallium/drivers/freedreno/freedreno_screen.c | 6 ++++-- src/gallium/drivers/freedreno/freedreno_screen.h | 2 +- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c index d37c9d4..f505733 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c @@ -104,6 +104,7 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs, OUT_RING(ring, base); /* RB_MRT[i].BASE_LO */ OUT_RING(ring, 0x00000000); /* RB_MRT[i].BASE_HI */ } else { + debug_assert((offset + size) <= fd_bo_size(rsc->bo)); OUT_RELOCW(ring, rsc->bo, offset, 0, 0); /* BASE_LO/HI */ } diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index aeccebd..c7ac0a2 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -110,7 +110,8 @@ calculate_tiles(struct fd_batch *batch) struct fd_gmem_stateobj *gmem = &ctx->gmem; struct pipe_scissor_state *scissor = &batch->max_scissor; struct pipe_framebuffer_state *pfb = &batch->framebuffer; - const uint32_t gmem_alignment = ctx->screen->gmem_alignment; + const uint32_t gmem_alignw = ctx->screen->gmem_alignw; + const uint32_t gmem_alignh = ctx->screen->gmem_alignh; const uint32_t gmem_size = ctx->screen->gmemsize_bytes; uint32_t minx, miny, width, height; uint32_t nbins_x = 1, nbins_y = 1; @@ -149,21 +150,21 @@ calculate_tiles(struct fd_batch *batch) height = pfb->height; } else { /* round down to multiple of alignment: */ - minx = scissor->minx & ~(gmem_alignment - 1); - miny = scissor->miny & ~(gmem_alignment - 1); + minx = scissor->minx & ~(gmem_alignw - 1); + miny = scissor->miny & ~(gmem_alignh - 1); width = scissor->maxx - minx; height = scissor->maxy - miny; } - bin_w = align(width, gmem_alignment); - bin_h = align(height, gmem_alignment); + bin_w = align(width, gmem_alignw); + bin_h = align(height, gmem_alignh); /* first, find a bin width that satisfies the maximum width * restrictions: */ while (bin_w > max_width) { nbins_x++; - bin_w = align(width / nbins_x, gmem_alignment); + bin_w = align(width / nbins_x, gmem_alignw); } if (fd_mesa_debug & FD_DBG_MSGS) { @@ -180,10 +181,10 @@ calculate_tiles(struct fd_batch *batch) while (total_size(cbuf_cpp, zsbuf_cpp, bin_w, bin_h, gmem) > gmem_size) { if (bin_w > bin_h) { nbins_x++; - bin_w = align(width / nbins_x, gmem_alignment); + bin_w = align(width / nbins_x, gmem_alignw); } else { nbins_y++; - bin_h = align(height / nbins_y, gmem_alignment); + bin_h = align(height / nbins_y, gmem_alignh); } } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index f1acf64..174c1d4 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -700,6 +700,7 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma { struct pipe_resource *prsc = &rsc->base.b; enum util_format_layout layout = util_format_description(format)->layout; + uint32_t pitchalign = fd_screen(prsc->screen)->gmem_alignw; uint32_t level, size = 0; uint32_t width = prsc->width0; uint32_t height = prsc->height0; @@ -715,9 +716,9 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma if (layout == UTIL_FORMAT_LAYOUT_ASTC) slice->pitch = width = - util_align_npot(width, 32 * util_format_get_blockwidth(format)); + util_align_npot(width, pitchalign * util_format_get_blockwidth(format)); else - slice->pitch = width = align(width, 32); + slice->pitch = width = align(width, pitchalign); slice->offset = size; blocks = util_format_get_nblocks(format, width, height); /* 1d array and 2d array textures must all have the same layer size @@ -882,6 +883,7 @@ fd_resource_from_handle(struct pipe_screen *pscreen, struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); struct fd_resource_slice *slice = &rsc->slices[0]; struct pipe_resource *prsc = &rsc->base.b; + uint32_t pitchalign = fd_screen(pscreen)->gmem_alignw; DBG("target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " "nr_samples=%u, usage=%u, bind=%x, flags=%x", @@ -911,7 +913,8 @@ fd_resource_from_handle(struct pipe_screen *pscreen, slice->offset = handle->offset; slice->size0 = handle->stride * prsc->height0; - if ((slice->pitch < align(prsc->width0, 32)) || (slice->pitch % 32)) + if ((slice->pitch < align(prsc->width0, pitchalign)) || + (slice->pitch & (pitchalign - 1))) goto fail; assert(rsc->cpp); @@ -1125,7 +1128,7 @@ fd_resource_context_init(struct pipe_context *pctx) pctx->transfer_flush_region = u_transfer_flush_region_vtbl; pctx->transfer_unmap = u_transfer_unmap_vtbl; pctx->buffer_subdata = u_default_buffer_subdata; - pctx->texture_subdata = u_default_texture_subdata; + pctx->texture_subdata = u_default_texture_subdata; pctx->create_surface = fd_create_surface; pctx->surface_destroy = fd_surface_destroy; pctx->resource_copy_region = fd_resource_copy_region; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 8ab0e37..8765d5c 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -679,9 +679,11 @@ fd_screen_create(struct fd_device *dev) } if (screen->gpu_id >= 500) { - screen->gmem_alignment = 64; + screen->gmem_alignw = 64; + screen->gmem_alignh = 32; } else { - screen->gmem_alignment = 32; + screen->gmem_alignw = 32; + screen->gmem_alignh = 32; } /* NOTE: don't enable reordering on a2xx, since completely untested. diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index 6a7b2a8..8319539 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -64,7 +64,7 @@ struct fd_screen { uint32_t chip_id; /* coreid:8 majorrev:8 minorrev:8 patch:8 */ uint32_t max_freq; uint32_t max_rts; /* max # of render targets */ - uint32_t gmem_alignment; + uint32_t gmem_alignw, gmem_alignh; bool has_timestamp; void *compiler; /* currently unused for a2xx */ -- 2.7.4