lima: move syncobj from lima_submit to lima_context
[mesa.git] / src / gallium / drivers / lima / lima_context.c
1 /*
2 * Copyright (c) 2017-2019 Lima Project
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, sub license,
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
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the 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 NON-INFRINGEMENT. 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
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25 #include "util/u_memory.h"
26 #include "util/u_blitter.h"
27 #include "util/u_upload_mgr.h"
28 #include "util/u_math.h"
29 #include "util/u_debug.h"
30 #include "util/ralloc.h"
31 #include "util/u_inlines.h"
32 #include "util/hash_table.h"
33
34 #include "lima_screen.h"
35 #include "lima_context.h"
36 #include "lima_resource.h"
37 #include "lima_bo.h"
38 #include "lima_submit.h"
39 #include "lima_util.h"
40 #include "lima_fence.h"
41
42 #include <drm-uapi/lima_drm.h>
43 #include <xf86drm.h>
44
45 int lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM;
46
47 uint32_t
48 lima_ctx_buff_va(struct lima_context *ctx, enum lima_ctx_buff buff)
49 {
50 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
51 struct lima_resource *res = lima_resource(cbs->res);
52
53 if (buff < lima_ctx_buff_num_gp)
54 lima_submit_add_bo(ctx->gp_submit, res->bo, LIMA_SUBMIT_BO_READ);
55 else
56 lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_READ);
57
58 return res->bo->va + cbs->offset;
59 }
60
61 void *
62 lima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff)
63 {
64 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
65 struct lima_resource *res = lima_resource(cbs->res);
66
67 return lima_bo_map(res->bo) + cbs->offset;
68 }
69
70 void *
71 lima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff,
72 unsigned size)
73 {
74 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
75 void *ret = NULL;
76
77 cbs->size = align(size, 0x40);
78
79 u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset,
80 &cbs->res, &ret);
81
82 return ret;
83 }
84
85 static int
86 lima_context_create_drm_ctx(struct lima_screen *screen)
87 {
88 struct drm_lima_ctx_create req = {0};
89
90 int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req);
91 if (ret)
92 return errno;
93
94 return req.id;
95 }
96
97 static void
98 lima_context_free_drm_ctx(struct lima_screen *screen, int id)
99 {
100 struct drm_lima_ctx_free req = {
101 .id = id,
102 };
103
104 drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req);
105 }
106
107 static void
108 lima_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
109 {
110 struct lima_context *ctx = lima_context(pctx);
111
112 if (ctx->framebuffer.base.zsbuf && (ctx->framebuffer.base.zsbuf->texture == prsc))
113 ctx->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL);
114
115 if (ctx->framebuffer.base.nr_cbufs &&
116 (ctx->framebuffer.base.cbufs[0]->texture == prsc))
117 ctx->resolve &= ~PIPE_CLEAR_COLOR0;
118 }
119
120 static void
121 lima_context_destroy(struct pipe_context *pctx)
122 {
123 struct lima_context *ctx = lima_context(pctx);
124 struct lima_screen *screen = lima_screen(pctx->screen);
125
126 lima_submit_fini(ctx);
127
128 if (ctx->pp_submit)
129 lima_submit_free(ctx->pp_submit);
130 if (ctx->gp_submit)
131 lima_submit_free(ctx->gp_submit);
132
133 for (int i = 0; i < lima_ctx_buff_num; i++)
134 pipe_resource_reference(&ctx->buffer_state[i].res, NULL);
135
136 lima_state_fini(ctx);
137
138 if (ctx->blitter)
139 util_blitter_destroy(ctx->blitter);
140
141 if (ctx->uploader)
142 u_upload_destroy(ctx->uploader);
143
144 slab_destroy_child(&ctx->transfer_pool);
145
146 for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) {
147 if (ctx->plb[i])
148 lima_bo_unreference(ctx->plb[i]);
149 if (ctx->gp_tile_heap[i])
150 lima_bo_unreference(ctx->gp_tile_heap[i]);
151 }
152
153 if (ctx->plb_gp_stream)
154 lima_bo_unreference(ctx->plb_gp_stream);
155
156 if (ctx->gp_output)
157 lima_bo_unreference(ctx->gp_output);
158
159 if (ctx->plb_pp_stream)
160 assert(!_mesa_hash_table_num_entries(ctx->plb_pp_stream));
161
162 lima_context_free_drm_ctx(screen, ctx->id);
163
164 ralloc_free(ctx);
165 }
166
167 static uint32_t
168 plb_pp_stream_hash(const void *key)
169 {
170 return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key));
171 }
172
173 static bool
174 plb_pp_stream_compare(const void *key1, const void *key2)
175 {
176 return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0;
177 }
178
179 static void
180 lima_set_debug_callback(struct pipe_context *pctx,
181 const struct pipe_debug_callback *cb)
182 {
183 struct lima_context *ctx = lima_context(pctx);
184
185 if (cb)
186 ctx->debug = *cb;
187 else
188 memset(&ctx->debug, 0, sizeof(ctx->debug));
189 }
190
191 struct pipe_context *
192 lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
193 {
194 struct lima_screen *screen = lima_screen(pscreen);
195 struct lima_context *ctx;
196
197 ctx = rzalloc(screen, struct lima_context);
198 if (!ctx)
199 return NULL;
200
201 ctx->id = lima_context_create_drm_ctx(screen);
202 if (ctx->id < 0) {
203 ralloc_free(ctx);
204 return NULL;
205 }
206
207 ctx->base.screen = pscreen;
208 ctx->base.destroy = lima_context_destroy;
209 ctx->base.set_debug_callback = lima_set_debug_callback;
210 ctx->base.invalidate_resource = lima_invalidate_resource;
211
212 lima_resource_context_init(ctx);
213 lima_fence_context_init(ctx);
214 lima_state_init(ctx);
215 lima_draw_init(ctx);
216 lima_program_init(ctx);
217 lima_query_init(ctx);
218
219 slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
220
221 ctx->blitter = util_blitter_create(&ctx->base);
222 if (!ctx->blitter)
223 goto err_out;
224
225 ctx->uploader = u_upload_create_default(&ctx->base);
226 if (!ctx->uploader)
227 goto err_out;
228 ctx->base.stream_uploader = ctx->uploader;
229 ctx->base.const_uploader = ctx->uploader;
230
231 ctx->damage_rect.minx = ctx->damage_rect.miny = 0xffff;
232 ctx->damage_rect.maxx = ctx->damage_rect.maxy = 0;
233
234 util_dynarray_init(&ctx->vs_cmd_array, ctx);
235 util_dynarray_init(&ctx->plbu_cmd_array, ctx);
236 util_dynarray_init(&ctx->plbu_cmd_head, ctx);
237
238 ctx->plb_size = screen->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE;
239 ctx->plb_gp_size = screen->plb_max_blk * 4;
240
241 uint32_t heap_flags;
242 if (screen->has_growable_heap_buffer) {
243 /* growable size buffer, initially will allocate 32K (by default)
244 * backup memory in kernel driver, and will allocate more when GP
245 * get out of memory interrupt. Max to 16M set here.
246 */
247 ctx->gp_tile_heap_size = 0x1000000;
248 heap_flags = LIMA_BO_FLAG_HEAP;
249 } else {
250 /* fix size buffer */
251 ctx->gp_tile_heap_size = 0x100000;
252 heap_flags = 0;
253 }
254
255 for (int i = 0; i < lima_ctx_num_plb; i++) {
256 ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0);
257 if (!ctx->plb[i])
258 goto err_out;
259 ctx->gp_tile_heap[i] = lima_bo_create(screen, ctx->gp_tile_heap_size, heap_flags);
260 if (!ctx->gp_tile_heap[i])
261 goto err_out;
262 }
263
264 unsigned plb_gp_stream_size =
265 align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE);
266 ctx->plb_gp_stream =
267 lima_bo_create(screen, plb_gp_stream_size, 0);
268 if (!ctx->plb_gp_stream)
269 goto err_out;
270 lima_bo_map(ctx->plb_gp_stream);
271
272 /* plb gp stream is static for any framebuffer */
273 for (int i = 0; i < lima_ctx_num_plb; i++) {
274 uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size;
275 for (int j = 0; j < screen->plb_max_blk; j++)
276 plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j;
277 }
278
279 if (screen->gpu_type == DRM_LIMA_PARAM_GPU_ID_MALI400) {
280 ctx->plb_pp_stream = _mesa_hash_table_create(
281 ctx, plb_pp_stream_hash, plb_pp_stream_compare);
282 if (!ctx->plb_pp_stream)
283 goto err_out;
284 }
285
286 ctx->gp_submit = lima_submit_create(ctx, LIMA_PIPE_GP);
287 if (!ctx->gp_submit)
288 goto err_out;
289
290 ctx->pp_submit = lima_submit_create(ctx, LIMA_PIPE_PP);
291 if (!ctx->pp_submit)
292 goto err_out;
293
294 if (!lima_submit_init(ctx))
295 goto err_out;
296
297 return &ctx->base;
298
299 err_out:
300 lima_context_destroy(&ctx->base);
301 return NULL;
302 }
303
304 bool
305 lima_need_flush(struct lima_context *ctx, struct lima_bo *bo, bool write)
306 {
307 return lima_submit_has_bo(ctx->gp_submit, bo, write) ||
308 lima_submit_has_bo(ctx->pp_submit, bo, write);
309 }