On Tue, Jun 26, 2012 at 7:34 PM, Vadim Girlin <vadimgir...@gmail.com> wrote: > Use r600_resource_texture::flished_depth_texture for GPU access, and > allocate it in the VRAM. For transfers we'll allocate untiled texture in the > GTT and store it in the r600_transfer::staging. > > Improves performance when flushed depth texture is frequently used by the > GPU (about 30% for Lightsmark). > > Signed-off-by: Vadim Girlin <vadimgir...@gmail.com> > --- > > Fixes fbo-clear-formats, fbo-generatemipmap-formats, no regressions on > evergreen
This looks similar to Fredrik's patch: http://people.freedesktop.org/~fredrik/0001-r600g-be-smarter-about-domain-selection-for-depth-te.patch Although I think your patch cleans things up a bit nicer. Alex > > src/gallium/drivers/r600/evergreen_state.c | 5 +- > src/gallium/drivers/r600/r600_blit.c | 21 +++--- > src/gallium/drivers/r600/r600_pipe.h | 4 +- > src/gallium/drivers/r600/r600_resource.h | 6 +- > src/gallium/drivers/r600/r600_state.c | 2 +- > src/gallium/drivers/r600/r600_texture.c | 106 > ++++++++++++++++------------ > 6 files changed, 83 insertions(+), 61 deletions(-) > > diff --git a/src/gallium/drivers/r600/evergreen_state.c > b/src/gallium/drivers/r600/evergreen_state.c > index f0fdd2b..2aa5ccb 100644 > --- a/src/gallium/drivers/r600/evergreen_state.c > +++ b/src/gallium/drivers/r600/evergreen_state.c > @@ -988,7 +988,7 @@ static struct pipe_sampler_view > *evergreen_create_sampler_view(struct pipe_conte > } > > if (tmp->is_depth && !tmp->is_flushing_texture) { > - r600_init_flushed_depth_texture(ctx, texture); > + r600_init_flushed_depth_texture(ctx, texture, NULL); > tmp = tmp->flushed_depth_texture; > if (!tmp) { > FREE(view); > @@ -1314,7 +1314,8 @@ static void evergreen_cb(struct r600_context *rctx, > struct r600_pipe_state *rsta > rctx->have_depth_fb = TRUE; > > if (rtex->is_depth && !rtex->is_flushing_texture) { > - r600_init_flushed_depth_texture(&rctx->context, > state->cbufs[cb]->texture); > + r600_init_flushed_depth_texture(&rctx->context, > + state->cbufs[cb]->texture, NULL); > rtex = rtex->flushed_depth_texture; > assert(rtex); > } > diff --git a/src/gallium/drivers/r600/r600_blit.c > b/src/gallium/drivers/r600/r600_blit.c > index 031cd39..90d1992 100644 > --- a/src/gallium/drivers/r600/r600_blit.c > +++ b/src/gallium/drivers/r600/r600_blit.c > @@ -114,13 +114,17 @@ static unsigned u_num_layers(struct pipe_resource *r, > unsigned level) > } > } > > -void r600_blit_uncompress_depth(struct pipe_context *ctx, struct > r600_resource_texture *texture) > +void r600_blit_uncompress_depth(struct pipe_context *ctx, > + struct r600_resource_texture *texture, > + struct r600_resource_texture *staging) > { > struct r600_context *rctx = (struct r600_context *)ctx; > unsigned layer, level; > float depth = 1.0f; > + struct r600_resource_texture *flushed_depth_texture = staging ? > + staging : texture->flushed_depth_texture; > > - if (!texture->dirty_db) > + if (!staging && !texture->dirty_db) > return; > > if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || > @@ -141,10 +145,10 @@ void r600_blit_uncompress_depth(struct pipe_context > *ctx, struct r600_resource_t > > zsurf = ctx->create_surface(ctx, > &texture->resource.b.b, &surf_tmpl); > > - surf_tmpl.format = > texture->flushed_depth_texture->real_format; > + surf_tmpl.format = flushed_depth_texture->real_format; > surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; > cbsurf = ctx->create_surface(ctx, > - (struct > pipe_resource*)texture->flushed_depth_texture, &surf_tmpl); > + (struct > pipe_resource*)flushed_depth_texture, &surf_tmpl); > > r600_blitter_begin(ctx, R600_DECOMPRESS); > util_blitter_custom_depth_stencil(rctx->blitter, > zsurf, cbsurf, rctx->custom_dsa_flush, depth); > @@ -155,7 +159,8 @@ void r600_blit_uncompress_depth(struct pipe_context *ctx, > struct r600_resource_t > } > } > > - texture->dirty_db = FALSE; > + if (!staging) > + texture->dirty_db = FALSE; > } > > void r600_flush_depth_textures(struct r600_context *rctx) > @@ -178,7 +183,7 @@ void r600_flush_depth_textures(struct r600_context *rctx) > if (tex->is_flushing_texture) > continue; > > - r600_blit_uncompress_depth(&rctx->context, tex); > + r600_blit_uncompress_depth(&rctx->context, tex, NULL); > } > > /* also check CB here */ > @@ -192,7 +197,7 @@ void r600_flush_depth_textures(struct r600_context *rctx) > if (tex->is_flushing_texture) > continue; > > - r600_blit_uncompress_depth(&rctx->context, tex); > + r600_blit_uncompress_depth(&rctx->context, tex, NULL); > } > } > > @@ -342,7 +347,7 @@ static void r600_resource_copy_region(struct pipe_context > *ctx, > } > > if (rsrc->is_depth && !rsrc->is_flushing_texture) > - r600_texture_depth_flush(ctx, src); > + r600_texture_depth_flush(ctx, src, NULL); > > restore_orig[0] = restore_orig[1] = FALSE; > > diff --git a/src/gallium/drivers/r600/r600_pipe.h > b/src/gallium/drivers/r600/r600_pipe.h > index 82c4a12..032a6ec 100644 > --- a/src/gallium/drivers/r600/r600_pipe.h > +++ b/src/gallium/drivers/r600/r600_pipe.h > @@ -426,7 +426,9 @@ void evergreen_update_dual_export_state(struct > r600_context * rctx); > > /* r600_blit.c */ > void r600_init_blit_functions(struct r600_context *rctx); > -void r600_blit_uncompress_depth(struct pipe_context *ctx, struct > r600_resource_texture *texture); > +void r600_blit_uncompress_depth(struct pipe_context *ctx, > + struct r600_resource_texture *texture, > + struct r600_resource_texture *staging); > void r600_flush_depth_textures(struct r600_context *rctx); > > /* r600_buffer.c */ > diff --git a/src/gallium/drivers/r600/r600_resource.h > b/src/gallium/drivers/r600/r600_resource.h > index 13fce00..c02fae1 100644 > --- a/src/gallium/drivers/r600/r600_resource.h > +++ b/src/gallium/drivers/r600/r600_resource.h > @@ -88,9 +88,11 @@ static INLINE struct r600_resource *r600_resource(struct > pipe_resource *r) > } > > void r600_init_flushed_depth_texture(struct pipe_context *ctx, > - struct pipe_resource *texture); > + struct pipe_resource *texture, > + struct r600_resource_texture **staging); > void r600_texture_depth_flush(struct pipe_context *ctx, > - struct pipe_resource *texture); > + struct pipe_resource *texture, > + struct r600_resource_texture **staging); > > /* r600_texture.c texture transfer functions. */ > struct pipe_transfer* r600_texture_get_transfer(struct pipe_context *ctx, > diff --git a/src/gallium/drivers/r600/r600_state.c > b/src/gallium/drivers/r600/r600_state.c > index bb72bf8..96344fe 100644 > --- a/src/gallium/drivers/r600/r600_state.c > +++ b/src/gallium/drivers/r600/r600_state.c > @@ -1000,7 +1000,7 @@ static struct pipe_sampler_view > *r600_create_sampler_view(struct pipe_context *c > } > > if (tmp->is_depth && !tmp->is_flushing_texture) { > - r600_init_flushed_depth_texture(ctx, texture); > + r600_init_flushed_depth_texture(ctx, texture, NULL); > tmp = tmp->flushed_depth_texture; > if (!tmp) { > FREE(view); > diff --git a/src/gallium/drivers/r600/r600_texture.c > b/src/gallium/drivers/r600/r600_texture.c > index 2368126..e24fcb3 100644 > --- a/src/gallium/drivers/r600/r600_texture.c > +++ b/src/gallium/drivers/r600/r600_texture.c > @@ -298,7 +298,8 @@ static int r600_init_surface(struct radeon_surface > *surface, > if (ptex->bind & PIPE_BIND_SCANOUT) { > surface->flags |= RADEON_SURF_SCANOUT; > } > - if (util_format_is_depth_and_stencil(ptex->format) && !is_transfer) { > + if ((ptex->bind & PIPE_BIND_DEPTH_STENCIL) && > + util_format_is_depth_and_stencil(ptex->format) && > !is_transfer) { > surface->flags |= RADEON_SURF_ZBUFFER; > surface->flags |= RADEON_SURF_SBUFFER; > } > @@ -517,7 +518,7 @@ r600_texture_create_object(struct pipe_screen *screen, > rtex->real_format = base->format; > > /* We must split depth and stencil into two separate buffers on > Evergreen. */ > - if (!(base->flags & R600_RESOURCE_FLAG_TRANSFER) && > + if ((base->bind & PIPE_BIND_DEPTH_STENCIL) && > ((struct r600_screen*)screen)->chip_class >= EVERGREEN && > util_format_is_depth_and_stencil(base->format) && > !rscreen->use_surface_alloc) { > @@ -561,7 +562,8 @@ r600_texture_create_object(struct pipe_screen *screen, > } > > /* only mark depth textures the HW can hit as depth textures */ > - if (util_format_is_depth_or_stencil(rtex->real_format) && > permit_hardware_blit(screen, base)) > + if (util_format_is_depth_or_stencil(rtex->real_format) && > + permit_hardware_blit(screen, base)) > rtex->is_depth = true; > > r600_setup_miptree(screen, rtex, array_mode); > @@ -729,12 +731,15 @@ struct pipe_resource *r600_texture_from_handle(struct > pipe_screen *screen, > } > > void r600_init_flushed_depth_texture(struct pipe_context *ctx, > - struct pipe_resource *texture) > + struct pipe_resource *texture, > + struct r600_resource_texture **staging) > { > struct r600_resource_texture *rtex = (struct > r600_resource_texture*)texture; > struct pipe_resource resource; > + struct r600_resource_texture **flushed_depth_texture = staging ? > + staging : &rtex->flushed_depth_texture; > > - if (rtex->flushed_depth_texture) > + if (!staging && rtex->flushed_depth_texture) > return; /* it's ready */ > > resource.target = texture->target; > @@ -745,32 +750,44 @@ void r600_init_flushed_depth_texture(struct > pipe_context *ctx, > resource.array_size = texture->array_size; > resource.last_level = texture->last_level; > resource.nr_samples = texture->nr_samples; > - resource.usage = PIPE_USAGE_DYNAMIC; > - resource.bind = texture->bind | PIPE_BIND_DEPTH_STENCIL; > - resource.flags = R600_RESOURCE_FLAG_TRANSFER | texture->flags; > + resource.usage = staging ? PIPE_USAGE_DYNAMIC : PIPE_USAGE_DEFAULT; > + resource.bind = texture->bind & ~PIPE_BIND_DEPTH_STENCIL; > + resource.flags = texture->flags; > + > + if (staging) > + resource.flags |= R600_RESOURCE_FLAG_TRANSFER; > + else > + rtex->dirty_db = TRUE; > > - rtex->flushed_depth_texture = (struct r600_resource_texture > *)ctx->screen->resource_create(ctx->screen, &resource); > - if (rtex->flushed_depth_texture == NULL) { > - R600_ERR("failed to create temporary texture to hold untiled > copy\n"); > + *flushed_depth_texture = (struct r600_resource_texture > *)ctx->screen->resource_create(ctx->screen, &resource); > + if (*flushed_depth_texture == NULL) { > + R600_ERR("failed to create temporary texture to hold flushed > depth\n"); > return; > } > > - ((struct r600_resource_texture > *)rtex->flushed_depth_texture)->is_flushing_texture = TRUE; > + (*flushed_depth_texture)->is_flushing_texture = TRUE; > + > } > > void r600_texture_depth_flush(struct pipe_context *ctx, > - struct pipe_resource *texture) > + struct pipe_resource *texture, > + struct r600_resource_texture **staging) > { > struct r600_resource_texture *rtex = (struct > r600_resource_texture*)texture; > > - r600_init_flushed_depth_texture(ctx, texture); > + r600_init_flushed_depth_texture(ctx, texture, staging); > > - if (!rtex->flushed_depth_texture) > - return; /* error */ > + if (staging) { > + if (!*staging) > + return; /* error */ > > - /* XXX: only do this if the depth texture has actually changed: > - */ > - r600_blit_uncompress_depth(ctx, rtex); > + r600_blit_uncompress_depth(ctx, rtex, *staging); > + } else { > + if (!rtex->flushed_depth_texture) > + return; /* error */ > + > + r600_blit_uncompress_depth(ctx, rtex, NULL); > + } > } > > /* Needs adjustment for pixelformat: > @@ -834,15 +851,18 @@ struct pipe_transfer* r600_texture_get_transfer(struct > pipe_context *ctx, > */ > /* XXX: when discard is true, no need to read back from depth > texture > */ > - r600_texture_depth_flush(ctx, texture); > - if (!rtex->flushed_depth_texture) { > + struct r600_resource_texture *staging_depth; > + > + r600_texture_depth_flush(ctx, texture, &staging_depth); > + if (!staging_depth) { > R600_ERR("failed to create temporary texture to hold > untiled copy\n"); > pipe_resource_reference(&trans->transfer.resource, > NULL); > FREE(trans); > return NULL; > } > - trans->transfer.stride = > rtex->flushed_depth_texture->pitch_in_bytes[level]; > - trans->offset = > r600_texture_get_offset(rtex->flushed_depth_texture, level, box->z); > + trans->transfer.stride = staging_depth->pitch_in_bytes[level]; > + trans->offset = r600_texture_get_offset(staging_depth, level, > box->z); > + trans->staging = (struct r600_resource*)staging_depth; > return &trans->transfer; > } else if (use_staging_texture) { > resource.target = PIPE_TEXTURE_2D; > @@ -897,15 +917,8 @@ void r600_texture_transfer_destroy(struct pipe_context > *ctx, > struct pipe_resource *texture = transfer->resource; > struct r600_resource_texture *rtex = (struct > r600_resource_texture*)texture; > > - if (rtransfer->staging) { > - if (transfer->usage & PIPE_TRANSFER_WRITE) { > - r600_copy_from_staging_texture(ctx, rtransfer); > - } > - pipe_resource_reference((struct > pipe_resource**)&rtransfer->staging, NULL); > - } > - > - if (rtex->is_depth && !rtex->is_flushing_texture) { > - if ((transfer->usage & PIPE_TRANSFER_WRITE) && > rtex->flushed_depth_texture) { > + if (rtex->is_depth) { > + if ((transfer->usage & PIPE_TRANSFER_WRITE) && > rtransfer->staging) { > struct pipe_box sbox; > > sbox.x = sbox.y = sbox.z = 0; > @@ -915,11 +928,18 @@ void r600_texture_transfer_destroy(struct pipe_context > *ctx, > sbox.depth = 1; > > ctx->resource_copy_region(ctx, texture, 0, 0, 0, 0, > - > &rtex->flushed_depth_texture->resource.b.b, 0, > + &rtransfer->staging->b.b, 0, > &sbox); > } > + } else if (rtransfer->staging) { > + if (transfer->usage & PIPE_TRANSFER_WRITE) { > + r600_copy_from_staging_texture(ctx, rtransfer); > + } > } > > + if (rtransfer->staging) > + pipe_resource_reference((struct > pipe_resource**)&rtransfer->staging, NULL); > + > pipe_resource_reference(&transfer->resource, NULL); > FREE(transfer); > } > @@ -930,6 +950,8 @@ void* r600_texture_transfer_map(struct pipe_context *ctx, > struct r600_context *rctx = (struct r600_context *)ctx; > struct r600_transfer *rtransfer = (struct r600_transfer*)transfer; > struct radeon_winsys_cs_handle *buf; > + struct r600_resource_texture *rtex = > + (struct r600_resource_texture*)transfer->resource; > enum pipe_format format = transfer->resource->format; > unsigned offset = 0; > char *map; > @@ -941,17 +963,13 @@ void* r600_texture_transfer_map(struct pipe_context > *ctx, > if (rtransfer->staging) { > buf = ((struct r600_resource *)rtransfer->staging)->cs_buf; > } else { > - struct r600_resource_texture *rtex = (struct > r600_resource_texture*)transfer->resource; > - > - if (rtex->flushed_depth_texture) > - buf = ((struct r600_resource > *)rtex->flushed_depth_texture)->cs_buf; > - else > - buf = ((struct r600_resource > *)transfer->resource)->cs_buf; > + buf = ((struct r600_resource *)transfer->resource)->cs_buf; > + } > > + if (rtex->is_depth || !rtransfer->staging) > offset = rtransfer->offset + > transfer->box.y / util_format_get_blockheight(format) > * transfer->stride + > transfer->box.x / util_format_get_blockwidth(format) * > util_format_get_blocksize(format); > - } > > if (!(map = rctx->ws->buffer_map(buf, rctx->cs, transfer->usage))) { > return NULL; > @@ -974,13 +992,7 @@ void r600_texture_transfer_unmap(struct pipe_context > *ctx, > if (rtransfer->staging) { > buf = ((struct r600_resource *)rtransfer->staging)->cs_buf; > } else { > - struct r600_resource_texture *rtex = (struct > r600_resource_texture*)transfer->resource; > - > - if (rtex->flushed_depth_texture) { > - buf = ((struct r600_resource > *)rtex->flushed_depth_texture)->cs_buf; > - } else { > - buf = ((struct r600_resource > *)transfer->resource)->cs_buf; > - } > + buf = ((struct r600_resource *)transfer->resource)->cs_buf; > } > rctx->ws->buffer_unmap(buf); > } > -- > 1.7.10.4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev