diff options
author | Eric Anholt <[email protected]> | 2017-11-02 16:59:10 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2018-02-23 15:07:26 -0800 |
commit | b4b4ada7616dec49e9386670e455553d277e5f85 (patch) | |
tree | 271278e4c74ab257f096bc79757db562e437c6fc /src/gallium | |
parent | 97dc0773032d6284ea5c63758abf704d877f65dc (diff) |
broadcom/vc5: Fix layout of 3D textures.
Cube maps are entire miptrees repeated, while 3D textures have each level
have all of its layers next to each other. Fixes tex3d and
tex-miplevel-selection GL2:texture() 3D.
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/vc5/vc5_resource.c | 105 | ||||
-rw-r--r-- | src/gallium/drivers/vc5/vc5_resource.h | 8 |
2 files changed, 81 insertions, 32 deletions
diff --git a/src/gallium/drivers/vc5/vc5_resource.c b/src/gallium/drivers/vc5/vc5_resource.c index 157eb1c1013..e1645a4fde9 100644 --- a/src/gallium/drivers/vc5/vc5_resource.c +++ b/src/gallium/drivers/vc5/vc5_resource.c @@ -75,18 +75,22 @@ vc5_debug_resource_layout(struct vc5_resource *rsc, const char *caller) int level_width = slice->stride / rsc->cpp; int level_height = slice->padded_height; + int level_depth = + u_minify(util_next_power_of_two(prsc->depth0), i); fprintf(stderr, "rsc %s %p (format %s), %dx%d: " - "level %d (%s) %dx%d -> %dx%d, stride %d@0x%08x\n", + "level %d (%s) %dx%dx%d -> %dx%dx%d, stride %d@0x%08x\n", caller, rsc, util_format_short_name(prsc->format), prsc->width0, prsc->height0, i, tiling_descriptions[slice->tiling], u_minify(prsc->width0, i), u_minify(prsc->height0, i), + u_minify(prsc->depth0, i), level_width, level_height, + level_depth, slice->stride, rsc->bo->offset + slice->offset); } @@ -98,14 +102,8 @@ vc5_resource_bo_alloc(struct vc5_resource *rsc) struct pipe_resource *prsc = &rsc->base; struct pipe_screen *pscreen = prsc->screen; struct vc5_bo *bo; - int layers = (prsc->target == PIPE_TEXTURE_3D ? - prsc->depth0 : prsc->array_size); - - bo = vc5_bo_alloc(vc5_screen(pscreen), - rsc->slices[0].offset + - rsc->slices[0].size + - rsc->cube_map_stride * layers - 1, - "resource"); + + bo = vc5_bo_alloc(vc5_screen(pscreen), rsc->size, "resource"); if (bo) { vc5_bo_unreference(&rsc->bo); rsc->bo = bo; @@ -128,13 +126,21 @@ vc5_resource_transfer_unmap(struct pipe_context *pctx, struct vc5_resource_slice *slice = &rsc->slices[ptrans->level]; if (ptrans->usage & PIPE_TRANSFER_WRITE) { - vc5_store_tiled_image(rsc->bo->map + slice->offset + - ptrans->box.z * rsc->cube_map_stride, - slice->stride, - trans->map, ptrans->stride, - slice->tiling, rsc->cpp, - slice->padded_height, - &ptrans->box); + for (int z = 0; z < ptrans->box.depth; z++) { + void *dst = rsc->bo->map + + vc5_layer_offset(&rsc->base, + ptrans->level, + ptrans->box.z + z); + vc5_store_tiled_image(dst, + slice->stride, + (trans->map + + ptrans->stride * + ptrans->box.height * z), + ptrans->stride, + slice->tiling, rsc->cpp, + slice->padded_height, + &ptrans->box); + } } free(trans->map); } @@ -259,13 +265,21 @@ vc5_resource_transfer_map(struct pipe_context *pctx, trans->map = malloc(ptrans->layer_stride * ptrans->box.depth); if (usage & PIPE_TRANSFER_READ) { - vc5_load_tiled_image(trans->map, ptrans->stride, - buf + slice->offset + - ptrans->box.z * rsc->cube_map_stride, - slice->stride, - slice->tiling, rsc->cpp, - slice->padded_height, + for (int z = 0; z < ptrans->box.depth; z++) { + void *src = rsc->bo->map + + vc5_layer_offset(&rsc->base, + ptrans->level, + ptrans->box.z + z); + vc5_load_tiled_image((trans->map + + ptrans->stride * + ptrans->box.height * z), + ptrans->stride, + src, + slice->stride, + slice->tiling, rsc->cpp, + slice->padded_height, &ptrans->box); + } } return trans->map; } else { @@ -378,8 +392,10 @@ vc5_setup_slices(struct vc5_resource *rsc) struct pipe_resource *prsc = &rsc->base; uint32_t width = prsc->width0; uint32_t height = prsc->height0; + uint32_t depth = prsc->depth0; uint32_t pot_width = util_next_power_of_two(width); uint32_t pot_height = util_next_power_of_two(height); + uint32_t pot_depth = util_next_power_of_two(depth); uint32_t offset = 0; uint32_t utile_w = vc5_utile_width(rsc->cpp); uint32_t utile_h = vc5_utile_height(rsc->cpp); @@ -396,7 +412,7 @@ vc5_setup_slices(struct vc5_resource *rsc) for (int i = prsc->last_level; i >= 0; i--) { struct vc5_resource_slice *slice = &rsc->slices[i]; - uint32_t level_width, level_height; + uint32_t level_width, level_height, level_depth; if (i < 2) { level_width = u_minify(width, i); level_height = u_minify(height, i); @@ -404,6 +420,10 @@ vc5_setup_slices(struct vc5_resource *rsc) level_width = u_minify(pot_width, i); level_height = u_minify(pot_height, i); } + if (i < 1) + level_depth = u_minify(depth, i); + else + level_depth = u_minify(pot_depth, i); if (msaa) { level_width *= 2; @@ -468,6 +488,9 @@ vc5_setup_slices(struct vc5_resource *rsc) slice->padded_height = level_height; slice->size = level_height * slice->stride; + offset += slice->size * level_depth; + + /* The HW aligns level 1's base to a page if any of level 1 or * below could be UIF XOR. The lower levels then inherit the * alignment for as long as necesary, thanks to being power of @@ -476,11 +499,10 @@ vc5_setup_slices(struct vc5_resource *rsc) if (i == 1 && level_width > 4 * uif_block_w && level_height > PAGE_CACHE_MINUS_1_5_UB_ROWS * uif_block_h) { - slice->size = align(slice->size, VC5_UIFCFG_PAGE_SIZE); + offset = align(offset, VC5_UIFCFG_PAGE_SIZE); } - - offset += slice->size; } + rsc->size = offset; /* UIF/UBLINEAR levels need to be aligned to UIF-blocks, and LT only * needs to be aligned to utile boundaries. Since tiles are laid out @@ -493,15 +515,34 @@ vc5_setup_slices(struct vc5_resource *rsc) uint32_t page_align_offset = (align(rsc->slices[0].offset, 4096) - rsc->slices[0].offset); if (page_align_offset) { + rsc->size += page_align_offset; for (int i = 0; i <= prsc->last_level; i++) rsc->slices[i].offset += page_align_offset; } - /* Arrays, cubes, and 3D textures have a stride which is the distance - * from one full mipmap tree to the next (64b aligned). + /* Arrays and cube textures have a stride which is the distance from + * one full mipmap tree to the next (64b aligned). For 3D textures, + * we need to program the stride between slices of miplevel 0. */ - rsc->cube_map_stride = align(rsc->slices[0].offset + - rsc->slices[0].size, 64); + if (prsc->target != PIPE_TEXTURE_3D) { + rsc->cube_map_stride = align(rsc->slices[0].offset + + rsc->slices[0].size, 64); + rsc->size += rsc->cube_map_stride * (prsc->array_size - 1); + } else { + rsc->cube_map_stride = rsc->slices[0].size; + } +} + +uint32_t +vc5_layer_offset(struct pipe_resource *prsc, uint32_t level, uint32_t layer) +{ + struct vc5_resource *rsc = vc5_resource(prsc); + struct vc5_resource_slice *slice = &rsc->slices[level]; + + if (prsc->target == PIPE_TEXTURE_3D) + return slice->offset + layer * slice->size; + else + return slice->offset + layer * rsc->cube_map_stride; } static struct vc5_resource * @@ -737,8 +778,8 @@ vc5_create_surface(struct pipe_context *pctx, psurf->u.tex.first_layer = surf_tmpl->u.tex.first_layer; psurf->u.tex.last_layer = surf_tmpl->u.tex.last_layer; - surface->offset = (slice->offset + - psurf->u.tex.first_layer * rsc->cube_map_stride); + surface->offset = vc5_layer_offset(ptex, level, + psurf->u.tex.first_layer); surface->tiling = slice->tiling; surface->format = vc5_get_rt_format(&screen->devinfo, psurf->format); diff --git a/src/gallium/drivers/vc5/vc5_resource.h b/src/gallium/drivers/vc5/vc5_resource.h index 1bba480115b..2af355354ab 100644 --- a/src/gallium/drivers/vc5/vc5_resource.h +++ b/src/gallium/drivers/vc5/vc5_resource.h @@ -74,6 +74,10 @@ struct vc5_resource_slice { uint32_t offset; uint32_t stride; uint32_t padded_height; + /* Size of a single pane of the slice. For 3D textures, there will be + * a number of panes equal to the minified, power-of-two-aligned + * depth. + */ uint32_t size; uint8_t ub_pad; enum vc5_tiling_mode tiling; @@ -113,6 +117,7 @@ struct vc5_resource { struct vc5_bo *bo; struct vc5_resource_slice slices[VC5_MAX_MIP_LEVELS]; uint32_t cube_map_stride; + uint32_t size; int cpp; bool tiled; @@ -163,5 +168,8 @@ void vc5_resource_screen_init(struct pipe_screen *pscreen); void vc5_resource_context_init(struct pipe_context *pctx); struct pipe_resource *vc5_resource_create(struct pipe_screen *pscreen, const struct pipe_resource *tmpl); +uint32_t vc5_layer_offset(struct pipe_resource *prsc, uint32_t level, + uint32_t layer); + #endif /* VC5_RESOURCE_H */ |