From 8257bb963f0b21c0c35da479707b5cacbc1c2824 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Mon, 12 Nov 2012 20:08:19 +0100 Subject: [PATCH] llvmpipe: always allocate whole miptrees not individual levels MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is preparation work for using mip level offsets + base_ptr for texture sampling instead of per-mip pointers. Reviewed-by: Brian Paul Reviewed-by: José Fonseca --- src/gallium/drivers/llvmpipe/lp_texture.c | 134 ++++++++++++---------- src/gallium/drivers/llvmpipe/lp_texture.h | 7 +- 2 files changed, 81 insertions(+), 60 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index b4ea94ca1ae..f61e3781406 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -332,7 +332,7 @@ llvmpipe_resource_create(struct pipe_screen *_screen, static void llvmpipe_resource_destroy(struct pipe_screen *pscreen, - struct pipe_resource *pt) + struct pipe_resource *pt) { struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); struct llvmpipe_resource *lpr = llvmpipe_resource(pt); @@ -342,9 +342,9 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, struct sw_winsys *winsys = screen->winsys; winsys->displaytarget_destroy(winsys, lpr->dt); - if (lpr->tiled[0].data) { - align_free(lpr->tiled[0].data); - lpr->tiled[0].data = NULL; + if (lpr->tiled_img.data) { + align_free(lpr->tiled_img.data); + lpr->tiled_img.data = NULL; } FREE(lpr->layout[0]); @@ -354,23 +354,19 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, uint level; /* free linear image data */ - for (level = 0; level < Elements(lpr->linear); level++) { - if (lpr->linear[level].data) { - align_free(lpr->linear[level].data); - lpr->linear[level].data = NULL; - } + if (lpr->linear_img.data) { + align_free(lpr->linear_img.data); + lpr->linear_img.data = NULL; } /* free tiled image data */ - for (level = 0; level < Elements(lpr->tiled); level++) { - if (lpr->tiled[level].data) { - align_free(lpr->tiled[level].data); - lpr->tiled[level].data = NULL; - } + if (lpr->tiled_img.data) { + align_free(lpr->tiled_img.data); + lpr->tiled_img.data = NULL; } /* free layout flag arrays */ - for (level = 0; level < Elements(lpr->tiled); level++) { + for (level = 0; level < Elements(lpr->layout); level++) { FREE(lpr->layout[level]); lpr->layout[level] = NULL; } @@ -434,7 +430,7 @@ llvmpipe_resource_map(struct pipe_resource *resource, map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); /* install this linear image in texture data structure */ - lpr->linear[level].data = map; + lpr->linear_img.data = map; /* make sure tiled data gets converted to linear data */ map2 = llvmpipe_get_texture_image(lpr, 0, 0, tex_usage, layout); @@ -496,8 +492,8 @@ llvmpipe_resource_data(struct pipe_resource *resource) static struct pipe_resource * llvmpipe_resource_from_handle(struct pipe_screen *screen, - const struct pipe_resource *template, - struct winsys_handle *whandle) + const struct pipe_resource *template, + struct winsys_handle *whandle) { struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; struct llvmpipe_resource *lpr; @@ -911,17 +907,17 @@ llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, unsigned offset; if (layout == LP_TEX_LAYOUT_LINEAR) { - img = &lpr->linear[level]; + img = &lpr->linear_img; + offset = lpr->linear_mip_offsets[level]; } else { assert (layout == LP_TEX_LAYOUT_TILED); - img = &lpr->tiled[level]; + img = &lpr->tiled_img; + offset = lpr->tiled_mip_offsets[level]; } if (face_slice > 0) - offset = face_slice * tex_image_face_size(lpr, level, layout); - else - offset = 0; + offset += face_slice * tex_image_face_size(lpr, level, layout); return (ubyte *) img->data + offset; } @@ -976,23 +972,29 @@ llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr, /** * Allocate storage for a linear or tile texture image (all cube - * faces and all 3D slices. + * faces and all 3D slices, all levels). */ static void -alloc_image_data(struct llvmpipe_resource *lpr, unsigned level, +alloc_image_data(struct llvmpipe_resource *lpr, enum lp_texture_layout layout) { uint alignment = MAX2(16, util_cpu_caps.cacheline); + uint level; + uint offset = 0; if (lpr->dt) - assert(level == 0); + assert(lpr->base.last_level == 0); if (layout == LP_TEX_LAYOUT_TILED) { /* tiled data is stored in regular memory */ - uint buffer_size = tex_image_size(lpr, level, layout); - lpr->tiled[level].data = align_malloc(buffer_size, alignment); - if (lpr->tiled[level].data) { - memset(lpr->tiled[level].data, 0, buffer_size); + for (level = 0; level <= lpr->base.last_level; level++) { + uint buffer_size = tex_image_size(lpr, level, layout); + lpr->tiled_mip_offsets[level] = offset; + offset += align(buffer_size, alignment); + } + lpr->tiled_img.data = align_malloc(offset, alignment); + if (lpr->tiled_img.data) { + memset(lpr->tiled_img.data, 0, offset); } } else { @@ -1004,16 +1006,24 @@ alloc_image_data(struct llvmpipe_resource *lpr, unsigned level, struct llvmpipe_screen *screen = llvmpipe_screen(lpr->base.screen); struct sw_winsys *winsys = screen->winsys; - lpr->linear[0].data = + lpr->linear_img.data = winsys->displaytarget_map(winsys, lpr->dt, PIPE_TRANSFER_READ_WRITE); } else { /* not a display target - allocate regular memory */ - uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR); - lpr->linear[level].data = align_malloc(buffer_size, alignment); - if (lpr->linear[level].data) { - memset(lpr->linear[level].data, 0, buffer_size); + /* + * Offset calculation for start of a specific mip/layer is always + * offset = lpr->linear_mip_offsets[level] + lpr->img_stride[level] * layer + */ + for (level = 0; level <= lpr->base.last_level; level++) { + uint buffer_size = tex_image_size(lpr, level, LP_TEX_LAYOUT_LINEAR); + lpr->linear_mip_offsets[level] = offset; + offset += align(buffer_size, alignment); + } + lpr->linear_img.data = align_malloc(offset, alignment); + if (lpr->linear_img.data) { + memset(lpr->linear_img.data, 0, offset); } } } @@ -1049,6 +1059,8 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, const unsigned height = u_minify(lpr->base.height0, level); const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; + unsigned target_offset, other_offset; + unsigned *target_off_ptr, *other_off_ptr; enum lp_texture_layout other_layout; boolean only_allocate; @@ -1070,18 +1082,22 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, } if (lpr->dt) { - assert(lpr->linear[level].data); + assert(lpr->linear_img.data); } /* which is target? which is other? */ if (layout == LP_TEX_LAYOUT_LINEAR) { - target_img = &lpr->linear[level]; - other_img = &lpr->tiled[level]; + target_img = &lpr->linear_img; + target_off_ptr = lpr->linear_mip_offsets; + other_img = &lpr->tiled_img; + other_off_ptr = lpr->tiled_mip_offsets; other_layout = LP_TEX_LAYOUT_TILED; } else { - target_img = &lpr->tiled[level]; - other_img = &lpr->linear[level]; + target_img = &lpr->tiled_img; + target_off_ptr = lpr->tiled_mip_offsets; + other_img = &lpr->linear_img; + other_off_ptr = lpr->linear_mip_offsets; other_layout = LP_TEX_LAYOUT_LINEAR; } @@ -1090,21 +1106,23 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, if (!target_data) { /* allocate memory for the target image now */ - alloc_image_data(lpr, level, layout); + alloc_image_data(lpr, layout); target_data = target_img->data; } + target_offset = target_off_ptr[level]; + other_offset = other_off_ptr[level]; + if (face_slice > 0) { - unsigned target_offset, other_offset; + target_offset += face_slice * tex_image_face_size(lpr, level, layout); + other_offset += face_slice * tex_image_face_size(lpr, level, other_layout); + } - target_offset = face_slice * tex_image_face_size(lpr, level, layout); - other_offset = face_slice * tex_image_face_size(lpr, level, other_layout); - if (target_data) { - target_data = (uint8_t *) target_data + target_offset; - } - if (other_data) { - other_data = (uint8_t *) other_data + other_offset; - } + if (target_data) { + target_data = (uint8_t *) target_data + target_offset; + } + if (other_data) { + other_data = (uint8_t *) other_data + other_offset; } if (only_allocate) { @@ -1202,7 +1220,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, enum lp_texture_usage usage, unsigned x, unsigned y) { - struct llvmpipe_texture_image *linear_img = &lpr->linear[level]; + struct llvmpipe_texture_image *linear_img = &lpr->linear_img; enum lp_texture_layout cur_layout, new_layout; const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; boolean convert; @@ -1214,7 +1232,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, if (!linear_img->data) { /* allocate memory for the linear image now */ - alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR); + alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR); } /* compute address of the slice/face of the image that contains the tile */ @@ -1253,7 +1271,7 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, enum lp_texture_usage usage, unsigned x, unsigned y) { - struct llvmpipe_texture_image *tiled_img = &lpr->tiled[level]; + struct llvmpipe_texture_image *tiled_img = &lpr->tiled_img; enum lp_texture_layout cur_layout, new_layout; const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; boolean convert; @@ -1265,7 +1283,7 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, if (!tiled_img->data) { /* allocate memory for the tiled image now */ - alloc_image_data(lpr, level, LP_TEX_LAYOUT_TILED); + alloc_image_data(lpr, LP_TEX_LAYOUT_TILED); } /* compute address of the slice/face of the image that contains the tile */ @@ -1309,7 +1327,7 @@ llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr, unsigned x, unsigned y, uint8_t *tile) { - struct llvmpipe_texture_image *linear_img = &lpr->linear[level]; + struct llvmpipe_texture_image *linear_img = &lpr->linear_img; const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE; uint8_t *linear_image; @@ -1318,7 +1336,7 @@ llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr, if (!linear_img->data) { /* allocate memory for the linear image now */ - alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR); + alloc_image_data(lpr, LP_TEX_LAYOUT_LINEAR); } /* compute address of the slice/face of the image that contains the tile */ @@ -1397,10 +1415,10 @@ llvmpipe_resource_size(const struct pipe_resource *resource) unsigned lvl, size = 0; for (lvl = 0; lvl <= lpr->base.last_level; lvl++) { - if (lpr->linear[lvl].data) + if (lpr->linear_img.data) size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_LINEAR); - if (lpr->tiled[lvl].data) + if (lpr->tiled_img.data) size += tex_image_size(lpr, lvl, LP_TEX_LAYOUT_TILED); } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index b4a0dfd1c36..73eaddc27ed 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -94,6 +94,9 @@ struct llvmpipe_resource unsigned tiles_per_image[LP_MAX_TEXTURE_LEVELS]; /** Number of 3D slices or cube faces per level */ unsigned num_slices_faces[LP_MAX_TEXTURE_LEVELS]; + /** Offset to start of mipmap level, in bytes */ + unsigned tiled_mip_offsets[LP_MAX_TEXTURE_LEVELS]; + unsigned linear_mip_offsets[LP_MAX_TEXTURE_LEVELS]; /** * Display target, for textures with the PIPE_BIND_DISPLAY_TARGET @@ -104,8 +107,8 @@ struct llvmpipe_resource /** * Malloc'ed data for regular textures, or a mapping to dt above. */ - struct llvmpipe_texture_image tiled[LP_MAX_TEXTURE_LEVELS]; - struct llvmpipe_texture_image linear[LP_MAX_TEXTURE_LEVELS]; + struct llvmpipe_texture_image tiled_img; + struct llvmpipe_texture_image linear_img; /** * Data for non-texture resources. -- 2.30.2