From 7557f1605968c39d680545d5b8457d17eea3b922 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 6 Mar 2020 13:34:23 +0200 Subject: [PATCH] iris: share buffer managers accross screens St happilly uses pipe_resources created with one screen with other screens. Unfortunately our resources have a single identifier that related to a given screen and its associated DRM file descriptor. To workaround this, let's share the buffer manager between screens for a given DRM device. That way handles are always valid. v2: Don't forget to close the fd that bufmgr now owns Take a copy of the fd to ensure it stays alive even if the dri layer closes it Signed-off-by: Lionel Landwerlin Cc: Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/1373 Reviewed-by: Adam Jackson Reviewed-by: Rafael Antognolli Part-of: --- src/gallium/drivers/iris/iris_bufmgr.c | 88 ++++++++++++++++++++++++-- src/gallium/drivers/iris/iris_bufmgr.h | 11 ++-- src/gallium/drivers/iris/iris_screen.c | 19 +++--- src/gallium/drivers/iris/iris_screen.h | 2 +- 4 files changed, 101 insertions(+), 19 deletions(-) diff --git a/src/gallium/drivers/iris/iris_bufmgr.c b/src/gallium/drivers/iris/iris_bufmgr.c index b0259e7d607..ca8db31aed3 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.c +++ b/src/gallium/drivers/iris/iris_bufmgr.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "errno.h" #include "common/gen_aux_map.h" @@ -126,6 +127,13 @@ struct bo_cache_bucket { }; struct iris_bufmgr { + /** + * List into the list of bufmgr. + */ + struct list_head link; + + uint32_t refcount; + int fd; mtx_t lock; @@ -152,6 +160,12 @@ struct iris_bufmgr { struct gen_aux_map_context *aux_map_ctx; }; +static mtx_t global_bufmgr_list_mutex = _MTX_INITIALIZER_NP; +static struct list_head global_bufmgr_list = { + .next = &global_bufmgr_list, + .prev = &global_bufmgr_list, +}; + static int bo_set_tiling_internal(struct iris_bo *bo, uint32_t tiling_mode, uint32_t stride); @@ -1201,7 +1215,7 @@ iris_bo_wait(struct iris_bo *bo, int64_t timeout_ns) return ret; } -void +static void iris_bufmgr_destroy(struct iris_bufmgr *bufmgr) { /* Free aux-map buffers */ @@ -1237,6 +1251,8 @@ iris_bufmgr_destroy(struct iris_bufmgr *bufmgr) util_vma_heap_finish(&bufmgr->vma_allocator[z]); } + close(bufmgr->fd); + free(bufmgr); } @@ -1622,8 +1638,8 @@ static struct gen_mapped_pinned_buffer_alloc aux_map_allocator = { * * \param fd File descriptor of the opened DRM device. */ -struct iris_bufmgr * -iris_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) +static struct iris_bufmgr * +iris_bufmgr_create(struct gen_device_info *devinfo, int fd, bool bo_reuse) { uint64_t gtt_size = iris_gtt_size(fd); if (gtt_size <= IRIS_MEMZONE_OTHER_START) @@ -1642,9 +1658,12 @@ iris_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) * Don't do this! Ensure that each library/bufmgr has its own device * fd so that its namespace does not clash with another. */ - bufmgr->fd = fd; + bufmgr->fd = dup(fd); + + p_atomic_set(&bufmgr->refcount, 1); if (mtx_init(&bufmgr->lock, mtx_plain) != 0) { + close(bufmgr->fd); free(bufmgr); return NULL; } @@ -1700,6 +1719,67 @@ iris_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) return bufmgr; } +static struct iris_bufmgr * +iris_bufmgr_ref(struct iris_bufmgr *bufmgr) +{ + p_atomic_inc(&bufmgr->refcount); + return bufmgr; +} + +void +iris_bufmgr_unref(struct iris_bufmgr *bufmgr) +{ + mtx_lock(&global_bufmgr_list_mutex); + if (p_atomic_dec_zero(&bufmgr->refcount)) { + list_del(&bufmgr->link); + iris_bufmgr_destroy(bufmgr); + } + mtx_unlock(&global_bufmgr_list_mutex); +} + +/** + * Gets an already existing GEM buffer manager or create a new one. + * + * \param fd File descriptor of the opened DRM device. + */ +struct iris_bufmgr * +iris_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, bool bo_reuse) +{ + struct stat st; + + if (fstat(fd, &st)) + return NULL; + + struct iris_bufmgr *bufmgr = NULL; + + mtx_lock(&global_bufmgr_list_mutex); + list_for_each_entry(struct iris_bufmgr, iter_bufmgr, &global_bufmgr_list, link) { + struct stat iter_st; + if (fstat(iter_bufmgr->fd, &iter_st)) + continue; + + if (st.st_rdev == iter_st.st_rdev) { + assert(iter_bufmgr->bo_reuse == bo_reuse); + bufmgr = iris_bufmgr_ref(iter_bufmgr); + goto unlock; + } + } + + bufmgr = iris_bufmgr_create(devinfo, fd, bo_reuse); + list_addtail(&bufmgr->link, &global_bufmgr_list); + + unlock: + mtx_unlock(&global_bufmgr_list_mutex); + + return bufmgr; +} + +int +iris_bufmgr_get_fd(struct iris_bufmgr *bufmgr) +{ + return bufmgr->fd; +} + void* iris_bufmgr_get_aux_map_context(struct iris_bufmgr *bufmgr) { diff --git a/src/gallium/drivers/iris/iris_bufmgr.h b/src/gallium/drivers/iris/iris_bufmgr.h index 1d6ef975559..caeba61a650 100644 --- a/src/gallium/drivers/iris/iris_bufmgr.h +++ b/src/gallium/drivers/iris/iris_bufmgr.h @@ -285,10 +285,11 @@ static inline int iris_bo_unmap(struct iris_bo *bo) { return 0; } */ void iris_bo_wait_rendering(struct iris_bo *bo); + /** - * Tears down the buffer manager instance. + * Unref a buffer manager instance. */ -void iris_bufmgr_destroy(struct iris_bufmgr *bufmgr); +void iris_bufmgr_unref(struct iris_bufmgr *bufmgr); /** * Get the current tiling (and resulting swizzling) mode for the bo. @@ -329,8 +330,10 @@ int iris_bo_busy(struct iris_bo *bo); int iris_bo_madvise(struct iris_bo *bo, int madv); /* drm_bacon_bufmgr_gem.c */ -struct iris_bufmgr *iris_bufmgr_init(struct gen_device_info *devinfo, int fd, - bool bo_reuse); +struct iris_bufmgr *iris_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, + bool bo_reuse); +int iris_bufmgr_get_fd(struct iris_bufmgr *bufmgr); + struct iris_bo *iris_bo_gem_create_from_name(struct iris_bufmgr *bufmgr, const char *name, unsigned handle); diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c index d6c7e4b0ac5..6afd1235f8c 100644 --- a/src/gallium/drivers/iris/iris_screen.c +++ b/src/gallium/drivers/iris/iris_screen.c @@ -527,9 +527,8 @@ iris_destroy_screen(struct pipe_screen *pscreen) struct iris_screen *screen = (struct iris_screen *) pscreen; iris_bo_unreference(screen->workaround_bo); u_transfer_helper_destroy(pscreen->transfer_helper); - iris_bufmgr_destroy(screen->bufmgr); + iris_bufmgr_unref(screen->bufmgr); disk_cache_destroy(screen->disk_cache); - close(screen->fd); ralloc_free(screen); } @@ -635,8 +634,6 @@ iris_screen_create(int fd, const struct pipe_screen_config *config) if (!screen) return NULL; - screen->fd = fd; - if (!gen_get_device_info_from_fd(fd, &screen->devinfo)) return NULL; screen->pci_id = screen->devinfo.chipset_id; @@ -645,11 +642,6 @@ iris_screen_create(int fd, const struct pipe_screen_config *config) if (screen->devinfo.gen < 8 || screen->devinfo.is_cherryview) return NULL; - screen->aperture_bytes = get_aperture_size(fd); - - if (getenv("INTEL_NO_HW") != NULL) - screen->no_hw = true; - bool bo_reuse = false; int bo_reuse_mode = driQueryOptioni(config->options, "bo_reuse"); switch (bo_reuse_mode) { @@ -660,10 +652,17 @@ iris_screen_create(int fd, const struct pipe_screen_config *config) break; } - screen->bufmgr = iris_bufmgr_init(&screen->devinfo, fd, bo_reuse); + screen->bufmgr = iris_bufmgr_get_for_fd(&screen->devinfo, fd, bo_reuse); if (!screen->bufmgr) return NULL; + screen->fd = iris_bufmgr_get_fd(screen->bufmgr); + + screen->aperture_bytes = get_aperture_size(fd); + + if (getenv("INTEL_NO_HW") != NULL) + screen->no_hw = true; + screen->workaround_bo = iris_bo_alloc(screen->bufmgr, "workaround", 4096, IRIS_MEMZONE_OTHER); if (!screen->workaround_bo) diff --git a/src/gallium/drivers/iris/iris_screen.h b/src/gallium/drivers/iris/iris_screen.h index 34f6fd1c16b..cd5bac9e54e 100644 --- a/src/gallium/drivers/iris/iris_screen.h +++ b/src/gallium/drivers/iris/iris_screen.h @@ -49,7 +49,7 @@ struct iris_screen { /** Global slab allocator for iris_transfer_map objects */ struct slab_parent_pool transfer_pool; - /** drm device file descriptor */ + /** drm device file descriptor, on shared with bufmgr, do not close. */ int fd; /** PCI ID for our GPU device */ -- 2.30.2