X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fpanfrost%2Fpan_resource.c;h=6eeb4b832ed3d829bd2aa845773357858acf6b19;hb=4c52e16c9c296988dea283164622373caaf228e5;hp=97ab2f9d9a4ecda0fda5566562b6b45462d7a8c1;hpb=154cb725d4a14d3d0360ee240665dd87281043cd;p=mesa.git diff --git a/src/gallium/drivers/panfrost/pan_resource.c b/src/gallium/drivers/panfrost/pan_resource.c index 97ab2f9d9a4..6eeb4b832ed 100644 --- a/src/gallium/drivers/panfrost/pan_resource.c +++ b/src/gallium/drivers/panfrost/pan_resource.c @@ -34,7 +34,7 @@ #include "drm-uapi/drm_fourcc.h" #include "state_tracker/winsys_handle.h" -#include "util/u_format.h" +#include "util/format/u_format.h" #include "util/u_memory.h" #include "util/u_surface.h" #include "util/u_transfer.h" @@ -47,8 +47,9 @@ #include "pan_resource.h" #include "pan_util.h" #include "pan_tiling.h" +#include "panfrost-quirks.h" -static void +void panfrost_resource_reset_damage(struct panfrost_resource *pres) { /* We set the damage extent to the full resource size but keep the @@ -83,7 +84,9 @@ panfrost_resource_from_handle(struct pipe_screen *pscreen, prsc->screen = pscreen; rsc->bo = panfrost_bo_import(screen, whandle->handle); + rsc->internal_format = templat->format; rsc->slices[0].stride = whandle->stride; + rsc->slices[0].offset = whandle->offset; rsc->slices[0].initialized = true; panfrost_resource_reset_damage(rsc); @@ -117,6 +120,7 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, handle->handle = rsrc->bo->gem_handle; handle->stride = rsrc->slices[0].stride; + handle->offset = rsrc->slices[0].offset; return TRUE; } else if (handle->type == WINSYS_HANDLE_TYPE_FD) { if (scanout) { @@ -134,13 +138,14 @@ panfrost_resource_get_handle(struct pipe_screen *pscreen, return true; } else { - int fd = panfrost_bo_export(screen, rsrc->bo); + int fd = panfrost_bo_export(rsrc->bo); if (fd < 0) return false; handle->handle = fd; handle->stride = rsrc->slices[0].stride; + handle->offset = rsrc->slices[0].offset; return true; } } @@ -310,6 +315,9 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size) /* Compute the would-be stride */ unsigned stride = bytes_per_pixel * effective_width; + if (util_format_is_compressed(res->format)) + stride /= 4; + /* ..but cache-line align it for performance */ if (can_align_stride && pres->layout == PAN_LINEAR) stride = ALIGN_POT(stride, 64); @@ -319,6 +327,8 @@ panfrost_setup_slices(struct panfrost_resource *pres, size_t *bo_size) unsigned slice_one_size = slice->stride * effective_height; unsigned slice_full_size = slice_one_size * effective_depth; + slice->size0 = slice_one_size; + /* Report 2D size for 3D texturing */ if (l == 0) @@ -383,29 +393,34 @@ panfrost_resource_create_bo(struct panfrost_screen *screen, struct panfrost_reso * AFBC: Compressed and renderable (so always desirable for non-scanout * rendertargets). Cheap to sample from. The format is black box, so we * can't read/write from software. - */ - - /* Tiling textures is almost always faster, unless we only use it once */ - - 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); - - /* TODO: Reenable tiling on SFBD systems when we support rendering to - * tiled formats with SFBD */ - bool should_tile = is_streaming && is_texture && is_2d && !screen->require_sfbd; - - /* Depth/stencil can't be tiled, only linear or AFBC */ - should_tile &= !(res->bind & PIPE_BIND_DEPTH_STENCIL); + * + * Tiling textures is almost always faster, unless we only use it once. + * Only a few types of resources can be tiled, ensure the bind is only + * (a combination of) one of the following */ + + const unsigned valid_binding = + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLENDABLE | + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET; + + unsigned bpp = util_format_get_blocksizebits(res->format); + bool is_2d = (res->target == PIPE_TEXTURE_2D); + bool is_sane_bpp = bpp == 8 || bpp == 16 || bpp == 32 || bpp == 64 || bpp == 128; + bool should_tile = (res->usage != PIPE_USAGE_STREAM); + bool must_tile = (res->bind & PIPE_BIND_DEPTH_STENCIL) && (screen->quirks & MIDGARD_SFBD); + bool can_tile = is_2d && is_sane_bpp && ((res->bind & ~valid_binding) == 0); /* FBOs we would like to checksum, if at all possible */ - bool can_checksum = !(res->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)); + bool can_checksum = !(res->bind & ~valid_binding); bool should_checksum = res->bind & PIPE_BIND_RENDER_TARGET; pres->checksummed = can_checksum && should_checksum; /* Set the layout appropriately */ - pres->layout = should_tile ? PAN_TILED : PAN_LINEAR; + assert(!(must_tile && !can_tile)); /* must_tile => can_tile */ + pres->layout = ((can_tile && should_tile) || must_tile) ? PAN_TILED : PAN_LINEAR; size_t bo_size; @@ -511,6 +526,7 @@ panfrost_resource_create(struct pipe_screen *screen, so->base = *template; so->base.screen = screen; + so->internal_format = template->format; pipe_reference_init(&so->base.reference, 1); @@ -533,12 +549,21 @@ panfrost_resource_destroy(struct pipe_screen *screen, renderonly_scanout_destroy(rsrc->scanout, pscreen->ro); if (rsrc->bo) - panfrost_bo_unreference(screen, rsrc->bo); + panfrost_bo_unreference(rsrc->bo); util_range_destroy(&rsrc->valid_buffer_range); ralloc_free(rsrc); } +static unsigned +panfrost_get_layer_stride(struct panfrost_resource *rsrc, unsigned level) +{ + if (rsrc->base.target == PIPE_TEXTURE_3D) + return rsrc->slices[level].size0; + else + return rsrc->cubemap_stride; +} + static void * panfrost_transfer_map(struct pipe_context *pctx, struct pipe_resource *resource, @@ -547,6 +572,7 @@ panfrost_transfer_map(struct pipe_context *pctx, const struct pipe_box *box, struct pipe_transfer **out_transfer) { + struct panfrost_context *ctx = pan_context(pctx); int bytes_per_pixel = util_format_get_blocksize(resource->format); struct panfrost_resource *rsrc = pan_resource(resource); struct panfrost_bo *bo = rsrc->bo; @@ -561,50 +587,55 @@ panfrost_transfer_map(struct pipe_context *pctx, *out_transfer = &transfer->base; /* If we haven't already mmaped, now's the time */ - - if (!bo->cpu) { - struct panfrost_screen *screen = pan_screen(pctx->screen); - panfrost_bo_mmap(screen, bo); - } - - /* Check if we're bound for rendering and this is a read pixels. If so, - * we need to flush */ - - struct panfrost_context *ctx = pan_context(pctx); - struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer; - - bool is_bound = false; - - for (unsigned c = 0; c < fb->nr_cbufs; ++c) { - /* If cbufs is NULL, we're definitely not bound here */ - - if (fb->cbufs[c]) - is_bound |= fb->cbufs[c]->texture == resource; - } - - if (is_bound && (usage & PIPE_TRANSFER_READ)) { - assert(level == 0); - panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); - } - - /* TODO: Respect usage flags */ + panfrost_bo_mmap(bo); if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) { - /* TODO: reallocate */ - //printf("debug: Missed reallocate\n"); + /* If the BO is used by one of the pending batches or if it's + * not ready yet (still accessed by one of the already flushed + * batches), we try to allocate a new one to avoid waiting. + */ + if (panfrost_pending_batches_access_bo(ctx, bo) || + !panfrost_bo_wait(bo, 0, PAN_BO_ACCESS_RW)) { + struct panfrost_screen *screen = pan_screen(pctx->screen); + /* We want the BO to be MMAPed. */ + uint32_t flags = bo->flags & ~PAN_BO_DELAY_MMAP; + struct panfrost_bo *newbo = NULL; + + /* When the BO has been imported/exported, we can't + * replace it by another one, otherwise the + * importer/exporter wouldn't see the change we're + * doing to it. + */ + if (!(bo->flags & (PAN_BO_IMPORTED | PAN_BO_EXPORTED))) + newbo = panfrost_bo_create(screen, bo->size, + flags); + + if (newbo) { + panfrost_bo_unreference(bo); + rsrc->bo = newbo; + bo = newbo; + } else { + uint32_t access = PAN_BO_ACCESS_RW; + + /* Allocation failed or was impossible, let's + * fall back on a flush+wait. + */ + panfrost_flush_batches_accessing_bo(ctx, bo, + access); + panfrost_bo_wait(bo, INT64_MAX, access); + } + } } else if ((usage & PIPE_TRANSFER_WRITE) && resource->target == PIPE_BUFFER && !util_ranges_intersect(&rsrc->valid_buffer_range, box->x, box->x + box->width)) { /* No flush for writes to uninitialized */ } else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { if (usage & PIPE_TRANSFER_WRITE) { - /* STUB: flush reading */ - //printf("debug: missed reading flush %d\n", resource->target); + panfrost_flush_batches_accessing_bo(ctx, bo, PAN_BO_ACCESS_RW); + panfrost_bo_wait(bo, INT64_MAX, PAN_BO_ACCESS_RW); } else if (usage & PIPE_TRANSFER_READ) { - /* STUB: flush writing */ - //printf("debug: missed writing flush %d (%d-%d)\n", resource->target, box->x, box->x + box->width); - } else { - /* Why are you even mapping?! */ + panfrost_flush_batches_accessing_bo(ctx, bo, PAN_BO_ACCESS_WRITE); + panfrost_bo_wait(bo, INT64_MAX, PAN_BO_ACCESS_WRITE); } } @@ -626,17 +657,17 @@ panfrost_transfer_map(struct pipe_context *pctx, panfrost_load_tiled_image( transfer->map, bo->cpu + rsrc->slices[level].offset, - box, + box->x, box->y, box->width, box->height, transfer->base.stride, rsrc->slices[level].stride, - util_format_get_blocksize(resource->format)); + resource->format); } } return transfer->map; } else { transfer->base.stride = rsrc->slices[level].stride; - transfer->base.layer_stride = rsrc->cubemap_stride; + transfer->base.layer_stride = panfrost_get_layer_stride(rsrc, level); /* By mapping direct-write, we're implicitly already * initialized (maybe), so be conservative */ @@ -646,7 +677,7 @@ panfrost_transfer_map(struct pipe_context *pctx, return bo->cpu + rsrc->slices[level].offset - + transfer->base.box.z * rsrc->cubemap_stride + + transfer->base.box.z * transfer->base.layer_stride + transfer->base.box.y * rsrc->slices[level].stride + transfer->base.box.x * bytes_per_pixel; } @@ -677,16 +708,17 @@ panfrost_transfer_unmap(struct pipe_context *pctx, panfrost_store_tiled_image( bo->cpu + prsrc->slices[transfer->level].offset, trans->map, - &transfer->box, + transfer->box.x, transfer->box.y, + transfer->box.width, transfer->box.height, prsrc->slices[transfer->level].stride, transfer->stride, - util_format_get_blocksize(prsrc->base.format)); + prsrc->base.format); } } } - util_range_add(&prsrc->valid_buffer_range, + util_range_add(&prsrc->base, &prsrc->valid_buffer_range, transfer->box.x, transfer->box.x + transfer->box.width); @@ -705,7 +737,7 @@ panfrost_transfer_flush_region(struct pipe_context *pctx, struct panfrost_resource *rsc = pan_resource(transfer->resource); if (transfer->resource->target == PIPE_BUFFER) { - util_range_add(&rsc->valid_buffer_range, + util_range_add(&rsc->base, &rsc->valid_buffer_range, transfer->box.x + box->x, transfer->box.x + box->x + box->width); } else { @@ -721,8 +753,9 @@ panfrost_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *pr } static enum pipe_format -panfrost_resource_get_internal_format(struct pipe_resource *prsrc) { - return prsrc->format; +panfrost_resource_get_internal_format(struct pipe_resource *rsrc) { + struct panfrost_resource *prsrc = (struct panfrost_resource *) rsrc; + return prsrc->internal_format; } static bool @@ -752,11 +785,8 @@ panfrost_generate_mipmap( * reorder-type optimizations in place. But for now prioritize * correctness. */ - struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); - bool has_draws = batch->last_job.gpu; - - if (has_draws) - panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); + panfrost_flush_batches_accessing_bo(ctx, rsrc->bo, PAN_BO_ACCESS_RW); + panfrost_bo_wait(rsrc->bo, INT64_MAX, PAN_BO_ACCESS_RW); /* We've flushed the original buffer if needed, now trigger a blit */ @@ -769,8 +799,10 @@ panfrost_generate_mipmap( /* If the blit was successful, flush once more. If it wasn't, well, let * the state tracker deal with it. */ - if (blit_res) - panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME); + if (blit_res) { + panfrost_flush_batches_accessing_bo(ctx, rsrc->bo, PAN_BO_ACCESS_WRITE); + panfrost_bo_wait(rsrc->bo, INT64_MAX, PAN_BO_ACCESS_WRITE); + } return blit_res; } @@ -783,7 +815,7 @@ panfrost_get_texture_address( unsigned level, unsigned face) { unsigned level_offset = rsrc->slices[level].offset; - unsigned face_offset = face * rsrc->cubemap_stride; + unsigned face_offset = face * panfrost_get_layer_stride(rsrc, level); return rsrc->bo->gpu + level_offset + face_offset; } @@ -843,7 +875,7 @@ panfrost_resource_hint_layout( /* If we grew in size, reallocate the BO */ if (new_size > rsrc->bo->size) { - panfrost_bo_release(screen, rsrc->bo, true); + panfrost_bo_unreference(rsrc->bo); rsrc->bo = panfrost_bo_create(screen, new_size, PAN_BO_DELAY_MMAP); } }