1 /*
2 * Copyright (C) 2019-2020 Collabora, Ltd.
3 * © Copyright 2018 Alyssa Rosenzweig
4 * Copyright © 2014-2017 Broadcom
5 * Copyright (C) 2017 Intel Corporation
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 *
26 */
27
28 #include <errno.h>
29 #include <poll.h>
30
31 #include "pan_bo.h"
32 #include "pan_context.h"
33 #include "pan_minmax_cache.h"
34
35 #include "util/format/u_format.h"
36 #include "util/half_float.h"
37 #include "util/libsync.h"
38 #include "util/macros.h"
39 #include "util/u_debug_cb.h"
40 #include "util/u_helpers.h"
41 #include "util/u_inlines.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 #include "util/u_prim.h"
45 #include "util/u_prim_restart.h"
46 #include "util/u_surface.h"
47 #include "util/u_upload_mgr.h"
48 #include "util/u_vbuf.h"
49
50 #include "compiler/nir/nir_serialize.h"
51 #include "util/pan_lower_framebuffer.h"
52 #include "decode.h"
53 #include "pan_device.h"
54 #include "pan_fence.h"
55 #include "pan_screen.h"
56 #include "pan_util.h"
57
58 static void
panfrost_clear(struct pipe_context * pipe,unsigned buffers,const struct pipe_scissor_state * scissor_state,const union pipe_color_union * color,double depth,unsigned stencil)59 panfrost_clear(struct pipe_context *pipe, unsigned buffers,
60 const struct pipe_scissor_state *scissor_state,
61 const union pipe_color_union *color, double depth,
62 unsigned stencil)
63 {
64 if (!panfrost_render_condition_check(pan_context(pipe)))
65 return;
66
67 /* Only get batch after checking the render condition, since the check can
68 * cause the batch to be flushed.
69 */
70 struct panfrost_context *ctx = pan_context(pipe);
71 struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx);
72
73 /* At the start of the batch, we can clear for free */
74 if (batch->draw_count == 0) {
75 panfrost_batch_clear(batch, buffers, color, depth, stencil);
76 return;
77 }
78
79 /* Once there is content, clear with a fullscreen quad */
80 panfrost_blitter_save(ctx, PAN_RENDER_CLEAR);
81
82 perf_debug(ctx, "Clearing with quad");
83 util_blitter_clear(
84 ctx->blitter, ctx->pipe_framebuffer.width, ctx->pipe_framebuffer.height,
85 util_framebuffer_get_num_layers(&ctx->pipe_framebuffer), buffers, color,
86 depth, stencil,
87 util_framebuffer_get_num_samples(&ctx->pipe_framebuffer) > 1);
88 }
89
90 bool
panfrost_writes_point_size(struct panfrost_context * ctx)91 panfrost_writes_point_size(struct panfrost_context *ctx)
92 {
93 struct panfrost_compiled_shader *vs = ctx->prog[PIPE_SHADER_VERTEX];
94 assert(vs != NULL);
95
96 return vs->info.vs.writes_point_size && ctx->active_prim == MESA_PRIM_POINTS;
97 }
98
99 /* The entire frame is in memory -- send it off to the kernel! */
100
101 void
panfrost_flush(struct pipe_context * pipe,struct pipe_fence_handle ** fence,unsigned flags)102 panfrost_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence,
103 unsigned flags)
104 {
105 struct panfrost_context *ctx = pan_context(pipe);
106 struct panfrost_device *dev = pan_device(pipe->screen);
107
108 /* Submit all pending jobs */
109 panfrost_flush_all_batches(ctx, NULL);
110
111 if (fence) {
112 struct pipe_fence_handle *f = panfrost_fence_create(ctx);
113 pipe->screen->fence_reference(pipe->screen, fence, NULL);
114 *fence = f;
115 }
116
117 if (dev->debug & PAN_DBG_TRACE)
118 pandecode_next_frame(dev->decode_ctx);
119 }
120
121 static void
panfrost_texture_barrier(struct pipe_context * pipe,unsigned flags)122 panfrost_texture_barrier(struct pipe_context *pipe, unsigned flags)
123 {
124 struct panfrost_context *ctx = pan_context(pipe);
125 panfrost_flush_all_batches(ctx, "Texture barrier");
126 }
127
128 static void
panfrost_set_frontend_noop(struct pipe_context * pipe,bool enable)129 panfrost_set_frontend_noop(struct pipe_context *pipe, bool enable)
130 {
131 struct panfrost_context *ctx = pan_context(pipe);
132 panfrost_flush_all_batches(ctx, "Frontend no-op change");
133 ctx->is_noop = enable;
134 }
135
136 static void
panfrost_generic_cso_delete(struct pipe_context * pctx,void * hwcso)137 panfrost_generic_cso_delete(struct pipe_context *pctx, void *hwcso)
138 {
139 free(hwcso);
140 }
141
142 static void
panfrost_bind_blend_state(struct pipe_context * pipe,void * cso)143 panfrost_bind_blend_state(struct pipe_context *pipe, void *cso)
144 {
145 struct panfrost_context *ctx = pan_context(pipe);
146 ctx->blend = cso;
147 ctx->dirty |= PAN_DIRTY_BLEND;
148 }
149
150 static void
panfrost_set_blend_color(struct pipe_context * pipe,const struct pipe_blend_color * blend_color)151 panfrost_set_blend_color(struct pipe_context *pipe,
152 const struct pipe_blend_color *blend_color)
153 {
154 struct panfrost_context *ctx = pan_context(pipe);
155 ctx->dirty |= PAN_DIRTY_BLEND;
156
157 if (blend_color)
158 ctx->blend_color = *blend_color;
159 }
160
161 /* Create a final blend given the context */
162
163 mali_ptr
panfrost_get_blend(struct panfrost_batch * batch,unsigned rti,struct panfrost_bo ** bo,unsigned * shader_offset)164 panfrost_get_blend(struct panfrost_batch *batch, unsigned rti,
165 struct panfrost_bo **bo, unsigned *shader_offset)
166 {
167 struct panfrost_context *ctx = batch->ctx;
168 struct panfrost_device *dev = pan_device(ctx->base.screen);
169 struct panfrost_blend_state *blend = ctx->blend;
170 struct pan_blend_info info = blend->info[rti];
171 struct pipe_surface *surf = batch->key.cbufs[rti];
172 enum pipe_format fmt = surf->format;
173
174 /* Use fixed-function if the equation permits, the format is blendable,
175 * and no more than one unique constant is accessed */
176 if (info.fixed_function && dev->blendable_formats[fmt].internal &&
177 pan_blend_is_homogenous_constant(info.constant_mask,
178 ctx->blend_color.color)) {
179 return 0;
180 }
181
182 /* On all architectures, we can disable writes for a blend descriptor,
183 * at which point the format doesn't matter.
184 */
185 if (!info.enabled)
186 return 0;
187
188 /* On Bifrost and newer, we can also use fixed-function for opaque
189 * output regardless of the format by configuring the appropriate
190 * conversion descriptor in the internal blend descriptor. (Midgard
191 * requires a blend shader even for this case.)
192 */
193 if (dev->arch >= 6 && info.opaque)
194 return 0;
195
196 /* Otherwise, we need to grab a shader */
197 struct pan_blend_state pan_blend = blend->pan;
198 unsigned nr_samples = surf->nr_samples ?: surf->texture->nr_samples;
199
200 pan_blend.rts[rti].format = fmt;
201 pan_blend.rts[rti].nr_samples = nr_samples;
202 memcpy(pan_blend.constants, ctx->blend_color.color,
203 sizeof(pan_blend.constants));
204
205 /* Upload the shader, sharing a BO */
206 if (!(*bo)) {
207 *bo = panfrost_batch_create_bo(batch, 4096, PAN_BO_EXECUTE,
208 PIPE_SHADER_FRAGMENT, "Blend shader");
209 }
210
211 struct panfrost_compiled_shader *ss = ctx->prog[PIPE_SHADER_FRAGMENT];
212
213 /* Default for Midgard */
214 nir_alu_type col0_type = nir_type_float32;
215 nir_alu_type col1_type = nir_type_float32;
216
217 /* Bifrost has per-output types, respect them */
218 if (dev->arch >= 6) {
219 col0_type = ss->info.bifrost.blend[rti].type;
220 col1_type = ss->info.bifrost.blend_src1_type;
221 }
222
223 pthread_mutex_lock(&dev->blend_shaders.lock);
224 struct pan_blend_shader_variant *shader =
225 pan_screen(ctx->base.screen)
226 ->vtbl.get_blend_shader(&dev->blend_shaders, &pan_blend, col0_type,
227 col1_type, rti);
228
229 /* Size check and upload */
230 unsigned offset = *shader_offset;
231 assert((offset + shader->binary.size) < 4096);
232 memcpy((*bo)->ptr.cpu + offset, shader->binary.data, shader->binary.size);
233 *shader_offset += shader->binary.size;
234 pthread_mutex_unlock(&dev->blend_shaders.lock);
235
236 return ((*bo)->ptr.gpu + offset) | shader->first_tag;
237 }
238
239 static void
panfrost_bind_rasterizer_state(struct pipe_context * pctx,void * hwcso)240 panfrost_bind_rasterizer_state(struct pipe_context *pctx, void *hwcso)
241 {
242 struct panfrost_context *ctx = pan_context(pctx);
243 ctx->rasterizer = hwcso;
244
245 /* We can assume rasterizer is always dirty, the dependencies are
246 * too intricate to bother tracking in detail. However we could
247 * probably diff the renderers for viewport dirty tracking, that
248 * just cares about the scissor enable and the depth clips. */
249 ctx->dirty |= PAN_DIRTY_SCISSOR | PAN_DIRTY_RASTERIZER;
250 }
251
252 static void
panfrost_set_shader_images(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned count,unsigned unbind_num_trailing_slots,const struct pipe_image_view * iviews)253 panfrost_set_shader_images(struct pipe_context *pctx,
254 enum pipe_shader_type shader, unsigned start_slot,
255 unsigned count, unsigned unbind_num_trailing_slots,
256 const struct pipe_image_view *iviews)
257 {
258 struct panfrost_context *ctx = pan_context(pctx);
259 ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_IMAGE;
260
261 /* Unbind start_slot...start_slot+count */
262 if (!iviews) {
263 for (int i = start_slot;
264 i < start_slot + count + unbind_num_trailing_slots; i++) {
265 pipe_resource_reference(&ctx->images[shader][i].resource, NULL);
266 }
267
268 ctx->image_mask[shader] &= ~(((1ull << count) - 1) << start_slot);
269 return;
270 }
271
272 /* Bind start_slot...start_slot+count */
273 for (int i = 0; i < count; i++) {
274 const struct pipe_image_view *image = &iviews[i];
275 SET_BIT(ctx->image_mask[shader], 1 << (start_slot + i), image->resource);
276
277 if (!image->resource) {
278 util_copy_image_view(&ctx->images[shader][start_slot + i], NULL);
279 continue;
280 }
281
282 struct panfrost_resource *rsrc = pan_resource(image->resource);
283
284 /* Images don't work with AFBC/AFRC, since they require pixel-level
285 * granularity */
286 if (drm_is_afbc(rsrc->image.layout.modifier) ||
287 drm_is_afrc(rsrc->image.layout.modifier)) {
288 pan_resource_modifier_convert(
289 ctx, rsrc, DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED, true,
290 "Shader image");
291 }
292
293 util_copy_image_view(&ctx->images[shader][start_slot + i], image);
294 }
295
296 /* Unbind start_slot+count...start_slot+count+unbind_num_trailing_slots */
297 for (int i = 0; i < unbind_num_trailing_slots; i++) {
298 SET_BIT(ctx->image_mask[shader], 1 << (start_slot + count + i), NULL);
299 util_copy_image_view(&ctx->images[shader][start_slot + count + i], NULL);
300 }
301 }
302
303 static void
panfrost_bind_vertex_elements_state(struct pipe_context * pctx,void * hwcso)304 panfrost_bind_vertex_elements_state(struct pipe_context *pctx, void *hwcso)
305 {
306 struct panfrost_context *ctx = pan_context(pctx);
307 ctx->vertex = hwcso;
308 ctx->dirty |= PAN_DIRTY_VERTEX;
309 }
310
311 static void
panfrost_bind_sampler_states(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned num_sampler,void ** sampler)312 panfrost_bind_sampler_states(struct pipe_context *pctx,
313 enum pipe_shader_type shader, unsigned start_slot,
314 unsigned num_sampler, void **sampler)
315 {
316 struct panfrost_context *ctx = pan_context(pctx);
317 ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SAMPLER;
318
319 for (unsigned i = 0; i < num_sampler; i++) {
320 unsigned p = start_slot + i;
321 ctx->samplers[shader][p] = sampler ? sampler[i] : NULL;
322 if (ctx->samplers[shader][p])
323 ctx->valid_samplers[shader] |= BITFIELD_BIT(p);
324 else
325 ctx->valid_samplers[shader] &= ~BITFIELD_BIT(p);
326 }
327
328 ctx->sampler_count[shader] = util_last_bit(ctx->valid_samplers[shader]);
329 }
330
331 static void
panfrost_set_vertex_buffers(struct pipe_context * pctx,unsigned num_buffers,const struct pipe_vertex_buffer * buffers)332 panfrost_set_vertex_buffers(struct pipe_context *pctx, unsigned num_buffers,
333 const struct pipe_vertex_buffer *buffers)
334 {
335 struct panfrost_context *ctx = pan_context(pctx);
336
337 util_set_vertex_buffers_mask(ctx->vertex_buffers, &ctx->vb_mask, buffers,
338 num_buffers, true);
339
340 ctx->dirty |= PAN_DIRTY_VERTEX;
341 }
342
343 static void
panfrost_set_constant_buffer(struct pipe_context * pctx,enum pipe_shader_type shader,uint index,bool take_ownership,const struct pipe_constant_buffer * buf)344 panfrost_set_constant_buffer(struct pipe_context *pctx,
345 enum pipe_shader_type shader, uint index,
346 bool take_ownership,
347 const struct pipe_constant_buffer *buf)
348 {
349 struct panfrost_context *ctx = pan_context(pctx);
350 struct panfrost_constant_buffer *pbuf = &ctx->constant_buffer[shader];
351
352 util_copy_constant_buffer(&pbuf->cb[index], buf, take_ownership);
353
354 unsigned mask = (1 << index);
355
356 if (unlikely(!buf)) {
357 pbuf->enabled_mask &= ~mask;
358 return;
359 }
360
361 pbuf->enabled_mask |= mask;
362 ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_CONST;
363 }
364
365 static void
panfrost_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref ref)366 panfrost_set_stencil_ref(struct pipe_context *pctx,
367 const struct pipe_stencil_ref ref)
368 {
369 struct panfrost_context *ctx = pan_context(pctx);
370 ctx->stencil_ref = ref;
371 ctx->dirty |= PAN_DIRTY_ZS;
372 }
373
374 static void
panfrost_set_sampler_views(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start_slot,unsigned num_views,unsigned unbind_num_trailing_slots,bool take_ownership,struct pipe_sampler_view ** views)375 panfrost_set_sampler_views(struct pipe_context *pctx,
376 enum pipe_shader_type shader, unsigned start_slot,
377 unsigned num_views,
378 unsigned unbind_num_trailing_slots,
379 bool take_ownership,
380 struct pipe_sampler_view **views)
381 {
382 struct panfrost_context *ctx = pan_context(pctx);
383 ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_TEXTURE;
384
385 unsigned new_nr = 0;
386 unsigned i;
387
388 for (i = 0; i < num_views; ++i) {
389 struct pipe_sampler_view *view = views ? views[i] : NULL;
390 unsigned p = i + start_slot;
391
392 if (view)
393 new_nr = p + 1;
394
395 if (take_ownership) {
396 pipe_sampler_view_reference(
397 (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], NULL);
398 ctx->sampler_views[shader][i] = (struct panfrost_sampler_view *)view;
399 } else {
400 pipe_sampler_view_reference(
401 (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], view);
402 }
403 }
404
405 for (; i < num_views + unbind_num_trailing_slots; i++) {
406 unsigned p = i + start_slot;
407 pipe_sampler_view_reference(
408 (struct pipe_sampler_view **)&ctx->sampler_views[shader][p], NULL);
409 }
410
411 /* If the sampler view count is higher than the greatest sampler view
412 * we touch, it can't change */
413 if (ctx->sampler_view_count[shader] >
414 start_slot + num_views + unbind_num_trailing_slots)
415 return;
416
417 /* If we haven't set any sampler views here, search lower numbers for
418 * set sampler views */
419 if (new_nr == 0) {
420 for (i = 0; i < start_slot; ++i) {
421 if (ctx->sampler_views[shader][i])
422 new_nr = i + 1;
423 }
424 }
425
426 ctx->sampler_view_count[shader] = new_nr;
427 }
428
429 static void
panfrost_set_shader_buffers(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned count,const struct pipe_shader_buffer * buffers,unsigned writable_bitmask)430 panfrost_set_shader_buffers(struct pipe_context *pctx,
431 enum pipe_shader_type shader, unsigned start,
432 unsigned count,
433 const struct pipe_shader_buffer *buffers,
434 unsigned writable_bitmask)
435 {
436 struct panfrost_context *ctx = pan_context(pctx);
437
438 util_set_shader_buffers_mask(ctx->ssbo[shader], &ctx->ssbo_mask[shader],
439 buffers, start, count);
440
441 ctx->dirty_shader[shader] |= PAN_DIRTY_STAGE_SSBO;
442 }
443
444 static void
panfrost_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * fb)445 panfrost_set_framebuffer_state(struct pipe_context *pctx,
446 const struct pipe_framebuffer_state *fb)
447 {
448 struct panfrost_context *ctx = pan_context(pctx);
449
450 util_copy_framebuffer_state(&ctx->pipe_framebuffer, fb);
451 ctx->batch = NULL;
452
453 /* Hot draw call path needs the mask of active render targets */
454 ctx->fb_rt_mask = 0;
455
456 for (unsigned i = 0; i < ctx->pipe_framebuffer.nr_cbufs; ++i) {
457 if (ctx->pipe_framebuffer.cbufs[i])
458 ctx->fb_rt_mask |= BITFIELD_BIT(i);
459 }
460 }
461
462 static void
panfrost_bind_depth_stencil_state(struct pipe_context * pipe,void * cso)463 panfrost_bind_depth_stencil_state(struct pipe_context *pipe, void *cso)
464 {
465 struct panfrost_context *ctx = pan_context(pipe);
466 ctx->depth_stencil = cso;
467 ctx->dirty |= PAN_DIRTY_ZS;
468 }
469
470 static void
panfrost_set_sample_mask(struct pipe_context * pipe,unsigned sample_mask)471 panfrost_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
472 {
473 struct panfrost_context *ctx = pan_context(pipe);
474 ctx->sample_mask = sample_mask;
475 ctx->dirty |= PAN_DIRTY_MSAA;
476 }
477
478 static void
panfrost_set_min_samples(struct pipe_context * pipe,unsigned min_samples)479 panfrost_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
480 {
481 struct panfrost_context *ctx = pan_context(pipe);
482 ctx->min_samples = min_samples;
483 ctx->dirty |= PAN_DIRTY_MSAA;
484 }
485
486 static void
panfrost_set_clip_state(struct pipe_context * pipe,const struct pipe_clip_state * clip)487 panfrost_set_clip_state(struct pipe_context *pipe,
488 const struct pipe_clip_state *clip)
489 {
490 // struct panfrost_context *panfrost = pan_context(pipe);
491 }
492
493 static void
panfrost_set_viewport_states(struct pipe_context * pipe,unsigned start_slot,unsigned num_viewports,const struct pipe_viewport_state * viewports)494 panfrost_set_viewport_states(struct pipe_context *pipe, unsigned start_slot,
495 unsigned num_viewports,
496 const struct pipe_viewport_state *viewports)
497 {
498 struct panfrost_context *ctx = pan_context(pipe);
499
500 assert(start_slot == 0);
501 assert(num_viewports == 1);
502
503 ctx->pipe_viewport = *viewports;
504 ctx->dirty |= PAN_DIRTY_VIEWPORT;
505 }
506
507 static void
panfrost_set_scissor_states(struct pipe_context * pipe,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissors)508 panfrost_set_scissor_states(struct pipe_context *pipe, unsigned start_slot,
509 unsigned num_scissors,
510 const struct pipe_scissor_state *scissors)
511 {
512 struct panfrost_context *ctx = pan_context(pipe);
513
514 assert(start_slot == 0);
515 assert(num_scissors == 1);
516
517 ctx->scissor = *scissors;
518 ctx->dirty |= PAN_DIRTY_SCISSOR;
519 }
520
521 static void
panfrost_set_polygon_stipple(struct pipe_context * pipe,const struct pipe_poly_stipple * stipple)522 panfrost_set_polygon_stipple(struct pipe_context *pipe,
523 const struct pipe_poly_stipple *stipple)
524 {
525 // struct panfrost_context *panfrost = pan_context(pipe);
526 }
527
528 static void
panfrost_set_active_query_state(struct pipe_context * pipe,bool enable)529 panfrost_set_active_query_state(struct pipe_context *pipe, bool enable)
530 {
531 struct panfrost_context *ctx = pan_context(pipe);
532 ctx->active_queries = enable;
533 ctx->dirty |= PAN_DIRTY_OQ;
534 }
535
536 static void
panfrost_render_condition(struct pipe_context * pipe,struct pipe_query * query,bool condition,enum pipe_render_cond_flag mode)537 panfrost_render_condition(struct pipe_context *pipe, struct pipe_query *query,
538 bool condition, enum pipe_render_cond_flag mode)
539 {
540 struct panfrost_context *ctx = pan_context(pipe);
541
542 ctx->cond_query = (struct panfrost_query *)query;
543 ctx->cond_cond = condition;
544 ctx->cond_mode = mode;
545 }
546
547 static void
panfrost_destroy(struct pipe_context * pipe)548 panfrost_destroy(struct pipe_context *pipe)
549 {
550 struct panfrost_context *panfrost = pan_context(pipe);
551 struct panfrost_device *dev = pan_device(pipe->screen);
552
553 pan_screen(pipe->screen)->vtbl.context_cleanup(panfrost);
554
555 if (panfrost->writers)
556 _mesa_hash_table_destroy(panfrost->writers, NULL);
557
558 if (panfrost->blitter)
559 util_blitter_destroy(panfrost->blitter);
560
561 util_unreference_framebuffer_state(&panfrost->pipe_framebuffer);
562 if (pipe->stream_uploader)
563 u_upload_destroy(pipe->stream_uploader);
564
565 panfrost_pool_cleanup(&panfrost->descs);
566 panfrost_pool_cleanup(&panfrost->shaders);
567 panfrost_afbc_context_destroy(panfrost);
568
569 util_dynarray_foreach(&panfrost->global_buffers, struct pipe_resource *, res) {
570 pipe_resource_reference(res, NULL);
571 }
572
573 util_dynarray_fini(&panfrost->global_buffers);
574
575 drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->in_sync_obj);
576 if (panfrost->in_sync_fd != -1) {
577 close(panfrost->in_sync_fd);
578 panfrost->in_sync_fd = -1;
579 }
580
581 drmSyncobjDestroy(panfrost_device_fd(dev), panfrost->syncobj);
582 ralloc_free(pipe);
583 }
584
585 static struct pipe_query *
panfrost_create_query(struct pipe_context * pipe,unsigned type,unsigned index)586 panfrost_create_query(struct pipe_context *pipe, unsigned type, unsigned index)
587 {
588 struct panfrost_context *ctx = pan_context(pipe);
589 struct panfrost_device *dev = pan_device(ctx->base.screen);
590 struct panfrost_query *q = rzalloc(pipe, struct panfrost_query);
591
592 q->type = type;
593 q->index = index;
594
595 unsigned size = 0;
596
597 switch (q->type) {
598 case PIPE_QUERY_OCCLUSION_COUNTER:
599 case PIPE_QUERY_OCCLUSION_PREDICATE:
600 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
601 size = sizeof(uint64_t) * dev->core_id_range;
602 break;
603 case PIPE_QUERY_TIMESTAMP:
604 size = sizeof(uint64_t);
605 break;
606 case PIPE_QUERY_TIME_ELAPSED:
607 size = sizeof(uint64_t) * 2;
608 break;
609 default:
610 break;
611 }
612
613 /* Allocate a resource for the query results to be stored */
614 if (size > 0) {
615 q->rsrc =
616 pipe_buffer_create(ctx->base.screen, PIPE_BIND_QUERY_BUFFER, 0, size);
617
618 if (!q->rsrc) {
619 ralloc_free(q);
620 return NULL;
621 }
622
623 /* Default to 0 if nothing at all drawn. */
624 uint8_t *zeroes = alloca(size);
625 memset(zeroes, 0, size);
626 pipe_buffer_write(pipe, q->rsrc, 0, size, zeroes);
627 }
628
629 return (struct pipe_query *)q;
630 }
631
632 static void
panfrost_destroy_query(struct pipe_context * pipe,struct pipe_query * q)633 panfrost_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
634 {
635 struct panfrost_query *query = (struct panfrost_query *)q;
636
637 if (query->rsrc)
638 pipe_resource_reference(&query->rsrc, NULL);
639
640 ralloc_free(q);
641 }
642
643 static void
panfrost_emit_write_timestamp(struct panfrost_context * ctx,struct panfrost_resource * rsrc,unsigned offset,const char * reason)644 panfrost_emit_write_timestamp(struct panfrost_context *ctx,
645 struct panfrost_resource *rsrc, unsigned offset,
646 const char *reason)
647 {
648 struct panfrost_screen *screen = pan_screen(ctx->base.screen);
649 struct panfrost_batch *batch = panfrost_get_fresh_batch_for_fbo(ctx, reason);
650
651 screen->vtbl.emit_write_timestamp(batch, rsrc, offset);
652 }
653
654 static bool
panfrost_begin_query(struct pipe_context * pipe,struct pipe_query * q)655 panfrost_begin_query(struct pipe_context *pipe, struct pipe_query *q)
656 {
657 struct panfrost_context *ctx = pan_context(pipe);
658 struct panfrost_device *dev = pan_device(ctx->base.screen);
659 struct panfrost_query *query = (struct panfrost_query *)q;
660
661 switch (query->type) {
662 case PIPE_QUERY_OCCLUSION_COUNTER:
663 case PIPE_QUERY_OCCLUSION_PREDICATE:
664 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: {
665 unsigned size = sizeof(uint64_t) * dev->core_id_range;
666
667 /* Default to 0 if nothing at all drawn. */
668 uint8_t *zeroes = alloca(size);
669 memset(zeroes, 0, size);
670 pipe_buffer_write(pipe, query->rsrc, 0, size, zeroes);
671
672 query->msaa = (ctx->pipe_framebuffer.samples > 1);
673 ctx->occlusion_query = query;
674 ctx->dirty |= PAN_DIRTY_OQ;
675 break;
676 }
677
678 case PIPE_QUERY_TIMESTAMP:
679 case PIPE_QUERY_TIMESTAMP_DISJOINT:
680 /* This is a no op on query start */
681 break;
682
683 case PIPE_QUERY_TIME_ELAPSED: {
684 struct panfrost_resource *rsrc = pan_resource(query->rsrc);
685 panfrost_emit_write_timestamp(ctx, rsrc, 0, "TIME_ELAPSED begin_query");
686 break;
687 }
688
689 /* Geometry statistics are computed in the driver. XXX: geom/tess
690 * shaders.. */
691
692 case PIPE_QUERY_PRIMITIVES_GENERATED:
693 query->start = ctx->prims_generated;
694 break;
695 case PIPE_QUERY_PRIMITIVES_EMITTED:
696 query->start = ctx->tf_prims_generated;
697 break;
698
699 case PAN_QUERY_DRAW_CALLS:
700 query->start = ctx->draw_calls;
701 break;
702
703 default:
704 break;
705 }
706
707 return true;
708 }
709
710 static bool
panfrost_end_query(struct pipe_context * pipe,struct pipe_query * q)711 panfrost_end_query(struct pipe_context *pipe, struct pipe_query *q)
712 {
713 struct panfrost_context *ctx = pan_context(pipe);
714 struct panfrost_query *query = (struct panfrost_query *)q;
715
716 switch (query->type) {
717 case PIPE_QUERY_OCCLUSION_COUNTER:
718 case PIPE_QUERY_OCCLUSION_PREDICATE:
719 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
720 ctx->occlusion_query = NULL;
721 ctx->dirty |= PAN_DIRTY_OQ;
722 break;
723 case PIPE_QUERY_TIMESTAMP: {
724 struct panfrost_resource *rsrc = pan_resource(query->rsrc);
725 panfrost_emit_write_timestamp(ctx, rsrc, 0, "TIMESTAMP end_query");
726 break;
727 }
728 case PIPE_QUERY_TIMESTAMP_DISJOINT:
729 /* This is a no op */
730 break;
731 case PIPE_QUERY_TIME_ELAPSED: {
732 struct panfrost_resource *rsrc = pan_resource(query->rsrc);
733 panfrost_emit_write_timestamp(ctx, rsrc, sizeof(uint64_t),
734 "TIME_ELAPSED end_query");
735 break;
736 }
737 case PIPE_QUERY_PRIMITIVES_GENERATED:
738 query->end = ctx->prims_generated;
739 break;
740 case PIPE_QUERY_PRIMITIVES_EMITTED:
741 query->end = ctx->tf_prims_generated;
742 break;
743 case PAN_QUERY_DRAW_CALLS:
744 query->end = ctx->draw_calls;
745 break;
746 }
747
748 return true;
749 }
750
751 static bool
panfrost_get_query_result(struct pipe_context * pipe,struct pipe_query * q,bool wait,union pipe_query_result * vresult)752 panfrost_get_query_result(struct pipe_context *pipe, struct pipe_query *q,
753 bool wait, union pipe_query_result *vresult)
754 {
755 struct panfrost_query *query = (struct panfrost_query *)q;
756 struct panfrost_context *ctx = pan_context(pipe);
757 struct panfrost_device *dev = pan_device(ctx->base.screen);
758 struct panfrost_resource *rsrc = pan_resource(query->rsrc);
759
760 switch (query->type) {
761 case PIPE_QUERY_OCCLUSION_COUNTER:
762 case PIPE_QUERY_OCCLUSION_PREDICATE:
763 case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE:
764 panfrost_flush_writer(ctx, rsrc, "Occlusion query");
765 panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
766
767 /* Read back the query results */
768 uint64_t *result = (uint64_t *)rsrc->bo->ptr.cpu;
769
770 if (query->type == PIPE_QUERY_OCCLUSION_COUNTER) {
771 uint64_t passed = 0;
772 for (int i = 0; i < dev->core_id_range; ++i)
773 passed += result[i];
774
775 if (dev->arch <= 5 && !query->msaa)
776 passed /= 4;
777
778 vresult->u64 = passed;
779 } else {
780 vresult->b = !!result[0];
781 }
782
783 break;
784
785 case PIPE_QUERY_TIMESTAMP: {
786 panfrost_flush_writer(ctx, rsrc, "Timestamp query");
787 panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
788 uint64_t *timestamp = (uint64_t *)rsrc->bo->ptr.cpu;
789
790 vresult->u64 = pan_gpu_time_to_ns(dev, *timestamp);
791 break;
792 }
793
794 case PIPE_QUERY_TIMESTAMP_DISJOINT: {
795 vresult->timestamp_disjoint.frequency =
796 dev->kmod.props.timestamp_frequency;
797 vresult->timestamp_disjoint.disjoint = false;
798 break;
799 }
800
801 case PIPE_QUERY_TIME_ELAPSED: {
802 panfrost_flush_writer(ctx, rsrc, "Time elapsed query");
803 panfrost_bo_wait(rsrc->bo, INT64_MAX, false);
804 uint64_t *timestamp = (uint64_t *)rsrc->bo->ptr.cpu;
805
806 vresult->u64 = pan_gpu_time_to_ns(dev, timestamp[1] - timestamp[0]);
807 break;
808 }
809
810 case PIPE_QUERY_PRIMITIVES_GENERATED:
811 case PIPE_QUERY_PRIMITIVES_EMITTED:
812 panfrost_flush_all_batches(ctx, "Primitive count query");
813 vresult->u64 = query->end - query->start;
814 break;
815
816 case PAN_QUERY_DRAW_CALLS:
817 vresult->u64 = query->end - query->start;
818 break;
819
820 default:
821 /* TODO: more queries */
822 break;
823 }
824
825 return true;
826 }
827
828 /*
829 * Check the render condition for software condition rendering.
830 *
831 * Note: this may invalidate the batch!
832 */
833 bool
panfrost_render_condition_check(struct panfrost_context * ctx)834 panfrost_render_condition_check(struct panfrost_context *ctx)
835 {
836 if (!ctx->cond_query)
837 return true;
838
839 perf_debug(ctx, "Implementing conditional rendering on the CPU");
840
841 union pipe_query_result res = {0};
842 bool wait = ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT &&
843 ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
844
845 struct pipe_query *pq = (struct pipe_query *)ctx->cond_query;
846
847 if (panfrost_get_query_result(&ctx->base, pq, wait, &res))
848 return res.u64 != ctx->cond_cond;
849
850 return true;
851 }
852
853 static struct pipe_stream_output_target *
panfrost_create_stream_output_target(struct pipe_context * pctx,struct pipe_resource * prsc,unsigned buffer_offset,unsigned buffer_size)854 panfrost_create_stream_output_target(struct pipe_context *pctx,
855 struct pipe_resource *prsc,
856 unsigned buffer_offset,
857 unsigned buffer_size)
858 {
859 struct pipe_stream_output_target *target;
860
861 target = &rzalloc(pctx, struct panfrost_streamout_target)->base;
862
863 if (!target)
864 return NULL;
865
866 pipe_reference_init(&target->reference, 1);
867 pipe_resource_reference(&target->buffer, prsc);
868
869 target->context = pctx;
870 target->buffer_offset = buffer_offset;
871 target->buffer_size = buffer_size;
872
873 return target;
874 }
875
876 static void
panfrost_stream_output_target_destroy(struct pipe_context * pctx,struct pipe_stream_output_target * target)877 panfrost_stream_output_target_destroy(struct pipe_context *pctx,
878 struct pipe_stream_output_target *target)
879 {
880 pipe_resource_reference(&target->buffer, NULL);
881 ralloc_free(target);
882 }
883
884 static void
panfrost_set_stream_output_targets(struct pipe_context * pctx,unsigned num_targets,struct pipe_stream_output_target ** targets,const unsigned * offsets)885 panfrost_set_stream_output_targets(struct pipe_context *pctx,
886 unsigned num_targets,
887 struct pipe_stream_output_target **targets,
888 const unsigned *offsets)
889 {
890 struct panfrost_context *ctx = pan_context(pctx);
891 struct panfrost_streamout *so = &ctx->streamout;
892
893 assert(num_targets <= ARRAY_SIZE(so->targets));
894
895 for (unsigned i = 0; i < num_targets; i++) {
896 if (targets[i] && offsets[i] != -1)
897 pan_so_target(targets[i])->offset = offsets[i];
898
899 pipe_so_target_reference(&so->targets[i], targets[i]);
900 }
901
902 for (unsigned i = num_targets; i < so->num_targets; i++)
903 pipe_so_target_reference(&so->targets[i], NULL);
904
905 so->num_targets = num_targets;
906 ctx->dirty |= PAN_DIRTY_SO;
907 }
908
909 static void
panfrost_set_global_binding(struct pipe_context * pctx,unsigned first,unsigned count,struct pipe_resource ** resources,uint32_t ** handles)910 panfrost_set_global_binding(struct pipe_context *pctx, unsigned first,
911 unsigned count, struct pipe_resource **resources,
912 uint32_t **handles)
913 {
914 struct panfrost_context *ctx = pan_context(pctx);
915
916 unsigned old_size =
917 util_dynarray_num_elements(&ctx->global_buffers, *resources);
918
919 if (old_size < first + count) {
920 /* we are screwed no matter what */
921 if (!util_dynarray_grow(&ctx->global_buffers, *resources,
922 (first + count) - old_size))
923 unreachable("out of memory");
924
925 for (unsigned i = old_size; i < first + count; i++)
926 *util_dynarray_element(&ctx->global_buffers, struct pipe_resource *,
927 i) = NULL;
928 }
929
930 for (unsigned i = 0; i < count; ++i) {
931 struct pipe_resource **res = util_dynarray_element(
932 &ctx->global_buffers, struct pipe_resource *, first + i);
933 if (resources && resources[i]) {
934 pipe_resource_reference(res, resources[i]);
935
936 /* The handle points to uint32_t, but space is allocated for 64
937 * bits. We need to respect the offset passed in. This interface
938 * is so bad.
939 */
940 uint64_t addr = 0;
941 struct panfrost_resource *rsrc = pan_resource(resources[i]);
942
943 memcpy(&addr, handles[i], sizeof(addr));
944 addr += rsrc->bo->ptr.gpu;
945 memcpy(handles[i], &addr, sizeof(addr));
946 } else {
947 pipe_resource_reference(res, NULL);
948 }
949 }
950 }
951
952 static void
panfrost_memory_barrier(struct pipe_context * pctx,unsigned flags)953 panfrost_memory_barrier(struct pipe_context *pctx, unsigned flags)
954 {
955 /* TODO: Be smart and only flush the minimum needed, maybe emitting a
956 * cache flush job if that would help */
957 panfrost_flush_all_batches(pan_context(pctx), "Memory barrier");
958 }
959
960 static void
panfrost_create_fence_fd(struct pipe_context * pctx,struct pipe_fence_handle ** pfence,int fd,enum pipe_fd_type type)961 panfrost_create_fence_fd(struct pipe_context *pctx,
962 struct pipe_fence_handle **pfence, int fd,
963 enum pipe_fd_type type)
964 {
965 *pfence = panfrost_fence_from_fd(pan_context(pctx), fd, type);
966 }
967
968 static void
panfrost_fence_server_sync(struct pipe_context * pctx,struct pipe_fence_handle * f)969 panfrost_fence_server_sync(struct pipe_context *pctx,
970 struct pipe_fence_handle *f)
971 {
972 struct panfrost_device *dev = pan_device(pctx->screen);
973 struct panfrost_context *ctx = pan_context(pctx);
974 int fd = -1, ret;
975
976 ret = drmSyncobjExportSyncFile(panfrost_device_fd(dev), f->syncobj, &fd);
977 assert(!ret);
978
979 sync_accumulate("panfrost", &ctx->in_sync_fd, fd);
980 close(fd);
981 }
982
983 struct pipe_context *
panfrost_create_context(struct pipe_screen * screen,void * priv,unsigned flags)984 panfrost_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
985 {
986 struct panfrost_context *ctx = rzalloc(NULL, struct panfrost_context);
987
988 if (!ctx)
989 return NULL;
990
991 struct pipe_context *gallium = (struct pipe_context *)ctx;
992 struct panfrost_device *dev = pan_device(screen);
993
994 int ret;
995
996 /* Create a syncobj in a signaled state. Will be updated to point to the
997 * last queued job out_sync every time we submit a new job.
998 */
999 ret = drmSyncobjCreate(panfrost_device_fd(dev), DRM_SYNCOBJ_CREATE_SIGNALED,
1000 &ctx->syncobj);
1001 if (ret) {
1002 ralloc_free(ctx);
1003 return NULL;
1004 }
1005
1006 gallium->screen = screen;
1007
1008 gallium->destroy = panfrost_destroy;
1009
1010 gallium->set_framebuffer_state = panfrost_set_framebuffer_state;
1011 gallium->set_debug_callback = u_default_set_debug_callback;
1012
1013 gallium->create_fence_fd = panfrost_create_fence_fd;
1014 gallium->fence_server_sync = panfrost_fence_server_sync;
1015
1016 gallium->flush = panfrost_flush;
1017 gallium->clear = panfrost_clear;
1018 gallium->clear_texture = u_default_clear_texture;
1019 gallium->texture_barrier = panfrost_texture_barrier;
1020 gallium->set_frontend_noop = panfrost_set_frontend_noop;
1021
1022 gallium->set_vertex_buffers = panfrost_set_vertex_buffers;
1023 gallium->set_constant_buffer = panfrost_set_constant_buffer;
1024 gallium->set_shader_buffers = panfrost_set_shader_buffers;
1025 gallium->set_shader_images = panfrost_set_shader_images;
1026
1027 gallium->set_stencil_ref = panfrost_set_stencil_ref;
1028
1029 gallium->set_sampler_views = panfrost_set_sampler_views;
1030
1031 gallium->bind_rasterizer_state = panfrost_bind_rasterizer_state;
1032 gallium->delete_rasterizer_state = panfrost_generic_cso_delete;
1033
1034 gallium->bind_vertex_elements_state = panfrost_bind_vertex_elements_state;
1035 gallium->delete_vertex_elements_state = panfrost_generic_cso_delete;
1036
1037 gallium->delete_sampler_state = panfrost_generic_cso_delete;
1038 gallium->bind_sampler_states = panfrost_bind_sampler_states;
1039
1040 gallium->bind_depth_stencil_alpha_state = panfrost_bind_depth_stencil_state;
1041 gallium->delete_depth_stencil_alpha_state = panfrost_generic_cso_delete;
1042
1043 gallium->set_sample_mask = panfrost_set_sample_mask;
1044 gallium->set_min_samples = panfrost_set_min_samples;
1045
1046 gallium->set_clip_state = panfrost_set_clip_state;
1047 gallium->set_viewport_states = panfrost_set_viewport_states;
1048 gallium->set_scissor_states = panfrost_set_scissor_states;
1049 gallium->set_polygon_stipple = panfrost_set_polygon_stipple;
1050 gallium->set_active_query_state = panfrost_set_active_query_state;
1051 gallium->render_condition = panfrost_render_condition;
1052
1053 gallium->create_query = panfrost_create_query;
1054 gallium->destroy_query = panfrost_destroy_query;
1055 gallium->begin_query = panfrost_begin_query;
1056 gallium->end_query = panfrost_end_query;
1057 gallium->get_query_result = panfrost_get_query_result;
1058
1059 gallium->create_stream_output_target = panfrost_create_stream_output_target;
1060 gallium->stream_output_target_destroy =
1061 panfrost_stream_output_target_destroy;
1062 gallium->set_stream_output_targets = panfrost_set_stream_output_targets;
1063
1064 gallium->bind_blend_state = panfrost_bind_blend_state;
1065 gallium->delete_blend_state = panfrost_generic_cso_delete;
1066
1067 gallium->set_blend_color = panfrost_set_blend_color;
1068
1069 gallium->set_global_binding = panfrost_set_global_binding;
1070 gallium->memory_barrier = panfrost_memory_barrier;
1071
1072 pan_screen(screen)->vtbl.context_populate_vtbl(gallium);
1073
1074 panfrost_resource_context_init(gallium);
1075 panfrost_shader_context_init(gallium);
1076 panfrost_afbc_context_init(ctx);
1077
1078 gallium->stream_uploader = u_upload_create_default(gallium);
1079 gallium->const_uploader = gallium->stream_uploader;
1080
1081 panfrost_pool_init(&ctx->descs, ctx, dev, 0, 4096, "Descriptors", true,
1082 false);
1083
1084 panfrost_pool_init(&ctx->shaders, ctx, dev, PAN_BO_EXECUTE, 4096, "Shaders",
1085 true, false);
1086
1087 ctx->blitter = util_blitter_create(gallium);
1088
1089 ctx->writers = _mesa_hash_table_create(gallium, _mesa_hash_pointer,
1090 _mesa_key_pointer_equal);
1091
1092 assert(ctx->blitter);
1093
1094 /* Prepare for render! */
1095
1096 /* By default mask everything on */
1097 ctx->sample_mask = ~0;
1098 ctx->active_queries = true;
1099
1100 util_dynarray_init(&ctx->global_buffers, ctx);
1101
1102 /* Sync object/FD used for NATIVE_FENCE_FD. */
1103 ctx->in_sync_fd = -1;
1104 ret = drmSyncobjCreate(panfrost_device_fd(dev), 0, &ctx->in_sync_obj);
1105 assert(!ret);
1106
1107 ret = pan_screen(screen)->vtbl.context_init(ctx);
1108
1109 if (ret) {
1110 gallium->destroy(gallium);
1111 return NULL;
1112 }
1113
1114 return gallium;
1115 }
1116
1117 void
panfrost_context_reinit(struct panfrost_context * ctx)1118 panfrost_context_reinit(struct panfrost_context *ctx)
1119 {
1120 pan_screen(ctx->base.screen)->vtbl.context_cleanup(ctx);
1121 ASSERTED int ret = pan_screen(ctx->base.screen)->vtbl.context_init(ctx);
1122 assert(!ret);
1123 }
1124