struct pipe_context * fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, const uint8_t *primtypes, void *priv) { struct fd_screen *screen = fd_screen(pscreen); struct pipe_context *pctx; int i; ctx->screen = screen; ctx->primtypes = primtypes; ctx->primtype_mask = 0; for (i = 0; i < PIPE_PRIM_MAX; i++) if (primtypes[i]) ctx->primtype_mask |= (1 << i); /* need some sane default in case state tracker doesn't * set some state: */ ctx->sample_mask = 0xffff; pctx = &ctx->base; pctx->screen = pscreen; pctx->priv = priv; pctx->flush = fd_context_flush; for (i = 0; i < ARRAY_SIZE(ctx->rings); i++) { ctx->rings[i] = fd_ringbuffer_new(screen->pipe, 0x100000); if (!ctx->rings[i]) goto fail; } fd_context_next_rb(pctx); fd_reset_wfi(ctx); util_dynarray_init(&ctx->draw_patches); util_slab_create(&ctx->transfer_pool, sizeof(struct pipe_transfer), 16, UTIL_SLAB_SINGLETHREADED); fd_draw_init(pctx); fd_resource_context_init(pctx); fd_query_context_init(pctx); fd_texture_init(pctx); fd_state_init(pctx); ctx->blitter = util_blitter_create(pctx); if (!ctx->blitter) goto fail; ctx->primconvert = util_primconvert_create(pctx, ctx->primtype_mask); if (!ctx->primconvert) goto fail; return pctx; fail: pctx->destroy(pctx); return NULL; }
static void timestamp_resume(struct fd_acc_query *aq, struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->draw; OUT_PKT7(ring, CP_EVENT_WRITE, 4); OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_AND_INV_EVENT) | CP_EVENT_WRITE_0_TIMESTAMP); OUT_RELOCW(ring, query_sample(aq, start)); OUT_RING(ring, 0x00000000); fd_reset_wfi(batch); }
static void render_sysmem(struct fd_batch *batch) { struct fd_context *ctx = batch->ctx; ctx->emit_sysmem_prep(batch); fd_hw_query_prepare_tile(batch, 0, batch->gmem); /* emit IB to drawcmds: */ ctx->emit_ib(batch->gmem, batch->draw); fd_reset_wfi(batch); }
static void occlusion_resume(struct fd_acc_query *aq, struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->draw; OUT_PKT4(ring, REG_A5XX_RB_SAMPLE_COUNT_CONTROL, 1); OUT_RING(ring, A5XX_RB_SAMPLE_COUNT_CONTROL_COPY); OUT_PKT4(ring, REG_A5XX_RB_SAMPLE_COUNT_ADDR_LO, 2); OUT_RELOCW(ring, query_sample(aq, start)); OUT_PKT7(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, ZPASS_DONE); fd_reset_wfi(batch); fd5_context(batch->ctx)->samples_passed_queries++; }
static void draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, struct fd6_emit *emit, unsigned index_offset) { const struct pipe_draw_info *info = emit->info; enum pc_di_primtype primtype = ctx->primtypes[info->mode]; fd6_emit_state(ctx, ring, emit); if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE)) fd6_emit_vertex_bufs(ring, emit); OUT_PKT4(ring, REG_A6XX_VFD_INDEX_OFFSET, 2); OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */ OUT_RING(ring, info->start_instance); /* VFD_INSTANCE_START_OFFSET */ OUT_PKT4(ring, REG_A6XX_PC_RESTART_INDEX, 1); OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */ info->restart_index : 0xffffffff); fd6_emit_render_cntl(ctx, false, emit->key.binning_pass); /* for debug after a lock up, write a unique counter value * to scratch7 for each draw, to make it easier to match up * register dumps to cmdstream. The combination of IB * (scratch6) and DRAW is enough to "triangulate" the * particular draw that caused lockup. */ emit_marker6(ring, 7); if (info->indirect) { draw_emit_indirect(ctx->batch, ring, primtype, emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, info, index_offset); } else { draw_emit(ctx->batch, ring, primtype, emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, info, index_offset); } emit_marker6(ring, 7); fd_reset_wfi(ctx->batch); }
void fd_gmem_render_tiles(struct fd_batch *batch) { struct fd_context *ctx = batch->ctx; struct pipe_framebuffer_state *pfb = &batch->framebuffer; bool sysmem = false; if (ctx->emit_sysmem_prep) { if (batch->cleared || batch->gmem_reason || (batch->num_draws > 5)) { DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u", batch->cleared, batch->gmem_reason, batch->num_draws); } else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) { sysmem = true; } } fd_reset_wfi(batch); ctx->stats.batch_total++; if (sysmem) { DBG("%p: rendering sysmem %ux%u (%s/%s)", batch, pfb->width, pfb->height, util_format_short_name(pipe_surface_format(pfb->cbufs[0])), util_format_short_name(pipe_surface_format(pfb->zsbuf))); fd_hw_query_prepare(batch, 1); render_sysmem(batch); ctx->stats.batch_sysmem++; } else { struct fd_gmem_stateobj *gmem = &ctx->gmem; calculate_tiles(batch); DBG("%p: rendering %dx%d tiles %ux%u (%s/%s)", batch, pfb->width, pfb->height, gmem->nbins_x, gmem->nbins_y, util_format_short_name(pipe_surface_format(pfb->cbufs[0])), util_format_short_name(pipe_surface_format(pfb->zsbuf))); fd_hw_query_prepare(batch, gmem->nbins_x * gmem->nbins_y); render_tiles(batch); ctx->stats.batch_gmem++; } flush_ring(batch); }
static void occlusion_pause(struct fd_acc_query *aq, struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->draw; OUT_PKT7(ring, CP_MEM_WRITE, 4); OUT_RELOCW(ring, query_sample(aq, stop)); OUT_RING(ring, 0xffffffff); OUT_RING(ring, 0xffffffff); OUT_PKT7(ring, CP_WAIT_MEM_WRITES, 0); OUT_PKT4(ring, REG_A5XX_RB_SAMPLE_COUNT_CONTROL, 1); OUT_RING(ring, A5XX_RB_SAMPLE_COUNT_CONTROL_COPY); OUT_PKT4(ring, REG_A5XX_RB_SAMPLE_COUNT_ADDR_LO, 2); OUT_RELOCW(ring, query_sample(aq, stop)); OUT_PKT7(ring, CP_EVENT_WRITE, 1); OUT_RING(ring, ZPASS_DONE); fd_reset_wfi(batch); OUT_PKT7(ring, CP_WAIT_REG_MEM, 6); OUT_RING(ring, 0x00000014); // XXX OUT_RELOC(ring, query_sample(aq, stop)); OUT_RING(ring, 0xffffffff); OUT_RING(ring, 0xffffffff); OUT_RING(ring, 0x00000010); // XXX /* result += stop - start: */ OUT_PKT7(ring, CP_MEM_TO_MEM, 9); OUT_RING(ring, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_NEG_C); OUT_RELOCW(ring, query_sample(aq, result)); /* dst */ OUT_RELOC(ring, query_sample(aq, result)); /* srcA */ OUT_RELOC(ring, query_sample(aq, stop)); /* srcB */ OUT_RELOC(ring, query_sample(aq, start)); /* srcC */ fd5_context(batch->ctx)->samples_passed_queries--; }
static void render_tiles(struct fd_batch *batch) { struct fd_context *ctx = batch->ctx; struct fd_gmem_stateobj *gmem = &ctx->gmem; int i; ctx->emit_tile_init(batch); if (batch->restore) ctx->stats.batch_restore++; for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) { struct fd_tile *tile = &ctx->tile[i]; DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d", tile->bin_h, tile->yoff, tile->bin_w, tile->xoff); ctx->emit_tile_prep(batch, tile); if (batch->restore) { ctx->emit_tile_mem2gmem(batch, tile); } ctx->emit_tile_renderprep(batch, tile); fd_hw_query_prepare_tile(batch, i, batch->gmem); /* emit IB to drawcmds: */ ctx->emit_ib(batch->gmem, batch->draw); fd_reset_wfi(batch); /* emit gmem2mem to transfer tile back to system memory: */ ctx->emit_tile_gmem2mem(batch, tile); } if (ctx->emit_tile_fini) ctx->emit_tile_fini(batch); }
static void timestamp_pause(struct fd_acc_query *aq, struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->draw; OUT_PKT7(ring, CP_EVENT_WRITE, 4); OUT_RING(ring, CP_EVENT_WRITE_0_EVENT(CACHE_FLUSH_AND_INV_EVENT) | CP_EVENT_WRITE_0_TIMESTAMP); OUT_RELOCW(ring, query_sample(aq, stop)); OUT_RING(ring, 0x00000000); fd_reset_wfi(batch); fd_wfi(batch, ring); /* result += stop - start: */ OUT_PKT7(ring, CP_MEM_TO_MEM, 9); OUT_RING(ring, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_NEG_C); OUT_RELOCW(ring, query_sample(aq, result)); /* dst */ OUT_RELOC(ring, query_sample(aq, result)); /* srcA */ OUT_RELOC(ring, query_sample(aq, stop)); /* srcB */ OUT_RELOC(ring, query_sample(aq, start)); /* srcC */ }