#include <xf86drm.h>
#include <xf86drmMode.h>
+#include "util/u_hash_table.h"
#include "util/u_memory.h"
#include "util/ralloc.h"
static bool dump_stats = false;
static void
+vc4_bo_cache_free_all(struct vc4_bo_cache *cache);
+
+static void
vc4_bo_dump_stats(struct vc4_screen *screen)
{
struct vc4_bo_cache *cache = &screen->bo_cache;
fprintf(stderr, " BOs allocated: %d\n", screen->bo_count);
- fprintf(stderr, " BOs size: %dkb\n", screen->bo_size / 102);
+ fprintf(stderr, " BOs size: %dkb\n", screen->bo_size / 1024);
fprintf(stderr, " BOs cached: %d\n", cache->bo_count);
- fprintf(stderr, " BOs cached size: %dkb\n", cache->bo_size / 102);
+ fprintf(stderr, " BOs cached size: %dkb\n", cache->bo_size / 1024);
if (!list_empty(&cache->time_list)) {
struct vc4_bo *first = LIST_ENTRY(struct vc4_bo,
bo->name = name;
bo->private = true;
+ bool cleared_and_retried = false;
+retry:
if (!using_vc4_simulator) {
struct drm_vc4_create_bo create;
memset(&create, 0, sizeof(create));
assert(create.size >= size);
}
if (ret != 0) {
- fprintf(stderr, "create ioctl failure\n");
- abort();
+ if (!list_empty(&screen->bo_cache.time_list) &&
+ !cleared_and_retried) {
+ cleared_and_retried = true;
+ vc4_bo_cache_free_all(&screen->bo_cache);
+ goto retry;
+ }
+
+ free(bo);
+ return NULL;
}
screen->bo_count++;
}
}
+static void
+vc4_bo_cache_free_all(struct vc4_bo_cache *cache)
+{
+ pipe_mutex_lock(cache->lock);
+ list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
+ time_list) {
+ vc4_bo_remove_from_cache(cache, bo);
+ vc4_bo_free(bo);
+ }
+ pipe_mutex_unlock(cache->lock);
+}
+
void
vc4_bo_last_unreference_locked_timed(struct vc4_bo *bo, time_t time)
{
uint32_t winsys_stride,
uint32_t handle, uint32_t size)
{
- struct vc4_bo *bo = CALLOC_STRUCT(vc4_bo);
+ struct vc4_bo *bo;
assert(size);
+ pipe_mutex_lock(screen->bo_handles_mutex);
+
+ bo = util_hash_table_get(screen->bo_handles, (void*)(uintptr_t)handle);
+ if (bo) {
+ pipe_reference(NULL, &bo->reference);
+ goto done;
+ }
+
+ bo = CALLOC_STRUCT(vc4_bo);
pipe_reference_init(&bo->reference, 1);
bo->screen = screen;
bo->handle = handle;
bo->map = malloc(bo->size);
#endif
+ util_hash_table_set(screen->bo_handles, (void *)(uintptr_t)handle, bo);
+
+done:
+ pipe_mutex_unlock(screen->bo_handles_mutex);
return bo;
}
bo->handle);
return -1;
}
+
+ pipe_mutex_lock(bo->screen->bo_handles_mutex);
bo->private = false;
+ util_hash_table_set(bo->screen->bo_handles, (void *)(uintptr_t)bo->handle, bo);
+ pipe_mutex_unlock(bo->screen->bo_handles_mutex);
return fd;
}
screen->bo_count++;
screen->bo_size += bo->size;
if (dump_stats) {
- fprintf(stderr, "Allocated shader %dkb:\n", size / 1024);
+ fprintf(stderr, "Allocated shader %dkb:\n", bo->size / 1024);
vc4_bo_dump_stats(screen);
}
struct vc4_screen *screen = vc4_screen(pscreen);
struct vc4_bo_cache *cache = &screen->bo_cache;
- list_for_each_entry_safe(struct vc4_bo, bo, &cache->time_list,
- time_list) {
- vc4_bo_remove_from_cache(cache, bo);
- vc4_bo_free(bo);
- }
+ vc4_bo_cache_free_all(cache);
if (dump_stats) {
fprintf(stderr, "BO stats after screen destroy:\n");