[Mesa-dev] [PATCH 4/4] radeon: cache the last used userptr

Christian König deathsimple at vodafone.de
Wed Aug 6 04:39:03 PDT 2014


> What is this patch good for?
Nothing in particular, I just wanted to test how much overhead creating 
a new BO each time we do transfer_inline_write actually makes.

BTW: Implementing transfer_inline_write using userptrs was just a prove 
of concept. It turned out to actually be way slower than just copying 
with the CPU because we need to block for the copy to complete.

For a real use case we need to support creating textures from 
application supplied pointers and implement the matching OpenGL 
extensions, but you probably know that better than I do.

Christian.

Am 06.08.2014 um 13:24 schrieb Marek Olšák:
> What is this patch good for?
>
> Marek
>
> 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>
>>
>> Signed-off-by: Christian König <christian.koenig at amd.com>
>> ---
>>   src/gallium/drivers/radeon/r600_pipe_common.c |  9 ++++++
>>   src/gallium/drivers/radeon/r600_pipe_common.h | 11 +++++++
>>   src/gallium/drivers/radeon/r600_texture.c     | 41 +++++++++++++++++++++++++--
>>   3 files changed, 59 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
>> index 69d344e..f745311 100644
>> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
>> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
>> @@ -770,11 +770,20 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen,
>>                  }
>>          }
>>
>> +       pipe_mutex_init(rscreen->userptr_lock);
>> +
>>          return true;
>>   }
>>
>>   void r600_destroy_common_screen(struct r600_common_screen *rscreen)
>>   {
>> +       unsigned i;
>> +
>> +       for (i = 0; i < R600_USERPTR_CACHE; ++i)
>> +               pipe_resource_reference((struct pipe_resource **)&rscreen->userptr[i].tex, NULL);
>> +
>> +       pipe_mutex_destroy(rscreen->userptr_lock);
>> +
>>          pipe_mutex_destroy(rscreen->aux_context_lock);
>>          rscreen->aux_context->destroy(rscreen->aux_context);
>>
>> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
>> index dcec2bb..88dbaf8 100644
>> --- a/src/gallium/drivers/radeon/r600_pipe_common.h
>> +++ b/src/gallium/drivers/radeon/r600_pipe_common.h
>> @@ -97,6 +97,8 @@
>>
>>   #define R600_MAP_BUFFER_ALIGNMENT 64
>>
>> +#define R600_USERPTR_CACHE 32
>> +
>>   struct r600_common_context;
>>
>>   struct radeon_shader_binary {
>> @@ -258,6 +260,15 @@ struct r600_common_screen {
>>          struct r600_resource            *trace_bo;
>>          uint32_t                        *trace_ptr;
>>          unsigned                        cs_count;
>> +
>> +       struct {
>> +               struct r600_texture     *tex;
>> +               void                    *pointer;
>> +               unsigned                offset;
>> +               unsigned                size;
>> +       }                               userptr[R600_USERPTR_CACHE];
>> +       unsigned                        userptr_idx;
>> +       pipe_mutex                      userptr_lock;
>>   };
>>
>>   /* This encapsulates a state or an operation which can emitted into the GPU
>> diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
>> index 89b3b55..c3ff96c 100644
>> --- a/src/gallium/drivers/radeon/r600_texture.c
>> +++ b/src/gallium/drivers/radeon/r600_texture.c
>> @@ -855,10 +855,11 @@ static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
>>   {
>>          struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
>>          struct radeon_surface surface = {};
>> +       struct pipe_resource *res = NULL;
>>          struct r600_texture *tex;
>>          unsigned offset, size;
>>          struct pb_buffer *buf;
>> -       int r;
>> +       int r, i;
>>
>>          /* Support only 2D textures without mipmaps */
>>          if ((templ->target != PIPE_TEXTURE_2D && templ->target != PIPE_TEXTURE_RECT) ||
>> @@ -877,16 +878,52 @@ static struct r600_texture *r600_texture_from_ptr(struct pipe_screen *screen,
>>          if (size < 64*1024)
>>                  return NULL;
>>
>> +       pipe_mutex_lock(rscreen->userptr_lock);
>> +       for (i = 0; i < R600_USERPTR_CACHE; ++i) {
>> +
>> +               if (rscreen->userptr[i].pointer != pointer ||
>> +                   rscreen->userptr[i].offset != offset ||
>> +                   rscreen->userptr[i].size != size ||
>> +                   !rscreen->userptr[i].tex)
>> +                       continue;
>> +
>> +               tex = rscreen->userptr[i].tex;
>> +               if (tex->resource.b.b.width0 != templ->width0 &&
>> +                   tex->resource.b.b.height0 != templ->height0 &&
>> +                   tex->resource.b.b.target != templ->target &&
>> +                   tex->resource.b.b.format != templ->format)
>> +                       continue;
>> +
>> +               pipe_resource_reference(&res, (struct pipe_resource *)tex);
>> +               pipe_mutex_unlock(rscreen->userptr_lock);
>> +               return (struct r600_texture *)res;
>> +       }
>> +       pipe_mutex_unlock(rscreen->userptr_lock);
>> +
>>          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);
>> +       r = r600_init_surface(rscreen, &surface, templ, RADEON_SURF_MODE_LINEAR, false);
>>          if (r)
>>                  return NULL;
>>
>>          tex = r600_texture_create_object(screen, templ, stride, buf, &surface);
>>          tex->surface.level[0].offset += offset;
>> +
>> +       pipe_mutex_lock(rscreen->userptr_lock);
>> +       ++rscreen->userptr_idx;
>> +       rscreen->userptr_idx %= R600_USERPTR_CACHE;
>> +
>> +       i = rscreen->userptr_idx;
>> +       pipe_resource_reference((struct pipe_resource **)&rscreen->userptr[i].tex,
>> +                               (struct pipe_resource *)tex);
>> +       rscreen->userptr[i].pointer = pointer;
>> +       rscreen->userptr[i].offset = offset;
>> +       rscreen->userptr[i].size = size;
>> +
>> +       pipe_mutex_unlock(rscreen->userptr_lock);
>> +
>>          return tex;
>>   }
>>
>> --
>> 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