xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/panfrost/pan_context.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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