X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_bufmgr.c;h=a786e8ee939ad354320a01b1243f233d26f3ee07;hb=518537d1c8c8958db97bc08bf28182cc9e43921b;hp=0653f882323225e95b7c4b776e74849bd9778804;hpb=ef578906d849bf05d04d246e9e3994146dddc01d;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c index 0653f882323..a786e8ee939 100644 --- a/src/gallium/drivers/vc4/vc4_bufmgr.c +++ b/src/gallium/drivers/vc4/vc4_bufmgr.c @@ -30,24 +30,50 @@ #include "util/u_hash_table.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "util/ralloc.h" #include "vc4_context.h" #include "vc4_screen.h" -#ifdef HAVE_VALGRIND -#include -#include -#define VG(x) x -#else -#define VG(x) -#endif - static bool dump_stats = false; static void vc4_bo_cache_free_all(struct vc4_bo_cache *cache); +void +vc4_bo_debug_describe(char* buf, const struct vc4_bo *ptr) +{ + sprintf(buf, "vc4_bo<%s,%u,%u>", ptr->name ? ptr->name : "?", + ptr->handle, ptr->size); +} + +void +vc4_bo_label(struct vc4_screen *screen, struct vc4_bo *bo, const char *fmt, ...) +{ + /* Perform BO labeling by default on debug builds (so that you get + * whole-system allocation information), or if VC4_DEBUG=surf is set + * (for debugging a single app's allocation). + */ +#ifndef DEBUG + if (!(vc4_debug & VC4_DEBUG_SURFACE)) + return; +#endif + va_list va; + va_start(va, fmt); + char *name = ralloc_vasprintf(NULL, fmt, va); + va_end(va); + + struct drm_vc4_label_bo label = { + .handle = bo->handle, + .len = strlen(name), + .name = (uintptr_t)name, + }; + vc4_ioctl(screen->fd, DRM_IOCTL_VC4_LABEL_BO, &label); + + ralloc_free(name); +} + static void vc4_bo_dump_stats(struct vc4_screen *screen) { @@ -58,7 +84,7 @@ vc4_bo_dump_stats(struct vc4_screen *screen) fprintf(stderr, " BOs cached: %d\n", cache->bo_count); fprintf(stderr, " BOs cached size: %dkb\n", cache->bo_size / 1024); - if (!list_empty(&cache->time_list)) { + if (!list_is_empty(&cache->time_list)) { struct vc4_bo *first = LIST_ENTRY(struct vc4_bo, cache->time_list.next, time_list); @@ -74,7 +100,7 @@ vc4_bo_dump_stats(struct vc4_screen *screen) struct timespec time; clock_gettime(CLOCK_MONOTONIC, &time); fprintf(stderr, " now: %ld\n", - time.tv_sec); + (long)time.tv_sec); } } @@ -87,34 +113,105 @@ vc4_bo_remove_from_cache(struct vc4_bo_cache *cache, struct vc4_bo *bo) cache->bo_size -= bo->size; } +static void vc4_bo_purgeable(struct vc4_bo *bo) +{ + struct drm_vc4_gem_madvise arg = { + .handle = bo->handle, + .madv = VC4_MADV_DONTNEED, + }; + + if (bo->screen->has_madvise) + vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg); +} + +static bool vc4_bo_unpurgeable(struct vc4_bo *bo) +{ + struct drm_vc4_gem_madvise arg = { + .handle = bo->handle, + .madv = VC4_MADV_WILLNEED, + }; + + if (!bo->screen->has_madvise) + return true; + + if (vc4_ioctl(bo->screen->fd, DRM_IOCTL_VC4_GEM_MADVISE, &arg)) + return false; + + return arg.retained; +} + +static void +vc4_bo_free(struct vc4_bo *bo) +{ + struct vc4_screen *screen = bo->screen; + + if (bo->map) { + if (using_vc4_simulator && bo->name && + strcmp(bo->name, "winsys") == 0) { + free(bo->map); + } else { + munmap(bo->map, bo->size); + VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0)); + } + } + + struct drm_gem_close c; + memset(&c, 0, sizeof(c)); + c.handle = bo->handle; + int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c); + if (ret != 0) + fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno)); + + screen->bo_count--; + screen->bo_size -= bo->size; + + if (dump_stats) { + fprintf(stderr, "Freed %s%s%dkb:\n", + bo->name ? bo->name : "", + bo->name ? " " : "", + bo->size / 1024); + vc4_bo_dump_stats(screen); + } + + free(bo); +} + static struct vc4_bo * vc4_bo_from_cache(struct vc4_screen *screen, uint32_t size, const char *name) { struct vc4_bo_cache *cache = &screen->bo_cache; uint32_t page_index = size / 4096 - 1; + struct vc4_bo *iter, *tmp, *bo = NULL; if (cache->size_list_size <= page_index) return NULL; - struct vc4_bo *bo = NULL; mtx_lock(&cache->lock); - if (!list_empty(&cache->size_list[page_index])) { - bo = LIST_ENTRY(struct vc4_bo, cache->size_list[page_index].next, - size_list); - - /* Check that the BO has gone idle. If not, then we want to - * allocate something new instead, since we assume that the - * user will proceed to CPU map it and fill it with stuff. + LIST_FOR_EACH_ENTRY_SAFE(iter, tmp, &cache->size_list[page_index], + size_list) { + /* Check that the BO has gone idle. If not, then none of the + * other BOs (pushed to the list after later rendering) are + * likely to be idle, either. */ - if (!vc4_bo_wait(bo, 0, NULL)) { - mtx_unlock(&cache->lock); - return NULL; - } + if (!vc4_bo_wait(iter, 0, NULL)) + break; + + if (!vc4_bo_unpurgeable(iter)) { + /* The BO has been purged. Free it and try to find + * another one in the cache. + */ + vc4_bo_remove_from_cache(cache, iter); + vc4_bo_free(iter); + continue; + } + bo = iter; pipe_reference_init(&bo->reference, 1); vc4_bo_remove_from_cache(cache, bo); + vc4_bo_label(screen, bo, "%s", name); bo->name = name; + break; } mtx_unlock(&cache->lock); return bo; @@ -158,7 +255,7 @@ vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name) bo->handle = create.handle; if (ret != 0) { - if (!list_empty(&screen->bo_cache.time_list) && + if (!list_is_empty(&screen->bo_cache.time_list) && !cleared_and_retried) { cleared_and_retried = true; vc4_bo_cache_free_all(&screen->bo_cache); @@ -176,6 +273,8 @@ vc4_bo_alloc(struct vc4_screen *screen, uint32_t size, const char *name) vc4_bo_dump_stats(screen); } + vc4_bo_label(screen, bo, "%s", name); + return bo; } @@ -191,42 +290,6 @@ vc4_bo_last_unreference(struct vc4_bo *bo) mtx_unlock(&screen->bo_cache.lock); } -static void -vc4_bo_free(struct vc4_bo *bo) -{ - struct vc4_screen *screen = bo->screen; - - if (bo->map) { - if (using_vc4_simulator && bo->name && - strcmp(bo->name, "winsys") == 0) { - free(bo->map); - } else { - munmap(bo->map, bo->size); - VG(VALGRIND_FREELIKE_BLOCK(bo->map, 0)); - } - } - - struct drm_gem_close c; - memset(&c, 0, sizeof(c)); - c.handle = bo->handle; - int ret = vc4_ioctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &c); - if (ret != 0) - fprintf(stderr, "close object %d: %s\n", bo->handle, strerror(errno)); - - screen->bo_count--; - screen->bo_size -= bo->size; - - if (dump_stats) { - fprintf(stderr, "Freed %s%s%dkb:\n", - bo->name ? bo->name : "", - bo->name ? " " : "", - bo->size / 1024); - vc4_bo_dump_stats(screen); - } - - free(bo); -} - static void free_stale_bos(struct vc4_screen *screen, time_t time) { @@ -296,6 +359,7 @@ vc4_bo_last_unreference_locked_timed(struct vc4_bo *bo, time_t time) cache->size_list_size = page_index + 1; } + vc4_bo_purgeable(bo); bo->free_time = time; list_addtail(&bo->size_list, &cache->size_list[page_index]); list_addtail(&bo->time_list, &cache->time_list); @@ -307,13 +371,13 @@ vc4_bo_last_unreference_locked_timed(struct vc4_bo *bo, time_t time) vc4_bo_dump_stats(screen); } bo->name = NULL; + vc4_bo_label(screen, bo, "mesa cache"); free_stale_bos(screen, time); } static struct vc4_bo * vc4_bo_open_handle(struct vc4_screen *screen, - uint32_t winsys_stride, uint32_t handle, uint32_t size) { struct vc4_bo *bo; @@ -324,7 +388,7 @@ vc4_bo_open_handle(struct vc4_screen *screen, bo = util_hash_table_get(screen->bo_handles, (void*)(uintptr_t)handle); if (bo) { - pipe_reference(NULL, &bo->reference); + vc4_bo_reference(bo); goto done; } @@ -337,12 +401,11 @@ vc4_bo_open_handle(struct vc4_screen *screen, bo->private = false; #ifdef USE_VC4_SIMULATOR - vc4_simulator_open_from_handle(screen->fd, winsys_stride, - bo->handle, bo->size); + vc4_simulator_open_from_handle(screen->fd, bo->handle, bo->size); bo->map = malloc(bo->size); #endif - util_hash_table_set(screen->bo_handles, (void *)(uintptr_t)handle, bo); + _mesa_hash_table_insert(screen->bo_handles, (void *)(uintptr_t)handle, bo); done: mtx_unlock(&screen->bo_handles_mutex); @@ -350,8 +413,7 @@ done: } struct vc4_bo * -vc4_bo_open_name(struct vc4_screen *screen, uint32_t name, - uint32_t winsys_stride) +vc4_bo_open_name(struct vc4_screen *screen, uint32_t name) { struct drm_gem_open o = { .name = name @@ -363,11 +425,11 @@ vc4_bo_open_name(struct vc4_screen *screen, uint32_t name, return NULL; } - return vc4_bo_open_handle(screen, winsys_stride, o.handle, o.size); + return vc4_bo_open_handle(screen, o.handle, o.size); } struct vc4_bo * -vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd, uint32_t winsys_stride) +vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd) { uint32_t handle; int ret = drmPrimeFDToHandle(screen->fd, fd, &handle); @@ -384,7 +446,7 @@ vc4_bo_open_dmabuf(struct vc4_screen *screen, int fd, uint32_t winsys_stride) return NULL; } - return vc4_bo_open_handle(screen, winsys_stride, handle, size); + return vc4_bo_open_handle(screen, handle, size); } int @@ -401,7 +463,7 @@ vc4_bo_get_dmabuf(struct vc4_bo *bo) mtx_lock(&bo->screen->bo_handles_mutex); bo->private = false; - util_hash_table_set(bo->screen->bo_handles, (void *)(uintptr_t)bo->handle, bo); + _mesa_hash_table_insert(bo->screen->bo_handles, (void *)(uintptr_t)bo->handle, bo); mtx_unlock(&bo->screen->bo_handles_mutex); return fd;