lima: implement PLB PP stream cache
[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_job.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_job *job = lima_job_get(ctx);
51 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
52 struct lima_resource *res = lima_resource(cbs->res);
53 int pipe = buff < lima_ctx_buff_num_gp ? LIMA_PIPE_GP : LIMA_PIPE_PP;
54
55 lima_job_add_bo(job, pipe, res->bo, LIMA_SUBMIT_BO_READ);
56
57 return res->bo->va + cbs->offset;
58 }
59
60 void *
61 lima_ctx_buff_map(struct lima_context *ctx, enum lima_ctx_buff buff)
62 {
63 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
64 struct lima_resource *res = lima_resource(cbs->res);
65
66 return lima_bo_map(res->bo) + cbs->offset;
67 }
68
69 void *
70 lima_ctx_buff_alloc(struct lima_context *ctx, enum lima_ctx_buff buff,
71 unsigned size)
72 {
73 struct lima_ctx_buff_state *cbs = ctx->buffer_state + buff;
74 void *ret = NULL;
75
76 cbs->size = align(size, 0x40);
77
78 u_upload_alloc(ctx->uploader, 0, cbs->size, 0x40, &cbs->offset,
79 &cbs->res, &ret);
80
81 return ret;
82 }
83
84 static int
85 lima_context_create_drm_ctx(struct lima_screen *screen)
86 {
87 struct drm_lima_ctx_create req = {0};
88
89 int ret = drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_CREATE, &req);
90 if (ret)
91 return errno;
92
93 return req.id;
94 }
95
96 static void
97 lima_context_free_drm_ctx(struct lima_screen *screen, int id)
98 {
99 struct drm_lima_ctx_free req = {
100 .id = id,
101 };
102
103 drmIoctl(screen->fd, DRM_IOCTL_LIMA_CTX_FREE, &req);
104 }
105
106 static void
107 lima_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
108 {
109 struct lima_context *ctx = lima_context(pctx);
110
111 struct hash_entry *entry = _mesa_hash_table_search(ctx->write_jobs, prsc);
112 if (!entry)
113 return;
114
115 struct lima_job *job = entry->data;
116 if (job->key.zsbuf && (job->key.zsbuf->texture == prsc))
117 job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL);
118
119 if (job->key.cbuf && (job->key.cbuf->texture == prsc))
120 job->resolve &= ~PIPE_CLEAR_COLOR0;
121 }
122
123 static void
124 plb_pp_stream_delete_fn(struct hash_entry *entry)
125 {
126 struct lima_ctx_plb_pp_stream *s = entry->data;
127
128 lima_bo_unreference(s->bo);
129 list_del(&s->lru_list);
130 ralloc_free(s);
131 }
132
133 static void
134 lima_context_destroy(struct pipe_context *pctx)
135 {
136 struct lima_context *ctx = lima_context(pctx);
137 struct lima_screen *screen = lima_screen(pctx->screen);
138
139 lima_job_fini(ctx);
140
141 for (int i = 0; i < lima_ctx_buff_num; i++)
142 pipe_resource_reference(&ctx->buffer_state[i].res, NULL);
143
144 lima_state_fini(ctx);
145
146 if (ctx->blitter)
147 util_blitter_destroy(ctx->blitter);
148
149 if (ctx->uploader)
150 u_upload_destroy(ctx->uploader);
151
152 slab_destroy_child(&ctx->transfer_pool);
153
154 for (int i = 0; i < LIMA_CTX_PLB_MAX_NUM; i++) {
155 if (ctx->plb[i])
156 lima_bo_unreference(ctx->plb[i]);
157 if (ctx->gp_tile_heap[i])
158 lima_bo_unreference(ctx->gp_tile_heap[i]);
159 }
160
161 if (ctx->plb_gp_stream)
162 lima_bo_unreference(ctx->plb_gp_stream);
163
164 if (ctx->gp_output)
165 lima_bo_unreference(ctx->gp_output);
166
167 _mesa_hash_table_destroy(ctx->plb_pp_stream,
168 plb_pp_stream_delete_fn);
169
170 lima_context_free_drm_ctx(screen, ctx->id);
171
172 ralloc_free(ctx);
173 }
174
175 static uint32_t
176 plb_pp_stream_hash(const void *key)
177 {
178 return _mesa_hash_data(key, sizeof(struct lima_ctx_plb_pp_stream_key));
179 }
180
181 static bool
182 plb_pp_stream_compare(const void *key1, const void *key2)
183 {
184 return memcmp(key1, key2, sizeof(struct lima_ctx_plb_pp_stream_key)) == 0;
185 }
186
187 static void
188 lima_set_debug_callback(struct pipe_context *pctx,
189 const struct pipe_debug_callback *cb)
190 {
191 struct lima_context *ctx = lima_context(pctx);
192
193 if (cb)
194 ctx->debug = *cb;
195 else
196 memset(&ctx->debug, 0, sizeof(ctx->debug));
197 }
198
199 struct pipe_context *
200 lima_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
201 {
202 struct lima_screen *screen = lima_screen(pscreen);
203 struct lima_context *ctx;
204
205 ctx = rzalloc(screen, struct lima_context);
206 if (!ctx)
207 return NULL;
208
209 ctx->id = lima_context_create_drm_ctx(screen);
210 if (ctx->id < 0) {
211 ralloc_free(ctx);
212 return NULL;
213 }
214
215 ctx->base.screen = pscreen;
216 ctx->base.destroy = lima_context_destroy;
217 ctx->base.set_debug_callback = lima_set_debug_callback;
218 ctx->base.invalidate_resource = lima_invalidate_resource;
219
220 lima_resource_context_init(ctx);
221 lima_fence_context_init(ctx);
222 lima_state_init(ctx);
223 lima_draw_init(ctx);
224 lima_program_init(ctx);
225 lima_query_init(ctx);
226
227 slab_create_child(&ctx->transfer_pool, &screen->transfer_pool);
228
229 ctx->blitter = util_blitter_create(&ctx->base);
230 if (!ctx->blitter)
231 goto err_out;
232
233 ctx->uploader = u_upload_create_default(&ctx->base);
234 if (!ctx->uploader)
235 goto err_out;
236 ctx->base.stream_uploader = ctx->uploader;
237 ctx->base.const_uploader = ctx->uploader;
238
239 ctx->plb_size = screen->plb_max_blk * LIMA_CTX_PLB_BLK_SIZE;
240 ctx->plb_gp_size = screen->plb_max_blk * 4;
241
242 uint32_t heap_flags;
243 if (screen->has_growable_heap_buffer) {
244 /* growable size buffer, initially will allocate 32K (by default)
245 * backup memory in kernel driver, and will allocate more when GP
246 * get out of memory interrupt. Max to 16M set here.
247 */
248 ctx->gp_tile_heap_size = 0x1000000;
249 heap_flags = LIMA_BO_FLAG_HEAP;
250 } else {
251 /* fix size buffer */
252 ctx->gp_tile_heap_size = 0x100000;
253 heap_flags = 0;
254 }
255
256 for (int i = 0; i < lima_ctx_num_plb; i++) {
257 ctx->plb[i] = lima_bo_create(screen, ctx->plb_size, 0);
258 if (!ctx->plb[i])
259 goto err_out;
260 ctx->gp_tile_heap[i] = lima_bo_create(screen, ctx->gp_tile_heap_size, heap_flags);
261 if (!ctx->gp_tile_heap[i])
262 goto err_out;
263 }
264
265 unsigned plb_gp_stream_size =
266 align(ctx->plb_gp_size * lima_ctx_num_plb, LIMA_PAGE_SIZE);
267 ctx->plb_gp_stream =
268 lima_bo_create(screen, plb_gp_stream_size, 0);
269 if (!ctx->plb_gp_stream)
270 goto err_out;
271 lima_bo_map(ctx->plb_gp_stream);
272
273 /* plb gp stream is static for any framebuffer */
274 for (int i = 0; i < lima_ctx_num_plb; i++) {
275 uint32_t *plb_gp_stream = ctx->plb_gp_stream->map + i * ctx->plb_gp_size;
276 for (int j = 0; j < screen->plb_max_blk; j++)
277 plb_gp_stream[j] = ctx->plb[i]->va + LIMA_CTX_PLB_BLK_SIZE * j;
278 }
279
280 list_inithead(&ctx->plb_pp_stream_lru_list);
281 ctx->plb_pp_stream = _mesa_hash_table_create(
282 ctx, plb_pp_stream_hash, plb_pp_stream_compare);
283 if (!ctx->plb_pp_stream)
284 goto err_out;
285
286 if (!lima_job_init(ctx))
287 goto err_out;
288
289 return &ctx->base;
290
291 err_out:
292 lima_context_destroy(&ctx->base);
293 return NULL;
294 }