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

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


I only know about AMD_pinned_memory, which is for buffers only. I
don't know about an API for creating textures from user pointers. Yes,
there are pixel buffer objects, but they are a lot more difficult to
implement and they are defined such that a zero-copy approach to get a
texture is not possible.

Marek

On Wed, Aug 6, 2014 at 1:39 PM, Christian König <deathsimple at vodafone.de> wrote:
>> 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