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