llvmpipe: add support for EXT_memory_object(_fd)
Enable the import of memory via opaque fd handles, which are based upon memory-fds. The extension is necessary for sharing images and buffers from Vulkan. Reviewed-by: Dave Airlie <airlied@redhat.com> Tested-by: Heinrich Fink <hfink@snap.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12345>
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
#include "lp_rast.h"
|
#include "lp_rast.h"
|
||||||
|
|
||||||
#include "frontend/sw_winsys.h"
|
#include "frontend/sw_winsys.h"
|
||||||
|
#include "git_sha1.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include "drm-uapi/drm_fourcc.h"
|
#include "drm-uapi/drm_fourcc.h"
|
||||||
@@ -334,6 +335,104 @@ llvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
|
|||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct pipe_memory_object *
|
||||||
|
llvmpipe_memobj_create_from_handle(struct pipe_screen *pscreen,
|
||||||
|
struct winsys_handle *handle,
|
||||||
|
bool dedicated)
|
||||||
|
{
|
||||||
|
#ifdef PIPE_MEMORY_FD
|
||||||
|
struct llvmpipe_memory_object *memobj = CALLOC_STRUCT(llvmpipe_memory_object);
|
||||||
|
|
||||||
|
if (handle->type == WINSYS_HANDLE_TYPE_FD &&
|
||||||
|
pscreen->import_memory_fd(pscreen, handle->handle, &memobj->data, &memobj->size)) {
|
||||||
|
return &memobj->b;
|
||||||
|
}
|
||||||
|
free(memobj);
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
llvmpipe_memobj_destroy(struct pipe_screen *pscreen,
|
||||||
|
struct pipe_memory_object *memobj)
|
||||||
|
{
|
||||||
|
if (!memobj)
|
||||||
|
return;
|
||||||
|
struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
|
||||||
|
#ifdef PIPE_MEMORY_FD
|
||||||
|
pscreen->free_memory_fd(pscreen, lpmo->data);
|
||||||
|
#endif
|
||||||
|
free(lpmo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pipe_resource *
|
||||||
|
llvmpipe_resource_from_memobj(struct pipe_screen *pscreen,
|
||||||
|
const struct pipe_resource *templat,
|
||||||
|
struct pipe_memory_object *memobj,
|
||||||
|
uint64_t offset)
|
||||||
|
{
|
||||||
|
if (!memobj)
|
||||||
|
return NULL;
|
||||||
|
struct llvmpipe_screen *screen = llvmpipe_screen(pscreen);
|
||||||
|
struct llvmpipe_memory_object *lpmo = llvmpipe_memory_object(memobj);
|
||||||
|
struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
|
||||||
|
lpr->base = *templat;
|
||||||
|
|
||||||
|
lpr->screen = screen;
|
||||||
|
pipe_reference_init(&lpr->base.reference, 1);
|
||||||
|
lpr->base.screen = &screen->base;
|
||||||
|
|
||||||
|
if (llvmpipe_resource_is_texture(&lpr->base)) {
|
||||||
|
/* texture map */
|
||||||
|
if (!llvmpipe_texture_layout(screen, lpr, false))
|
||||||
|
goto fail;
|
||||||
|
if(lpmo->size < lpr->size_required)
|
||||||
|
goto fail;
|
||||||
|
lpr->tex_data = lpmo->data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* other data (vertex buffer, const buffer, etc) */
|
||||||
|
const uint bytes = templat->width0;
|
||||||
|
assert(util_format_get_blocksize(templat->format) == 1);
|
||||||
|
assert(templat->height0 == 1);
|
||||||
|
assert(templat->depth0 == 1);
|
||||||
|
assert(templat->last_level == 0);
|
||||||
|
/*
|
||||||
|
* Reserve some extra storage since if we'd render to a buffer we
|
||||||
|
* read/write always LP_RASTER_BLOCK_SIZE pixels, but the element
|
||||||
|
* offset doesn't need to be aligned to LP_RASTER_BLOCK_SIZE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* buffers don't really have stride but it's probably safer
|
||||||
|
* (for code doing same calculations for buffers and textures)
|
||||||
|
* to put something reasonable in there.
|
||||||
|
*/
|
||||||
|
lpr->row_stride[0] = bytes;
|
||||||
|
|
||||||
|
lpr->size_required = bytes;
|
||||||
|
if (!(templat->flags & PIPE_RESOURCE_FLAG_DONT_OVER_ALLOCATE))
|
||||||
|
lpr->size_required += (LP_RASTER_BLOCK_SIZE - 1) * 4 * sizeof(float);
|
||||||
|
|
||||||
|
if(lpmo->size < lpr->size_required)
|
||||||
|
goto fail;
|
||||||
|
lpr->data = lpmo->data;
|
||||||
|
}
|
||||||
|
lpr->id = id_counter++;
|
||||||
|
lpr->imported_memory = true;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
mtx_lock(&resource_list_mutex);
|
||||||
|
insert_at_tail(&resource_list, lpr);
|
||||||
|
mtx_unlock(&resource_list_mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return &lpr->base;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(lpr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
llvmpipe_resource_destroy(struct pipe_screen *pscreen,
|
llvmpipe_resource_destroy(struct pipe_screen *pscreen,
|
||||||
struct pipe_resource *pt)
|
struct pipe_resource *pt)
|
||||||
@@ -350,13 +449,16 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen,
|
|||||||
else if (llvmpipe_resource_is_texture(pt)) {
|
else if (llvmpipe_resource_is_texture(pt)) {
|
||||||
/* free linear image data */
|
/* free linear image data */
|
||||||
if (lpr->tex_data) {
|
if (lpr->tex_data) {
|
||||||
align_free(lpr->tex_data);
|
if (!lpr->imported_memory)
|
||||||
|
align_free(lpr->tex_data);
|
||||||
lpr->tex_data = NULL;
|
lpr->tex_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!lpr->userBuffer) {
|
else if (!lpr->userBuffer) {
|
||||||
if (lpr->data)
|
if (lpr->data) {
|
||||||
align_free(lpr->data);
|
if (!lpr->imported_memory)
|
||||||
|
align_free(lpr->data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@@ -850,6 +952,28 @@ static void llvmpipe_free_memory(struct pipe_screen *screen,
|
|||||||
os_free_aligned(pmem);
|
os_free_aligned(pmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PIPE_MEMORY_FD
|
||||||
|
|
||||||
|
static const char *driver_id = "llvmpipe" MESA_GIT_SHA1;
|
||||||
|
|
||||||
|
static struct pipe_memory_allocation *llvmpipe_allocate_memory_fd(struct pipe_screen *screen, uint64_t size, int *fd)
|
||||||
|
{
|
||||||
|
return os_malloc_aligned_fd(size, 256, fd, "llvmpipe memory fd", driver_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool llvmpipe_import_memory_fd(struct pipe_screen *screen, int fd, struct pipe_memory_allocation **ptr, uint64_t *size)
|
||||||
|
{
|
||||||
|
return os_import_memory_fd(fd, (void**)ptr, size, driver_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void llvmpipe_free_memory_fd(struct pipe_screen *screen,
|
||||||
|
struct pipe_memory_allocation *pmem)
|
||||||
|
{
|
||||||
|
os_free_fd(pmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool llvmpipe_resource_bind_backing(struct pipe_screen *screen,
|
static bool llvmpipe_resource_bind_backing(struct pipe_screen *screen,
|
||||||
struct pipe_resource *pt,
|
struct pipe_resource *pt,
|
||||||
struct pipe_memory_allocation *pmem,
|
struct pipe_memory_allocation *pmem,
|
||||||
@@ -995,16 +1119,25 @@ llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
|
|||||||
/* screen->resource_create_front = llvmpipe_resource_create_front; */
|
/* screen->resource_create_front = llvmpipe_resource_create_front; */
|
||||||
screen->resource_destroy = llvmpipe_resource_destroy;
|
screen->resource_destroy = llvmpipe_resource_destroy;
|
||||||
screen->resource_from_handle = llvmpipe_resource_from_handle;
|
screen->resource_from_handle = llvmpipe_resource_from_handle;
|
||||||
|
screen->resource_from_memobj = llvmpipe_resource_from_memobj;
|
||||||
screen->resource_get_handle = llvmpipe_resource_get_handle;
|
screen->resource_get_handle = llvmpipe_resource_get_handle;
|
||||||
screen->can_create_resource = llvmpipe_can_create_resource;
|
screen->can_create_resource = llvmpipe_can_create_resource;
|
||||||
|
|
||||||
screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
|
screen->resource_create_unbacked = llvmpipe_resource_create_unbacked;
|
||||||
|
|
||||||
|
screen->memobj_create_from_handle = llvmpipe_memobj_create_from_handle;
|
||||||
|
screen->memobj_destroy = llvmpipe_memobj_destroy;
|
||||||
|
|
||||||
screen->resource_get_info = llvmpipe_get_resource_info;
|
screen->resource_get_info = llvmpipe_get_resource_info;
|
||||||
screen->resource_get_param = llvmpipe_resource_get_param;
|
screen->resource_get_param = llvmpipe_resource_get_param;
|
||||||
screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
|
screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
|
||||||
screen->allocate_memory = llvmpipe_allocate_memory;
|
screen->allocate_memory = llvmpipe_allocate_memory;
|
||||||
screen->free_memory = llvmpipe_free_memory;
|
screen->free_memory = llvmpipe_free_memory;
|
||||||
|
#ifdef PIPE_MEMORY_FD
|
||||||
|
screen->allocate_memory_fd = llvmpipe_allocate_memory_fd;
|
||||||
|
screen->import_memory_fd = llvmpipe_import_memory_fd;
|
||||||
|
screen->free_memory_fd = llvmpipe_free_memory_fd;
|
||||||
|
#endif
|
||||||
screen->map_memory = llvmpipe_map_memory;
|
screen->map_memory = llvmpipe_map_memory;
|
||||||
screen->unmap_memory = llvmpipe_unmap_memory;
|
screen->unmap_memory = llvmpipe_unmap_memory;
|
||||||
|
|
||||||
|
@@ -99,6 +99,7 @@ struct llvmpipe_resource
|
|||||||
uint64_t size_required;
|
uint64_t size_required;
|
||||||
uint64_t backing_offset;
|
uint64_t backing_offset;
|
||||||
bool backable;
|
bool backable;
|
||||||
|
bool imported_memory;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/** for linked list */
|
/** for linked list */
|
||||||
struct llvmpipe_resource *prev, *next;
|
struct llvmpipe_resource *prev, *next;
|
||||||
@@ -111,6 +112,13 @@ struct llvmpipe_transfer
|
|||||||
struct pipe_transfer base;
|
struct pipe_transfer base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct llvmpipe_memory_object
|
||||||
|
{
|
||||||
|
struct pipe_memory_object b;
|
||||||
|
struct pipe_memory_allocation *data;
|
||||||
|
uint64_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** cast wrappers */
|
/** cast wrappers */
|
||||||
static inline struct llvmpipe_resource *
|
static inline struct llvmpipe_resource *
|
||||||
@@ -133,6 +141,12 @@ llvmpipe_transfer(struct pipe_transfer *pt)
|
|||||||
return (struct llvmpipe_transfer *) pt;
|
return (struct llvmpipe_transfer *) pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct llvmpipe_memory_object *
|
||||||
|
llvmpipe_memory_object(struct pipe_memory_object *pt)
|
||||||
|
{
|
||||||
|
return (struct llvmpipe_memory_object *) pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen);
|
void llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen);
|
||||||
void llvmpipe_init_context_resource_funcs(struct pipe_context *pipe);
|
void llvmpipe_init_context_resource_funcs(struct pipe_context *pipe);
|
||||||
|
@@ -1354,6 +1354,10 @@ enum pipe_perf_counter_data_type
|
|||||||
|
|
||||||
#define PIPE_UUID_SIZE 16
|
#define PIPE_UUID_SIZE 16
|
||||||
|
|
||||||
|
#ifdef PIPE_OS_UNIX
|
||||||
|
#define PIPE_MEMORY_FD
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user