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

Marek Olšák maraeo at gmail.com
Mon Feb 9 16:29:44 PST 2015


Hi Christian,

What hardware is this supported on? SI and later? Or even r600? r300?

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


More information about the mesa-dev mailing list