[Mesa-dev] [PATCH] winsys/radeon: add user pointer support

Alex Deucher alexdeucher at gmail.com
Mon Feb 9 18:41:02 PST 2015


On Mon, Feb 9, 2015 at 7:29 PM, Marek Olšák <maraeo at gmail.com> wrote:
> Hi Christian,
>
> What hardware is this supported on? SI and later? Or even r600? r300?

Theoretically r300 and newer hardware, however, the kernel currently
only allows it on r600 and newer since we never tested it on r300
class hardware.

Alex

>
> Thanks,
>
> Marek
>
> On Thu, Feb 5, 2015 at 6:34 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/winsys/radeon/drm/radeon_drm_bo.c | 102 ++++++++++++++++++++++++++
>>  src/gallium/winsys/radeon/drm/radeon_winsys.h |  11 +++
>>  2 files changed, 113 insertions(+)
>>
>> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> index 1ebec10..2605ca6 100644
>> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
>> @@ -42,6 +42,24 @@
>>  #include <fcntl.h>
>>  #include <stdio.h>
>>
>> +#ifndef DRM_RADEON_GEM_USERPTR
>> +
>> +#define DRM_RADEON_GEM_USERPTR         0x2d
>> +
>> +#define RADEON_GEM_USERPTR_READONLY    (1 << 0)
>> +#define RADEON_GEM_USERPTR_ANONONLY    (1 << 1)
>> +#define RADEON_GEM_USERPTR_VALIDATE    (1 << 2)
>> +#define RADEON_GEM_USERPTR_REGISTER    (1 << 3)
>> +
>> +struct drm_radeon_gem_userptr {
>> +       uint64_t                addr;
>> +       uint64_t                size;
>> +       uint32_t                flags;
>> +       uint32_t                handle;
>> +};
>> +
>> +#endif
>> +
>>  extern const struct pb_vtbl radeon_bo_vtbl;
>>
>>  static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
>> @@ -846,6 +864,89 @@ radeon_winsys_bo_create(struct radeon_winsys *rws,
>>      return (struct pb_buffer*)buffer;
>>  }
>>
>> +static struct pb_buffer *radeon_winsys_bo_from_ptr(struct radeon_winsys *rws,
>> +                                                   void *pointer, unsigned size)
>> +{
>> +    struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
>> +    struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
>> +    struct drm_radeon_gem_userptr args;
>> +    struct radeon_bo *bo;
>> +    int r;
>> +
>> +    bo = CALLOC_STRUCT(radeon_bo);
>> +    if (!bo)
>> +        return NULL;
>> +
>> +    memset(&args, 0, sizeof(args));
>> +    args.addr = (uintptr_t)pointer;
>> +    args.size = size;
>> +    args.flags = RADEON_GEM_USERPTR_ANONONLY |
>> +        RADEON_GEM_USERPTR_VALIDATE |
>> +        RADEON_GEM_USERPTR_REGISTER;
>> +    if (drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR,
>> +                            &args, sizeof(args))) {
>> +        FREE(bo);
>> +        return NULL;
>> +    }
>> +
>> +    pipe_mutex_lock(mgr->bo_handles_mutex);
>> +
>> +    /* Initialize it. */
>> +    pipe_reference_init(&bo->base.reference, 1);
>> +    bo->handle = args.handle;
>> +    bo->base.alignment = 0;
>> +    bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
>> +    bo->base.size = size;
>> +    bo->base.vtbl = &radeon_bo_vtbl;
>> +    bo->mgr = mgr;
>> +    bo->rws = mgr->rws;
>> +    bo->va = 0;
>> +    bo->initial_domain = RADEON_DOMAIN_GTT;
>> +    pipe_mutex_init(bo->map_mutex);
>> +
>> +    util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)bo->handle, bo);
>> +
>> +    pipe_mutex_unlock(mgr->bo_handles_mutex);
>> +
>> +    if (mgr->va) {
>> +        struct drm_radeon_gem_va va;
>> +
>> +        bo->va = radeon_bomgr_find_va(mgr, bo->base.size, 1 << 20);
>> +
>> +        va.handle = bo->handle;
>> +        va.operation = RADEON_VA_MAP;
>> +        va.vm_id = 0;
>> +        va.offset = bo->va;
>> +        va.flags = RADEON_VM_PAGE_READABLE |
>> +                   RADEON_VM_PAGE_WRITEABLE |
>> +                   RADEON_VM_PAGE_SNOOPED;
>> +        va.offset = bo->va;
>> +        r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va));
>> +        if (r && va.operation == RADEON_VA_RESULT_ERROR) {
>> +            fprintf(stderr, "radeon: Failed to assign virtual address space\n");
>> +            radeon_bo_destroy(&bo->base);
>> +            return NULL;
>> +        }
>> +        pipe_mutex_lock(mgr->bo_handles_mutex);
>> +        if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
>> +            struct pb_buffer *b = &bo->base;
>> +            struct radeon_bo *old_bo =
>> +                util_hash_table_get(mgr->bo_vas, (void*)(uintptr_t)va.offset);
>> +
>> +            pipe_mutex_unlock(mgr->bo_handles_mutex);
>> +            pb_reference(&b, &old_bo->base);
>> +            return b;
>> +        }
>> +
>> +        util_hash_table_set(mgr->bo_vas, (void*)(uintptr_t)bo->va, bo);
>> +        pipe_mutex_unlock(mgr->bo_handles_mutex);
>> +    }
>> +
>> +    ws->allocated_gtt += align(bo->base.size, 4096);
>> +
>> +    return (struct pb_buffer*)bo;
>> +}
>> +
>>  static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws,
>>                                                        struct winsys_handle *whandle,
>>                                                        unsigned *stride)
>> @@ -1040,6 +1141,7 @@ void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
>>      ws->base.buffer_is_busy = radeon_bo_is_busy;
>>      ws->base.buffer_create = radeon_winsys_bo_create;
>>      ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
>> +    ws->base.buffer_from_ptr = radeon_winsys_bo_from_ptr;
>>      ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
>>      ws->base.buffer_get_virtual_address = radeon_winsys_bo_va;
>>      ws->base.buffer_get_initial_domain = radeon_bo_get_initial_domain;
>> diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
>> index 5dc9313..d9fa1ab 100644
>> --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
>> +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
>> @@ -394,6 +394,17 @@ struct radeon_winsys {
>>                                              unsigned *stride);
>>
>>      /**
>> +     * Get a winsys buffer from a user pointer. The resulting buffer can't be
>> +     * mapped or exported. Both pointer and size must be page aligned.
>> +     *
>> +     * \param ws        The winsys this function is called from.
>> +     * \param pointer   User pointer to turn into a buffer object.
>> +     * \param Size      Size in bytes for the new buffer.
>> +     */
>> +    struct pb_buffer *(*buffer_from_ptr)(struct radeon_winsys *ws,
>> +                                         void *pointer, unsigned size);
>> +
>> +    /**
>>       * Get a winsys handle from a winsys buffer. The internal structure
>>       * of the handle is platform-specific and only a winsys should access it.
>>       *
>> --
>> 1.9.1
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> _______________________________________________
> 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