[Mesa-dev] [PATCH 3/4] radeon: accelerate transfer_inline_write

Marek Olšák maraeo at gmail.com
Wed Aug 6 04:45:25 PDT 2014


On Tue, Aug 5, 2014 at 7:31 PM, Christian König <deathsimple at vodafone.de> wrote:
> From: Christian König <christian.koenig at amd.com>
>
> Not completely implemented, cause we need DMA copy support for every hw generation.
>
> Signed-off-by: Christian König <christian.koenig at amd.com>
> ---
>  src/gallium/drivers/radeon/r600_buffer_common.c |   2 +-
>  src/gallium/drivers/radeon/r600_pipe_common.c   |   2 +-
>  src/gallium/drivers/radeon/r600_texture.c       | 104 ++++++++++++++++++++++--
>  3 files changed, 100 insertions(+), 8 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c
> index d747cbc..28ab30c 100644
> --- a/src/gallium/drivers/radeon/r600_buffer_common.c
> +++ b/src/gallium/drivers/radeon/r600_buffer_common.c
> @@ -372,7 +372,7 @@ static const struct u_resource_vtbl r600_buffer_vtbl =
>         r600_buffer_transfer_map,       /* transfer_map */
>         NULL,                           /* transfer_flush_region */
>         r600_buffer_transfer_unmap,     /* transfer_unmap */
> -       NULL                            /* transfer_inline_write */
> +       u_default_transfer_inline_write /* transfer_inline_write */
>  };
>
>  struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 3476021..69d344e 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -153,7 +153,7 @@ bool r600_common_context_init(struct r600_common_context *rctx,
>         rctx->b.transfer_map = u_transfer_map_vtbl;
>         rctx->b.transfer_flush_region = u_default_transfer_flush_region;
>         rctx->b.transfer_unmap = u_transfer_unmap_vtbl;
> -       rctx->b.transfer_inline_write = u_default_transfer_inline_write;
> +       rctx->b.transfer_inline_write = u_transfer_inline_write_vtbl;
>          rctx->b.memory_barrier = r600_memory_barrier;
>         rctx->b.flush = r600_flush_from_st;
>
> diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
> index 482bbff..89b3b55 100644
> --- a/src/gallium/drivers/radeon/r600_texture.c
> +++ b/src/gallium/drivers/radeon/r600_texture.c
> @@ -849,6 +849,47 @@ static struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen
>                                                                   stride, buf, &surface);
>  }
>
> +static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
> +                                                 const struct pipe_resource *templ,
> +                                                 void *pointer, unsigned stride)
> +{
> +       struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
> +       struct radeon_surface surface = {};
> +       struct r600_texture *tex;
> +       unsigned offset, size;
> +       struct pb_buffer *buf;
> +       int r;
> +
> +       /* Support only 2D textures without mipmaps */
> +       if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
> +             templ->depth0 != 1 || templ->last_level != 0)
> +               return NULL;
> +
> +       /* stride needs to be at least dw aligned */
> +       if (stride % 4)
> +               return NULL;
> +
> +       offset = ((uintptr_t)pointer) & 0xfff;
> +       pointer = (void *)(((uintptr_t)pointer) - offset);
> +       size = align(stride * templ->height0 + offset, 0x1000);
> +
> +       /* avoid the overhead for small copies */
> +       if (size < 64*1024)
> +               return NULL;
> +
> +       buf = rscreen->ws->buffer_from_ptr(rscreen->ws, pointer, size);
> +       if (!buf)
> +               return NULL;
> +
> +       r = r600_init_surface(rscreen, &surface, templ, RADEON_SURF_MODE_LINEAR_ALIGNED, false);

I know you change it the next patch, but I think the alignment for
LINEAR (not ALIGNED) is 8 pixels, right? Of course, libdrm_radeon
should be reviewed if it doesn't over-align the stride. The safest
thing would be to check if stride == surface[0].pitch_in_bytes.


> +       if (r)
> +               return NULL;
> +
> +       tex = r600_texture_create_object(screen, templ, stride, buf, &surface);
> +       tex->surface.level[0].offset += offset;
> +       return tex;
> +}
> +
>  bool r600_init_flushed_depth_texture(struct pipe_context *ctx,
>                                      struct pipe_resource *texture,
>                                      struct r600_texture **staging)
> @@ -1112,14 +1153,65 @@ static void r600_texture_transfer_unmap(struct pipe_context *ctx,
>         FREE(transfer);
>  }
>
> +static void r600_texture_transfer_inline_write(struct pipe_context *ctx,
> +                                              struct pipe_resource *dst,
> +                                              unsigned level, unsigned usage,
> +                                              const struct pipe_box *box,
> +                                              const void *data,
> +                                              unsigned stride,
> +                                              unsigned layer_stride)
> +{
> +       struct r600_common_context *rctx = (struct r600_common_context*)ctx;
> +       struct r600_texture *rsrc;
> +       struct pipe_resource *src, templ = {};
> +       struct pipe_box src_box = {};
> +
> +       templ.target = PIPE_TEXTURE_2D;
> +       templ.format = dst->format;
> +
> +       templ.width0 = box->width;
> +       templ.height0 = box->height;
> +       templ.depth0 = 1;
> +       templ.array_size = 1;
> +
> +       templ.usage = PIPE_USAGE_STAGING;
> +       templ.bind = PIPE_BIND_TRANSFER_READ;
> +
> +       rsrc = r600_texture_from_ptr(ctx->screen, &templ, (void *)data, stride);
> +       src = (struct pipe_resource *)rsrc;
> +       if (!src) {

As an optimization, you can test if the dst texture is referenced or
busy and if yes, use u_default_transfer_inline_write. If there is
non-trivial rendering going on, the buffer_wait call below will cost a
lot.

Marek

> +               u_default_transfer_inline_write(ctx, dst, level, usage, box,
> +                                               data, stride, layer_stride);
> +               return;
> +       }
> +
> +       src_box.width = box->width;
> +       src_box.height = box->height;
> +       src_box.depth = box->depth;
> +       rctx->dma_copy(ctx, dst, level, box->x, box->y, box->z, src, 0, &src_box);
> +
> +       if (rctx->ws->cs_is_buffer_referenced(rctx->rings.gfx.cs, rsrc->resource.cs_buf,
> +                                             RADEON_USAGE_READ))
> +               rctx->rings.gfx.flush(ctx, 0, NULL);
> +
> +       if (rctx->rings.dma.cs &&
> +           rctx->ws->cs_is_buffer_referenced(rctx->rings.dma.cs, rsrc->resource.cs_buf,
> +                                            RADEON_USAGE_READ))
> +               rctx->rings.dma.flush(ctx, 0, NULL);
> +
> +       rctx->ws->buffer_wait(rsrc->resource.buf, RADEON_USAGE_READWRITE);
> +
> +       pipe_resource_reference(&src, NULL);
> +}
> +
>  static const struct u_resource_vtbl r600_texture_vtbl =
>  {
> -       NULL,                           /* get_handle */
> -       r600_texture_destroy,           /* resource_destroy */
> -       r600_texture_transfer_map,      /* transfer_map */
> -       NULL,                           /* transfer_flush_region */
> -       r600_texture_transfer_unmap,    /* transfer_unmap */
> -       NULL                            /* transfer_inline_write */
> +       NULL,                                   /* get_handle */
> +       r600_texture_destroy,                   /* resource_destroy */
> +       r600_texture_transfer_map,              /* transfer_map */
> +       NULL,                                   /* transfer_flush_region */
> +       r600_texture_transfer_unmap,            /* transfer_unmap */
> +       r600_texture_transfer_inline_write      /* transfer_inline_write */
>  };
>
>  struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list