Mesa (main): llvmpipe: add support for EXT_memory_object(_fd)
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Oct 6 14:18:21 UTC 2021
Module: Mesa
Branch: main
Commit: 1608a815e3305d229091c346373c379900a8351f
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=1608a815e3305d229091c346373c379900a8351f
Author: Thomas Wagner <twagner at snap.com>
Date: Wed Aug 11 10:31:41 2021 +0200
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 at redhat.com>
Tested-by: Heinrich Fink <hfink at snap.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12345>
---
src/gallium/drivers/llvmpipe/lp_texture.c | 139 +++++++++++++++++++++++++++++-
src/gallium/drivers/llvmpipe/lp_texture.h | 14 +++
src/gallium/include/pipe/p_defines.h | 4 +
3 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index eb635b6fc94..d303e8abbd5 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -52,6 +52,7 @@
#include "lp_rast.h"
#include "frontend/sw_winsys.h"
+#include "git_sha1.h"
#ifndef _WIN32
#include "drm-uapi/drm_fourcc.h"
@@ -334,6 +335,104 @@ llvmpipe_resource_create_unbacked(struct pipe_screen *_screen,
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
llvmpipe_resource_destroy(struct pipe_screen *pscreen,
struct pipe_resource *pt)
@@ -350,13 +449,16 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen,
else if (llvmpipe_resource_is_texture(pt)) {
/* free linear image data */
if (lpr->tex_data) {
- align_free(lpr->tex_data);
+ if (!lpr->imported_memory)
+ align_free(lpr->tex_data);
lpr->tex_data = NULL;
}
}
else if (!lpr->userBuffer) {
- if (lpr->data)
- align_free(lpr->data);
+ if (lpr->data) {
+ if (!lpr->imported_memory)
+ align_free(lpr->data);
+ }
}
}
#ifdef DEBUG
@@ -850,6 +952,28 @@ static void llvmpipe_free_memory(struct pipe_screen *screen,
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,
struct pipe_resource *pt,
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_destroy = llvmpipe_resource_destroy;
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->can_create_resource = llvmpipe_can_create_resource;
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_param = llvmpipe_resource_get_param;
screen->resource_from_user_memory = llvmpipe_resource_from_user_memory;
screen->allocate_memory = llvmpipe_allocate_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->unmap_memory = llvmpipe_unmap_memory;
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
index d1ba22b2685..eabfbeca8f0 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.h
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -99,6 +99,7 @@ struct llvmpipe_resource
uint64_t size_required;
uint64_t backing_offset;
bool backable;
+ bool imported_memory;
#ifdef DEBUG
/** for linked list */
struct llvmpipe_resource *prev, *next;
@@ -111,6 +112,13 @@ struct llvmpipe_transfer
struct pipe_transfer base;
};
+struct llvmpipe_memory_object
+{
+ struct pipe_memory_object b;
+ struct pipe_memory_allocation *data;
+ uint64_t size;
+};
+
/** cast wrappers */
static inline struct llvmpipe_resource *
@@ -133,6 +141,12 @@ llvmpipe_transfer(struct pipe_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_context_resource_funcs(struct pipe_context *pipe);
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 123c2b4d0f6..608667b1468 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -1354,6 +1354,10 @@ enum pipe_perf_counter_data_type
#define PIPE_UUID_SIZE 16
+#ifdef PIPE_OS_UNIX
+#define PIPE_MEMORY_FD
+#endif
+
#ifdef __cplusplus
}
#endif
More information about the mesa-commit
mailing list