~mmach/netext73/mesa_2004

« back to all changes in this revision

Viewing changes to src/gallium/drivers/freedreno/freedreno_context.c

  • Committer: mmach
  • Date: 2021-03-12 20:48:59 UTC
  • Revision ID: netbit73@gmail.com-20210312204859-i194ujlcu82pq61p
21

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "freedreno_blitter.h"
29
29
#include "freedreno_draw.h"
30
30
#include "freedreno_fence.h"
31
 
#include "freedreno_log.h"
32
31
#include "freedreno_program.h"
33
32
#include "freedreno_resource.h"
34
33
#include "freedreno_texture.h"
39
38
#include "freedreno_util.h"
40
39
#include "util/u_upload_mgr.h"
41
40
 
42
 
#if DETECT_OS_ANDROID
43
 
#include "util/u_process.h"
44
 
#include <sys/stat.h>
45
 
#include <sys/types.h>
46
 
#endif
47
 
 
48
41
static void
49
42
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
50
43
                unsigned flags)
51
44
{
52
45
        struct fd_context *ctx = fd_context(pctx);
53
46
        struct pipe_fence_handle *fence = NULL;
54
 
        // TODO we want to lookup batch if it exists, but not create one if not.
55
 
        struct fd_batch *batch = fd_context_batch(ctx);
56
 
 
57
 
        DBG("%p: flush: flags=%x\n", ctx->batch, flags);
 
47
        struct fd_batch *batch = NULL;
 
48
 
 
49
        /* We want to lookup current batch if it exists, but not create a new
 
50
         * one if not (unless we need a fence)
 
51
         */
 
52
        fd_batch_reference(&batch, ctx->batch);
 
53
 
 
54
        DBG("%p: flush: flags=%x", batch, flags);
58
55
 
59
56
        /* In some sequence of events, we can end up with a last_fence that is
60
57
         * not an "fd" fence, which results in eglDupNativeFenceFDANDROID()
73
70
                goto out;
74
71
        }
75
72
 
76
 
        if (!batch) {
 
73
        if (fencep && !batch) {
 
74
                batch = fd_context_batch(ctx);
 
75
        } else if (!batch) {
77
76
                fd_bc_dump(ctx->screen, "%p: NULL batch, remaining:\n", ctx);
78
77
                return;
79
78
        }
105
104
 
106
105
        fd_fence_ref(&fence, NULL);
107
106
 
108
 
        if (flags & PIPE_FLUSH_END_OF_FRAME)
109
 
                fd_log_eof(ctx);
 
107
        fd_batch_reference(&batch, NULL);
 
108
 
 
109
        u_trace_context_process(&ctx->trace_context,
 
110
                !!(flags & PIPE_FLUSH_END_OF_FRAME));
110
111
}
111
112
 
112
113
static void
194
195
        if (!ctx->batch)
195
196
                return;
196
197
 
 
198
        struct fd_batch *batch = fd_context_batch_locked(ctx);
 
199
 
197
200
        ctx->batch->needs_flush = true;
198
201
 
199
202
        if (ctx->screen->gpu_id >= 500) {
200
 
                fd_emit_string5(ctx->batch->draw, string, len);
 
203
                fd_emit_string5(batch->draw, string, len);
201
204
        } else {
202
 
                fd_emit_string(ctx->batch->draw, string, len);
203
 
        }
 
205
                fd_emit_string(batch->draw, string, len);
 
206
        }
 
207
 
 
208
        fd_batch_unlock_submit(batch);
 
209
        fd_batch_reference(&batch, NULL);
 
210
}
 
211
 
 
212
/**
 
213
 * If we have a pending fence_server_sync() (GPU side sync), flush now.
 
214
 * The alternative to try to track this with batch dependencies gets
 
215
 * hairy quickly.
 
216
 *
 
217
 * Call this before switching to a different batch, to handle this case.
 
218
 */
 
219
void
 
220
fd_context_switch_from(struct fd_context *ctx)
 
221
{
 
222
        if (ctx->batch && (ctx->batch->in_fence_fd != -1))
 
223
                fd_batch_flush(ctx->batch);
 
224
}
 
225
 
 
226
/**
 
227
 * If there is a pending fence-fd that we need to sync on, this will
 
228
 * transfer the reference to the next batch we are going to render
 
229
 * to.
 
230
 */
 
231
void
 
232
fd_context_switch_to(struct fd_context *ctx, struct fd_batch *batch)
 
233
{
 
234
        if (ctx->in_fence_fd != -1) {
 
235
                sync_accumulate("freedreno", &batch->in_fence_fd, ctx->in_fence_fd);
 
236
                close(ctx->in_fence_fd);
 
237
                ctx->in_fence_fd = -1;
 
238
        }
 
239
}
 
240
 
 
241
/**
 
242
 * Return a reference to the current batch, caller must unref.
 
243
 */
 
244
struct fd_batch *
 
245
fd_context_batch(struct fd_context *ctx)
 
246
{
 
247
        struct fd_batch *batch = NULL;
 
248
 
 
249
        fd_batch_reference(&batch, ctx->batch);
 
250
 
 
251
        if (unlikely(!batch)) {
 
252
                batch = fd_batch_from_fb(&ctx->screen->batch_cache, ctx, &ctx->framebuffer);
 
253
                util_copy_framebuffer_state(&batch->framebuffer, &ctx->framebuffer);
 
254
                fd_batch_reference(&ctx->batch, batch);
 
255
                fd_context_all_dirty(ctx);
 
256
        }
 
257
        fd_context_switch_to(ctx, batch);
 
258
 
 
259
        return batch;
 
260
}
 
261
 
 
262
/**
 
263
 * Return a locked reference to the current batch.  A batch with emit
 
264
 * lock held is protected against flushing while the lock is held.
 
265
 * The emit-lock should be acquired before screen-lock.  The emit-lock
 
266
 * should be held while emitting cmdstream.
 
267
 */
 
268
struct fd_batch *
 
269
fd_context_batch_locked(struct fd_context *ctx)
 
270
{
 
271
        struct fd_batch *batch = NULL;
 
272
 
 
273
        while (!batch) {
 
274
                batch = fd_context_batch(ctx);
 
275
                if (!fd_batch_lock_submit(batch)) {
 
276
                        fd_batch_reference(&batch, NULL);
 
277
                }
 
278
        }
 
279
 
 
280
        return batch;
204
281
}
205
282
 
206
283
void
215
292
        list_del(&ctx->node);
216
293
        fd_screen_unlock(ctx->screen);
217
294
 
218
 
        fd_log_process(ctx, true);
219
 
        assert(list_is_empty(&ctx->log_chunks));
220
 
 
221
295
        fd_fence_ref(&ctx->last_fence, NULL);
222
296
 
223
297
        if (ctx->in_fence_fd != -1)
224
298
                close(ctx->in_fence_fd);
225
299
 
 
300
        for (i = 0; i < ARRAY_SIZE(ctx->pvtmem); i++) {
 
301
                if (ctx->pvtmem[i].bo)
 
302
                        fd_bo_del(ctx->pvtmem[i].bo);
 
303
        }
 
304
 
226
305
        util_copy_framebuffer_state(&ctx->framebuffer, NULL);
227
306
        fd_batch_reference(&ctx->batch, NULL);  /* unref current batch */
228
307
        fd_bc_invalidate_context(ctx);
253
332
        fd_device_del(ctx->dev);
254
333
        fd_pipe_del(ctx->pipe);
255
334
 
256
 
        mtx_destroy(&ctx->gmem_lock);
 
335
        simple_mtx_destroy(&ctx->gmem_lock);
 
336
 
 
337
        u_trace_context_fini(&ctx->trace_context);
257
338
 
258
339
        if (fd_mesa_debug & (FD_DBG_BSTAT | FD_DBG_MSGS)) {
259
340
                printf("batch_total=%u, batch_sysmem=%u, batch_gmem=%u, batch_nondraw=%u, batch_restore=%u\n",
308
389
        return status;
309
390
}
310
391
 
 
392
static void
 
393
fd_trace_record_ts(struct u_trace *ut, struct pipe_resource *timestamps,
 
394
                unsigned idx)
 
395
{
 
396
        struct fd_batch *batch = container_of(ut, struct fd_batch, trace);
 
397
        struct fd_ringbuffer *ring = batch->nondraw ? batch->draw : batch->gmem;
 
398
 
 
399
        if (ring->cur == batch->last_timestamp_cmd) {
 
400
                uint64_t *ts = fd_bo_map(fd_resource(timestamps)->bo);
 
401
                ts[idx] = U_TRACE_NO_TIMESTAMP;
 
402
                return;
 
403
        }
 
404
 
 
405
        unsigned ts_offset = idx * sizeof(uint64_t);
 
406
        batch->ctx->record_timestamp(ring, fd_resource(timestamps)->bo, ts_offset);
 
407
        batch->last_timestamp_cmd = ring->cur;
 
408
}
 
409
 
 
410
static uint64_t
 
411
fd_trace_read_ts(struct u_trace_context *utctx,
 
412
                struct pipe_resource *timestamps, unsigned idx)
 
413
{
 
414
        struct fd_context *ctx = container_of(utctx, struct fd_context, trace_context);
 
415
        struct fd_bo *ts_bo = fd_resource(timestamps)->bo;
 
416
 
 
417
        /* Only need to stall on results for the first entry: */
 
418
        if (idx == 0) {
 
419
                int ret = fd_bo_cpu_prep(ts_bo, ctx->pipe, DRM_FREEDRENO_PREP_READ);
 
420
                if (ret)
 
421
                        return U_TRACE_NO_TIMESTAMP;
 
422
        }
 
423
 
 
424
        uint64_t *ts = fd_bo_map(ts_bo);
 
425
 
 
426
        /* Don't translate the no-timestamp marker: */
 
427
        if (ts[idx] == U_TRACE_NO_TIMESTAMP)
 
428
                return U_TRACE_NO_TIMESTAMP;
 
429
 
 
430
        return ctx->ts_to_ns(ts[idx]);
 
431
}
 
432
 
311
433
/* TODO we could combine a few of these small buffers (solid_vbuf,
312
434
 * blit_texcoord_vbuf, and vsc_size_mem, into a single buffer and
313
435
 * save a tiny bit of memory
417
539
                if (primtypes[i])
418
540
                        ctx->primtype_mask |= (1 << i);
419
541
 
420
 
        (void) mtx_init(&ctx->gmem_lock, mtx_plain);
 
542
        simple_mtx_init(&ctx->gmem_lock, mtx_plain);
421
543
 
422
544
        /* need some sane default in case gallium frontends don't
423
545
         * set some state:
461
583
 
462
584
        list_inithead(&ctx->hw_active_queries);
463
585
        list_inithead(&ctx->acc_active_queries);
464
 
        list_inithead(&ctx->log_chunks);
465
586
 
466
587
        fd_screen_lock(ctx->screen);
 
588
        ctx->seqno = ++screen->ctx_seqno;
467
589
        list_add(&ctx->node, &ctx->screen->context_list);
468
590
        fd_screen_unlock(ctx->screen);
469
591
 
470
592
        ctx->current_scissor = &ctx->disabled_scissor;
471
593
 
472
 
        ctx->log_out = stdout;
473
 
 
474
 
        if ((fd_mesa_debug & FD_DBG_LOG) &&
475
 
                        !(ctx->record_timestamp && ctx->ts_to_ns)) {
476
 
                printf("logging not supported!\n");
477
 
                fd_mesa_debug &= ~FD_DBG_LOG;
478
 
        }
479
 
 
480
 
#if DETECT_OS_ANDROID
481
 
        if (fd_mesa_debug & FD_DBG_LOG) {
482
 
                static unsigned idx = 0;
483
 
                char *p;
484
 
                asprintf(&p, "/data/fdlog/%s-%d.log", util_get_process_name(), idx++);
485
 
 
486
 
                FILE *f = fopen(p, "w");
487
 
                if (f)
488
 
                        ctx->log_out = f;
489
 
        }
490
 
#endif
 
594
        u_trace_context_init(&ctx->trace_context, pctx,
 
595
                        fd_trace_record_ts, fd_trace_read_ts);
491
596
 
492
597
        return pctx;
493
598