2 * © Copyright 2018 Alyssa Rosenzweig
3 * Copyright (C) 2019 Collabora, Ltd.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 /* Transient command stream pooling: command stream uploads try to simply copy
30 * into whereever we left off. If there isn't space, we allocate a new entry
31 * into the pool and copy there */
33 static struct panfrost_bo
*
34 panfrost_pool_alloc_backing(struct pan_pool
*pool
, size_t bo_sz
)
36 /* We don't know what the BO will be used for, so let's flag it
37 * RW and attach it to both the fragment and vertex/tiler jobs.
38 * TODO: if we want fine grained BO assignment we should pass
39 * flags to this function and keep the read/write,
40 * fragment/vertex+tiler pools separate.
42 struct panfrost_bo
*bo
= panfrost_bo_create(pool
->dev
, bo_sz
,
45 util_dynarray_append(&pool
->bos
, struct panfrost_bo
*, bo
);
46 pool
->transient_bo
= bo
;
47 pool
->transient_offset
= 0;
53 panfrost_pool_init(struct pan_pool
*pool
, void *memctx
,
54 struct panfrost_device
*dev
,
55 unsigned create_flags
, bool prealloc
)
57 memset(pool
, 0, sizeof(*pool
));
59 pool
->create_flags
= create_flags
;
60 util_dynarray_init(&pool
->bos
, memctx
);
63 panfrost_pool_alloc_backing(pool
, TRANSIENT_SLAB_SIZE
);
67 panfrost_pool_cleanup(struct pan_pool
*pool
)
69 util_dynarray_foreach(&pool
->bos
, struct panfrost_bo
*, bo
)
70 panfrost_bo_unreference(*bo
);
72 util_dynarray_fini(&pool
->bos
);
76 panfrost_pool_get_bo_handles(struct pan_pool
*pool
, uint32_t *handles
)
79 util_dynarray_foreach(&pool
->bos
, struct panfrost_bo
*, bo
) {
80 assert((*bo
)->gem_handle
> 0);
81 handles
[idx
++] = (*bo
)->gem_handle
;
83 /* Update the BO access flags so that panfrost_bo_wait() knows
84 * about all pending accesses.
85 * We only keep the READ/WRITE info since this is all the BO
86 * wait logic cares about.
87 * We also preserve existing flags as this batch might not
88 * be the first one to access the BO.
90 (*bo
)->gpu_access
|= PAN_BO_ACCESS_RW
;
94 struct panfrost_transfer
95 panfrost_pool_alloc_aligned(struct pan_pool
*pool
, size_t sz
, unsigned alignment
)
97 assert(alignment
== util_next_power_of_two(alignment
));
99 /* Find or create a suitable BO */
100 struct panfrost_bo
*bo
= pool
->transient_bo
;
101 unsigned offset
= ALIGN_POT(pool
->transient_offset
, alignment
);
103 /* If we don't fit, allocate a new backing */
104 if (unlikely(bo
== NULL
|| (offset
+ sz
) >= TRANSIENT_SLAB_SIZE
)) {
105 bo
= panfrost_pool_alloc_backing(pool
,
106 ALIGN_POT(MAX2(TRANSIENT_SLAB_SIZE
, sz
), 4096));
110 pool
->transient_offset
= offset
+ sz
;
112 struct panfrost_transfer ret
= {
113 .cpu
= bo
->cpu
+ offset
,
114 .gpu
= bo
->gpu
+ offset
,
121 panfrost_pool_upload(struct pan_pool
*pool
, const void *data
, size_t sz
)
123 return panfrost_pool_upload_aligned(pool
, data
, sz
, sz
);
127 panfrost_pool_upload_aligned(struct pan_pool
*pool
, const void *data
, size_t sz
, unsigned alignment
)
129 struct panfrost_transfer transfer
= panfrost_pool_alloc_aligned(pool
, sz
, alignment
);
130 memcpy(transfer
.cpu
, data
, sz
);