• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 enum panvk_priv_mem_flags {
123    PANVK_PRIV_MEM_OWNED_BY_POOL = BITFIELD_BIT(0),
124 };
125 
126 struct panvk_priv_mem {
127    uintptr_t bo;
128    unsigned offset;
129 };
130 
131 #define PANVK_PRIV_MEM_FLAGS_MASK ((uintptr_t)7)
132 
133 static struct panvk_priv_bo *
panvk_priv_mem_bo(struct panvk_priv_mem mem)134 panvk_priv_mem_bo(struct panvk_priv_mem mem)
135 {
136    return (struct panvk_priv_bo *)(mem.bo & ~PANVK_PRIV_MEM_FLAGS_MASK);
137 }
138 
139 static uint32_t
panvk_priv_mem_flags(struct panvk_priv_mem mem)140 panvk_priv_mem_flags(struct panvk_priv_mem mem)
141 {
142    return mem.bo & PANVK_PRIV_MEM_FLAGS_MASK;
143 }
144 
145 static inline uint64_t
panvk_priv_mem_dev_addr(struct panvk_priv_mem mem)146 panvk_priv_mem_dev_addr(struct panvk_priv_mem mem)
147 {
148    struct panvk_priv_bo *bo = panvk_priv_mem_bo(mem);
149 
150    return bo ? bo->addr.dev + mem.offset : 0;
151 }
152 
153 static inline void *
panvk_priv_mem_host_addr(struct panvk_priv_mem mem)154 panvk_priv_mem_host_addr(struct panvk_priv_mem mem)
155 {
156    struct panvk_priv_bo *bo = panvk_priv_mem_bo(mem);
157 
158    return bo && bo->addr.host ? (uint8_t *)bo->addr.host + mem.offset : NULL;
159 }
160 
161 struct panvk_pool_alloc_info {
162    size_t size;
163    unsigned alignment;
164 };
165 
166 static inline struct panvk_pool_alloc_info
panvk_pool_descs_to_alloc_info(const struct pan_desc_alloc_info * descs)167 panvk_pool_descs_to_alloc_info(const struct pan_desc_alloc_info *descs)
168 {
169    struct panvk_pool_alloc_info alloc_info = {
170       .alignment = descs[0].align,
171    };
172 
173    for (unsigned i = 0; descs[i].size; i++)
174       alloc_info.size += descs[i].size * descs[i].nelems;
175 
176    return alloc_info;
177 }
178 
179 struct panvk_priv_mem panvk_pool_alloc_mem(struct panvk_pool *pool,
180                                            struct panvk_pool_alloc_info info);
181 
182 static inline void
panvk_pool_free_mem(struct panvk_priv_mem * mem)183 panvk_pool_free_mem(struct panvk_priv_mem *mem)
184 {
185    struct panvk_priv_bo *bo = panvk_priv_mem_bo(*mem);
186    uint32_t flags = panvk_priv_mem_flags(*mem);
187 
188    if (bo) {
189       if (likely(!(flags & PANVK_PRIV_MEM_OWNED_BY_POOL)))
190          panvk_priv_bo_unref(bo);
191 
192       memset(mem, 0, sizeof(*mem));
193    }
194 }
195 
196 static inline struct panvk_priv_mem
panvk_pool_upload_aligned(struct panvk_pool * pool,const void * data,size_t sz,unsigned alignment)197 panvk_pool_upload_aligned(struct panvk_pool *pool, const void *data, size_t sz,
198                           unsigned alignment)
199 {
200    struct panvk_pool_alloc_info info = {
201       .size = sz,
202       .alignment = alignment,
203    };
204 
205    struct panvk_priv_mem mem = panvk_pool_alloc_mem(pool, info);
206    memcpy(panvk_priv_mem_host_addr(mem), data, sz);
207    return mem;
208 }
209 
210 static inline struct panvk_priv_mem
panvk_pool_upload(struct panvk_pool * pool,const void * data,size_t sz)211 panvk_pool_upload(struct panvk_pool *pool, const void *data, size_t sz)
212 {
213    return panvk_pool_upload_aligned(pool, data, sz, sz);
214 }
215 
216 #define panvk_pool_alloc_desc(pool, name)                                      \
217    panvk_pool_alloc_mem(pool, panvk_pool_descs_to_alloc_info(                  \
218                                  PAN_DESC_AGGREGATE(PAN_DESC(name))))
219 
220 #define panvk_pool_alloc_desc_array(pool, count, name)                         \
221    panvk_pool_alloc_mem(pool,                                                  \
222                         panvk_pool_descs_to_alloc_info(                        \
223                            PAN_DESC_AGGREGATE(PAN_DESC_ARRAY(count, name))))
224 
225 #define panvk_pool_alloc_desc_aggregate(pool, ...)                             \
226    panvk_pool_alloc_mem(                                                       \
227       pool, panvk_pool_descs_to_alloc_info(PAN_DESC_AGGREGATE(__VA_ARGS__)))
228 
229 #endif
230