From: Marek Olšák <marek.ol...@amd.com> --- src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 2 +- src/gallium/auxiliary/pipebuffer/pb_cache.c | 20 ++++++++++++++++---- src/gallium/auxiliary/pipebuffer/pb_cache.h | 6 ++++-- src/gallium/winsys/amdgpu/drm/amdgpu_bo.c | 1 - src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c | 3 ++- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 1 - src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 3 ++- 7 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 24831f6..4e70048 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -297,16 +297,16 @@ pb_cache_manager_create(struct pb_manager *provider, return NULL; mgr = CALLOC_STRUCT(pb_cache_manager); if (!mgr) return NULL; mgr->base.destroy = pb_cache_manager_destroy; mgr->base.create_buffer = pb_cache_manager_create_buffer; mgr->base.flush = pb_cache_manager_flush; mgr->provider = provider; - pb_cache_init(&mgr->cache, usecs, size_factor, bypass_usage, + pb_cache_init(&mgr->cache, 1, usecs, size_factor, bypass_usage, maximum_cache_size, _pb_cache_buffer_destroy, pb_cache_can_reclaim_buffer); return &mgr->base; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_cache.c b/src/gallium/auxiliary/pipebuffer/pb_cache.c index dd479ae..af899a2 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_cache.c @@ -85,21 +85,21 @@ pb_cache_add_buffer(struct pb_cache_entry *entry) struct pb_cache *mgr = entry->mgr; struct list_head *cache = &mgr->buckets[entry->bucket_index]; struct pb_buffer *buf = entry->buffer; unsigned i; mtx_lock(&mgr->mutex); assert(!pipe_is_referenced(&buf->reference)); int64_t current_time = os_time_get(); - for (i = 0; i < ARRAY_SIZE(mgr->buckets); i++) + for (i = 0; i < mgr->num_heaps; i++) release_expired_buffers_locked(&mgr->buckets[i], current_time); /* Directly release any buffer that exceeds the limit. */ if (mgr->cache_size + buf->size > mgr->max_cache_size) { mgr->destroy_buffer(buf); mtx_unlock(&mgr->mutex); return; } entry->start = os_time_get(); @@ -146,20 +146,22 @@ pb_cache_is_buffer_compat(struct pb_cache_entry *entry, struct pb_buffer * pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size, unsigned alignment, unsigned usage, unsigned bucket_index) { struct pb_cache_entry *entry; struct pb_cache_entry *cur_entry; struct list_head *cur, *next; int64_t now; int ret = 0; + + assert(bucket_index < mgr->num_heaps); struct list_head *cache = &mgr->buckets[bucket_index]; mtx_lock(&mgr->mutex); entry = NULL; cur = cache->next; next = cur->next; /* search in the expired buffers, freeing them in the process */ now = os_time_get(); @@ -222,39 +224,41 @@ pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size, * Empty the cache. Useful when there is not enough memory. */ void pb_cache_release_all_buffers(struct pb_cache *mgr) { struct list_head *curr, *next; struct pb_cache_entry *buf; unsigned i; mtx_lock(&mgr->mutex); - for (i = 0; i < ARRAY_SIZE(mgr->buckets); i++) { + for (i = 0; i < mgr->num_heaps; i++) { struct list_head *cache = &mgr->buckets[i]; curr = cache->next; next = curr->next; while (curr != cache) { buf = LIST_ENTRY(struct pb_cache_entry, curr, head); destroy_buffer_locked(buf); curr = next; next = curr->next; } } mtx_unlock(&mgr->mutex); } void pb_cache_init_entry(struct pb_cache *mgr, struct pb_cache_entry *entry, struct pb_buffer *buf, unsigned bucket_index) { + assert(bucket_index < mgr->num_heaps); + memset(entry, 0, sizeof(*entry)); entry->buffer = buf; entry->mgr = mgr; entry->bucket_index = bucket_index; } /** * Initialize a caching buffer manager. * * @param mgr The cache buffer manager @@ -263,40 +267,48 @@ pb_cache_init_entry(struct pb_cache *mgr, struct pb_cache_entry *entry, * @param size_factor Declare buffers that are size_factor times bigger than * the requested size as cache hits. * @param bypass_usage Bitmask. If (requested usage & bypass_usage) != 0, * buffer allocation requests are rejected. * @param maximum_cache_size Maximum size of all unused buffers the cache can * hold. * @param destroy_buffer Function that destroys a buffer for good. * @param can_reclaim Whether a buffer can be reclaimed (e.g. is not busy) */ void -pb_cache_init(struct pb_cache *mgr, uint usecs, float size_factor, +pb_cache_init(struct pb_cache *mgr, uint num_heaps, + uint usecs, float size_factor, unsigned bypass_usage, uint64_t maximum_cache_size, void (*destroy_buffer)(struct pb_buffer *buf), bool (*can_reclaim)(struct pb_buffer *buf)) { unsigned i; - for (i = 0; i < ARRAY_SIZE(mgr->buckets); i++) + mgr->buckets = CALLOC(num_heaps, sizeof(struct list_head)); + if (!mgr->buckets) + return; + + for (i = 0; i < num_heaps; i++) LIST_INITHEAD(&mgr->buckets[i]); (void) mtx_init(&mgr->mutex, mtx_plain); mgr->cache_size = 0; mgr->max_cache_size = maximum_cache_size; + mgr->num_heaps = num_heaps; mgr->usecs = usecs; mgr->num_buffers = 0; mgr->bypass_usage = bypass_usage; mgr->size_factor = size_factor; mgr->destroy_buffer = destroy_buffer; mgr->can_reclaim = can_reclaim; } /** * Deinitialize the manager completely. */ void pb_cache_deinit(struct pb_cache *mgr) { pb_cache_release_all_buffers(mgr); mtx_destroy(&mgr->mutex); + FREE(mgr->buckets); + mgr->buckets = NULL; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_cache.h b/src/gallium/auxiliary/pipebuffer/pb_cache.h index d082eca..904095c 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_cache.h +++ b/src/gallium/auxiliary/pipebuffer/pb_cache.h @@ -43,38 +43,40 @@ struct pb_cache_entry struct pb_cache *mgr; int64_t start, end; /**< Caching time interval */ unsigned bucket_index; }; struct pb_cache { /* The cache is divided into buckets for minimizing cache misses. * The driver controls which buffer goes into which bucket. */ - struct list_head buckets[4]; + struct list_head *buckets; mtx_t mutex; uint64_t cache_size; uint64_t max_cache_size; + unsigned num_heaps; unsigned usecs; unsigned num_buffers; unsigned bypass_usage; float size_factor; void (*destroy_buffer)(struct pb_buffer *buf); bool (*can_reclaim)(struct pb_buffer *buf); }; void pb_cache_add_buffer(struct pb_cache_entry *entry); struct pb_buffer *pb_cache_reclaim_buffer(struct pb_cache *mgr, pb_size size, unsigned alignment, unsigned usage, unsigned bucket_index); void pb_cache_release_all_buffers(struct pb_cache *mgr); void pb_cache_init_entry(struct pb_cache *mgr, struct pb_cache_entry *entry, struct pb_buffer *buf, unsigned bucket_index); -void pb_cache_init(struct pb_cache *mgr, uint usecs, float size_factor, +void pb_cache_init(struct pb_cache *mgr, uint num_heaps, + uint usecs, float size_factor, unsigned bypass_usage, uint64_t maximum_cache_size, void (*destroy_buffer)(struct pb_buffer *buf), bool (*can_reclaim)(struct pb_buffer *buf)); void pb_cache_deinit(struct pb_cache *mgr); #endif diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c index 4b12735..92c314e 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_bo.c @@ -1219,21 +1219,20 @@ no_slab: alignment = align(alignment, ws->info.gart_page_size); bool use_reusable_pool = flags & RADEON_FLAG_NO_INTERPROCESS_SHARING; if (use_reusable_pool) { int heap = radeon_get_heap_index(domain, flags); assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS); usage = 1 << heap; /* Only set one usage bit for each heap. */ pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap); - assert(pb_cache_bucket < ARRAY_SIZE(ws->bo_cache.buckets)); /* Get a buffer from the cache. */ bo = (struct amdgpu_winsys_bo*) pb_cache_reclaim_buffer(&ws->bo_cache, size, alignment, usage, pb_cache_bucket); if (bo) return &bo->base; } /* Create a new one. */ diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c index ab91faf..707ebf9 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_winsys.c @@ -278,21 +278,22 @@ amdgpu_winsys_create(int fd, const struct pipe_screen_config *config, goto fail; ws->dev = dev; ws->info.drm_major = drm_major; ws->info.drm_minor = drm_minor; if (!do_winsys_init(ws, fd)) goto fail_alloc; /* Create managers. */ - pb_cache_init(&ws->bo_cache, 500000, ws->check_vm ? 1.0f : 2.0f, 0, + pb_cache_init(&ws->bo_cache, 4, + 500000, ws->check_vm ? 1.0f : 2.0f, 0, (ws->info.vram_size + ws->info.gart_size) / 8, amdgpu_bo_destroy, amdgpu_bo_can_reclaim); if (!pb_slabs_init(&ws->bo_slabs, AMDGPU_SLAB_MIN_SIZE_LOG2, AMDGPU_SLAB_MAX_SIZE_LOG2, RADEON_MAX_SLAB_HEAPS, ws, amdgpu_bo_can_reclaim_slab, amdgpu_bo_slab_alloc, amdgpu_bo_slab_free)) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index fc95a98..4be6f40 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -978,21 +978,20 @@ no_slab: bool use_reusable_pool = flags & RADEON_FLAG_NO_INTERPROCESS_SHARING; /* Shared resources don't use cached heaps. */ if (use_reusable_pool) { int heap = radeon_get_heap_index(domain, flags); assert(heap >= 0 && heap < RADEON_MAX_CACHED_HEAPS); usage = 1 << heap; /* Only set one usage bit for each heap. */ pb_cache_bucket = radeon_get_pb_cache_bucket_index(heap); - assert(pb_cache_bucket < ARRAY_SIZE(ws->bo_cache.buckets)); bo = radeon_bo(pb_cache_reclaim_buffer(&ws->bo_cache, size, alignment, usage, pb_cache_bucket)); if (bo) return &bo->base; } bo = radeon_create_bo(ws, size, alignment, usage, domain, flags, pb_cache_bucket); if (!bo) { diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index e600199..f7d7998 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -752,21 +752,22 @@ radeon_drm_winsys_create(int fd, const struct pipe_screen_config *config, if (!ws) { mtx_unlock(&fd_tab_mutex); return NULL; } ws->fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); if (!do_winsys_init(ws)) goto fail1; - pb_cache_init(&ws->bo_cache, 500000, ws->check_vm ? 1.0f : 2.0f, 0, + pb_cache_init(&ws->bo_cache, 4, + 500000, ws->check_vm ? 1.0f : 2.0f, 0, MIN2(ws->info.vram_size, ws->info.gart_size), radeon_bo_destroy, radeon_bo_can_reclaim); if (ws->info.has_virtual_memory) { /* There is no fundamental obstacle to using slab buffer allocation * without GPUVM, but enabling it requires making sure that the drivers * honor the address offset. */ if (!pb_slabs_init(&ws->bo_slabs, -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev