X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fdrivers%2Ffreedreno%2Ffreedreno_resource.c;h=8147ff57a990c880303f2c0b804e88fa885ae5c8;hb=a331d7d1cdfdc971f707fb6b1f71edbad622c804;hp=e1375d24837ef8dd2f654274ad3995620db24c4b;hpb=d848bee50faa98af493975c28377712c04d72277;p=mesa.git diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index e1375d24837..8147ff57a99 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -121,7 +121,7 @@ do_blit(struct fd_context *ctx, const struct pipe_blit_info *blit, bool fallback if (!fallback) { /* do blit on gpu: */ fd_blitter_pipe_begin(ctx, false, true, FD_STAGE_BLIT); - util_blitter_blit(ctx->blitter, blit); + ctx->blit(ctx, blit); fd_blitter_pipe_end(ctx); } else { /* do blit on cpu: */ @@ -290,6 +290,7 @@ fd_alloc_staging(struct fd_context *ctx, struct fd_resource *rsc, tmpl.depth0 = box->depth; tmpl.array_size = 1; tmpl.last_level = 0; + tmpl.bind |= PIPE_BIND_LINEAR; struct pipe_resource *pstaging = pctx->screen->resource_create(pctx->screen, &tmpl); @@ -300,7 +301,7 @@ fd_alloc_staging(struct fd_context *ctx, struct fd_resource *rsc, } static void -fd_blit_staging(struct fd_context *ctx, struct fd_transfer *trans) +fd_blit_from_staging(struct fd_context *ctx, struct fd_transfer *trans) { struct pipe_resource *dst = trans->base.resource; struct pipe_blit_info blit = {0}; @@ -317,7 +318,26 @@ fd_blit_staging(struct fd_context *ctx, struct fd_transfer *trans) blit.filter = PIPE_TEX_FILTER_NEAREST; do_blit(ctx, &blit, false); - pipe_resource_reference(&trans->staging_prsc, NULL); +} + +static void +fd_blit_to_staging(struct fd_context *ctx, struct fd_transfer *trans) +{ + struct pipe_resource *src = trans->base.resource; + struct pipe_blit_info blit = {0}; + + blit.src.resource = src; + blit.src.format = src->format; + blit.src.level = trans->base.level; + blit.src.box = trans->base.box; + blit.dst.resource = trans->staging_prsc; + blit.dst.format = trans->staging_prsc->format; + blit.dst.level = 0; + blit.dst.box = trans->staging_box; + blit.mask = util_format_get_mask(trans->staging_prsc->format); + blit.filter = PIPE_TEX_FILTER_NEAREST; + + do_blit(ctx, &blit, false); } static unsigned @@ -396,8 +416,11 @@ fd_resource_transfer_unmap(struct pipe_context *pctx, struct fd_resource *rsc = fd_resource(ptrans->resource); struct fd_transfer *trans = fd_transfer(ptrans); - if (trans->staging_prsc) - fd_blit_staging(ctx, trans); + if (trans->staging_prsc) { + if (ptrans->usage & PIPE_TRANSFER_WRITE) + fd_blit_from_staging(ctx, trans); + pipe_resource_reference(&trans->staging_prsc, NULL); + } if (!(ptrans->usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { fd_bo_cpu_fini(rsc->bo); @@ -447,6 +470,44 @@ fd_resource_transfer_map(struct pipe_context *pctx, ptrans->stride = util_format_get_nblocksx(format, slice->pitch) * rsc->cpp; ptrans->layer_stride = rsc->layer_first ? rsc->layer_size : slice->size0; + /* we always need a staging texture for tiled buffers: + * + * TODO we might sometimes want to *also* shadow the resource to avoid + * splitting a batch.. for ex, mid-frame texture uploads to a tiled + * texture. + */ + if (rsc->tile_mode) { + struct fd_resource *staging_rsc; + + staging_rsc = fd_alloc_staging(ctx, rsc, level, box); + if (staging_rsc) { + // TODO for PIPE_TRANSFER_READ, need to do untiling blit.. + trans->staging_prsc = &staging_rsc->base; + trans->base.stride = util_format_get_nblocksx(format, + staging_rsc->slices[0].pitch) * staging_rsc->cpp; + trans->base.layer_stride = staging_rsc->layer_first ? + staging_rsc->layer_size : staging_rsc->slices[0].size0; + trans->staging_box = *box; + trans->staging_box.x = 0; + trans->staging_box.y = 0; + trans->staging_box.z = 0; + + if (usage & PIPE_TRANSFER_READ) { + fd_blit_to_staging(ctx, trans); + fd_bo_cpu_prep(rsc->bo, ctx->pipe, DRM_FREEDRENO_PREP_READ); + } + + buf = fd_bo_map(staging_rsc->bo); + offset = 0; + + *pptrans = ptrans; + + ctx->stats.staging_uploads++; + + return buf; + } + } + if (ctx->in_shadow && !(usage & PIPE_TRANSFER_READ)) usage |= PIPE_TRANSFER_UNSYNCHRONIZED; @@ -500,6 +561,7 @@ fd_resource_transfer_map(struct pipe_context *pctx, if (needs_flush && fd_try_shadow_resource(ctx, rsc, level, box)) { needs_flush = busy = false; rebind_resource(ctx, prsc); + ctx->stats.shadow_uploads++; } else { struct fd_resource *staging_rsc; @@ -531,6 +593,8 @@ fd_resource_transfer_map(struct pipe_context *pctx, fd_batch_reference(&write_batch, NULL); + ctx->stats.staging_uploads++; + return buf; } } @@ -613,9 +677,6 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma */ uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size; - if (is_a5xx(screen) && (rsc->base.target >= PIPE_TEXTURE_2D)) - height = align(height, screen->gmem_alignh); - for (level = 0; level <= prsc->last_level; level++) { struct fd_resource_slice *slice = fd_resource_slice(rsc, level); uint32_t blocks; @@ -653,12 +714,12 @@ setup_slices(struct fd_resource *rsc, uint32_t alignment, enum pipe_format forma } static uint32_t -slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) +slice_alignment(enum pipe_texture_target target) { /* on a3xx, 2d array and 3d textures seem to want their * layers aligned to page boundaries: */ - switch (tmpl->target) { + switch (target) { case PIPE_TEXTURE_3D: case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: @@ -668,6 +729,36 @@ slice_alignment(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) } } +/* cross generation texture layout to plug in to screen->setup_slices().. + * replace with generation specific one as-needed. + * + * TODO for a4xx probably can extract out the a4xx specific logic int + * a small fd4_setup_slices() wrapper that sets up layer_first, and then + * calls this. + */ +uint32_t +fd_setup_slices(struct fd_resource *rsc) +{ + uint32_t alignment; + + alignment = slice_alignment(rsc->base.target); + + struct fd_screen *screen = fd_screen(rsc->base.screen); + if (is_a4xx(screen)) { + switch (rsc->base.target) { + case PIPE_TEXTURE_3D: + rsc->layer_first = false; + break; + default: + rsc->layer_first = true; + alignment = 1; + break; + } + } + + return setup_slices(rsc, alignment, rsc->base.format); +} + /* special case to resize query buf after allocated.. */ void fd_resource_resize(struct pipe_resource *prsc, uint32_t sz) @@ -679,7 +770,7 @@ fd_resource_resize(struct pipe_resource *prsc, uint32_t sz) debug_assert(prsc->bind == PIPE_BIND_QUERY_BUFFER); prsc->width0 = sz; - realloc_bo(rsc, setup_slices(rsc, 1, prsc->format)); + realloc_bo(rsc, fd_screen(prsc->screen)->setup_slices(rsc)); } // TODO common helper? @@ -712,7 +803,7 @@ fd_resource_create(struct pipe_screen *pscreen, struct fd_resource *rsc = CALLOC_STRUCT(fd_resource); struct pipe_resource *prsc = &rsc->base; enum pipe_format format = tmpl->format; - uint32_t size, alignment; + uint32_t size; DBG("%p: target=%d, format=%s, %ux%ux%u, array_size=%u, last_level=%u, " "nr_samples=%u, usage=%u, bind=%x, flags=%x", prsc, @@ -726,6 +817,18 @@ fd_resource_create(struct pipe_screen *pscreen, *prsc = *tmpl; +#define LINEAR \ + (PIPE_BIND_SCANOUT | \ + PIPE_BIND_LINEAR | \ + PIPE_BIND_DISPLAY_TARGET) + + if (screen->tile_mode && + (tmpl->target != PIPE_BUFFER) && + (tmpl->bind & PIPE_BIND_SAMPLER_VIEW) && + !(tmpl->bind & LINEAR)) { + rsc->tile_mode = screen->tile_mode(tmpl); + } + pipe_reference_init(&prsc->reference, 1); prsc->screen = pscreen; @@ -734,6 +837,8 @@ fd_resource_create(struct pipe_screen *pscreen, rsc->internal_format = format; rsc->cpp = util_format_get_blocksize(format); + prsc->nr_samples = MAX2(1, prsc->nr_samples); + rsc->cpp *= prsc->nr_samples; assert(rsc->cpp); @@ -753,20 +858,7 @@ fd_resource_create(struct pipe_screen *pscreen, rsc->lrz = fd_bo_new(screen->dev, size, flags); } - alignment = slice_alignment(pscreen, tmpl); - if (is_a4xx(screen) || is_a5xx(screen)) { - switch (tmpl->target) { - case PIPE_TEXTURE_3D: - rsc->layer_first = false; - break; - default: - rsc->layer_first = true; - alignment = 1; - break; - } - } - - size = setup_slices(rsc, alignment, format); + size = screen->setup_slices(rsc); /* special case for hw-query buffer, which we need to allocate before we * know the size: @@ -829,7 +921,9 @@ fd_resource_from_handle(struct pipe_screen *pscreen, if (!rsc->bo) goto fail; - rsc->cpp = util_format_get_blocksize(tmpl->format); + prsc->nr_samples = MAX2(1, prsc->nr_samples); + rsc->internal_format = tmpl->format; + rsc->cpp = prsc->nr_samples * util_format_get_blocksize(tmpl->format); slice->pitch = handle->stride / rsc->cpp; slice->offset = handle->offset; slice->size0 = handle->stride * prsc->height0; @@ -939,14 +1033,6 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) struct pipe_blit_info info = *blit_info; bool discard = false; - if (info.src.resource->nr_samples > 1 && - info.dst.resource->nr_samples <= 1 && - !util_format_is_depth_or_stencil(info.src.resource->format) && - !util_format_is_pure_integer(info.src.resource->format)) { - DBG("color resolve unimplemented"); - return; - } - if (info.render_condition_enable && !fd_render_condition_check(pctx)) return; @@ -974,7 +1060,7 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) } fd_blitter_pipe_begin(ctx, info.render_condition_enable, discard, FD_STAGE_BLIT); - util_blitter_blit(ctx->blitter, &info); + ctx->blit(ctx, &info); fd_blitter_pipe_end(ctx); } @@ -1087,7 +1173,8 @@ static const struct u_transfer_vtbl transfer_vtbl = { void fd_resource_screen_init(struct pipe_screen *pscreen) { - bool fake_rgtc = fd_screen(pscreen)->gpu_id < 400; + struct fd_screen *screen = fd_screen(pscreen); + bool fake_rgtc = screen->gpu_id < 400; pscreen->resource_create = u_transfer_helper_resource_create; pscreen->resource_from_handle = fd_resource_from_handle; @@ -1096,6 +1183,9 @@ fd_resource_screen_init(struct pipe_screen *pscreen) pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, fake_rgtc, true); + + if (!screen->setup_slices) + screen->setup_slices = fd_setup_slices; } void