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