xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_mempool.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * © Copyright 2017-2018 Alyssa Rosenzweig
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  */
24 
25 #ifndef __PANVK_POOL_H__
26 #define __PANVK_POOL_H__
27 
28 #include "panvk_priv_bo.h"
29 
30 #include "pan_pool.h"
31 
32 #include "util/list.h"
33 #include "util/simple_mtx.h"
34 
35 struct panvk_bo_pool {
36    struct list_head free_bos;
37 };
38 
39 static inline void
panvk_bo_pool_init(struct panvk_bo_pool * bo_pool)40 panvk_bo_pool_init(struct panvk_bo_pool *bo_pool)
41 {
42    list_inithead(&bo_pool->free_bos);
43 }
44 
45 void panvk_bo_pool_cleanup(struct panvk_bo_pool *bo_pool);
46 
47 struct panvk_pool_properties {
48    /* BO flags to use in the pool */
49    unsigned create_flags;
50 
51    /* Allocation granularity. */
52    size_t slab_size;
53 
54    /* Label for created BOs */
55    const char *label;
56 
57    /* When false, BOs allocated by the pool are not retained by the pool
58     * when they leave the transient_bo field. */
59    bool owns_bos;
60 
61    /* If pool is shared and not externally protected, this should be true. */
62    bool needs_locking;
63 
64    bool prealloc;
65 };
66 
67 /* Represents grow-only memory. It may be owned by the batch (OpenGL), or may
68    be unowned for persistent uploads. */
69 
70 struct panvk_pool {
71    /* Inherit from pan_pool */
72    struct pan_pool base;
73 
74    /* Parent device for allocation */
75    struct panvk_device *dev;
76 
77    /* Pool properties. */
78    struct panvk_pool_properties props;
79 
80    /* Before allocating a new BO, check if the BO pool has free BOs.
81     * When returning BOs, if bo_pool != NULL, return them to this bo_pool.
82     */
83    struct panvk_bo_pool *bo_pool;
84 
85    /* BOs allocated by this pool */
86    struct list_head bos;
87    struct list_head big_bos;
88    unsigned bo_count;
89 
90    /* Lock used to protect allocation when the pool is shared. */
91    simple_mtx_t lock;
92 
93    /* Current transient BO */
94    struct panvk_priv_bo *transient_bo;
95 
96    /* Within the topmost transient BO, how much has been used? */
97    unsigned transient_offset;
98 };
99 
100 static inline struct panvk_pool *
to_panvk_pool(struct pan_pool * pool)101 to_panvk_pool(struct pan_pool *pool)
102 {
103    return container_of(pool, struct panvk_pool, base);
104 }
105 
106 void panvk_pool_init(struct panvk_pool *pool, struct panvk_device *dev,
107                      struct panvk_bo_pool *bo_pool,
108                      const struct panvk_pool_properties *props);
109 
110 void panvk_pool_reset(struct panvk_pool *pool);
111 
112 void panvk_pool_cleanup(struct panvk_pool *pool);
113 
114 static inline unsigned
panvk_pool_num_bos(struct panvk_pool * pool)115 panvk_pool_num_bos(struct panvk_pool *pool)
116 {
117    return pool->bo_count;
118 }
119 
120 void panvk_pool_get_bo_handles(struct panvk_pool *pool, uint32_t *handles);
121 
122 struct panvk_priv_mem {
123    struct panvk_priv_bo *bo;
124    unsigned offset;
125 };
126 
127 static inline uint64_t
panvk_priv_mem_dev_addr(struct panvk_priv_mem mem)128 panvk_priv_mem_dev_addr(struct panvk_priv_mem mem)
129 {
130    return mem.bo ? mem.bo->addr.dev + mem.offset : 0;
131 }
132 
133 static inline void *
panvk_priv_mem_host_addr(struct panvk_priv_mem mem)134 panvk_priv_mem_host_addr(struct panvk_priv_mem mem)
135 {
136    return mem.bo && mem.bo->addr.host
137              ? (uint8_t *)mem.bo->addr.host + mem.offset
138              : NULL;
139 }
140 
141 struct panvk_pool_alloc_info {
142    size_t size;
143    unsigned alignment;
144 };
145 
146 static inline struct panvk_pool_alloc_info
panvk_pool_descs_to_alloc_info(const struct pan_desc_alloc_info * descs)147 panvk_pool_descs_to_alloc_info(const struct pan_desc_alloc_info *descs)
148 {
149    struct panvk_pool_alloc_info alloc_info = {
150       .alignment = descs[0].align,
151    };
152 
153    for (unsigned i = 0; descs[i].size; i++)
154       alloc_info.size += descs[i].size * descs[i].nelems;
155 
156    return alloc_info;
157 }
158 
159 struct panvk_priv_mem panvk_pool_alloc_mem(struct panvk_pool *pool,
160                                            struct panvk_pool_alloc_info info);
161 
162 static inline void
panvk_pool_free_mem(struct panvk_pool * pool,struct panvk_priv_mem mem)163 panvk_pool_free_mem(struct panvk_pool *pool, struct panvk_priv_mem mem)
164 {
165    if (!pool->props.owns_bos)
166       panvk_priv_bo_unref(mem.bo);
167 }
168 
169 static inline struct panvk_priv_mem
panvk_pool_upload_aligned(struct panvk_pool * pool,const void * data,size_t sz,unsigned alignment)170 panvk_pool_upload_aligned(struct panvk_pool *pool, const void *data, size_t sz,
171                           unsigned alignment)
172 {
173    struct panvk_pool_alloc_info info = {
174       .size = sz,
175       .alignment = alignment,
176    };
177 
178    struct panvk_priv_mem mem = panvk_pool_alloc_mem(pool, info);
179    memcpy(panvk_priv_mem_host_addr(mem), data, sz);
180    return mem;
181 }
182 
183 static inline struct panvk_priv_mem
panvk_pool_upload(struct panvk_pool * pool,const void * data,size_t sz)184 panvk_pool_upload(struct panvk_pool *pool, const void *data, size_t sz)
185 {
186    return panvk_pool_upload_aligned(pool, data, sz, sz);
187 }
188 
189 #define panvk_pool_alloc_desc(pool, name)                                      \
190    panvk_pool_alloc_mem(pool, panvk_pool_descs_to_alloc_info(                  \
191                                  PAN_DESC_AGGREGATE(PAN_DESC(name))))
192 
193 #define panvk_pool_alloc_desc_array(pool, count, name)                         \
194    panvk_pool_alloc_mem(pool,                                                  \
195                         panvk_pool_descs_to_alloc_info(                        \
196                            PAN_DESC_AGGREGATE(PAN_DESC_ARRAY(count, name))))
197 
198 #define panvk_pool_alloc_desc_aggregate(pool, ...)                             \
199    panvk_pool_alloc_mem(                                                       \
200       pool, panvk_pool_descs_to_alloc_info(PAN_DESC_AGGREGATE(__VA_ARGS__)))
201 
202 #endif
203