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