From aa5bc35f31863fd15219849bc09826fe5be3a2ba Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 2 Jul 2019 11:37:40 +0200 Subject: [PATCH] panfrost: Move BO meta-data out of panfrost_bo That's what most (all?) implementation seem to do, and my understanding is that a BO is just a bunch of memory that can be used for anything GPU related, not only texture/FB resources. Let's move those meta data in panfrost_resource so we can use panfrost_bo for all kind of memory allocation and make BO allocation more consistent. Signed-off-by: Boris Brezillon --- src/gallium/drivers/panfrost/pan_context.c | 12 +- src/gallium/drivers/panfrost/pan_fragment.c | 2 +- src/gallium/drivers/panfrost/pan_mfbd.c | 24 ++-- src/gallium/drivers/panfrost/pan_resource.c | 126 ++++++++++---------- src/gallium/drivers/panfrost/pan_resource.h | 24 ++-- src/gallium/drivers/panfrost/pan_sfbd.c | 4 +- 6 files changed, 98 insertions(+), 94 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index c78042d412d..139e0a1140c 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -797,7 +797,7 @@ panfrost_upload_tex( unsigned last_layer = pview->u.tex.last_layer; /* Lower-bit is set when sampling from colour AFBC */ - bool is_afbc = rsrc->bo->layout == PAN_AFBC; + bool is_afbc = rsrc->layout == PAN_AFBC; bool is_zs = rsrc->base.bind & PIPE_BIND_DEPTH_STENCIL; unsigned afbc_bit = (is_afbc && !is_zs) ? 1 : 0; @@ -818,7 +818,7 @@ panfrost_upload_tex( if (has_manual_stride) { view->hw.payload[idx++] = - rsrc->bo->slices[l].stride; + rsrc->slices[l].stride; } } } @@ -1469,7 +1469,7 @@ panfrost_draw_wallpaper(struct pipe_context *pipe) struct panfrost_resource *rsrc = pan_resource(surf->texture); unsigned level = surf->u.tex.level; - if (!rsrc->bo->slices[level].initialized) + if (!rsrc->slices[level].initialized) return; /* Save the batch */ @@ -2203,7 +2203,7 @@ panfrost_create_sampler_view( unsigned usage2_layout = 0x10; - switch (prsrc->bo->layout) { + switch (prsrc->layout) { case PAN_AFBC: usage2_layout |= 0x8 | 0x4; break; @@ -2226,9 +2226,9 @@ panfrost_create_sampler_view( unsigned first_level = template->u.tex.first_level; unsigned last_level = template->u.tex.last_level; - if (prsrc->bo->layout == PAN_LINEAR) { + if (prsrc->layout == PAN_LINEAR) { for (unsigned l = first_level; l <= last_level; ++l) { - unsigned actual_stride = prsrc->bo->slices[l].stride; + unsigned actual_stride = prsrc->slices[l].stride; unsigned width = u_minify(texture->width0, l); unsigned comp_stride = width * bytes_per_pixel; diff --git a/src/gallium/drivers/panfrost/pan_fragment.c b/src/gallium/drivers/panfrost/pan_fragment.c index 5dbca021141..ed8677d1afd 100644 --- a/src/gallium/drivers/panfrost/pan_fragment.c +++ b/src/gallium/drivers/panfrost/pan_fragment.c @@ -36,7 +36,7 @@ panfrost_initialize_surface(struct pipe_surface *surf) unsigned level = surf->u.tex.level; struct panfrost_resource *rsrc = pan_resource(surf->texture); - rsrc->bo->slices[level].initialized = true; + rsrc->slices[level].initialized = true; } /* Generate a fragment job. This should be called once per frame. (According to diff --git a/src/gallium/drivers/panfrost/pan_mfbd.c b/src/gallium/drivers/panfrost/pan_mfbd.c index b209ecbf580..b435d20b758 100644 --- a/src/gallium/drivers/panfrost/pan_mfbd.c +++ b/src/gallium/drivers/panfrost/pan_mfbd.c @@ -128,7 +128,7 @@ panfrost_mfbd_set_cbuf( unsigned level = surf->u.tex.level; unsigned first_layer = surf->u.tex.first_layer; assert(surf->u.tex.last_layer == first_layer); - int stride = rsrc->bo->slices[level].stride; + int stride = rsrc->slices[level].stride; mali_ptr base = panfrost_get_texture_address(rsrc, level, first_layer); @@ -136,18 +136,18 @@ panfrost_mfbd_set_cbuf( /* Now, we set the layout specific pieces */ - if (rsrc->bo->layout == PAN_LINEAR) { + if (rsrc->layout == PAN_LINEAR) { rt->format.block = MALI_MFBD_BLOCK_LINEAR; rt->framebuffer = base; rt->framebuffer_stride = stride / 16; - } else if (rsrc->bo->layout == PAN_TILED) { + } else if (rsrc->layout == PAN_TILED) { rt->format.block = MALI_MFBD_BLOCK_TILED; rt->framebuffer = base; rt->framebuffer_stride = stride; - } else if (rsrc->bo->layout == PAN_AFBC) { + } else if (rsrc->layout == PAN_AFBC) { rt->format.block = MALI_MFBD_BLOCK_AFBC; - unsigned header_size = rsrc->bo->slices[level].header_size; + unsigned header_size = rsrc->slices[level].header_size; rt->framebuffer = base + header_size; rt->afbc.metadata = base; @@ -173,11 +173,11 @@ panfrost_mfbd_set_zsbuf( unsigned level = surf->u.tex.level; assert(surf->u.tex.first_layer == 0); - unsigned offset = rsrc->bo->slices[level].offset; + unsigned offset = rsrc->slices[level].offset; - if (rsrc->bo->layout == PAN_AFBC) { + if (rsrc->layout == PAN_AFBC) { mali_ptr base = rsrc->bo->gpu + offset; - unsigned header_size = rsrc->bo->slices[level].header_size; + unsigned header_size = rsrc->slices[level].header_size; fb->mfbd_flags |= MALI_MFBD_EXTRA; @@ -194,8 +194,8 @@ panfrost_mfbd_set_zsbuf( fbx->ds_afbc.zero1 = 0x10009; fbx->ds_afbc.padding = 0x1000; - } else if (rsrc->bo->layout == PAN_LINEAR) { - int stride = rsrc->bo->slices[level].stride; + } else if (rsrc->layout == PAN_LINEAR) { + int stride = rsrc->slices[level].stride; fb->mfbd_flags |= MALI_MFBD_EXTRA; fbx->flags |= MALI_EXTRA_PRESENT | MALI_EXTRA_ZS | 0x1; @@ -328,9 +328,9 @@ panfrost_mfbd_fragment(struct panfrost_context *ctx, bool has_draws) struct panfrost_resource *rsrc = pan_resource(surf->texture); struct panfrost_bo *bo = rsrc->bo; - if (bo->checksummed) { + if (rsrc->checksummed) { unsigned level = surf->u.tex.level; - struct panfrost_slice *slice = &bo->slices[level]; + struct panfrost_slice *slice = &rsrc->slices[level]; fb.mfbd_flags |= MALI_MFBD_EXTRA; fbx.flags |= MALI_EXTRA_PRESENT; diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 680b98a6cac..8901aeee09b 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -71,8 +71,8 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, prsc->screen = pscreen; rsc->bo = panfrost_drm_import_bo(screen, whandle); - rsc->bo->slices[0].stride = whandle->stride; - rsc->bo->slices[0].initialized = true; + rsc->slices[0].stride = whandle->stride; + rsc->slices[0].initialized = true; if (screen->ro) { rsc->scanout = @@ -103,7 +103,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, return TRUE; handle->handle = rsrc->bo->gem_handle; - handle->stride = rsrc->bo->slices[0].stride; + handle->stride = rsrc->slices[0].stride; return TRUE; } else if (handle->type == WINSYS_HANDLE_TYPE_FD) { if (scanout) { @@ -122,7 +122,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, return TRUE; } else return panfrost_drm_export_bo(screen, rsrc->bo->gem_handle, - rsrc->bo->slices[0].stride, + rsrc->slices[0].stride, handle); } @@ -237,12 +237,13 @@ panfrost_compute_checksum_sizes( /* Setup the mip tree given a particular layout, possibly with checksumming */ static void -panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo) +panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size) { - unsigned width = tmpl->width0; - unsigned height = tmpl->height0; - unsigned depth = tmpl->depth0; - unsigned bytes_per_pixel = util_format_get_blocksize(tmpl->format); + struct pipe_resource *res = &pres->base; + unsigned width = res->width0; + unsigned height = res->height0; + unsigned depth = res->depth0; + unsigned bytes_per_pixel = util_format_get_blocksize(res->format); assert(depth > 0); @@ -251,24 +252,24 @@ panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo) * necessary, but we're not *that* pressed for memory and it * makes code a lot simpler */ - bool renderable = tmpl->bind & + bool renderable = res->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL); - bool afbc = bo->layout == PAN_AFBC; - bool tiled = bo->layout == PAN_TILED; + bool afbc = pres->layout == PAN_AFBC; + bool tiled = pres->layout == PAN_TILED; bool should_align = renderable || tiled; /* We don't know how to specify a 2D stride for 3D textures */ bool can_align_stride = - tmpl->target != PIPE_TEXTURE_3D; + res->target != PIPE_TEXTURE_3D; should_align &= can_align_stride; unsigned offset = 0; unsigned size_2d = 0; - for (unsigned l = 0; l <= tmpl->last_level; ++l) { - struct panfrost_slice *slice = &bo->slices[l]; + for (unsigned l = 0; l <= res->last_level; ++l) { + struct panfrost_slice *slice = &pres->slices[l]; unsigned effective_width = width; unsigned effective_height = height; @@ -287,7 +288,7 @@ panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo) unsigned stride = bytes_per_pixel * effective_width; /* ..but cache-line align it for performance */ - if (can_align_stride && bo->layout == PAN_LINEAR) + if (can_align_stride && pres->layout == PAN_LINEAR) stride = ALIGN(stride, 64); slice->stride = stride; @@ -311,7 +312,7 @@ panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo) offset += slice_full_size; /* Add a checksum region if necessary */ - if (bo->checksummed) { + if (pres->checksummed) { slice->checksum_offset = offset; unsigned size = panfrost_compute_checksum_sizes( @@ -325,27 +326,26 @@ panfrost_setup_slices(const struct pipe_resource *tmpl, struct panfrost_bo *bo) depth = u_minify(depth, 1); } - assert(tmpl->array_size); + assert(res->array_size); - if (tmpl->target != PIPE_TEXTURE_3D) { + if (res->target != PIPE_TEXTURE_3D) { /* Arrays and cubemaps have the entire miptree duplicated */ - bo->cubemap_stride = ALIGN(offset, 64); - bo->size = ALIGN(bo->cubemap_stride * tmpl->array_size, 4096); + pres->cubemap_stride = ALIGN(offset, 64); + *bo_size = ALIGN(pres->cubemap_stride * res->array_size, 4096); } else { /* 3D strides across the 2D layers */ - assert(tmpl->array_size == 1); + assert(res->array_size == 1); - bo->cubemap_stride = size_2d; - bo->size = ALIGN(offset, 4096); + pres->cubemap_stride = size_2d; + *bo_size = ALIGN(offset, 4096); } } -static struct panfrost_bo * -panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *template) +static void +panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_resource *pres) { - struct panfrost_bo *bo = rzalloc(screen, struct panfrost_bo); - pipe_reference_init(&bo->reference, 1); + struct pipe_resource *res = &pres->base; /* Based on the usage, figure out what storing will be used. There are * various tradeoffs: @@ -364,35 +364,39 @@ panfrost_create_bo(struct panfrost_screen *screen, const struct pipe_resource *t /* Tiling textures is almost always faster, unless we only use it once */ - bool is_texture = (template->bind & PIPE_BIND_SAMPLER_VIEW); - bool is_2d = template->depth0 == 1 && template->array_size == 1; - bool is_streaming = (template->usage != PIPE_USAGE_STREAM); + bool is_texture = (res->bind & PIPE_BIND_SAMPLER_VIEW); + bool is_2d = res->depth0 == 1 && res->array_size == 1; + bool is_streaming = (res->usage != PIPE_USAGE_STREAM); bool should_tile = is_streaming && is_texture && is_2d; /* Depth/stencil can't be tiled, only linear or AFBC */ - should_tile &= !(template->bind & PIPE_BIND_DEPTH_STENCIL); + should_tile &= !(res->bind & PIPE_BIND_DEPTH_STENCIL); /* FBOs we would like to checksum, if at all possible */ - bool can_checksum = !(template->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)); - bool should_checksum = template->bind & PIPE_BIND_RENDER_TARGET; + bool can_checksum = !(res->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)); + bool should_checksum = res->bind & PIPE_BIND_RENDER_TARGET; - bo->checksummed = can_checksum && should_checksum; + pres->checksummed = can_checksum && should_checksum; /* Set the layout appropriately */ - bo->layout = should_tile ? PAN_TILED : PAN_LINEAR; + pres->layout = should_tile ? PAN_TILED : PAN_LINEAR; + + size_t bo_size; - panfrost_setup_slices(template, bo); + panfrost_setup_slices(pres, &bo_size); struct panfrost_memory mem; + struct panfrost_bo *bo = rzalloc(screen, struct panfrost_bo); - panfrost_drm_allocate_slab(screen, &mem, bo->size / 4096, true, 0, 0, 0); + pipe_reference_init(&bo->reference, 1); + panfrost_drm_allocate_slab(screen, &mem, bo_size / 4096, true, 0, 0, 0); bo->cpu = mem.cpu; bo->gpu = mem.gpu; bo->gem_handle = mem.gem_handle; - - return bo; + bo->size = bo_size; + pres->bo = bo; } static struct pipe_resource * @@ -428,7 +432,7 @@ panfrost_resource_create(struct pipe_screen *screen, util_range_init(&so->valid_buffer_range); - so->bo = panfrost_create_bo(pscreen, template); + panfrost_resource_create_bo(pscreen, so); return (struct pipe_resource *)so; } @@ -538,7 +542,7 @@ panfrost_transfer_map(struct pipe_context *pctx, } } - if (bo->layout != PAN_LINEAR) { + if (rsrc->layout != PAN_LINEAR) { /* Non-linear resources need to be indirectly mapped */ if (usage & PIPE_TRANSFER_MAP_DIRECTLY) @@ -549,35 +553,35 @@ panfrost_transfer_map(struct pipe_context *pctx, transfer->map = rzalloc_size(transfer, transfer->base.layer_stride * box->depth); assert(box->depth == 1); - if ((usage & PIPE_TRANSFER_READ) && bo->slices[level].initialized) { - if (bo->layout == PAN_AFBC) { + if ((usage & PIPE_TRANSFER_READ) && rsrc->slices[level].initialized) { + if (rsrc->layout == PAN_AFBC) { DBG("Unimplemented: reads from AFBC"); - } else if (bo->layout == PAN_TILED) { + } else if (rsrc->layout == PAN_TILED) { panfrost_load_tiled_image( transfer->map, - bo->cpu + bo->slices[level].offset, + bo->cpu + rsrc->slices[level].offset, box, transfer->base.stride, - bo->slices[level].stride, + rsrc->slices[level].stride, util_format_get_blocksize(resource->format)); } } return transfer->map; } else { - transfer->base.stride = bo->slices[level].stride; - transfer->base.layer_stride = bo->cubemap_stride; + transfer->base.stride = rsrc->slices[level].stride; + transfer->base.layer_stride = rsrc->cubemap_stride; /* By mapping direct-write, we're implicitly already * initialized (maybe), so be conservative */ if ((usage & PIPE_TRANSFER_WRITE) && (usage & PIPE_TRANSFER_MAP_DIRECTLY)) - bo->slices[level].initialized = true; + rsrc->slices[level].initialized = true; return bo->cpu - + bo->slices[level].offset - + transfer->base.box.z * bo->cubemap_stride - + transfer->base.box.y * bo->slices[level].stride + + rsrc->slices[level].offset + + transfer->base.box.z * rsrc->cubemap_stride + + transfer->base.box.y * rsrc->slices[level].stride + transfer->base.box.x * bytes_per_pixel; } } @@ -596,18 +600,18 @@ panfrost_transfer_unmap(struct pipe_context *pctx, if (transfer->usage & PIPE_TRANSFER_WRITE) { unsigned level = transfer->level; - bo->slices[level].initialized = true; + prsrc->slices[level].initialized = true; - if (bo->layout == PAN_AFBC) { + if (prsrc->layout == PAN_AFBC) { DBG("Unimplemented: writes to AFBC\n"); - } else if (bo->layout == PAN_TILED) { + } else if (prsrc->layout == PAN_TILED) { assert(transfer->box.depth == 1); panfrost_store_tiled_image( - bo->cpu + bo->slices[level].offset, + bo->cpu + prsrc->slices[level].offset, trans->map, &transfer->box, - bo->slices[level].stride, + prsrc->slices[level].stride, transfer->stride, util_format_get_blocksize(prsrc->base.format)); } @@ -719,7 +723,7 @@ panfrost_generate_mipmap( assert(rsrc->bo); for (unsigned l = base_level + 1; l <= last_level; ++l) - rsrc->bo->slices[l].initialized = false; + rsrc->slices[l].initialized = false; /* Beyond that, we just delegate the hard stuff. We're careful to * include flushes on both ends to make sure the data is really valid. @@ -757,8 +761,8 @@ panfrost_get_texture_address( struct panfrost_resource *rsrc, unsigned level, unsigned face) { - unsigned level_offset = rsrc->bo->slices[level].offset; - unsigned face_offset = face * rsrc->bo->cubemap_stride; + unsigned level_offset = rsrc->slices[level].offset; + unsigned face_offset = face * rsrc->cubemap_stride; return rsrc->bo->gpu + level_offset + face_offset; } diff --git a/src/gallium/drivers/panfrost/pan_resource.h b/src/gallium/drivers/panfrost/pan_resource.h index 003211b8c4a..d1f0ffc84e1 100644 --- a/src/gallium/drivers/panfrost/pan_resource.h +++ b/src/gallium/drivers/panfrost/pan_resource.h @@ -60,9 +60,6 @@ struct panfrost_slice { struct panfrost_bo { struct pipe_reference reference; - /* Description of the mip levels */ - struct panfrost_slice slices[MAX_MIP_LEVELS]; - /* Mapping for the entire object (all levels) */ uint8_t *cpu; @@ -72,15 +69,6 @@ struct panfrost_bo { /* Size of all entire trees */ size_t size; - /* Distance from tree to tree */ - unsigned cubemap_stride; - - /* Internal layout (tiled?) */ - enum panfrost_memory_layout layout; - - /* Is transaciton elimination enabled? */ - bool checksummed; - int gem_handle; }; @@ -99,6 +87,18 @@ struct panfrost_resource { struct panfrost_resource *separate_stencil; struct util_range valid_buffer_range; + + /* Description of the mip levels */ + struct panfrost_slice slices[MAX_MIP_LEVELS]; + + /* Distance from tree to tree */ + unsigned cubemap_stride; + + /* Internal layout (tiled?) */ + enum panfrost_memory_layout layout; + + /* Is transaciton elimination enabled? */ + bool checksummed; }; static inline struct panfrost_resource * diff --git a/src/gallium/drivers/panfrost/pan_sfbd.c b/src/gallium/drivers/panfrost/pan_sfbd.c index c9b0414b50c..eccae888e82 100644 --- a/src/gallium/drivers/panfrost/pan_sfbd.c +++ b/src/gallium/drivers/panfrost/pan_sfbd.c @@ -91,11 +91,11 @@ panfrost_sfbd_set_cbuf( { struct panfrost_resource *rsrc = pan_resource(surf->texture); - signed stride = rsrc->bo->slices[0].stride; + signed stride = rsrc->slices[0].stride; fb->format = panfrost_sfbd_format(surf); - if (rsrc->bo->layout == PAN_LINEAR) { + if (rsrc->layout == PAN_LINEAR) { fb->framebuffer = rsrc->bo->gpu; fb->stride = stride; } else { -- 2.30.2