From 4094558e8643a266dfc8da9bc073751a3736a2fb Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Fri, 6 Mar 2020 17:06:25 +0200 Subject: [PATCH] i965: share buffer managers across screens 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/mesa/drivers/dri/i965/brw_bufmgr.c | 85 ++++++++++++++++++++++-- src/mesa/drivers/dri/i965/brw_bufmgr.h | 11 +-- src/mesa/drivers/dri/i965/intel_screen.c | 8 ++- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c index 8c1a6a722f5..e3c5ec3e51a 100644 --- a/src/mesa/drivers/dri/i965/brw_bufmgr.c +++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c @@ -136,6 +136,10 @@ struct bo_cache_bucket { }; struct brw_bufmgr { + uint32_t refcount; + + struct list_head link; + int fd; mtx_t lock; @@ -157,6 +161,12 @@ struct brw_bufmgr { uint64_t initial_kflags; }; +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 brw_bo *bo, uint32_t tiling_mode, uint32_t stride); @@ -1279,8 +1289,19 @@ brw_bo_wait(struct brw_bo *bo, int64_t timeout_ns) } void -brw_bufmgr_destroy(struct brw_bufmgr *bufmgr) +brw_bufmgr_unref(struct brw_bufmgr *bufmgr) { + mtx_lock(&global_bufmgr_list_mutex); + if (p_atomic_dec_zero(&bufmgr->refcount)) { + list_del(&bufmgr->link); + } else { + bufmgr = NULL; + } + mtx_unlock(&global_bufmgr_list_mutex); + + if (!bufmgr) + return; + mtx_destroy(&bufmgr->lock); /* Free any cached buffer objects we were going to reuse */ @@ -1309,6 +1330,9 @@ brw_bufmgr_destroy(struct brw_bufmgr *bufmgr) } } + close(bufmgr->fd); + bufmgr->fd = -1; + free(bufmgr); } @@ -1651,14 +1675,21 @@ brw_using_softpin(struct brw_bufmgr *bufmgr) return bufmgr->initial_kflags & EXEC_OBJECT_PINNED; } +static struct brw_bufmgr * +brw_bufmgr_ref(struct brw_bufmgr *bufmgr) +{ + p_atomic_inc(&bufmgr->refcount); + return bufmgr; +} + /** * Initializes the GEM buffer manager, which uses the kernel to allocate, map, * and manage map buffer objections. * * \param fd File descriptor of the opened DRM device. */ -struct brw_bufmgr * -brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) +static struct brw_bufmgr * +brw_bufmgr_create(struct gen_device_info *devinfo, int fd, bool bo_reuse) { struct brw_bufmgr *bufmgr; @@ -1675,9 +1706,16 @@ brw_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); + if (bufmgr->fd < 0) { + free(bufmgr); + return NULL; + } + + p_atomic_set(&bufmgr->refcount, 1); if (mtx_init(&bufmgr->lock, mtx_plain) != 0) { + close(bufmgr->fd); free(bufmgr); return NULL; } @@ -1719,6 +1757,7 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) * might actually mean requiring 4.14. */ fprintf(stderr, "i965 requires softpin (Kernel 4.5) on Gen10+."); + close(bufmgr->fd); free(bufmgr); return NULL; } @@ -1733,3 +1772,41 @@ brw_bufmgr_init(struct gen_device_info *devinfo, int fd, bool bo_reuse) return bufmgr; } + +struct brw_bufmgr * +brw_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, bool bo_reuse) +{ + struct stat st; + + if (fstat(fd, &st)) + return NULL; + + struct brw_bufmgr *bufmgr = NULL; + + mtx_lock(&global_bufmgr_list_mutex); + list_for_each_entry(struct brw_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 = brw_bufmgr_ref(iter_bufmgr); + goto unlock; + } + } + + bufmgr = brw_bufmgr_create(devinfo, fd, bo_reuse); + list_addtail(&bufmgr->link, &global_bufmgr_list); + + unlock: + mtx_unlock(&global_bufmgr_list_mutex); + + return bufmgr; +} + +int +brw_bufmgr_get_fd(struct brw_bufmgr *bufmgr) +{ + return bufmgr->fd; +} diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.h b/src/mesa/drivers/dri/i965/brw_bufmgr.h index 5dc342cf8c6..499309b5bd3 100644 --- a/src/mesa/drivers/dri/i965/brw_bufmgr.h +++ b/src/mesa/drivers/dri/i965/brw_bufmgr.h @@ -300,9 +300,9 @@ int brw_bo_subdata(struct brw_bo *bo, uint64_t offset, void brw_bo_wait_rendering(struct brw_bo *bo); /** - * Tears down the buffer manager instance. + * Unref a buffer manager instance. */ -void brw_bufmgr_destroy(struct brw_bufmgr *bufmgr); +void brw_bufmgr_unref(struct brw_bufmgr *bufmgr); /** * Get the current tiling (and resulting swizzling) mode for the bo. @@ -343,8 +343,9 @@ int brw_bo_busy(struct brw_bo *bo); int brw_bo_madvise(struct brw_bo *bo, int madv); /* drm_bacon_bufmgr_gem.c */ -struct brw_bufmgr *brw_bufmgr_init(struct gen_device_info *devinfo, int fd, - bool bo_reuse); +struct brw_bufmgr *brw_bufmgr_get_for_fd(struct gen_device_info *devinfo, int fd, + bool bo_reuse); + struct brw_bo *brw_bo_gem_create_from_name(struct brw_bufmgr *bufmgr, const char *name, unsigned int handle); @@ -359,6 +360,8 @@ int brw_hw_context_set_priority(struct brw_bufmgr *bufmgr, void brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id); +int brw_bufmgr_get_fd(struct brw_bufmgr *bufmgr); + int brw_bo_gem_export_to_prime(struct brw_bo *bo, int *prime_fd); struct brw_bo *brw_bo_gem_create_from_prime(struct brw_bufmgr *bufmgr, int prime_fd); diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c index 02d2406c93d..abc899c8163 100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -1707,7 +1707,7 @@ intelDestroyScreen(__DRIscreen * sPriv) { struct intel_screen *screen = sPriv->driverPrivate; - brw_bufmgr_destroy(screen->bufmgr); + brw_bufmgr_unref(screen->bufmgr); driDestroyOptionInfo(&screen->optionCache); disk_cache_destroy(screen->disk_cache); @@ -1910,6 +1910,8 @@ err_out: static bool intel_init_bufmgr(struct intel_screen *screen) { + __DRIscreen *dri_screen = screen->driScrnPriv; + if (getenv("INTEL_NO_HW") != NULL) screen->no_hw = true; @@ -1923,12 +1925,13 @@ intel_init_bufmgr(struct intel_screen *screen) break; } - screen->bufmgr = brw_bufmgr_init(&screen->devinfo, screen->fd, bo_reuse); + screen->bufmgr = brw_bufmgr_get_for_fd(&screen->devinfo, dri_screen->fd, bo_reuse); if (screen->bufmgr == NULL) { fprintf(stderr, "[%s:%u] Error initializing buffer manager.\n", __func__, __LINE__); return false; } + screen->fd = brw_bufmgr_get_fd(screen->bufmgr); if (!intel_get_boolean(screen, I915_PARAM_HAS_EXEC_NO_RELOC)) { fprintf(stderr, "[%s: %u] Kernel 3.9 required.\n", __func__, __LINE__); @@ -2561,7 +2564,6 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen) return NULL; } - screen->fd = dri_screen->fd; if (!intel_init_bufmgr(screen)) return NULL; -- 2.30.2