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