X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnouveau%2Fnouveau_mm.c;h=43b3d99f48a7e5a6de75de5f4460ecfd6953ef45;hb=1a99fc0fd022018ed056cd42f299d5ad1a02c264;hp=1c4bb61af88e9db201c1ec13d2d8bbe9af691dca;hpb=2f30a5bdaad480118e23ac4243de3b4a11ba62a8;p=mesa.git diff --git a/src/gallium/drivers/nouveau/nouveau_mm.c b/src/gallium/drivers/nouveau/nouveau_mm.c index 1c4bb61af88..43b3d99f48a 100644 --- a/src/gallium/drivers/nouveau/nouveau_mm.c +++ b/src/gallium/drivers/nouveau/nouveau_mm.c @@ -1,15 +1,23 @@ +#include + #include "util/u_inlines.h" #include "util/u_memory.h" -#include "util/u_double_list.h" +#include "util/list.h" +#include "nouveau_winsys.h" #include "nouveau_screen.h" #include "nouveau_mm.h" -#include "nouveau/nouveau_bo.h" +/* TODO: Higher orders can waste a lot of space for npot size buffers, should + * add an extra cache for such buffer objects. + * + * HACK: Max order == 21 to accommodate TF2's 1.5 MiB, frequently reallocated + * vertex buffer (VM flush (?) decreases performance dramatically). + */ -#define MM_MIN_ORDER 7 -#define MM_MAX_ORDER 20 +#define MM_MIN_ORDER 7 /* >= 6 to not violate ARB_map_buffer_alignment */ +#define MM_MAX_ORDER 21 #define MM_NUM_BUCKETS (MM_MAX_ORDER - MM_MIN_ORDER + 1) @@ -26,8 +34,8 @@ struct mm_bucket { struct nouveau_mman { struct nouveau_device *dev; struct mm_bucket bucket[MM_NUM_BUCKETS]; - uint32_t storage_type; uint32_t domain; + union nouveau_bo_config config; uint64_t allocated; }; @@ -62,7 +70,7 @@ mm_slab_alloc(struct mm_slab *slab) return -1; } -static INLINE void +static inline void mm_slab_free(struct mm_slab *slab, int i) { assert(i < slab->count); @@ -71,7 +79,7 @@ mm_slab_free(struct mm_slab *slab, int i) assert(slab->free <= slab->count); } -static INLINE int +static inline int mm_get_order(uint32_t size) { int s = __builtin_clz(size) ^ 31; @@ -96,12 +104,12 @@ mm_bucket_by_size(struct nouveau_mman *cache, unsigned size) } /* size of bo allocation for slab with chunks of (1 << chunk_order) bytes */ -static INLINE uint32_t +static inline uint32_t mm_default_slab_size(unsigned chunk_order) { static const int8_t slab_order[MM_MAX_ORDER - MM_MIN_ORDER + 1] = { - 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22 + 12, 12, 13, 14, 14, 17, 17, 17, 17, 19, 19, 20, 21, 22, 22 }; assert(chunk_order <= MM_MAX_ORDER && chunk_order >= MM_MIN_ORDER); @@ -126,8 +134,9 @@ mm_slab_new(struct nouveau_mman *cache, int chunk_order) memset(&slab->bits[0], ~0, words * 4); slab->bo = NULL; - ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, - 0, cache->storage_type, &slab->bo); + + ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, + &slab->bo); if (ret) { FREE(slab); return PIPE_ERROR_OUT_OF_MEMORY; @@ -143,8 +152,9 @@ mm_slab_new(struct nouveau_mman *cache, int chunk_order) cache->allocated += size; - debug_printf("MM: new slab, total memory = %lu KiB\n", - cache->allocated / 1024); + if (nouveau_mesa_debug) + debug_printf("MM: new slab, total memory = %"PRIu64" KiB\n", + cache->allocated / 1024); return PIPE_OK; } @@ -152,7 +162,7 @@ mm_slab_new(struct nouveau_mman *cache, int chunk_order) /* @return token to identify slab or NULL if we just allocated a new bo */ struct nouveau_mm_allocation * nouveau_mm_allocate(struct nouveau_mman *cache, - uint32_t size, struct nouveau_bo **bo, uint32_t *offset) + uint32_t size, struct nouveau_bo **bo, uint32_t *offset) { struct mm_bucket *bucket; struct mm_slab *slab; @@ -161,10 +171,11 @@ nouveau_mm_allocate(struct nouveau_mman *cache, bucket = mm_bucket_by_size(cache, size); if (!bucket) { - ret = nouveau_bo_new_tile(cache->dev, cache->domain, 0, size, - 0, cache->storage_type, bo); + ret = nouveau_bo_new(cache->dev, cache->domain, 0, size, &cache->config, + bo); if (ret) - debug_printf("bo_new(%x, %x): %i\n", size, cache->storage_type, ret); + debug_printf("bo_new(%x, %x): %i\n", + size, cache->config.nv50.memtype, ret); *offset = 0; return NULL; @@ -210,21 +221,27 @@ nouveau_mm_free(struct nouveau_mm_allocation *alloc) mm_slab_free(slab, alloc->offset >> slab->order); + if (slab->free == slab->count) { + LIST_DEL(&slab->head); + LIST_ADDTAIL(&slab->head, &bucket->free); + } else if (slab->free == 1) { LIST_DEL(&slab->head); - - if (slab->count > 1) - LIST_ADDTAIL(&slab->head, &bucket->used); - else - LIST_ADDTAIL(&slab->head, &bucket->free); + LIST_ADDTAIL(&slab->head, &bucket->used); } FREE(alloc); } +void +nouveau_mm_free_work(void *data) +{ + nouveau_mm_free(data); +} + struct nouveau_mman * nouveau_mm_create(struct nouveau_device *dev, uint32_t domain, - uint32_t storage_type) + union nouveau_bo_config *config) { struct nouveau_mman *cache = MALLOC_STRUCT(nouveau_mman); int i; @@ -234,7 +251,7 @@ nouveau_mm_create(struct nouveau_device *dev, uint32_t domain, cache->dev = dev; cache->domain = domain; - cache->storage_type = storage_type; + cache->config = *config; cache->allocated = 0; for (i = 0; i < MM_NUM_BUCKETS; ++i) { @@ -246,7 +263,7 @@ nouveau_mm_create(struct nouveau_device *dev, uint32_t domain, return cache; } -static INLINE void +static inline void nouveau_mm_free_slabs(struct list_head *head) { struct mm_slab *slab, *next; @@ -276,5 +293,6 @@ nouveau_mm_destroy(struct nouveau_mman *cache) nouveau_mm_free_slabs(&cache->bucket[i].used); nouveau_mm_free_slabs(&cache->bucket[i].full); } -} + FREE(cache); +}