lima: use single BO for GP outputs
[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/u_suballoc.h"
33 #include "util/hash_table.h"
34
35 #include "lima_screen.h"
36 #include "lima_context.h"
37 #include "lima_resource.h"
38 #include "lima_bo.h"
39 #include "lima_submit.h"
40 #include "lima_util.h"
41 #include "lima_fence.h"
42
43 #include <drm-uapi/lima_drm.h>
44 #include <xf86drm.h>
45
46 int lima_ctx_num_plb = LIMA_CTX_PLB_DEF_NUM;
47
48 uint32_t
49 lima_ctx_buff_va(struct lima_context *ctx, enum lima_ctx_buff buff, unsigned submit)
50 {
51 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
52 struct lima_resource *res = lima_resource(cbs->res);
53
54 if (submit & LIMA_CTX_BUFF_SUBMIT_GP)
55 lima_submit_add_bo(ctx->gp_submit, res->bo, LIMA_SUBMIT_BO_READ);
56 if (submit & LIMA_CTX_BUFF_SUBMIT_PP)
57 lima_submit_add_bo(ctx->pp_submit, res->bo, LIMA_SUBMIT_BO_READ);
58
59 return res->bo->va + cbs->offset;
60 }
61
62 void *
63 lima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff)
64 {
65 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
66 struct lima_resource *res = lima_resource(cbs->res);
67
68 return lima_bo_map(res->bo) + cbs->offset;
69 }
70
71 void *
72 lima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff,
73 unsigned size, bool uploader)
74 {
75 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
76 void *ret = NULL;
77
78 cbs->size = align(size, 0x40);
79
80 if (uploader)
81 u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset,
82 &cbs->res, &ret);
83 else
84 u_suballocator_alloc(ctx->suballocator, cbs->size, 0x10,
85 &cbs->offset, &cbs->res);
86
87 return ret;
88 }
89
90 static int
91 lima_context_create_drm_ctx(struct lima_screen *screen)
92 {
93 struct drm_lima_ctx_create req = {0};
94
95 int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req);
96 if (ret)
97 return errno;
98
99 return req.id;
100 }
101
102 static void
103 lima_context_free_drm_ctx(struct lima_screen *screen, int id)
104 {
105 struct drm_lima_ctx_free req = {
106 .id = id,
107 };
108
109 drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req);
110 }
111
112 static void
113 lima_context_destroy(struct pipe_context *pctx)
114 {
115 struct lima_context *ctx = lima_context(pctx);
116 struct lima_screen *screen = lima_screen(pctx->screen);
117
118 if (ctx->pp_submit)
119 lima_submit_free(ctx->pp_submit);
120 if (ctx->gp_submit)
121 lima_submit_free(ctx->gp_submit);
122
123 for (int i = 0; i < lima_ctx_buff_num; i++)
124 pipe_resource_reference(&ctx->buffer_state[i].res, NULL);
125
126 lima_state_fini(ctx);
127
128 if (ctx->blitter)
129 util_blitter_destroy(ctx->blitter);
130
131 if (ctx->suballocator)
132 u_suballocator_destroy(ctx->suballocator);
133
134 if (ctx->uploader)
135 u_upload_destroy(ctx->uploader);
136
137 slab_destroy_child(&ctx->transfer_pool);
138
139 for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) {
140 if (ctx->plb[i])
141 lima_bo_unreference(ctx->plb[i]);
142 if (ctx->gp_tile_heap[i])
143 lima_bo_unreference(ctx->gp_tile_heap[i]);
144 }
145
146 if (ctx->plb_gp_stream)
147 lima_bo_unreference(ctx->plb_gp_stream);
148
149 if (ctx->gp_output)
150 lima_bo_unreference(ctx->gp_output);
151
152 if (ctx->plb_pp_stream)
153 assert(!_mesa_hash_table_num_entries(ctx->plb_pp_stream));
154
155 lima_context_free_drm_ctx(screen, ctx->id);
156
157 ralloc_free(ctx);
158 }
159
160 static uint32_t
161 plb_pp_stream_hash(const void *key)
162 {
163 return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key));
164 }
165
166 static bool
167 plb_pp_stream_compare(const void *key1, const void *key2)
168 {
169 return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0;
170 }
171
172 static void
173 lima_set_debug_callback(struct pipe_context *pctx,
174 const struct pipe_debug_callback *cb)
175 {
176 struct lima_context *ctx = lima_context(pctx);
177
178 if (cb)
179 ctx->debug = *cb;
180 else
181 memset(&ctx->debug, 0, sizeof(ctx->debug));
182 }
183
184 struct pipe_context *
185 lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
186 {
187 struct lima_screen *screen = lima_screen(pscreen);
188 struct lima_context *ctx;
189
190 ctx = rzalloc(screen, struct lima_context);
191 if (!ctx)
192 return NULL;
193
194 ctx->id = lima_context_create_drm_ctx(screen);
195 if (ctx->id < 0) {
196 ralloc_free(ctx);
197 return NULL;
198 }
199
200 ctx->base.screen = pscreen;
201 ctx->base.destroy = lima_context_destroy;
202 ctx->base.set_debug_callback = lima_set_debug_callback;
203
204 lima_resource_context_init(ctx);
205 lima_fence_context_init(ctx);
206 lima_state_init(ctx);
207 lima_draw_init(ctx);
208 lima_program_init(ctx);
209 lima_query_init(ctx);
210
211 slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
212
213 ctx->blitter = util_blitter_create(&ctx->base);
214 if (!ctx->blitter)
215 goto err_out;
216
217 ctx->uploader = u_upload_create_default(&ctx->base);
218 if (!ctx->uploader)
219 goto err_out;
220 ctx->base.stream_uploader = ctx->uploader;
221 ctx->base.const_uploader = ctx->uploader;
222
223 /* for varying output which need not mmap */
224 ctx->suballocator =
225 u_suballocator_create(&ctx->base, 1024 * 1024, 0,
226 PIPE_USAGE_STREAM, 0, false);
227 if (!ctx->suballocator)
228 goto err_out;
229
230 util_dynarray_init(&ctx->vs_cmd_array, ctx);
231 util_dynarray_init(&ctx->plbu_cmd_array, ctx);
232
233 ctx->plb_size = screen->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE;
234 ctx->plb_gp_size = screen->plb_max_blk * 4;
235
236 for (int i = 0; i < lima_ctx_num_plb; i++) {
237 ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0);
238 if (!ctx->plb[i])
239 goto err_out;
240 ctx->gp_tile_heap[i] = lima_bo_create(screen, gp_tile_heap_size, 0);
241 if (!ctx->gp_tile_heap[i])
242 goto err_out;
243 }
244
245 unsigned plb_gp_stream_size =
246 align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE);
247 ctx->plb_gp_stream =
248 lima_bo_create(screen, plb_gp_stream_size, 0);
249 if (!ctx->plb_gp_stream)
250 goto err_out;
251 lima_bo_map(ctx->plb_gp_stream);
252
253 /* plb gp stream is static for any framebuffer */
254 for (int i = 0; i < lima_ctx_num_plb; i++) {
255 uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size;
256 for (int j = 0; j < screen->plb_max_blk; j++)
257 plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j;
258 }
259
260 if (screen->gpu_type == DRM_LIMA_PARAM_GPU_ID_MALI400) {
261 ctx->plb_pp_stream = _mesa_hash_table_create(
262 ctx, plb_pp_stream_hash, plb_pp_stream_compare);
263 if (!ctx->plb_pp_stream)
264 goto err_out;
265 }
266
267 ctx->gp_submit = lima_submit_create(ctx, LIMA_PIPE_GP);
268 if (!ctx->gp_submit)
269 goto err_out;
270
271 ctx->pp_submit = lima_submit_create(ctx, LIMA_PIPE_PP);
272 if (!ctx->pp_submit)
273 goto err_out;
274
275 return &ctx->base;
276
277 err_out:
278 lima_context_destroy(&ctx->base);
279 return NULL;
280 }
281
282 bool
283 lima_need_flush(struct lima_context *ctx, struct lima_bo *bo, bool write)
284 {
285 return lima_submit_has_bo(ctx->gp_submit, bo, write) ||
286 lima_submit_has_bo(ctx->pp_submit, bo, write);
287 }
288
289 bool
290 lima_is_scanout(struct lima_context *ctx)
291 {
292 /* If there is no color buffer, it's an FBO */
293 if (!ctx->framebuffer.base.nr_cbufs)
294 return false;
295
296 return ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_DISPLAY_TARGET ||
297 ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SCANOUT ||
298 ctx->framebuffer.base.cbufs[0]->texture->bind & PIPE_BIND_SHARED;
299 }