diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index 0e053d62ce3..b71c77ddc6c 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -1377,6 +1377,9 @@ fd6_emit_tile_fini(struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->gmem; + if (batch->epilogue) + fd6_emit_ib(batch->gmem, batch->epilogue); + OUT_PKT4(ring, REG_A6XX_GRAS_LRZ_CNTL, 1); OUT_RING(ring, A6XX_GRAS_LRZ_CNTL_ENABLE | A6XX_GRAS_LRZ_CNTL_UNK3); @@ -1527,6 +1530,9 @@ fd6_emit_sysmem_fini(struct fd_batch *batch) { struct fd_ringbuffer *ring = batch->gmem; + if (batch->epilogue) + fd6_emit_ib(batch->gmem, batch->epilogue); + OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1); OUT_RING(ring, 0x0); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_query.c b/src/gallium/drivers/freedreno/a6xx/fd6_query.c index 8258760e2e6..a23b02f4e0b 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_query.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_query.c @@ -95,21 +95,20 @@ occlusion_pause(struct fd_acc_query *aq, struct fd_batch *batch) fd6_event_write(batch, ring, ZPASS_DONE, false); - 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 + /* To avoid stalling in the draw buffer, emit code the code to compute the + * counter delta in the epilogue ring. + */ + struct fd_ringbuffer *epilogue = fd_batch_get_epilogue(batch); + fd_wfi(batch, epilogue); /* result += stop - start: */ - OUT_PKT7(ring, CP_MEM_TO_MEM, 9); - OUT_RING(ring, CP_MEM_TO_MEM_0_DOUBLE | + OUT_PKT7(epilogue, CP_MEM_TO_MEM, 9); + OUT_RING(epilogue, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_NEG_C); - OUT_RELOC(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 */ + OUT_RELOC(epilogue, query_sample(aq, result)); /* dst */ + OUT_RELOC(epilogue, query_sample(aq, result)); /* srcA */ + OUT_RELOC(epilogue, query_sample(aq, stop)); /* srcB */ + OUT_RELOC(epilogue, query_sample(aq, start)); /* srcC */ fd6_context(batch->ctx)->samples_passed_queries--; } diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c b/src/gallium/drivers/freedreno/freedreno_batch.c index 288f3307ad3..b31dd2c02c8 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.c +++ b/src/gallium/drivers/freedreno/freedreno_batch.c @@ -161,6 +161,11 @@ batch_fini(struct fd_batch *batch) batch->lrz_clear = NULL; } + if (batch->epilogue) { + fd_ringbuffer_del(batch->epilogue); + batch->epilogue = NULL; + } + if (batch->tile_setup) { fd_ringbuffer_del(batch->tile_setup); batch->tile_setup = NULL; diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h index 6a48c3435ac..e64d9061b6b 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.h +++ b/src/gallium/drivers/freedreno/freedreno_batch.h @@ -184,6 +184,9 @@ struct fd_batch { /** tiling/gmem (IB0) cmdstream: */ struct fd_ringbuffer *gmem; + /** epilogue cmdstream: */ + struct fd_ringbuffer *epilogue; + // TODO maybe more generically split out clear and clear_binning rings? struct fd_ringbuffer *lrz_clear; struct fd_ringbuffer *tile_setup; @@ -336,4 +339,14 @@ fd_event_write(struct fd_batch *batch, struct fd_ringbuffer *ring, fd_reset_wfi(batch); } +static inline struct fd_ringbuffer * +fd_batch_get_epilogue(struct fd_batch *batch) +{ + if (batch->epilogue == NULL) + batch->epilogue = fd_submit_new_ringbuffer(batch->submit, 0x1000, 0); + + return batch->epilogue; +} + + #endif /* FREEDRENO_BATCH_H_ */