From b0fe621459c1b02b658f05ebbaba3ca68a7830de Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 1 Jun 2022 11:31:28 -0400 Subject: [PATCH] zink: add back kms handling removing this broke the ability to create system compositors rework it a bit though so that kms handles are stored and destroyed when the bo is freed Reviewed-by: Adam Jackson Part-of: --- src/gallium/drivers/zink/meson.build | 2 +- src/gallium/drivers/zink/zink_bo.c | 64 +++++++++++++++++++++--- src/gallium/drivers/zink/zink_bo.h | 14 ++++++ src/gallium/drivers/zink/zink_resource.c | 15 +++++- src/gallium/drivers/zink/zink_screen.h | 2 - 5 files changed, 85 insertions(+), 12 deletions(-) diff --git a/src/gallium/drivers/zink/meson.build b/src/gallium/drivers/zink/meson.build index 78975f90e93..4621e7f983e 100644 --- a/src/gallium/drivers/zink/meson.build +++ b/src/gallium/drivers/zink/meson.build @@ -92,7 +92,7 @@ libzink = static_library( include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_vulkan_util, inc_zink_vk], dependencies: [ idep_nir_headers, idep_mesautil, idep_vulkan_util_headers, - idep_vulkan_wsi_headers, idep_vulkan_util + idep_vulkan_wsi_headers, idep_vulkan_util, dep_libdrm ], c_args: zink_c_args, ) diff --git a/src/gallium/drivers/zink/zink_bo.c b/src/gallium/drivers/zink/zink_bo.c index 5afa5ec413e..d4b48d1b518 100644 --- a/src/gallium/drivers/zink/zink_bo.c +++ b/src/gallium/drivers/zink/zink_bo.c @@ -34,6 +34,11 @@ #include "zink_screen.h" #include "util/u_hash_table.h" +#if !defined(__APPLE__) && !defined(_WIN32) +#define ZINK_USE_DMABUF +#include +#endif + struct zink_bo; struct zink_sparse_backing_chunk { @@ -120,9 +125,19 @@ bo_destroy(struct zink_screen *screen, struct pb_buffer *pbuf) { struct zink_bo *bo = zink_bo(pbuf); - simple_mtx_lock(&screen->pb.bo_export_table_lock); - _mesa_hash_table_remove_key(screen->pb.bo_export_table, bo); - simple_mtx_unlock(&screen->pb.bo_export_table_lock); +#ifdef ZINK_USE_DMABUF + if (!bo->u.real.use_reusable_pool) { + simple_mtx_lock(&bo->u.real.export_lock); + list_for_each_entry_safe(struct bo_export, export, &bo->u.real.exports, link) { + struct drm_gem_close args = { .handle = export->gem_handle }; + drmIoctl(export->drm_fd, DRM_IOCTL_GEM_CLOSE, &args); + list_del(&export->link); + free(export); + } + simple_mtx_unlock(&bo->u.real.export_lock); + simple_mtx_destroy(&bo->u.real.export_lock); + } +#endif if (!bo->u.real.is_user_ptr && bo->u.real.cpu_ptr) { bo->u.real.map_count = 1; @@ -282,6 +297,11 @@ demote: if (init_pb_cache) { bo->u.real.use_reusable_pool = true; pb_cache_init_entry(&screen->pb.bo_cache, bo->cache_entry, &bo->base, heap); + } else { +#ifdef ZINK_USE_DMABUF + list_inithead(&bo->u.real.exports); + simple_mtx_init(&bo->u.real.export_lock, mtx_plain); +#endif } @@ -1065,6 +1085,40 @@ out: return ok; } +bool +zink_bo_get_kms_handle(struct zink_screen *screen, struct zink_bo *bo, int fd, uint32_t *handle) +{ +#ifdef ZINK_USE_DMABUF + assert(bo->mem && !bo->u.real.use_reusable_pool); + simple_mtx_lock(&bo->u.real.export_lock); + list_for_each_entry(struct bo_export, export, &bo->u.real.exports, link) { + if (export->drm_fd == fd) { + simple_mtx_unlock(&bo->u.real.export_lock); + *handle = export->gem_handle; + return true; + } + } + struct bo_export *export = CALLOC_STRUCT(bo_export); + if (!export) { + simple_mtx_unlock(&bo->u.real.export_lock); + return false; + } + bool success = drmPrimeFDToHandle(screen->drm_fd, fd, handle) == 0; + if (success) { + list_addtail(&export->link, &bo->u.real.exports); + export->gem_handle = *handle; + export->drm_fd = screen->drm_fd; + } else { + mesa_loge("zink: failed drmPrimeFDToHandle %s", strerror(errno)); + FREE(export); + } + simple_mtx_unlock(&bo->u.real.export_lock); + return success; +#else + return false; +#endif +} + static const struct pb_vtbl bo_slab_vtbl = { /* Cast to void* because one of the function parameters is a struct pointer instead of void*. */ (void*)bo_slab_destroy @@ -1214,8 +1268,6 @@ zink_bo_init(struct zink_screen *screen) min_slab_order = max_order + 1; } screen->pb.min_alloc_size = 1 << screen->pb.bo_slabs[0].min_order; - screen->pb.bo_export_table = util_hash_table_create_ptr_keys(); - simple_mtx_init(&screen->pb.bo_export_table_lock, mtx_plain); return true; } @@ -1227,6 +1279,4 @@ zink_bo_deinit(struct zink_screen *screen) pb_slabs_deinit(&screen->pb.bo_slabs[i]); } pb_cache_deinit(&screen->pb.bo_cache); - _mesa_hash_table_destroy(screen->pb.bo_export_table, NULL); - simple_mtx_destroy(&screen->pb.bo_export_table_lock); } diff --git a/src/gallium/drivers/zink/zink_bo.h b/src/gallium/drivers/zink/zink_bo.h index 82cedb170d4..19215a4bdc0 100644 --- a/src/gallium/drivers/zink/zink_bo.h +++ b/src/gallium/drivers/zink/zink_bo.h @@ -55,6 +55,15 @@ enum zink_alloc_flag { ZINK_ALLOC_NO_SUBALLOC = 1<<1, }; +struct bo_export { + /** File descriptor associated with a handle export. */ + int drm_fd; + + /** GEM handle in drm_fd */ + uint32_t gem_handle; + + struct list_head link; +}; struct zink_bo { struct pb_buffer base; @@ -63,6 +72,8 @@ struct zink_bo { struct { void *cpu_ptr; /* for user_ptr and permanent maps */ int map_count; + struct list_head exports; + simple_mtx_t export_lock; bool is_user_ptr; bool use_reusable_pool; @@ -175,6 +186,9 @@ zink_bo_deinit(struct zink_screen *screen); struct pb_buffer * zink_bo_create(struct zink_screen *screen, uint64_t size, unsigned alignment, enum zink_heap heap, enum zink_alloc_flag flags, const void *pNext); +bool +zink_bo_get_kms_handle(struct zink_screen *screen, struct zink_bo *bo, int fd, uint32_t *handle); + static inline uint64_t zink_bo_get_offset(const struct zink_bo *bo) { diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 2645450cfe7..6decdd6fefa 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -1299,14 +1299,16 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx, break; } - case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: return false; + case PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS: case PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED: case PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD: { #ifdef ZINK_USE_DMABUF memset(&whandle, 0, sizeof(whandle)); if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED) whandle.type = WINSYS_HANDLE_TYPE_SHARED; + if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS) + whandle.type = WINSYS_HANDLE_TYPE_KMS; else if (param == PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD) whandle.type = WINSYS_HANDLE_TYPE_FD; @@ -1342,7 +1344,7 @@ zink_resource_get_handle(struct pipe_screen *pscreen, struct zink_resource_object *obj = res->obj; #if !defined(_WIN32) - if (whandle->type == WINSYS_HANDLE_TYPE_KMS) { + if (whandle->type == WINSYS_HANDLE_TYPE_KMS && screen->drm_fd == -1) { whandle->handle = -1; } else { if (!res->obj->exportable) { @@ -1368,6 +1370,15 @@ zink_resource_get_handle(struct pipe_screen *pscreen, mesa_loge("ZINK: vkGetMemoryFdKHR failed"); return false; } + if (whandle->type == WINSYS_HANDLE_TYPE_KMS) { + uint32_t h; + bool ret = zink_bo_get_kms_handle(screen, obj->bo, fd, &h); + close(fd); + if (!ret) + return false; + fd = h; + } + whandle->handle = fd; } #else diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index 142c127f3c5..bbc98f0a981 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -128,8 +128,6 @@ struct zink_screen { struct pb_cache bo_cache; struct pb_slabs bo_slabs[NUM_SLAB_ALLOCATORS]; unsigned min_alloc_size; - struct hash_table *bo_export_table; - simple_mtx_t bo_export_table_lock; uint32_t next_bo_unique_id; } pb; uint8_t heap_map[VK_MAX_MEMORY_TYPES];