1/*
2 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
3 * Copyright © 2015 Advanced Micro Devices, Inc.
4 * Copyright © 2021 Valve Corporation
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
19 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * The above copyright notice and this permission notice (including the
25 * next paragraph) shall be included in all copies or substantial portions
26 * of the Software.
27 *
28 * Authors:
29 *    Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
30 */
31
32#include "zink_context.h"
33#include "zink_bo.h"
34#include "zink_resource.h"
35#include "zink_screen.h"
36#include "util/u_hash_table.h"
37
38#if !defined(__APPLE__) && !defined(_WIN32)
39#define ZINK_USE_DMABUF
40#include <xf86drm.h>
41#endif
42
43struct zink_bo;
44
45struct zink_sparse_backing_chunk {
46   uint32_t begin, end;
47};
48
49
50/*
51 * Sub-allocation information for a real buffer used as backing memory of a
52 * sparse buffer.
53 */
54struct zink_sparse_backing {
55   struct list_head list;
56
57   struct zink_bo *bo;
58
59   /* Sorted list of free chunks. */
60   struct zink_sparse_backing_chunk *chunks;
61   uint32_t max_chunks;
62   uint32_t num_chunks;
63};
64
65struct zink_sparse_commitment {
66   struct zink_sparse_backing *backing;
67   uint32_t page;
68};
69
70struct zink_slab {
71   struct pb_slab base;
72   unsigned entry_size;
73   struct zink_bo *buffer;
74   struct zink_bo *entries;
75};
76
77
78ALWAYS_INLINE static struct zink_slab *
79zink_slab(struct pb_slab *pslab)
80{
81   return (struct zink_slab*)pslab;
82}
83
84static struct pb_slabs *
85get_slabs(struct zink_screen *screen, uint64_t size, enum zink_alloc_flag flags)
86{
87   //struct pb_slabs *bo_slabs = ((flags & RADEON_FLAG_ENCRYPTED) && screen->info.has_tmz_support) ?
88      //screen->bo_slabs_encrypted : screen->bo_slabs;
89
90   struct pb_slabs *bo_slabs = screen->pb.bo_slabs;
91   /* Find the correct slab allocator for the given size. */
92   for (unsigned i = 0; i < NUM_SLAB_ALLOCATORS; i++) {
93      struct pb_slabs *slabs = &bo_slabs[i];
94
95      if (size <= 1ULL << (slabs->min_order + slabs->num_orders - 1))
96         return slabs;
97   }
98
99   assert(0);
100   return NULL;
101}
102
103/* Return the power of two size of a slab entry matching the input size. */
104static unsigned
105get_slab_pot_entry_size(struct zink_screen *screen, unsigned size)
106{
107   unsigned entry_size = util_next_power_of_two(size);
108   unsigned min_entry_size = 1 << screen->pb.bo_slabs[0].min_order;
109
110   return MAX2(entry_size, min_entry_size);
111}
112
113/* Return the slab entry alignment. */
114static unsigned get_slab_entry_alignment(struct zink_screen *screen, unsigned size)
115{
116   unsigned entry_size = get_slab_pot_entry_size(screen, size);
117
118   if (size <= entry_size * 3 / 4)
119      return entry_size / 4;
120
121   return entry_size;
122}
123
124static void
125bo_destroy(struct zink_screen *screen, struct pb_buffer *pbuf)
126{
127   struct zink_bo *bo = zink_bo(pbuf);
128
129#ifdef ZINK_USE_DMABUF
130   if (bo->mem && !bo->u.real.use_reusable_pool) {
131      simple_mtx_lock(&bo->u.real.export_lock);
132      list_for_each_entry_safe(struct bo_export, export, &bo->u.real.exports, link) {
133         struct drm_gem_close args = { .handle = export->gem_handle };
134         drmIoctl(export->drm_fd, DRM_IOCTL_GEM_CLOSE, &args);
135         list_del(&export->link);
136         free(export);
137      }
138      simple_mtx_unlock(&bo->u.real.export_lock);
139      simple_mtx_destroy(&bo->u.real.export_lock);
140   }
141#endif
142
143   if (!bo->u.real.is_user_ptr && bo->u.real.cpu_ptr) {
144      bo->u.real.map_count = 1;
145      bo->u.real.cpu_ptr = NULL;
146      zink_bo_unmap(screen, bo);
147   }
148
149   VKSCR(FreeMemory)(screen->dev, bo->mem, NULL);
150
151   simple_mtx_destroy(&bo->lock);
152   FREE(bo);
153}
154
155static bool
156bo_can_reclaim(struct zink_screen *screen, struct pb_buffer *pbuf)
157{
158   struct zink_bo *bo = zink_bo(pbuf);
159
160   return zink_screen_usage_check_completion(screen, bo->reads) && zink_screen_usage_check_completion(screen, bo->writes);
161}
162
163static bool
164bo_can_reclaim_slab(void *priv, struct pb_slab_entry *entry)
165{
166   struct zink_bo *bo = container_of(entry, struct zink_bo, u.slab.entry);
167
168   return bo_can_reclaim(priv, &bo->base);
169}
170
171static void
172bo_slab_free(struct zink_screen *screen, struct pb_slab *pslab)
173{
174   struct zink_slab *slab = zink_slab(pslab);
175   ASSERTED unsigned slab_size = slab->buffer->base.size;
176
177   assert(slab->base.num_entries * slab->entry_size <= slab_size);
178   FREE(slab->entries);
179   zink_bo_unref(screen, slab->buffer);
180   FREE(slab);
181}
182
183static void
184bo_slab_destroy(struct zink_screen *screen, struct pb_buffer *pbuf)
185{
186   struct zink_bo *bo = zink_bo(pbuf);
187
188   assert(!bo->mem);
189
190   //if (bo->base.usage & RADEON_FLAG_ENCRYPTED)
191      //pb_slab_free(get_slabs(screen, bo->base.size, RADEON_FLAG_ENCRYPTED), &bo->u.slab.entry);
192   //else
193      pb_slab_free(get_slabs(screen, bo->base.size, 0), &bo->u.slab.entry);
194}
195
196static void
197clean_up_buffer_managers(struct zink_screen *screen)
198{
199   for (unsigned i = 0; i < NUM_SLAB_ALLOCATORS; i++) {
200      pb_slabs_reclaim(&screen->pb.bo_slabs[i]);
201      //if (screen->info.has_tmz_support)
202         //pb_slabs_reclaim(&screen->bo_slabs_encrypted[i]);
203   }
204
205   pb_cache_release_all_buffers(&screen->pb.bo_cache);
206}
207
208static unsigned
209get_optimal_alignment(struct zink_screen *screen, uint64_t size, unsigned alignment)
210{
211   /* Increase the alignment for faster address translation and better memory
212    * access pattern.
213    */
214   if (size >= 4096) {
215      alignment = MAX2(alignment, 4096);
216   } else if (size) {
217      unsigned msb = util_last_bit(size);
218
219      alignment = MAX2(alignment, 1u << (msb - 1));
220   }
221   return alignment;
222}
223
224static void
225bo_destroy_or_cache(struct zink_screen *screen, struct pb_buffer *pbuf)
226{
227   struct zink_bo *bo = zink_bo(pbuf);
228
229   assert(bo->mem); /* slab buffers have a separate vtbl */
230   bo->reads = NULL;
231   bo->writes = NULL;
232
233   if (bo->u.real.use_reusable_pool)
234      pb_cache_add_buffer(bo->cache_entry);
235   else
236      bo_destroy(screen, pbuf);
237}
238
239static const struct pb_vtbl bo_vtbl = {
240   /* Cast to void* because one of the function parameters is a struct pointer instead of void*. */
241   (void*)bo_destroy_or_cache
242   /* other functions are never called */
243};
244
245static struct zink_bo *
246bo_create_internal(struct zink_screen *screen,
247                   uint64_t size,
248                   unsigned alignment,
249                   enum zink_heap heap,
250                   unsigned flags,
251                   const void *pNext)
252{
253   struct zink_bo *bo = NULL;
254   bool init_pb_cache;
255
256   /* too big for vk alloc */
257   if (size > UINT32_MAX)
258      return NULL;
259
260   alignment = get_optimal_alignment(screen, size, alignment);
261
262   VkMemoryAllocateInfo mai;
263   mai.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
264   mai.pNext = pNext;
265   mai.allocationSize = size;
266   mai.memoryTypeIndex = screen->heap_map[heap];
267   if (screen->info.mem_props.memoryTypes[mai.memoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
268      alignment = MAX2(alignment, screen->info.props.limits.minMemoryMapAlignment);
269      mai.allocationSize = align64(mai.allocationSize, screen->info.props.limits.minMemoryMapAlignment);
270   }
271   unsigned heap_idx = screen->info.mem_props.memoryTypes[screen->heap_map[heap]].heapIndex;
272   if (mai.allocationSize > screen->info.mem_props.memoryHeaps[heap_idx].size) {
273      mesa_loge("zink: can't allocate %"PRIu64" bytes from heap that's only %"PRIu64" bytes!\n", mai.allocationSize, screen->info.mem_props.memoryHeaps[heap_idx].size);
274      return NULL;
275   }
276
277   /* all non-suballocated bo can cache */
278   init_pb_cache = !pNext;
279
280   if (!bo)
281      bo = CALLOC(1, sizeof(struct zink_bo) + init_pb_cache * sizeof(struct pb_cache_entry));
282   if (!bo) {
283      return NULL;
284   }
285
286   VkResult ret = VKSCR(AllocateMemory)(screen->dev, &mai, NULL, &bo->mem);
287   if (!zink_screen_handle_vkresult(screen, ret)) {
288      mesa_loge("zink: couldn't allocate memory: heap=%u size=%" PRIu64, heap, size);
289      goto fail;
290   }
291
292   if (init_pb_cache) {
293      bo->u.real.use_reusable_pool = true;
294      pb_cache_init_entry(&screen->pb.bo_cache, bo->cache_entry, &bo->base, heap);
295   } else {
296#ifdef ZINK_USE_DMABUF
297      list_inithead(&bo->u.real.exports);
298      simple_mtx_init(&bo->u.real.export_lock, mtx_plain);
299#endif
300   }
301
302
303   simple_mtx_init(&bo->lock, mtx_plain);
304   pipe_reference_init(&bo->base.reference, 1);
305   bo->base.alignment_log2 = util_logbase2(alignment);
306   bo->base.size = mai.allocationSize;
307   bo->base.vtbl = &bo_vtbl;
308   bo->base.placement = screen->heap_flags[heap];
309   bo->base.usage = flags;
310   bo->unique_id = p_atomic_inc_return(&screen->pb.next_bo_unique_id);
311
312   return bo;
313
314fail:
315   bo_destroy(screen, (void*)bo);
316   return NULL;
317}
318
319/*
320 * Attempt to allocate the given number of backing pages. Fewer pages may be
321 * allocated (depending on the fragmentation of existing backing buffers),
322 * which will be reflected by a change to *pnum_pages.
323 */
324static struct zink_sparse_backing *
325sparse_backing_alloc(struct zink_screen *screen, struct zink_bo *bo,
326                     uint32_t *pstart_page, uint32_t *pnum_pages)
327{
328   struct zink_sparse_backing *best_backing;
329   unsigned best_idx;
330   uint32_t best_num_pages;
331
332   best_backing = NULL;
333   best_idx = 0;
334   best_num_pages = 0;
335
336   /* This is a very simple and inefficient best-fit algorithm. */
337   list_for_each_entry(struct zink_sparse_backing, backing, &bo->u.sparse.backing, list) {
338      for (unsigned idx = 0; idx < backing->num_chunks; ++idx) {
339         uint32_t cur_num_pages = backing->chunks[idx].end - backing->chunks[idx].begin;
340         if ((best_num_pages < *pnum_pages && cur_num_pages > best_num_pages) ||
341            (best_num_pages > *pnum_pages && cur_num_pages < best_num_pages)) {
342            best_backing = backing;
343            best_idx = idx;
344            best_num_pages = cur_num_pages;
345         }
346      }
347   }
348
349   /* Allocate a new backing buffer if necessary. */
350   if (!best_backing) {
351      struct pb_buffer *buf;
352      uint64_t size;
353      uint32_t pages;
354
355      best_backing = CALLOC_STRUCT(zink_sparse_backing);
356      if (!best_backing)
357         return NULL;
358
359      best_backing->max_chunks = 4;
360      best_backing->chunks = CALLOC(best_backing->max_chunks,
361                                    sizeof(*best_backing->chunks));
362      if (!best_backing->chunks) {
363         FREE(best_backing);
364         return NULL;
365      }
366
367      assert(bo->u.sparse.num_backing_pages < DIV_ROUND_UP(bo->base.size, ZINK_SPARSE_BUFFER_PAGE_SIZE));
368
369      size = MIN3(bo->base.size / 16,
370                  8 * 1024 * 1024,
371                  bo->base.size - (uint64_t)bo->u.sparse.num_backing_pages * ZINK_SPARSE_BUFFER_PAGE_SIZE);
372      size = MAX2(size, ZINK_SPARSE_BUFFER_PAGE_SIZE);
373
374      buf = zink_bo_create(screen, size, ZINK_SPARSE_BUFFER_PAGE_SIZE,
375                           ZINK_HEAP_DEVICE_LOCAL, 0, NULL);
376      if (!buf) {
377         FREE(best_backing->chunks);
378         FREE(best_backing);
379         return NULL;
380      }
381
382      /* We might have gotten a bigger buffer than requested via caching. */
383      pages = buf->size / ZINK_SPARSE_BUFFER_PAGE_SIZE;
384
385      best_backing->bo = zink_bo(buf);
386      best_backing->num_chunks = 1;
387      best_backing->chunks[0].begin = 0;
388      best_backing->chunks[0].end = pages;
389
390      list_add(&best_backing->list, &bo->u.sparse.backing);
391      bo->u.sparse.num_backing_pages += pages;
392
393      best_idx = 0;
394      best_num_pages = pages;
395   }
396
397   *pnum_pages = MIN2(*pnum_pages, best_num_pages);
398   *pstart_page = best_backing->chunks[best_idx].begin;
399   best_backing->chunks[best_idx].begin += *pnum_pages;
400
401   if (best_backing->chunks[best_idx].begin >= best_backing->chunks[best_idx].end) {
402      memmove(&best_backing->chunks[best_idx], &best_backing->chunks[best_idx + 1],
403              sizeof(*best_backing->chunks) * (best_backing->num_chunks - best_idx - 1));
404      best_backing->num_chunks--;
405   }
406
407   return best_backing;
408}
409
410static void
411sparse_free_backing_buffer(struct zink_screen *screen, struct zink_bo *bo,
412                           struct zink_sparse_backing *backing)
413{
414   bo->u.sparse.num_backing_pages -= backing->bo->base.size / ZINK_SPARSE_BUFFER_PAGE_SIZE;
415
416   list_del(&backing->list);
417   zink_bo_unref(screen, backing->bo);
418   FREE(backing->chunks);
419   FREE(backing);
420}
421
422/*
423 * Return a range of pages from the given backing buffer back into the
424 * free structure.
425 */
426static bool
427sparse_backing_free(struct zink_screen *screen, struct zink_bo *bo,
428                    struct zink_sparse_backing *backing,
429                    uint32_t start_page, uint32_t num_pages)
430{
431   uint32_t end_page = start_page + num_pages;
432   unsigned low = 0;
433   unsigned high = backing->num_chunks;
434
435   /* Find the first chunk with begin >= start_page. */
436   while (low < high) {
437      unsigned mid = low + (high - low) / 2;
438
439      if (backing->chunks[mid].begin >= start_page)
440         high = mid;
441      else
442         low = mid + 1;
443   }
444
445   assert(low >= backing->num_chunks || end_page <= backing->chunks[low].begin);
446   assert(low == 0 || backing->chunks[low - 1].end <= start_page);
447
448   if (low > 0 && backing->chunks[low - 1].end == start_page) {
449      backing->chunks[low - 1].end = end_page;
450
451      if (low < backing->num_chunks && end_page == backing->chunks[low].begin) {
452         backing->chunks[low - 1].end = backing->chunks[low].end;
453         memmove(&backing->chunks[low], &backing->chunks[low + 1],
454                 sizeof(*backing->chunks) * (backing->num_chunks - low - 1));
455         backing->num_chunks--;
456      }
457   } else if (low < backing->num_chunks && end_page == backing->chunks[low].begin) {
458      backing->chunks[low].begin = start_page;
459   } else {
460      if (backing->num_chunks >= backing->max_chunks) {
461         unsigned new_max_chunks = 2 * backing->max_chunks;
462         struct zink_sparse_backing_chunk *new_chunks =
463            REALLOC(backing->chunks,
464                    sizeof(*backing->chunks) * backing->max_chunks,
465                    sizeof(*backing->chunks) * new_max_chunks);
466         if (!new_chunks)
467            return false;
468
469         backing->max_chunks = new_max_chunks;
470         backing->chunks = new_chunks;
471      }
472
473      memmove(&backing->chunks[low + 1], &backing->chunks[low],
474              sizeof(*backing->chunks) * (backing->num_chunks - low));
475      backing->chunks[low].begin = start_page;
476      backing->chunks[low].end = end_page;
477      backing->num_chunks++;
478   }
479
480   if (backing->num_chunks == 1 && backing->chunks[0].begin == 0 &&
481       backing->chunks[0].end == backing->bo->base.size / ZINK_SPARSE_BUFFER_PAGE_SIZE)
482      sparse_free_backing_buffer(screen, bo, backing);
483
484   return true;
485}
486
487static void
488bo_sparse_destroy(struct zink_screen *screen, struct pb_buffer *pbuf)
489{
490   struct zink_bo *bo = zink_bo(pbuf);
491
492   assert(!bo->mem && bo->base.usage & ZINK_ALLOC_SPARSE);
493
494   while (!list_is_empty(&bo->u.sparse.backing)) {
495      sparse_free_backing_buffer(screen, bo,
496                                 container_of(bo->u.sparse.backing.next,
497                                              struct zink_sparse_backing, list));
498   }
499
500   FREE(bo->u.sparse.commitments);
501   simple_mtx_destroy(&bo->lock);
502   FREE(bo);
503}
504
505static const struct pb_vtbl bo_sparse_vtbl = {
506   /* Cast to void* because one of the function parameters is a struct pointer instead of void*. */
507   (void*)bo_sparse_destroy
508   /* other functions are never called */
509};
510
511static struct pb_buffer *
512bo_sparse_create(struct zink_screen *screen, uint64_t size)
513{
514   struct zink_bo *bo;
515
516   /* We use 32-bit page numbers; refuse to attempt allocating sparse buffers
517    * that exceed this limit. This is not really a restriction: we don't have
518    * that much virtual address space anyway.
519    */
520   if (size > (uint64_t)INT32_MAX * ZINK_SPARSE_BUFFER_PAGE_SIZE)
521      return NULL;
522
523   bo = CALLOC_STRUCT(zink_bo);
524   if (!bo)
525      return NULL;
526
527   simple_mtx_init(&bo->lock, mtx_plain);
528   pipe_reference_init(&bo->base.reference, 1);
529   bo->base.alignment_log2 = util_logbase2(ZINK_SPARSE_BUFFER_PAGE_SIZE);
530   bo->base.size = size;
531   bo->base.vtbl = &bo_sparse_vtbl;
532   bo->base.placement = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
533   bo->unique_id = p_atomic_inc_return(&screen->pb.next_bo_unique_id);
534   bo->base.usage = ZINK_ALLOC_SPARSE;
535
536   bo->u.sparse.num_va_pages = DIV_ROUND_UP(size, ZINK_SPARSE_BUFFER_PAGE_SIZE);
537   bo->u.sparse.commitments = CALLOC(bo->u.sparse.num_va_pages,
538                                     sizeof(*bo->u.sparse.commitments));
539   if (!bo->u.sparse.commitments)
540      goto error_alloc_commitments;
541
542   list_inithead(&bo->u.sparse.backing);
543
544   return &bo->base;
545
546error_alloc_commitments:
547   simple_mtx_destroy(&bo->lock);
548   FREE(bo);
549   return NULL;
550}
551
552struct pb_buffer *
553zink_bo_create(struct zink_screen *screen, uint64_t size, unsigned alignment, enum zink_heap heap, enum zink_alloc_flag flags, const void *pNext)
554{
555   struct zink_bo *bo;
556   /* pull in sparse flag */
557   flags |= zink_alloc_flags_from_heap(heap);
558
559   //struct pb_slabs *slabs = ((flags & RADEON_FLAG_ENCRYPTED) && screen->info.has_tmz_support) ?
560      //screen->bo_slabs_encrypted : screen->bo_slabs;
561   struct pb_slabs *slabs = screen->pb.bo_slabs;
562
563   struct pb_slabs *last_slab = &slabs[NUM_SLAB_ALLOCATORS - 1];
564   unsigned max_slab_entry_size = 1 << (last_slab->min_order + last_slab->num_orders - 1);
565
566   /* Sub-allocate small buffers from slabs. */
567   if (!(flags & (ZINK_ALLOC_NO_SUBALLOC | ZINK_ALLOC_SPARSE)) &&
568       size <= max_slab_entry_size) {
569      struct pb_slab_entry *entry;
570
571      if (heap < 0 || heap >= ZINK_HEAP_MAX)
572         goto no_slab;
573
574      unsigned alloc_size = size;
575
576      /* Always use slabs for sizes less than 4 KB because the kernel aligns
577       * everything to 4 KB.
578       */
579      if (size < alignment && alignment <= 4 * 1024)
580         alloc_size = alignment;
581
582      if (alignment > get_slab_entry_alignment(screen, alloc_size)) {
583         /* 3/4 allocations can return too small alignment. Try again with a power of two
584          * allocation size.
585          */
586         unsigned pot_size = get_slab_pot_entry_size(screen, alloc_size);
587
588         if (alignment <= pot_size) {
589            /* This size works but wastes some memory to fulfil the alignment. */
590            alloc_size = pot_size;
591         } else {
592            goto no_slab; /* can't fulfil alignment requirements */
593         }
594      }
595
596      struct pb_slabs *slabs = get_slabs(screen, alloc_size, flags);
597      bool reclaim_all = false;
598      if (heap == ZINK_HEAP_DEVICE_LOCAL_VISIBLE && !screen->resizable_bar) {
599         unsigned low_bound = 128 * 1024 * 1024; //128MB is a very small BAR
600         if (screen->info.driver_props.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY)
601            low_bound *= 2; //nvidia has fat textures or something
602         unsigned heapidx = screen->info.mem_props.memoryTypes[screen->heap_map[heap]].heapIndex;
603         reclaim_all = screen->info.mem_props.memoryHeaps[heapidx].size <= low_bound;
604      }
605      entry = pb_slab_alloc_reclaimed(slabs, alloc_size, heap, reclaim_all);
606      if (!entry) {
607         /* Clean up buffer managers and try again. */
608         clean_up_buffer_managers(screen);
609
610         entry = pb_slab_alloc_reclaimed(slabs, alloc_size, heap, true);
611      }
612      if (!entry)
613         return NULL;
614
615      bo = container_of(entry, struct zink_bo, u.slab.entry);
616      pipe_reference_init(&bo->base.reference, 1);
617      bo->base.size = size;
618      assert(alignment <= 1 << bo->base.alignment_log2);
619
620      return &bo->base;
621   }
622no_slab:
623
624   if (flags & ZINK_ALLOC_SPARSE) {
625      assert(ZINK_SPARSE_BUFFER_PAGE_SIZE % alignment == 0);
626
627      return bo_sparse_create(screen, size);
628   }
629
630   /* Align size to page size. This is the minimum alignment for normal
631    * BOs. Aligning this here helps the cached bufmgr. Especially small BOs,
632    * like constant/uniform buffers, can benefit from better and more reuse.
633    */
634   if (heap == ZINK_HEAP_DEVICE_LOCAL_VISIBLE) {
635      size = align64(size, screen->info.props.limits.minMemoryMapAlignment);
636      alignment = align(alignment, screen->info.props.limits.minMemoryMapAlignment);
637   }
638
639   bool use_reusable_pool = !(flags & ZINK_ALLOC_NO_SUBALLOC);
640
641   if (use_reusable_pool) {
642       /* Get a buffer from the cache. */
643       bo = (struct zink_bo*)
644            pb_cache_reclaim_buffer(&screen->pb.bo_cache, size, alignment, 0, heap);
645       if (bo)
646          return &bo->base;
647   }
648
649   /* Create a new one. */
650   bo = bo_create_internal(screen, size, alignment, heap, flags, pNext);
651   if (!bo) {
652      /* Clean up buffer managers and try again. */
653      clean_up_buffer_managers(screen);
654
655      bo = bo_create_internal(screen, size, alignment, heap, flags, pNext);
656      if (!bo)
657         return NULL;
658   }
659
660   return &bo->base;
661}
662
663void *
664zink_bo_map(struct zink_screen *screen, struct zink_bo *bo)
665{
666   void *cpu = NULL;
667   uint64_t offset = 0;
668   struct zink_bo *real;
669
670   if (bo->mem) {
671      real = bo;
672   } else {
673      real = bo->u.slab.real;
674      offset = bo->offset - real->offset;
675   }
676
677   cpu = p_atomic_read(&real->u.real.cpu_ptr);
678   if (!cpu) {
679      simple_mtx_lock(&real->lock);
680      /* Must re-check due to the possibility of a race. Re-check need not
681       * be atomic thanks to the lock. */
682      cpu = real->u.real.cpu_ptr;
683      if (!cpu) {
684         VkResult result = VKSCR(MapMemory)(screen->dev, real->mem, 0, real->base.size, 0, &cpu);
685         if (result != VK_SUCCESS) {
686            mesa_loge("ZINK: vkMapMemory failed (%s)", vk_Result_to_str(result));
687            simple_mtx_unlock(&real->lock);
688            return NULL;
689         }
690         p_atomic_set(&real->u.real.cpu_ptr, cpu);
691      }
692      simple_mtx_unlock(&real->lock);
693   }
694   p_atomic_inc(&real->u.real.map_count);
695
696   return (uint8_t*)cpu + offset;
697}
698
699void
700zink_bo_unmap(struct zink_screen *screen, struct zink_bo *bo)
701{
702   struct zink_bo *real = bo->mem ? bo : bo->u.slab.real;
703
704   assert(real->u.real.map_count != 0 && "too many unmaps");
705
706   if (p_atomic_dec_zero(&real->u.real.map_count)) {
707      p_atomic_set(&real->u.real.cpu_ptr, NULL);
708      VKSCR(UnmapMemory)(screen->dev, real->mem);
709   }
710}
711
712static VkSemaphore
713get_semaphore(struct zink_screen *screen)
714{
715   VkSemaphoreCreateInfo sci = {
716      VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
717      NULL,
718      0
719   };
720   VkSemaphore sem;
721   VkResult ret = VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &sem);
722   return ret == VK_SUCCESS ? sem : VK_NULL_HANDLE;
723}
724
725static VkSemaphore
726buffer_commit_single(struct zink_screen *screen, struct zink_resource *res, struct zink_bo *bo, uint32_t bo_offset, uint32_t offset, uint32_t size, bool commit, VkSemaphore wait)
727{
728   VkSemaphore sem = get_semaphore(screen);
729   VkBindSparseInfo sparse = {0};
730   sparse.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
731   sparse.bufferBindCount = res->obj->storage_buffer ? 2 : 1;
732   sparse.waitSemaphoreCount = !!wait;
733   sparse.pWaitSemaphores = &wait;
734   sparse.signalSemaphoreCount = 1;
735   sparse.pSignalSemaphores = &sem;
736
737   VkSparseBufferMemoryBindInfo sparse_bind[2];
738   sparse_bind[0].buffer = res->obj->buffer;
739   sparse_bind[1].buffer = res->obj->storage_buffer;
740   sparse_bind[0].bindCount = 1;
741   sparse_bind[1].bindCount = 1;
742   sparse.pBufferBinds = sparse_bind;
743
744   VkSparseMemoryBind mem_bind;
745   mem_bind.resourceOffset = offset;
746   mem_bind.size = MIN2(res->base.b.width0 - offset, size);
747   mem_bind.memory = commit ? (bo->mem ? bo->mem : bo->u.slab.real->mem) : VK_NULL_HANDLE;
748   mem_bind.memoryOffset = bo_offset * ZINK_SPARSE_BUFFER_PAGE_SIZE + (commit ? (bo->mem ? 0 : bo->offset) : 0);
749   mem_bind.flags = 0;
750   sparse_bind[0].pBinds = &mem_bind;
751   sparse_bind[1].pBinds = &mem_bind;
752
753   VkResult ret = VKSCR(QueueBindSparse)(screen->queue_sparse, 1, &sparse, VK_NULL_HANDLE);
754   if (zink_screen_handle_vkresult(screen, ret))
755      return sem;
756   VKSCR(DestroySemaphore)(screen->dev, sem, NULL);
757   return VK_NULL_HANDLE;
758}
759
760static bool
761buffer_bo_commit(struct zink_screen *screen, struct zink_resource *res, uint32_t offset, uint32_t size, bool commit, VkSemaphore *sem)
762{
763   bool ok = true;
764   struct zink_bo *bo = res->obj->bo;
765   assert(offset % ZINK_SPARSE_BUFFER_PAGE_SIZE == 0);
766   assert(offset <= bo->base.size);
767   assert(size <= bo->base.size - offset);
768   assert(size % ZINK_SPARSE_BUFFER_PAGE_SIZE == 0 || offset + size == bo->base.size);
769
770   struct zink_sparse_commitment *comm = bo->u.sparse.commitments;
771
772   uint32_t va_page = offset / ZINK_SPARSE_BUFFER_PAGE_SIZE;
773   uint32_t end_va_page = va_page + DIV_ROUND_UP(size, ZINK_SPARSE_BUFFER_PAGE_SIZE);
774   VkSemaphore cur_sem = VK_NULL_HANDLE;
775   if (commit) {
776      while (va_page < end_va_page) {
777         uint32_t span_va_page;
778
779         /* Skip pages that are already committed. */
780         if (comm[va_page].backing) {
781            va_page++;
782            continue;
783         }
784
785         /* Determine length of uncommitted span. */
786         span_va_page = va_page;
787         while (va_page < end_va_page && !comm[va_page].backing)
788            va_page++;
789
790         /* Fill the uncommitted span with chunks of backing memory. */
791         while (span_va_page < va_page) {
792            struct zink_sparse_backing *backing;
793            uint32_t backing_start, backing_size;
794
795            backing_size = va_page - span_va_page;
796            backing = sparse_backing_alloc(screen, bo, &backing_start, &backing_size);
797            if (!backing) {
798               ok = false;
799               goto out;
800            }
801            cur_sem = buffer_commit_single(screen, res, backing->bo, backing_start,
802                                           (uint64_t)span_va_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
803                                           (uint64_t)backing_size * ZINK_SPARSE_BUFFER_PAGE_SIZE, true, cur_sem);
804            if (!cur_sem) {
805               ok = sparse_backing_free(screen, bo, backing, backing_start, backing_size);
806               assert(ok && "sufficient memory should already be allocated");
807
808               ok = false;
809               goto out;
810            }
811
812            while (backing_size) {
813               comm[span_va_page].backing = backing;
814               comm[span_va_page].page = backing_start;
815               span_va_page++;
816               backing_start++;
817               backing_size--;
818            }
819         }
820      }
821   } else {
822      bool done = false;
823      uint32_t base_page = va_page;
824      while (va_page < end_va_page) {
825         struct zink_sparse_backing *backing;
826         uint32_t backing_start;
827         uint32_t span_pages;
828
829         /* Skip pages that are already uncommitted. */
830         if (!comm[va_page].backing) {
831            va_page++;
832            continue;
833         }
834
835         if (!done) {
836            cur_sem = buffer_commit_single(screen, res, NULL, 0,
837                                           (uint64_t)base_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
838                                           (uint64_t)(end_va_page - base_page) * ZINK_SPARSE_BUFFER_PAGE_SIZE, false, cur_sem);
839            if (!cur_sem) {
840               ok = false;
841               goto out;
842            }
843         }
844         done = true;
845
846         /* Group contiguous spans of pages. */
847         backing = comm[va_page].backing;
848         backing_start = comm[va_page].page;
849         comm[va_page].backing = NULL;
850
851         span_pages = 1;
852         va_page++;
853
854         while (va_page < end_va_page &&
855                comm[va_page].backing == backing &&
856                comm[va_page].page == backing_start + span_pages) {
857            comm[va_page].backing = NULL;
858            va_page++;
859            span_pages++;
860         }
861
862         if (!sparse_backing_free(screen, bo, backing, backing_start, span_pages)) {
863            /* Couldn't allocate tracking data structures, so we have to leak */
864            fprintf(stderr, "zink: leaking sparse backing memory\n");
865            ok = false;
866         }
867      }
868   }
869out:
870   *sem = cur_sem;
871   return ok;
872}
873
874static VkSemaphore
875texture_commit_single(struct zink_screen *screen, struct zink_resource *res, VkSparseImageMemoryBind *ibind, unsigned num_binds, bool commit, VkSemaphore wait)
876{
877   VkSemaphore sem = get_semaphore(screen);
878   VkBindSparseInfo sparse = {0};
879   sparse.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
880   sparse.imageBindCount = 1;
881   sparse.waitSemaphoreCount = !!wait;
882   sparse.pWaitSemaphores = &wait;
883   sparse.signalSemaphoreCount = 1;
884   sparse.pSignalSemaphores = &sem;
885
886   VkSparseImageMemoryBindInfo sparse_ibind;
887   sparse_ibind.image = res->obj->image;
888   sparse_ibind.bindCount = num_binds;
889   sparse_ibind.pBinds = ibind;
890   sparse.pImageBinds = &sparse_ibind;
891
892   VkResult ret = VKSCR(QueueBindSparse)(screen->queue_sparse, 1, &sparse, VK_NULL_HANDLE);
893   if (zink_screen_handle_vkresult(screen, ret))
894      return sem;
895   VKSCR(DestroySemaphore)(screen->dev, sem, NULL);
896   return VK_NULL_HANDLE;
897}
898
899static VkSemaphore
900texture_commit_miptail(struct zink_screen *screen, struct zink_resource *res, struct zink_bo *bo, uint32_t bo_offset, uint32_t offset, bool commit, VkSemaphore wait)
901{
902   VkSemaphore sem = get_semaphore(screen);
903   VkBindSparseInfo sparse = {0};
904   sparse.sType = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO;
905   sparse.imageOpaqueBindCount = 1;
906   sparse.waitSemaphoreCount = !!wait;
907   sparse.pWaitSemaphores = &wait;
908   sparse.signalSemaphoreCount = 1;
909   sparse.pSignalSemaphores = &sem;
910
911   VkSparseImageOpaqueMemoryBindInfo sparse_bind;
912   sparse_bind.image = res->obj->image;
913   sparse_bind.bindCount = 1;
914   sparse.pImageOpaqueBinds = &sparse_bind;
915
916   VkSparseMemoryBind mem_bind;
917   mem_bind.resourceOffset = offset;
918   mem_bind.size = MIN2(ZINK_SPARSE_BUFFER_PAGE_SIZE, res->sparse.imageMipTailSize - offset);
919   mem_bind.memory = commit ? (bo->mem ? bo->mem : bo->u.slab.real->mem) : VK_NULL_HANDLE;
920   mem_bind.memoryOffset = bo_offset + (commit ? (bo->mem ? 0 : bo->offset) : 0);
921   mem_bind.flags = 0;
922   sparse_bind.pBinds = &mem_bind;
923
924   VkResult ret = VKSCR(QueueBindSparse)(screen->queue_sparse, 1, &sparse, VK_NULL_HANDLE);
925   if (zink_screen_handle_vkresult(screen, ret))
926      return sem;
927   VKSCR(DestroySemaphore)(screen->dev, sem, NULL);
928   return VK_NULL_HANDLE;
929}
930
931bool
932zink_bo_commit(struct zink_screen *screen, struct zink_resource *res, unsigned level, struct pipe_box *box, bool commit, VkSemaphore *sem)
933{
934   bool ok = true;
935   struct zink_bo *bo = res->obj->bo;
936   VkSemaphore cur_sem = VK_NULL_HANDLE;
937
938   if (screen->faked_e5sparse && res->base.b.format == PIPE_FORMAT_R9G9B9E5_FLOAT)
939      return true;
940
941   simple_mtx_lock(&screen->queue_lock);
942   simple_mtx_lock(&bo->lock);
943   if (res->base.b.target == PIPE_BUFFER) {
944      ok = buffer_bo_commit(screen, res, box->x, box->width, commit, sem);
945      goto out;
946   }
947
948   int gwidth, gheight, gdepth;
949   gwidth = res->sparse.formatProperties.imageGranularity.width;
950   gheight = res->sparse.formatProperties.imageGranularity.height;
951   gdepth = res->sparse.formatProperties.imageGranularity.depth;
952   assert(gwidth && gheight && gdepth);
953
954   struct zink_sparse_commitment *comm = bo->u.sparse.commitments;
955   VkImageSubresource subresource = { res->aspect, level, 0 };
956   unsigned nwidth = DIV_ROUND_UP(box->width, gwidth);
957   unsigned nheight = DIV_ROUND_UP(box->height, gheight);
958   unsigned ndepth = DIV_ROUND_UP(box->depth, gdepth);
959   VkExtent3D lastBlockExtent = {
960			   (box->width % gwidth) ? box->width % gwidth : gwidth,
961			   (box->height % gheight) ? box->height % gheight : gheight,
962			   (box->depth % gdepth) ? box->depth % gdepth : gdepth
963   };
964#define NUM_BATCHED_BINDS 50
965   VkSparseImageMemoryBind ibind[NUM_BATCHED_BINDS];
966   uint32_t backing_start[NUM_BATCHED_BINDS], backing_size[NUM_BATCHED_BINDS];
967   struct zink_sparse_backing *backing[NUM_BATCHED_BINDS];
968   unsigned i = 0;
969   bool commits_pending = false;
970   uint32_t va_page_offset = 0;
971   for (unsigned l = 0; l < level; l++) {
972      unsigned mipwidth = DIV_ROUND_UP(MAX2(res->base.b.width0 >> l, 1), gwidth);
973      unsigned mipheight = DIV_ROUND_UP(MAX2(res->base.b.height0 >> l, 1), gheight);
974      unsigned mipdepth = DIV_ROUND_UP(res->base.b.array_size > 1 ? res->base.b.array_size : MAX2(res->base.b.depth0 >> l, 1), gdepth);
975      va_page_offset += mipwidth * mipheight * mipdepth;
976   }
977   for (unsigned d = 0; d < ndepth; d++) {
978      for (unsigned h = 0; h < nheight; h++) {
979         for (unsigned w = 0; w < nwidth; w++) {
980            ibind[i].subresource = subresource;
981            ibind[i].flags = 0;
982            // Offset
983            ibind[i].offset.x = w * gwidth;
984            ibind[i].offset.y = h * gheight;
985            if (res->base.b.array_size > 1) {
986               ibind[i].subresource.arrayLayer = d * gdepth;
987               ibind[i].offset.z = 0;
988            } else {
989               ibind[i].offset.z = d * gdepth;
990            }
991            // Size of the page
992            ibind[i].extent.width = (w == nwidth - 1) ? lastBlockExtent.width : gwidth;
993            ibind[i].extent.height = (h == nheight - 1) ? lastBlockExtent.height : gheight;
994            ibind[i].extent.depth = (d == ndepth - 1 && res->base.b.target != PIPE_TEXTURE_CUBE) ? lastBlockExtent.depth : gdepth;
995            uint32_t va_page = va_page_offset +
996                              (d + (box->z / gdepth)) * ((MAX2(res->base.b.width0 >> level, 1) / gwidth) * (MAX2(res->base.b.height0 >> level, 1) / gheight)) +
997                              (h + (box->y / gheight)) * (MAX2(res->base.b.width0 >> level, 1) / gwidth) +
998                              (w + (box->x / gwidth));
999
1000            uint32_t end_va_page = va_page + 1;
1001
1002            if (commit) {
1003               while (va_page < end_va_page) {
1004                  uint32_t span_va_page;
1005
1006                  /* Skip pages that are already committed. */
1007                  if (comm[va_page].backing) {
1008                     va_page++;
1009                     continue;
1010                  }
1011
1012                  /* Determine length of uncommitted span. */
1013                  span_va_page = va_page;
1014                  while (va_page < end_va_page && !comm[va_page].backing)
1015                     va_page++;
1016
1017                  /* Fill the uncommitted span with chunks of backing memory. */
1018                  while (span_va_page < va_page) {
1019                     backing_size[i] = va_page - span_va_page;
1020                     backing[i] = sparse_backing_alloc(screen, bo, &backing_start[i], &backing_size[i]);
1021                     if (!backing[i]) {
1022                        ok = false;
1023                        goto out;
1024                     }
1025                     if (level >= res->sparse.imageMipTailFirstLod) {
1026                        uint32_t offset = res->sparse.imageMipTailOffset + d * res->sparse.imageMipTailStride;
1027                        cur_sem = texture_commit_miptail(screen, res, backing[i]->bo, backing_start[i], offset, commit, cur_sem);
1028                        if (!cur_sem)
1029                           goto out;
1030                     } else {
1031                        ibind[i].memory = backing[i]->bo->mem ? backing[i]->bo->mem : backing[i]->bo->u.slab.real->mem;
1032                        ibind[i].memoryOffset = backing_start[i] * ZINK_SPARSE_BUFFER_PAGE_SIZE +
1033                                                (backing[i]->bo->mem ? 0 : backing[i]->bo->offset);
1034                        commits_pending = true;
1035                     }
1036
1037                     while (backing_size[i]) {
1038                        comm[span_va_page].backing = backing[i];
1039                        comm[span_va_page].page = backing_start[i];
1040                        span_va_page++;
1041                        backing_start[i]++;
1042                        backing_size[i]--;
1043                     }
1044                     i++;
1045                  }
1046               }
1047            } else {
1048               ibind[i].memory = VK_NULL_HANDLE;
1049               ibind[i].memoryOffset = 0;
1050
1051               while (va_page < end_va_page) {
1052                  /* Skip pages that are already uncommitted. */
1053                  if (!comm[va_page].backing) {
1054                     va_page++;
1055                     continue;
1056                  }
1057
1058                  /* Group contiguous spans of pages. */
1059                  backing[i] = comm[va_page].backing;
1060                  backing_start[i] = comm[va_page].page;
1061                  comm[va_page].backing = NULL;
1062
1063                  backing_size[i] = 1;
1064                  va_page++;
1065
1066                  while (va_page < end_va_page &&
1067                         comm[va_page].backing == backing[i] &&
1068                         comm[va_page].page == backing_start[i] + backing_size[i]) {
1069                     comm[va_page].backing = NULL;
1070                     va_page++;
1071                     backing_size[i]++;
1072                  }
1073                  if (level >= res->sparse.imageMipTailFirstLod) {
1074                     uint32_t offset = res->sparse.imageMipTailOffset + d * res->sparse.imageMipTailStride;
1075                     cur_sem = texture_commit_miptail(screen, res, NULL, 0, offset, commit, cur_sem);
1076                     if (!cur_sem)
1077                        goto out;
1078                  } else {
1079                     commits_pending = true;
1080                  }
1081                  i++;
1082               }
1083            }
1084            if (i == ARRAY_SIZE(ibind)) {
1085               cur_sem = texture_commit_single(screen, res, ibind, ARRAY_SIZE(ibind), commit, cur_sem);
1086               if (!cur_sem) {
1087                  for (unsigned s = 0; s < i; s++) {
1088                     ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
1089                     if (!ok) {
1090                        /* Couldn't allocate tracking data structures, so we have to leak */
1091                        fprintf(stderr, "zink: leaking sparse backing memory\n");
1092                     }
1093                  }
1094                  ok = false;
1095                  goto out;
1096               }
1097               commits_pending = false;
1098               i = 0;
1099            }
1100         }
1101      }
1102   }
1103   if (commits_pending) {
1104      cur_sem = texture_commit_single(screen, res, ibind, i, commit, cur_sem);
1105      if (!cur_sem) {
1106         for (unsigned s = 0; s < i; s++) {
1107            ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
1108            if (!ok) {
1109               /* Couldn't allocate tracking data structures, so we have to leak */
1110               fprintf(stderr, "zink: leaking sparse backing memory\n");
1111            }
1112         }
1113      }
1114      ok = false;
1115   }
1116out:
1117
1118   simple_mtx_unlock(&bo->lock);
1119   simple_mtx_unlock(&screen->queue_lock);
1120   *sem = cur_sem;
1121   return ok;
1122}
1123
1124bool
1125zink_bo_get_kms_handle(struct zink_screen *screen, struct zink_bo *bo, int fd, uint32_t *handle)
1126{
1127#ifdef ZINK_USE_DMABUF
1128   assert(bo->mem && !bo->u.real.use_reusable_pool);
1129   simple_mtx_lock(&bo->u.real.export_lock);
1130   list_for_each_entry(struct bo_export, export, &bo->u.real.exports, link) {
1131      if (export->drm_fd == fd) {
1132         simple_mtx_unlock(&bo->u.real.export_lock);
1133         *handle = export->gem_handle;
1134         return true;
1135      }
1136   }
1137   struct bo_export *export = CALLOC_STRUCT(bo_export);
1138   if (!export) {
1139      simple_mtx_unlock(&bo->u.real.export_lock);
1140      return false;
1141   }
1142   bool success = drmPrimeFDToHandle(screen->drm_fd, fd, handle) == 0;
1143   if (success) {
1144      list_addtail(&export->link, &bo->u.real.exports);
1145      export->gem_handle = *handle;
1146      export->drm_fd = screen->drm_fd;
1147   } else {
1148      mesa_loge("zink: failed drmPrimeFDToHandle %s", strerror(errno));
1149      FREE(export);
1150   }
1151   simple_mtx_unlock(&bo->u.real.export_lock);
1152   return success;
1153#else
1154   return false;
1155#endif
1156}
1157
1158static const struct pb_vtbl bo_slab_vtbl = {
1159   /* Cast to void* because one of the function parameters is a struct pointer instead of void*. */
1160   (void*)bo_slab_destroy
1161   /* other functions are never called */
1162};
1163
1164static struct pb_slab *
1165bo_slab_alloc(void *priv, unsigned heap, unsigned entry_size, unsigned group_index, bool encrypted)
1166{
1167   struct zink_screen *screen = priv;
1168   uint32_t base_id;
1169   unsigned slab_size = 0;
1170   struct zink_slab *slab = CALLOC_STRUCT(zink_slab);
1171
1172   if (!slab)
1173      return NULL;
1174
1175   //struct pb_slabs *slabs = ((flags & RADEON_FLAG_ENCRYPTED) && screen->info.has_tmz_support) ?
1176      //screen->bo_slabs_encrypted : screen->bo_slabs;
1177   struct pb_slabs *slabs = screen->pb.bo_slabs;
1178
1179   /* Determine the slab buffer size. */
1180   for (unsigned i = 0; i < NUM_SLAB_ALLOCATORS; i++) {
1181      unsigned max_entry_size = 1 << (slabs[i].min_order + slabs[i].num_orders - 1);
1182
1183      if (entry_size <= max_entry_size) {
1184         /* The slab size is twice the size of the largest possible entry. */
1185         slab_size = max_entry_size * 2;
1186
1187         if (!util_is_power_of_two_nonzero(entry_size)) {
1188            assert(util_is_power_of_two_nonzero(entry_size * 4 / 3));
1189
1190            /* If the entry size is 3/4 of a power of two, we would waste space and not gain
1191             * anything if we allocated only twice the power of two for the backing buffer:
1192             *   2 * 3/4 = 1.5 usable with buffer size 2
1193             *
1194             * Allocating 5 times the entry size leads us to the next power of two and results
1195             * in a much better memory utilization:
1196             *   5 * 3/4 = 3.75 usable with buffer size 4
1197             */
1198            if (entry_size * 5 > slab_size)
1199               slab_size = util_next_power_of_two(entry_size * 5);
1200         }
1201
1202         break;
1203      }
1204   }
1205   assert(slab_size != 0);
1206
1207   slab->buffer = zink_bo(zink_bo_create(screen, slab_size, slab_size, heap, 0, NULL));
1208   if (!slab->buffer)
1209      goto fail;
1210
1211   slab_size = slab->buffer->base.size;
1212
1213   slab->base.num_entries = slab_size / entry_size;
1214   slab->base.num_free = slab->base.num_entries;
1215   slab->entry_size = entry_size;
1216   slab->entries = CALLOC(slab->base.num_entries, sizeof(*slab->entries));
1217   if (!slab->entries)
1218      goto fail_buffer;
1219
1220   list_inithead(&slab->base.free);
1221
1222   base_id = p_atomic_fetch_add(&screen->pb.next_bo_unique_id, slab->base.num_entries);
1223   for (unsigned i = 0; i < slab->base.num_entries; ++i) {
1224      struct zink_bo *bo = &slab->entries[i];
1225
1226      simple_mtx_init(&bo->lock, mtx_plain);
1227      bo->base.alignment_log2 = util_logbase2(get_slab_entry_alignment(screen, entry_size));
1228      bo->base.size = entry_size;
1229      bo->base.vtbl = &bo_slab_vtbl;
1230      bo->offset = slab->buffer->offset + i * entry_size;
1231      bo->unique_id = base_id + i;
1232      bo->u.slab.entry.slab = &slab->base;
1233      bo->u.slab.entry.group_index = group_index;
1234      bo->u.slab.entry.entry_size = entry_size;
1235
1236      if (slab->buffer->mem) {
1237         /* The slab is not suballocated. */
1238         bo->u.slab.real = slab->buffer;
1239      } else {
1240         /* The slab is allocated out of a bigger slab. */
1241         bo->u.slab.real = slab->buffer->u.slab.real;
1242         assert(bo->u.slab.real->mem);
1243      }
1244      bo->base.placement = bo->u.slab.real->base.placement;
1245
1246      list_addtail(&bo->u.slab.entry.head, &slab->base.free);
1247   }
1248
1249   /* Wasted alignment due to slabs with 3/4 allocations being aligned to a power of two. */
1250   assert(slab->base.num_entries * entry_size <= slab_size);
1251
1252   return &slab->base;
1253
1254fail_buffer:
1255   zink_bo_unref(screen, slab->buffer);
1256fail:
1257   FREE(slab);
1258   return NULL;
1259}
1260
1261static struct pb_slab *
1262bo_slab_alloc_normal(void *priv, unsigned heap, unsigned entry_size, unsigned group_index)
1263{
1264   return bo_slab_alloc(priv, heap, entry_size, group_index, false);
1265}
1266
1267bool
1268zink_bo_init(struct zink_screen *screen)
1269{
1270   uint64_t total_mem = 0;
1271   for (uint32_t i = 0; i < screen->info.mem_props.memoryHeapCount; ++i)
1272      total_mem += screen->info.mem_props.memoryHeaps[i].size;
1273   /* Create managers. */
1274   pb_cache_init(&screen->pb.bo_cache, ZINK_HEAP_MAX,
1275                 500000, 2.0f, 0,
1276                 total_mem / 8, screen,
1277                 (void*)bo_destroy, (void*)bo_can_reclaim);
1278
1279   unsigned min_slab_order = MIN_SLAB_ORDER;  /* 256 bytes */
1280   unsigned max_slab_order = 20; /* 1 MB (slab size = 2 MB) */
1281   unsigned num_slab_orders_per_allocator = (max_slab_order - min_slab_order) /
1282                                            NUM_SLAB_ALLOCATORS;
1283
1284   /* Divide the size order range among slab managers. */
1285   for (unsigned i = 0; i < NUM_SLAB_ALLOCATORS; i++) {
1286      unsigned min_order = min_slab_order;
1287      unsigned max_order = MIN2(min_order + num_slab_orders_per_allocator,
1288                                max_slab_order);
1289
1290      if (!pb_slabs_init(&screen->pb.bo_slabs[i],
1291                         min_order, max_order,
1292                         ZINK_HEAP_MAX, true,
1293                         screen,
1294                         bo_can_reclaim_slab,
1295                         bo_slab_alloc_normal,
1296                         (void*)bo_slab_free)) {
1297         return false;
1298      }
1299      min_slab_order = max_order + 1;
1300   }
1301   screen->pb.min_alloc_size = 1 << screen->pb.bo_slabs[0].min_order;
1302   return true;
1303}
1304
1305void
1306zink_bo_deinit(struct zink_screen *screen)
1307{
1308   for (unsigned i = 0; i < NUM_SLAB_ALLOCATORS; i++) {
1309      if (screen->pb.bo_slabs[i].groups)
1310         pb_slabs_deinit(&screen->pb.bo_slabs[i]);
1311   }
1312   pb_cache_deinit(&screen->pb.bo_cache);
1313}
1314