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