• 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_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