X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fvc4%2Fvc4_bufmgr.c;h=716ca50ea0696ef2f34070bc16336ff569214f54;hb=376054fff34a5b2d2c123bdc5d27af6196ef0f51;hp=9c4cc4cba88cef4aeee87e2b911c336fa3054857;hpb=a8fd58eae59607ac42eaa7187b0d9e6c51b83af9;p=mesa.git diff --git a/src/gallium/drivers/vc4/vc4_bufmgr.c b/src/gallium/drivers/vc4/vc4_bufmgr.c index 9c4cc4cba88..716ca50ea06 100644 --- a/src/gallium/drivers/vc4/vc4_bufmgr.c +++ b/src/gallium/drivers/vc4/vc4_bufmgr.c @@ -30,6 +30,7 @@ #include "util/u_hash_table.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "util/ralloc.h" #include "vc4_context.h" @@ -48,6 +49,13 @@ 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) +{ + util_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, ...) { @@ -56,7 +64,7 @@ vc4_bo_label(struct vc4_screen *screen, struct vc4_bo *bo, const char *fmt, ...) * (for debugging a single app's allocation). */ #ifndef DEBUG - if (!(VC4_DEBUG & VC4_DEBUG_SURFACE)) + if (!(vc4_debug & VC4_DEBUG_SURFACE)) return; #endif va_list va; @@ -69,7 +77,7 @@ vc4_bo_label(struct vc4_screen *screen, struct vc4_bo *bo, const char *fmt, ...) .len = strlen(name), .name = (uintptr_t)name, }; - drmIoctl(screen->fd, DRM_IOCTL_VC4_LABEL_BO, &label); + vc4_ioctl(screen->fd, DRM_IOCTL_VC4_LABEL_BO, &label); ralloc_free(name); } @@ -113,35 +121,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; @@ -220,42 +298,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) { @@ -325,6 +367,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); @@ -343,7 +386,6 @@ vc4_bo_last_unreference_locked_timed(struct vc4_bo *bo, time_t 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; @@ -354,7 +396,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; } @@ -367,8 +409,7 @@ 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 @@ -380,8 +421,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 @@ -393,11 +433,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); @@ -414,7 +454,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