xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_bo.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * based in part on tu driver which is:
5*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Google LLC
6*61046927SAndroid Build Coastguard Worker  *
7*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
8*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
9*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
10*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
12*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
15*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
16*61046927SAndroid Build Coastguard Worker  * Software.
17*61046927SAndroid Build Coastguard Worker  *
18*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
25*61046927SAndroid Build Coastguard Worker  */
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include <assert.h>
28*61046927SAndroid Build Coastguard Worker #include <limits.h>
29*61046927SAndroid Build Coastguard Worker #include <stddef.h>
30*61046927SAndroid Build Coastguard Worker #include <stdint.h>
31*61046927SAndroid Build Coastguard Worker #include <stdio.h>
32*61046927SAndroid Build Coastguard Worker #include <vulkan/vulkan.h>
33*61046927SAndroid Build Coastguard Worker 
34*61046927SAndroid Build Coastguard Worker #if defined(HAVE_VALGRIND)
35*61046927SAndroid Build Coastguard Worker #   include <valgrind.h>
36*61046927SAndroid Build Coastguard Worker #   include <memcheck.h>
37*61046927SAndroid Build Coastguard Worker #endif
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker #include "hwdef/rogue_hw_utils.h"
40*61046927SAndroid Build Coastguard Worker #include "pvr_bo.h"
41*61046927SAndroid Build Coastguard Worker #include "pvr_debug.h"
42*61046927SAndroid Build Coastguard Worker #include "pvr_dump.h"
43*61046927SAndroid Build Coastguard Worker #include "pvr_private.h"
44*61046927SAndroid Build Coastguard Worker #include "pvr_types.h"
45*61046927SAndroid Build Coastguard Worker #include "pvr_util.h"
46*61046927SAndroid Build Coastguard Worker #include "pvr_winsys.h"
47*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
48*61046927SAndroid Build Coastguard Worker #include "util/rb_tree.h"
49*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
50*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
51*61046927SAndroid Build Coastguard Worker #include "vk_alloc.h"
52*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker struct pvr_bo_store {
55*61046927SAndroid Build Coastguard Worker    struct rb_tree tree;
56*61046927SAndroid Build Coastguard Worker    simple_mtx_t mutex;
57*61046927SAndroid Build Coastguard Worker    uint32_t size;
58*61046927SAndroid Build Coastguard Worker };
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker struct pvr_bo_store_entry {
61*61046927SAndroid Build Coastguard Worker    struct rb_node node;
62*61046927SAndroid Build Coastguard Worker    struct pvr_bo bo;
63*61046927SAndroid Build Coastguard Worker };
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker #define entry_from_node(node_) \
66*61046927SAndroid Build Coastguard Worker    container_of(node_, struct pvr_bo_store_entry, node)
67*61046927SAndroid Build Coastguard Worker #define entry_from_bo(bo_) container_of(bo_, struct pvr_bo_store_entry, bo)
68*61046927SAndroid Build Coastguard Worker 
pvr_dev_addr_cmp(const pvr_dev_addr_t a,const pvr_dev_addr_t b)69*61046927SAndroid Build Coastguard Worker static inline int pvr_dev_addr_cmp(const pvr_dev_addr_t a,
70*61046927SAndroid Build Coastguard Worker                                    const pvr_dev_addr_t b)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    const uint64_t addr_a = a.addr;
73*61046927SAndroid Build Coastguard Worker    const uint64_t addr_b = b.addr;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    if (addr_a < addr_b)
76*61046927SAndroid Build Coastguard Worker       return 1;
77*61046927SAndroid Build Coastguard Worker    else if (addr_a > addr_b)
78*61046927SAndroid Build Coastguard Worker       return -1;
79*61046927SAndroid Build Coastguard Worker    else
80*61046927SAndroid Build Coastguard Worker       return 0;
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker /* Borrowed from pandecode. Using this comparator allows us to lookup intervals
84*61046927SAndroid Build Coastguard Worker  * in the RB-tree without storing extra information.
85*61046927SAndroid Build Coastguard Worker  */
pvr_bo_store_entry_cmp_key(const struct rb_node * node,const void * const key)86*61046927SAndroid Build Coastguard Worker static inline int pvr_bo_store_entry_cmp_key(const struct rb_node *node,
87*61046927SAndroid Build Coastguard Worker                                              const void *const key)
88*61046927SAndroid Build Coastguard Worker {
89*61046927SAndroid Build Coastguard Worker    const struct pvr_winsys_vma *const vma = entry_from_node(node)->bo.vma;
90*61046927SAndroid Build Coastguard Worker    const pvr_dev_addr_t addr = *(const pvr_dev_addr_t *)key;
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker    if (addr.addr >= vma->dev_addr.addr &&
93*61046927SAndroid Build Coastguard Worker        addr.addr < (vma->dev_addr.addr + vma->size)) {
94*61046927SAndroid Build Coastguard Worker       return 0;
95*61046927SAndroid Build Coastguard Worker    }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker    return pvr_dev_addr_cmp(vma->dev_addr, addr);
98*61046927SAndroid Build Coastguard Worker }
99*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_entry_cmp(const struct rb_node * const a,const struct rb_node * const b)100*61046927SAndroid Build Coastguard Worker static inline int pvr_bo_store_entry_cmp(const struct rb_node *const a,
101*61046927SAndroid Build Coastguard Worker                                          const struct rb_node *const b)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker    return pvr_dev_addr_cmp(entry_from_node(a)->bo.vma->dev_addr,
104*61046927SAndroid Build Coastguard Worker                            entry_from_node(b)->bo.vma->dev_addr);
105*61046927SAndroid Build Coastguard Worker }
106*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_create(struct pvr_device * device)107*61046927SAndroid Build Coastguard Worker VkResult pvr_bo_store_create(struct pvr_device *device)
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker    struct pvr_bo_store *store;
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    if (!PVR_IS_DEBUG_SET(TRACK_BOS)) {
112*61046927SAndroid Build Coastguard Worker       device->bo_store = NULL;
113*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
114*61046927SAndroid Build Coastguard Worker    }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    store = vk_alloc(&device->vk.alloc,
117*61046927SAndroid Build Coastguard Worker                     sizeof(*store),
118*61046927SAndroid Build Coastguard Worker                     8,
119*61046927SAndroid Build Coastguard Worker                     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
120*61046927SAndroid Build Coastguard Worker    if (!store)
121*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
122*61046927SAndroid Build Coastguard Worker 
123*61046927SAndroid Build Coastguard Worker    rb_tree_init(&store->tree);
124*61046927SAndroid Build Coastguard Worker    store->size = 0;
125*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&store->mutex, mtx_plain);
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    device->bo_store = store;
128*61046927SAndroid Build Coastguard Worker 
129*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_destroy(struct pvr_device * device)132*61046927SAndroid Build Coastguard Worker void pvr_bo_store_destroy(struct pvr_device *device)
133*61046927SAndroid Build Coastguard Worker {
134*61046927SAndroid Build Coastguard Worker    struct pvr_bo_store *store = device->bo_store;
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker    if (likely(!store))
137*61046927SAndroid Build Coastguard Worker       return;
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    if (unlikely(!rb_tree_is_empty(&store->tree))) {
140*61046927SAndroid Build Coastguard Worker       debug_warning("Non-empty BO store destroyed; dump follows");
141*61046927SAndroid Build Coastguard Worker       pvr_bo_store_dump(device);
142*61046927SAndroid Build Coastguard Worker    }
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&store->mutex);
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker    vk_free(&device->vk.alloc, store);
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    device->bo_store = NULL;
149*61046927SAndroid Build Coastguard Worker }
150*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_insert(struct pvr_bo_store * const store,struct pvr_bo * const bo)151*61046927SAndroid Build Coastguard Worker static void pvr_bo_store_insert(struct pvr_bo_store *const store,
152*61046927SAndroid Build Coastguard Worker                                 struct pvr_bo *const bo)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    if (likely(!store))
155*61046927SAndroid Build Coastguard Worker       return;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&store->mutex);
158*61046927SAndroid Build Coastguard Worker    rb_tree_insert(&store->tree,
159*61046927SAndroid Build Coastguard Worker                   &entry_from_bo(bo)->node,
160*61046927SAndroid Build Coastguard Worker                   pvr_bo_store_entry_cmp);
161*61046927SAndroid Build Coastguard Worker    store->size++;
162*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&store->mutex);
163*61046927SAndroid Build Coastguard Worker }
164*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_remove(struct pvr_bo_store * const store,struct pvr_bo * const bo)165*61046927SAndroid Build Coastguard Worker static void pvr_bo_store_remove(struct pvr_bo_store *const store,
166*61046927SAndroid Build Coastguard Worker                                 struct pvr_bo *const bo)
167*61046927SAndroid Build Coastguard Worker {
168*61046927SAndroid Build Coastguard Worker    if (likely(!store))
169*61046927SAndroid Build Coastguard Worker       return;
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&store->mutex);
172*61046927SAndroid Build Coastguard Worker    rb_tree_remove(&store->tree, &entry_from_bo(bo)->node);
173*61046927SAndroid Build Coastguard Worker    store->size--;
174*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&store->mutex);
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_lookup(struct pvr_device * const device,const pvr_dev_addr_t addr)177*61046927SAndroid Build Coastguard Worker struct pvr_bo *pvr_bo_store_lookup(struct pvr_device *const device,
178*61046927SAndroid Build Coastguard Worker                                    const pvr_dev_addr_t addr)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker    struct pvr_bo_store *const store = device->bo_store;
181*61046927SAndroid Build Coastguard Worker    struct rb_node *node;
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    if (unlikely(!store))
184*61046927SAndroid Build Coastguard Worker       return NULL;
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&store->mutex);
187*61046927SAndroid Build Coastguard Worker    node = rb_tree_search(&store->tree, &addr, pvr_bo_store_entry_cmp_key);
188*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&store->mutex);
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    if (!node)
191*61046927SAndroid Build Coastguard Worker       return NULL;
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    return &entry_from_node(node)->bo;
194*61046927SAndroid Build Coastguard Worker }
195*61046927SAndroid Build Coastguard Worker 
pvr_bo_dump_line(struct pvr_dump_ctx * const ctx,const struct pvr_bo * bo,const uint32_t index,const uint32_t nr_bos_log10)196*61046927SAndroid Build Coastguard Worker static void pvr_bo_dump_line(struct pvr_dump_ctx *const ctx,
197*61046927SAndroid Build Coastguard Worker                              const struct pvr_bo *bo,
198*61046927SAndroid Build Coastguard Worker                              const uint32_t index,
199*61046927SAndroid Build Coastguard Worker                              const uint32_t nr_bos_log10)
200*61046927SAndroid Build Coastguard Worker {
201*61046927SAndroid Build Coastguard Worker    static const char *const pretty_sizes[64 + 1] = {
202*61046927SAndroid Build Coastguard Worker       "",        "1 B",     "2 B",     "4 B",     "8 B",     "16 B",
203*61046927SAndroid Build Coastguard Worker       "32 B",    "64 B",    "128 B",   "256 B",   "512 B",   "1 KiB",
204*61046927SAndroid Build Coastguard Worker       "2 KiB",   "4 KiB",   "8 KiB",   "16 KiB",  "32 KiB",  "64 KiB",
205*61046927SAndroid Build Coastguard Worker       "128 KiB", "256 KiB", "512 KiB", "1 MiB",   "2 MiB",   "4 MiB",
206*61046927SAndroid Build Coastguard Worker       "8 MiB",   "16 MiB",  "32 MiB",  "64 MiB",  "128 MiB", "256 MiB",
207*61046927SAndroid Build Coastguard Worker       "512 MiB", "1 GiB",   "2 GiB",   "4 GiB",   "8 GiB",   "16 GiB",
208*61046927SAndroid Build Coastguard Worker       "32 GiB",  "64 GiB",  "128 GiB", "256 GiB", "512 GiB", "1 TiB",
209*61046927SAndroid Build Coastguard Worker       "2 TiB",   "4 TiB",   "8 TiB",   "16 TiB",  "32 TiB",  "64 TiB",
210*61046927SAndroid Build Coastguard Worker       "128 TiB", "256 TiB", "512 TiB", "1 PiB",   "2 PiB",   "4 PiB",
211*61046927SAndroid Build Coastguard Worker       "8 PiB",   "16 PiB",  "32 PiB",  "64 PiB",  "128 PiB", "256 PiB",
212*61046927SAndroid Build Coastguard Worker       "512 PiB", "1 EiB",   "2 EiB",   "4 EiB",   "8 EiB",
213*61046927SAndroid Build Coastguard Worker    };
214*61046927SAndroid Build Coastguard Worker 
215*61046927SAndroid Build Coastguard Worker    const uint64_t size = bo->vma->size;
216*61046927SAndroid Build Coastguard Worker    const uint32_t size_log2 =
217*61046927SAndroid Build Coastguard Worker       util_is_power_of_two_or_zero64(size) ? util_last_bit(size) : 0;
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    pvr_dump_println(ctx,
220*61046927SAndroid Build Coastguard Worker                     "[%0*" PRIu32 "] " PVR_DEV_ADDR_FMT " -> %*p "
221*61046927SAndroid Build Coastguard Worker                     "(%s%s0x%" PRIx64 " bytes)",
222*61046927SAndroid Build Coastguard Worker                     nr_bos_log10,
223*61046927SAndroid Build Coastguard Worker                     index,
224*61046927SAndroid Build Coastguard Worker                     bo->vma->dev_addr.addr,
225*61046927SAndroid Build Coastguard Worker                     (int)sizeof(void *) * 2 + 2, /* nr hex digits + 0x prefix */
226*61046927SAndroid Build Coastguard Worker                     bo->bo->map,
227*61046927SAndroid Build Coastguard Worker                     pretty_sizes[size_log2],
228*61046927SAndroid Build Coastguard Worker                     size_log2 ? ", " : "",
229*61046927SAndroid Build Coastguard Worker                     size);
230*61046927SAndroid Build Coastguard Worker }
231*61046927SAndroid Build Coastguard Worker 
pvr_bo_store_dump(struct pvr_device * const device)232*61046927SAndroid Build Coastguard Worker bool pvr_bo_store_dump(struct pvr_device *const device)
233*61046927SAndroid Build Coastguard Worker {
234*61046927SAndroid Build Coastguard Worker    struct pvr_bo_store *const store = device->bo_store;
235*61046927SAndroid Build Coastguard Worker    const uint32_t nr_bos = store->size;
236*61046927SAndroid Build Coastguard Worker    const uint32_t nr_bos_log10 = u32_dec_digits(nr_bos);
237*61046927SAndroid Build Coastguard Worker    struct pvr_dump_ctx ctx;
238*61046927SAndroid Build Coastguard Worker    uint32_t bo_idx = 0;
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker    if (unlikely(!store)) {
241*61046927SAndroid Build Coastguard Worker       debug_warning("Requested BO store dump, but no BO store is present.");
242*61046927SAndroid Build Coastguard Worker       return false;
243*61046927SAndroid Build Coastguard Worker    }
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker    pvr_dump_begin(&ctx, stderr, "BO STORE", 1);
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker    pvr_dump_println(&ctx, "Dumping %" PRIu32 " BO store entries...", nr_bos);
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    pvr_dump_indent(&ctx);
250*61046927SAndroid Build Coastguard Worker    rb_tree_foreach_safe (struct pvr_bo_store_entry, entry, &store->tree, node) {
251*61046927SAndroid Build Coastguard Worker       pvr_bo_dump_line(&ctx, &entry->bo, bo_idx++, nr_bos_log10);
252*61046927SAndroid Build Coastguard Worker    }
253*61046927SAndroid Build Coastguard Worker    pvr_dump_dedent(&ctx);
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker    return pvr_dump_end(&ctx);
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker 
pvr_bo_list_dump(struct pvr_dump_ctx * const ctx,const struct list_head * const bo_list,const uint32_t nr_bos)258*61046927SAndroid Build Coastguard Worker void pvr_bo_list_dump(struct pvr_dump_ctx *const ctx,
259*61046927SAndroid Build Coastguard Worker                       const struct list_head *const bo_list,
260*61046927SAndroid Build Coastguard Worker                       const uint32_t nr_bos)
261*61046927SAndroid Build Coastguard Worker {
262*61046927SAndroid Build Coastguard Worker    const uint32_t real_nr_bos = nr_bos ? nr_bos : list_length(bo_list);
263*61046927SAndroid Build Coastguard Worker    const uint32_t nr_bos_log10 = u32_dec_digits(real_nr_bos);
264*61046927SAndroid Build Coastguard Worker    uint32_t bo_idx = 0;
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    list_for_each_entry (struct pvr_bo, bo, bo_list, link) {
267*61046927SAndroid Build Coastguard Worker       pvr_bo_dump_line(ctx, bo, bo_idx++, nr_bos_log10);
268*61046927SAndroid Build Coastguard Worker    }
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker 
pvr_bo_alloc_to_winsys_flags(uint64_t flags)271*61046927SAndroid Build Coastguard Worker static uint32_t pvr_bo_alloc_to_winsys_flags(uint64_t flags)
272*61046927SAndroid Build Coastguard Worker {
273*61046927SAndroid Build Coastguard Worker    uint32_t ws_flags = 0;
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    if (flags & (PVR_BO_ALLOC_FLAG_CPU_ACCESS | PVR_BO_ALLOC_FLAG_CPU_MAPPED))
276*61046927SAndroid Build Coastguard Worker       ws_flags |= PVR_WINSYS_BO_FLAG_CPU_ACCESS;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    if (flags & PVR_BO_ALLOC_FLAG_GPU_UNCACHED)
279*61046927SAndroid Build Coastguard Worker       ws_flags |= PVR_WINSYS_BO_FLAG_GPU_UNCACHED;
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker    if (flags & PVR_BO_ALLOC_FLAG_PM_FW_PROTECT)
282*61046927SAndroid Build Coastguard Worker       ws_flags |= PVR_WINSYS_BO_FLAG_PM_FW_PROTECT;
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker    return ws_flags;
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker static inline struct pvr_bo *
pvr_bo_alloc_bo(const struct pvr_device * const device)288*61046927SAndroid Build Coastguard Worker pvr_bo_alloc_bo(const struct pvr_device *const device)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker    size_t size;
291*61046927SAndroid Build Coastguard Worker    void *ptr;
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    if (unlikely(device->bo_store))
294*61046927SAndroid Build Coastguard Worker       size = sizeof(struct pvr_bo_store_entry);
295*61046927SAndroid Build Coastguard Worker    else
296*61046927SAndroid Build Coastguard Worker       size = sizeof(struct pvr_bo);
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker    ptr =
299*61046927SAndroid Build Coastguard Worker       vk_alloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
300*61046927SAndroid Build Coastguard Worker    if (unlikely(!ptr))
301*61046927SAndroid Build Coastguard Worker       return NULL;
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker    if (unlikely(device->bo_store))
304*61046927SAndroid Build Coastguard Worker       return &((struct pvr_bo_store_entry *)ptr)->bo;
305*61046927SAndroid Build Coastguard Worker    else
306*61046927SAndroid Build Coastguard Worker       return (struct pvr_bo *)ptr;
307*61046927SAndroid Build Coastguard Worker }
308*61046927SAndroid Build Coastguard Worker 
pvr_bo_free_bo(const struct pvr_device * const device,struct pvr_bo * const bo)309*61046927SAndroid Build Coastguard Worker static inline void pvr_bo_free_bo(const struct pvr_device *const device,
310*61046927SAndroid Build Coastguard Worker                                   struct pvr_bo *const bo)
311*61046927SAndroid Build Coastguard Worker {
312*61046927SAndroid Build Coastguard Worker    void *ptr;
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    if (unlikely(device->bo_store))
315*61046927SAndroid Build Coastguard Worker       ptr = entry_from_bo(bo);
316*61046927SAndroid Build Coastguard Worker    else
317*61046927SAndroid Build Coastguard Worker       ptr = bo;
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    vk_free(&device->vk.alloc, ptr);
320*61046927SAndroid Build Coastguard Worker }
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker /**
323*61046927SAndroid Build Coastguard Worker  * \brief Helper interface to allocate a GPU buffer and map it to both host and
324*61046927SAndroid Build Coastguard Worker  * device virtual memory. Host mapping is conditional and is controlled by
325*61046927SAndroid Build Coastguard Worker  * flags.
326*61046927SAndroid Build Coastguard Worker  *
327*61046927SAndroid Build Coastguard Worker  * \param[in] device      Logical device pointer.
328*61046927SAndroid Build Coastguard Worker  * \param[in] heap        Heap to allocate device virtual address from.
329*61046927SAndroid Build Coastguard Worker  * \param[in] size        Size of buffer to allocate.
330*61046927SAndroid Build Coastguard Worker  * \param[in] alignment   Required alignment of the allocation. Must be a power
331*61046927SAndroid Build Coastguard Worker  *                        of two.
332*61046927SAndroid Build Coastguard Worker  * \param[in] flags       Controls allocation, CPU and GPU mapping behavior
333*61046927SAndroid Build Coastguard Worker  *                        using PVR_BO_ALLOC_FLAG_*.
334*61046927SAndroid Build Coastguard Worker  * \param[out] pvr_bo_out On success output buffer is returned in this pointer.
335*61046927SAndroid Build Coastguard Worker  * \return VK_SUCCESS on success, or error code otherwise.
336*61046927SAndroid Build Coastguard Worker  *
337*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_free()
338*61046927SAndroid Build Coastguard Worker  */
pvr_bo_alloc(struct pvr_device * device,struct pvr_winsys_heap * heap,uint64_t size,uint64_t alignment,uint64_t flags,struct pvr_bo ** const pvr_bo_out)339*61046927SAndroid Build Coastguard Worker VkResult pvr_bo_alloc(struct pvr_device *device,
340*61046927SAndroid Build Coastguard Worker                       struct pvr_winsys_heap *heap,
341*61046927SAndroid Build Coastguard Worker                       uint64_t size,
342*61046927SAndroid Build Coastguard Worker                       uint64_t alignment,
343*61046927SAndroid Build Coastguard Worker                       uint64_t flags,
344*61046927SAndroid Build Coastguard Worker                       struct pvr_bo **const pvr_bo_out)
345*61046927SAndroid Build Coastguard Worker {
346*61046927SAndroid Build Coastguard Worker    struct pvr_bo *pvr_bo;
347*61046927SAndroid Build Coastguard Worker    VkResult result;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    pvr_bo = pvr_bo_alloc_bo(device);
350*61046927SAndroid Build Coastguard Worker    if (!pvr_bo) {
351*61046927SAndroid Build Coastguard Worker       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
352*61046927SAndroid Build Coastguard Worker       goto err_out;
353*61046927SAndroid Build Coastguard Worker    }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker    pvr_bo->ref_count = 1;
356*61046927SAndroid Build Coastguard Worker 
357*61046927SAndroid Build Coastguard Worker    result = device->ws->ops->buffer_create(device->ws,
358*61046927SAndroid Build Coastguard Worker                                            size,
359*61046927SAndroid Build Coastguard Worker                                            alignment,
360*61046927SAndroid Build Coastguard Worker                                            PVR_WINSYS_BO_TYPE_GPU,
361*61046927SAndroid Build Coastguard Worker                                            pvr_bo_alloc_to_winsys_flags(flags),
362*61046927SAndroid Build Coastguard Worker                                            &pvr_bo->bo);
363*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
364*61046927SAndroid Build Coastguard Worker       goto err_free_bo;
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker    if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED) {
367*61046927SAndroid Build Coastguard Worker       result = device->ws->ops->buffer_map(pvr_bo->bo);
368*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
369*61046927SAndroid Build Coastguard Worker          goto err_buffer_destroy;
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker       VG(VALGRIND_MAKE_MEM_DEFINED(pvr_bo->bo->map, pvr_bo->bo->size));
372*61046927SAndroid Build Coastguard Worker    }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    result = device->ws->ops->heap_alloc(heap, size, alignment, &pvr_bo->vma);
375*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
376*61046927SAndroid Build Coastguard Worker       goto err_buffer_unmap;
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    result = device->ws->ops->vma_map(pvr_bo->vma, pvr_bo->bo, 0, size, NULL);
379*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
380*61046927SAndroid Build Coastguard Worker       goto err_heap_free;
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    pvr_bo_store_insert(device->bo_store, pvr_bo);
383*61046927SAndroid Build Coastguard Worker    *pvr_bo_out = pvr_bo;
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
386*61046927SAndroid Build Coastguard Worker 
387*61046927SAndroid Build Coastguard Worker err_heap_free:
388*61046927SAndroid Build Coastguard Worker    device->ws->ops->heap_free(pvr_bo->vma);
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker err_buffer_unmap:
391*61046927SAndroid Build Coastguard Worker    if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED)
392*61046927SAndroid Build Coastguard Worker       device->ws->ops->buffer_unmap(pvr_bo->bo);
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker err_buffer_destroy:
395*61046927SAndroid Build Coastguard Worker    device->ws->ops->buffer_destroy(pvr_bo->bo);
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker err_free_bo:
398*61046927SAndroid Build Coastguard Worker    pvr_bo_free_bo(device, pvr_bo);
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker err_out:
401*61046927SAndroid Build Coastguard Worker    return result;
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker /**
405*61046927SAndroid Build Coastguard Worker  * \brief Interface to map the buffer into host virtual address space.
406*61046927SAndroid Build Coastguard Worker  *
407*61046927SAndroid Build Coastguard Worker  * Buffer should have been created with the #PVR_BO_ALLOC_FLAG_CPU_ACCESS
408*61046927SAndroid Build Coastguard Worker  * flag. It should also not already be mapped or it should have been unmapped
409*61046927SAndroid Build Coastguard Worker  * using #pvr_bo_cpu_unmap() before mapping again.
410*61046927SAndroid Build Coastguard Worker  *
411*61046927SAndroid Build Coastguard Worker  * \param[in] device Logical device pointer.
412*61046927SAndroid Build Coastguard Worker  * \param[in] pvr_bo Buffer to map.
413*61046927SAndroid Build Coastguard Worker  * \return Valid host virtual address on success, or NULL otherwise.
414*61046927SAndroid Build Coastguard Worker  *
415*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_alloc(), #PVR_BO_ALLOC_FLAG_CPU_MAPPED
416*61046927SAndroid Build Coastguard Worker  */
pvr_bo_cpu_map(struct pvr_device * device,struct pvr_bo * pvr_bo)417*61046927SAndroid Build Coastguard Worker VkResult pvr_bo_cpu_map(struct pvr_device *device, struct pvr_bo *pvr_bo)
418*61046927SAndroid Build Coastguard Worker {
419*61046927SAndroid Build Coastguard Worker    assert(!pvr_bo->bo->map);
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker    return device->ws->ops->buffer_map(pvr_bo->bo);
422*61046927SAndroid Build Coastguard Worker }
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker /**
425*61046927SAndroid Build Coastguard Worker  * \brief Interface to unmap the buffer from host virtual address space.
426*61046927SAndroid Build Coastguard Worker  *
427*61046927SAndroid Build Coastguard Worker  * Buffer should have a valid mapping, created either using #pvr_bo_cpu_map() or
428*61046927SAndroid Build Coastguard Worker  * by passing #PVR_BO_ALLOC_FLAG_CPU_MAPPED flag to #pvr_bo_alloc() at
429*61046927SAndroid Build Coastguard Worker  * allocation time.
430*61046927SAndroid Build Coastguard Worker  *
431*61046927SAndroid Build Coastguard Worker  * Buffer can be remapped using #pvr_bo_cpu_map().
432*61046927SAndroid Build Coastguard Worker  *
433*61046927SAndroid Build Coastguard Worker  * \param[in] device Logical device pointer.
434*61046927SAndroid Build Coastguard Worker  * \param[in] pvr_bo Buffer to unmap.
435*61046927SAndroid Build Coastguard Worker  */
pvr_bo_cpu_unmap(struct pvr_device * device,struct pvr_bo * pvr_bo)436*61046927SAndroid Build Coastguard Worker void pvr_bo_cpu_unmap(struct pvr_device *device, struct pvr_bo *pvr_bo)
437*61046927SAndroid Build Coastguard Worker {
438*61046927SAndroid Build Coastguard Worker    struct pvr_winsys_bo *bo = pvr_bo->bo;
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker    assert(bo->map);
441*61046927SAndroid Build Coastguard Worker 
442*61046927SAndroid Build Coastguard Worker #if defined(HAVE_VALGRIND)
443*61046927SAndroid Build Coastguard Worker    if (!bo->vbits)
444*61046927SAndroid Build Coastguard Worker       bo->vbits = vk_alloc(&device->vk.alloc,
445*61046927SAndroid Build Coastguard Worker                            bo->size,
446*61046927SAndroid Build Coastguard Worker                            8,
447*61046927SAndroid Build Coastguard Worker                            VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
448*61046927SAndroid Build Coastguard Worker    if (bo->vbits) {
449*61046927SAndroid Build Coastguard Worker       unsigned ret = VALGRIND_GET_VBITS(bo->map, bo->vbits, bo->size);
450*61046927SAndroid Build Coastguard Worker       if (ret != 0 && ret != 1)
451*61046927SAndroid Build Coastguard Worker          mesa_loge("Failed to get vbits; expect bad valgrind results.");
452*61046927SAndroid Build Coastguard Worker    } else {
453*61046927SAndroid Build Coastguard Worker       mesa_loge("Failed to alloc vbits storage; expect bad valgrind results.");
454*61046927SAndroid Build Coastguard Worker    }
455*61046927SAndroid Build Coastguard Worker #endif /* defined(HAVE_VALGRIND) */
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker    device->ws->ops->buffer_unmap(bo);
458*61046927SAndroid Build Coastguard Worker }
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker /**
461*61046927SAndroid Build Coastguard Worker  * \brief Interface to free the buffer object.
462*61046927SAndroid Build Coastguard Worker  *
463*61046927SAndroid Build Coastguard Worker  * \param[in] device Logical device pointer.
464*61046927SAndroid Build Coastguard Worker  * \param[in] pvr_bo Buffer to free.
465*61046927SAndroid Build Coastguard Worker  *
466*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_alloc()
467*61046927SAndroid Build Coastguard Worker  */
pvr_bo_free(struct pvr_device * device,struct pvr_bo * pvr_bo)468*61046927SAndroid Build Coastguard Worker void pvr_bo_free(struct pvr_device *device, struct pvr_bo *pvr_bo)
469*61046927SAndroid Build Coastguard Worker {
470*61046927SAndroid Build Coastguard Worker    if (!pvr_bo)
471*61046927SAndroid Build Coastguard Worker       return;
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    if (!p_atomic_dec_zero(&pvr_bo->ref_count))
474*61046927SAndroid Build Coastguard Worker       return;
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker #if defined(HAVE_VALGRIND)
477*61046927SAndroid Build Coastguard Worker    vk_free(&device->vk.alloc, pvr_bo->bo->vbits);
478*61046927SAndroid Build Coastguard Worker #endif /* defined(HAVE_VALGRIND) */
479*61046927SAndroid Build Coastguard Worker 
480*61046927SAndroid Build Coastguard Worker    pvr_bo_store_remove(device->bo_store, pvr_bo);
481*61046927SAndroid Build Coastguard Worker 
482*61046927SAndroid Build Coastguard Worker    device->ws->ops->vma_unmap(pvr_bo->vma);
483*61046927SAndroid Build Coastguard Worker    device->ws->ops->heap_free(pvr_bo->vma);
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    if (pvr_bo->bo->map)
486*61046927SAndroid Build Coastguard Worker       device->ws->ops->buffer_unmap(pvr_bo->bo);
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    device->ws->ops->buffer_destroy(pvr_bo->bo);
489*61046927SAndroid Build Coastguard Worker 
490*61046927SAndroid Build Coastguard Worker    pvr_bo_free_bo(device, pvr_bo);
491*61046927SAndroid Build Coastguard Worker }
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker /**
494*61046927SAndroid Build Coastguard Worker  * \brief Interface to initialize a pvr_suballocator.
495*61046927SAndroid Build Coastguard Worker  *
496*61046927SAndroid Build Coastguard Worker  * \param[in] allocator    Sub-allocator to initialize.
497*61046927SAndroid Build Coastguard Worker  * \param[in] heap         Heap to sub-allocate device virtual address from.
498*61046927SAndroid Build Coastguard Worker  * \param[in] device       Logical device pointer.
499*61046927SAndroid Build Coastguard Worker  * \param[in] default_size Minimum size used for pvr bo(s).
500*61046927SAndroid Build Coastguard Worker  *
501*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_suballocator_fini()
502*61046927SAndroid Build Coastguard Worker  */
pvr_bo_suballocator_init(struct pvr_suballocator * allocator,struct pvr_winsys_heap * heap,struct pvr_device * device,uint32_t default_size)503*61046927SAndroid Build Coastguard Worker void pvr_bo_suballocator_init(struct pvr_suballocator *allocator,
504*61046927SAndroid Build Coastguard Worker                               struct pvr_winsys_heap *heap,
505*61046927SAndroid Build Coastguard Worker                               struct pvr_device *device,
506*61046927SAndroid Build Coastguard Worker                               uint32_t default_size)
507*61046927SAndroid Build Coastguard Worker {
508*61046927SAndroid Build Coastguard Worker    *allocator = (struct pvr_suballocator){
509*61046927SAndroid Build Coastguard Worker       .device = device,
510*61046927SAndroid Build Coastguard Worker       .default_size = default_size,
511*61046927SAndroid Build Coastguard Worker       .heap = heap,
512*61046927SAndroid Build Coastguard Worker    };
513*61046927SAndroid Build Coastguard Worker 
514*61046927SAndroid Build Coastguard Worker    simple_mtx_init(&allocator->mtx, mtx_plain);
515*61046927SAndroid Build Coastguard Worker }
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker /**
518*61046927SAndroid Build Coastguard Worker  * \brief Interface to destroy a pvr_suballocator.
519*61046927SAndroid Build Coastguard Worker  *
520*61046927SAndroid Build Coastguard Worker  * \param[in] allocator Sub-allocator to clean-up.
521*61046927SAndroid Build Coastguard Worker  *
522*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_suballocator_init()
523*61046927SAndroid Build Coastguard Worker  */
pvr_bo_suballocator_fini(struct pvr_suballocator * allocator)524*61046927SAndroid Build Coastguard Worker void pvr_bo_suballocator_fini(struct pvr_suballocator *allocator)
525*61046927SAndroid Build Coastguard Worker {
526*61046927SAndroid Build Coastguard Worker    pvr_bo_free(allocator->device, allocator->bo);
527*61046927SAndroid Build Coastguard Worker    pvr_bo_free(allocator->device, allocator->bo_cached);
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker    simple_mtx_destroy(&allocator->mtx);
530*61046927SAndroid Build Coastguard Worker }
531*61046927SAndroid Build Coastguard Worker 
pvr_bo_get_ref(struct pvr_bo * bo)532*61046927SAndroid Build Coastguard Worker static inline struct pvr_bo *pvr_bo_get_ref(struct pvr_bo *bo)
533*61046927SAndroid Build Coastguard Worker {
534*61046927SAndroid Build Coastguard Worker    p_atomic_inc(&bo->ref_count);
535*61046927SAndroid Build Coastguard Worker 
536*61046927SAndroid Build Coastguard Worker    return bo;
537*61046927SAndroid Build Coastguard Worker }
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker /**
540*61046927SAndroid Build Coastguard Worker  * \brief Interface to sub-allocate buffer objects.
541*61046927SAndroid Build Coastguard Worker  *
542*61046927SAndroid Build Coastguard Worker  * \param[in]  allocator       Sub-allocator used to make a sub-allocation.
543*61046927SAndroid Build Coastguard Worker  * \param[in]  size            Size of buffer to sub-alllocate.
544*61046927SAndroid Build Coastguard Worker  * \param[in]  align           Required alignment of the allocation. Must be
545*61046927SAndroid Build Coastguard Worker  *                             a power of two.
546*61046927SAndroid Build Coastguard Worker  * \param[in]  zero_on_alloc   Require memory for the sub-allocation to be 0.
547*61046927SAndroid Build Coastguard Worker  * \param[out] suballoc_bo_out On success points to the sub-allocated buffer
548*61046927SAndroid Build Coastguard Worker  *                             object.
549*61046927SAndroid Build Coastguard Worker  * \return VK_SUCCESS on success, or error code otherwise.
550*61046927SAndroid Build Coastguard Worker  *
551*61046927SAndroid Build Coastguard Worker  * \sa # pvr_bo_suballoc_free()
552*61046927SAndroid Build Coastguard Worker  */
pvr_bo_suballoc(struct pvr_suballocator * allocator,uint32_t size,uint32_t align,bool zero_on_alloc,struct pvr_suballoc_bo ** const suballoc_bo_out)553*61046927SAndroid Build Coastguard Worker VkResult pvr_bo_suballoc(struct pvr_suballocator *allocator,
554*61046927SAndroid Build Coastguard Worker                          uint32_t size,
555*61046927SAndroid Build Coastguard Worker                          uint32_t align,
556*61046927SAndroid Build Coastguard Worker                          bool zero_on_alloc,
557*61046927SAndroid Build Coastguard Worker                          struct pvr_suballoc_bo **const suballoc_bo_out)
558*61046927SAndroid Build Coastguard Worker {
559*61046927SAndroid Build Coastguard Worker    const struct pvr_device_info *dev_info =
560*61046927SAndroid Build Coastguard Worker       &allocator->device->pdevice->dev_info;
561*61046927SAndroid Build Coastguard Worker    const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
562*61046927SAndroid Build Coastguard Worker    struct pvr_suballoc_bo *suballoc_bo;
563*61046927SAndroid Build Coastguard Worker    uint32_t alloc_size, aligned_size;
564*61046927SAndroid Build Coastguard Worker    VkResult result;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    suballoc_bo = vk_alloc(&allocator->device->vk.alloc,
567*61046927SAndroid Build Coastguard Worker                           sizeof(*suballoc_bo),
568*61046927SAndroid Build Coastguard Worker                           8,
569*61046927SAndroid Build Coastguard Worker                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
570*61046927SAndroid Build Coastguard Worker    if (!suballoc_bo)
571*61046927SAndroid Build Coastguard Worker       return vk_error(allocator->device, VK_ERROR_OUT_OF_HOST_MEMORY);
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker    /* This cache line value is used for all type of allocations (i.e. USC, PDS,
574*61046927SAndroid Build Coastguard Worker     * transfer and general), so always align them to at least the size of the
575*61046927SAndroid Build Coastguard Worker     * cache line.
576*61046927SAndroid Build Coastguard Worker     */
577*61046927SAndroid Build Coastguard Worker    align = MAX2(align, cache_line_size);
578*61046927SAndroid Build Coastguard Worker    assert(util_is_power_of_two_nonzero(align));
579*61046927SAndroid Build Coastguard Worker    aligned_size = ALIGN_POT(size, align);
580*61046927SAndroid Build Coastguard Worker 
581*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&allocator->mtx);
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker    if (allocator->bo) {
584*61046927SAndroid Build Coastguard Worker       uint32_t aligned_offset = ALIGN_POT(allocator->next_offset, align);
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker       if (aligned_offset + aligned_size <= allocator->bo->bo->size) {
587*61046927SAndroid Build Coastguard Worker          suballoc_bo->allocator = allocator;
588*61046927SAndroid Build Coastguard Worker          suballoc_bo->bo = pvr_bo_get_ref(allocator->bo);
589*61046927SAndroid Build Coastguard Worker          suballoc_bo->dev_addr =
590*61046927SAndroid Build Coastguard Worker             PVR_DEV_ADDR_OFFSET(allocator->bo->vma->dev_addr, aligned_offset);
591*61046927SAndroid Build Coastguard Worker          suballoc_bo->offset = aligned_offset;
592*61046927SAndroid Build Coastguard Worker          suballoc_bo->size = aligned_size;
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker          allocator->next_offset = aligned_offset + aligned_size;
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker          if (zero_on_alloc)
597*61046927SAndroid Build Coastguard Worker             memset(pvr_bo_suballoc_get_map_addr(suballoc_bo), 0, aligned_size);
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker          *suballoc_bo_out = suballoc_bo;
600*61046927SAndroid Build Coastguard Worker          simple_mtx_unlock(&allocator->mtx);
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
603*61046927SAndroid Build Coastguard Worker       } else {
604*61046927SAndroid Build Coastguard Worker          pvr_bo_free(allocator->device, allocator->bo);
605*61046927SAndroid Build Coastguard Worker          allocator->bo = NULL;
606*61046927SAndroid Build Coastguard Worker       }
607*61046927SAndroid Build Coastguard Worker    }
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker    alloc_size = MAX2(aligned_size, ALIGN_POT(allocator->default_size, align));
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker    if (allocator->bo_cached) {
612*61046927SAndroid Build Coastguard Worker       struct pvr_winsys_bo *bo_cached = allocator->bo_cached->bo;
613*61046927SAndroid Build Coastguard Worker 
614*61046927SAndroid Build Coastguard Worker       if (alloc_size <= bo_cached->size)
615*61046927SAndroid Build Coastguard Worker          allocator->bo = allocator->bo_cached;
616*61046927SAndroid Build Coastguard Worker       else
617*61046927SAndroid Build Coastguard Worker          pvr_bo_free(allocator->device, allocator->bo_cached);
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker       allocator->bo_cached = NULL;
620*61046927SAndroid Build Coastguard Worker    }
621*61046927SAndroid Build Coastguard Worker 
622*61046927SAndroid Build Coastguard Worker    if (!allocator->bo) {
623*61046927SAndroid Build Coastguard Worker       result = pvr_bo_alloc(allocator->device,
624*61046927SAndroid Build Coastguard Worker                             allocator->heap,
625*61046927SAndroid Build Coastguard Worker                             alloc_size,
626*61046927SAndroid Build Coastguard Worker                             align,
627*61046927SAndroid Build Coastguard Worker                             PVR_BO_ALLOC_FLAG_CPU_MAPPED,
628*61046927SAndroid Build Coastguard Worker                             &allocator->bo);
629*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS) {
630*61046927SAndroid Build Coastguard Worker          vk_free(&allocator->device->vk.alloc, suballoc_bo);
631*61046927SAndroid Build Coastguard Worker          simple_mtx_unlock(&allocator->mtx);
632*61046927SAndroid Build Coastguard Worker          return result;
633*61046927SAndroid Build Coastguard Worker       }
634*61046927SAndroid Build Coastguard Worker    }
635*61046927SAndroid Build Coastguard Worker 
636*61046927SAndroid Build Coastguard Worker    suballoc_bo->allocator = allocator;
637*61046927SAndroid Build Coastguard Worker    suballoc_bo->bo = pvr_bo_get_ref(allocator->bo);
638*61046927SAndroid Build Coastguard Worker    suballoc_bo->dev_addr = allocator->bo->vma->dev_addr;
639*61046927SAndroid Build Coastguard Worker    suballoc_bo->offset = 0;
640*61046927SAndroid Build Coastguard Worker    suballoc_bo->size = aligned_size;
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker    allocator->next_offset = aligned_size;
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker    if (zero_on_alloc)
645*61046927SAndroid Build Coastguard Worker       memset(pvr_bo_suballoc_get_map_addr(suballoc_bo), 0, aligned_size);
646*61046927SAndroid Build Coastguard Worker 
647*61046927SAndroid Build Coastguard Worker    *suballoc_bo_out = suballoc_bo;
648*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&allocator->mtx);
649*61046927SAndroid Build Coastguard Worker 
650*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
651*61046927SAndroid Build Coastguard Worker }
652*61046927SAndroid Build Coastguard Worker 
653*61046927SAndroid Build Coastguard Worker /**
654*61046927SAndroid Build Coastguard Worker  * \brief Interface to free a sub-allocated buffer object.
655*61046927SAndroid Build Coastguard Worker  *
656*61046927SAndroid Build Coastguard Worker  * \param[in] suballoc_bo Sub-allocated buffer object to free.
657*61046927SAndroid Build Coastguard Worker  *
658*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_suballoc()
659*61046927SAndroid Build Coastguard Worker  */
pvr_bo_suballoc_free(struct pvr_suballoc_bo * suballoc_bo)660*61046927SAndroid Build Coastguard Worker void pvr_bo_suballoc_free(struct pvr_suballoc_bo *suballoc_bo)
661*61046927SAndroid Build Coastguard Worker {
662*61046927SAndroid Build Coastguard Worker    if (!suballoc_bo)
663*61046927SAndroid Build Coastguard Worker       return;
664*61046927SAndroid Build Coastguard Worker 
665*61046927SAndroid Build Coastguard Worker    simple_mtx_lock(&suballoc_bo->allocator->mtx);
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker    if (p_atomic_read(&suballoc_bo->bo->ref_count) == 1 &&
668*61046927SAndroid Build Coastguard Worker        !suballoc_bo->allocator->bo_cached) {
669*61046927SAndroid Build Coastguard Worker       suballoc_bo->allocator->bo_cached = suballoc_bo->bo;
670*61046927SAndroid Build Coastguard Worker    } else {
671*61046927SAndroid Build Coastguard Worker       pvr_bo_free(suballoc_bo->allocator->device, suballoc_bo->bo);
672*61046927SAndroid Build Coastguard Worker    }
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    simple_mtx_unlock(&suballoc_bo->allocator->mtx);
675*61046927SAndroid Build Coastguard Worker 
676*61046927SAndroid Build Coastguard Worker    vk_free(&suballoc_bo->allocator->device->vk.alloc, suballoc_bo);
677*61046927SAndroid Build Coastguard Worker }
678*61046927SAndroid Build Coastguard Worker 
679*61046927SAndroid Build Coastguard Worker /**
680*61046927SAndroid Build Coastguard Worker  * \brief Interface to retrieve sub-allocated memory offset from the host
681*61046927SAndroid Build Coastguard Worker  * virtual address space.
682*61046927SAndroid Build Coastguard Worker  *
683*61046927SAndroid Build Coastguard Worker  * \param[in] suballoc_bo Sub-allocated buffer object pointer.
684*61046927SAndroid Build Coastguard Worker  *
685*61046927SAndroid Build Coastguard Worker  * \return Valid host virtual address on success.
686*61046927SAndroid Build Coastguard Worker  *
687*61046927SAndroid Build Coastguard Worker  * \sa #pvr_bo_suballoc()
688*61046927SAndroid Build Coastguard Worker  */
pvr_bo_suballoc_get_map_addr(const struct pvr_suballoc_bo * suballoc_bo)689*61046927SAndroid Build Coastguard Worker void *pvr_bo_suballoc_get_map_addr(const struct pvr_suballoc_bo *suballoc_bo)
690*61046927SAndroid Build Coastguard Worker {
691*61046927SAndroid Build Coastguard Worker    const struct pvr_bo *pvr_bo = suballoc_bo->bo;
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    assert((uint8_t *)pvr_bo->bo->map + suballoc_bo->offset <
694*61046927SAndroid Build Coastguard Worker           (uint8_t *)pvr_bo->bo->map + pvr_bo->bo->size);
695*61046927SAndroid Build Coastguard Worker 
696*61046927SAndroid Build Coastguard Worker    return (uint8_t *)pvr_bo->bo->map + suballoc_bo->offset;
697*61046927SAndroid Build Coastguard Worker }
698*61046927SAndroid Build Coastguard Worker 
699*61046927SAndroid Build Coastguard Worker #if defined(HAVE_VALGRIND)
pvr_bo_cpu_map_unchanged(struct pvr_device * device,struct pvr_bo * pvr_bo)700*61046927SAndroid Build Coastguard Worker VkResult pvr_bo_cpu_map_unchanged(struct pvr_device *device,
701*61046927SAndroid Build Coastguard Worker                                   struct pvr_bo *pvr_bo)
702*61046927SAndroid Build Coastguard Worker {
703*61046927SAndroid Build Coastguard Worker    VkResult result = pvr_bo_cpu_map(device, pvr_bo);
704*61046927SAndroid Build Coastguard Worker    if (result == VK_SUCCESS) {
705*61046927SAndroid Build Coastguard Worker       unsigned ret = VALGRIND_SET_VBITS(pvr_bo->bo->map,
706*61046927SAndroid Build Coastguard Worker                                         pvr_bo->bo->vbits,
707*61046927SAndroid Build Coastguard Worker                                         pvr_bo->bo->size);
708*61046927SAndroid Build Coastguard Worker       if (ret != 0 && ret != 1)
709*61046927SAndroid Build Coastguard Worker          mesa_loge("Failed to set vbits; expect bad valgrind results.");
710*61046927SAndroid Build Coastguard Worker    }
711*61046927SAndroid Build Coastguard Worker 
712*61046927SAndroid Build Coastguard Worker    return result;
713*61046927SAndroid Build Coastguard Worker }
714*61046927SAndroid Build Coastguard Worker #endif /* defined(HAVE_VALGRIND) */
715