OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
- OUT_WFI (ring);
-
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, info->min_index); /* VFD_INDEX_MIN */
OUT_RING(ring, info->max_index); /* VFD_INDEX_MAX */
OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) |
A3XX_RB_BLEND_ALPHA_FLOAT(1.0));
- fd3_emit_rbrc_draw_state(ring,
+ fd3_emit_rbrc_draw_state(ctx, ring,
A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER));
if (buffers & PIPE_CLEAR_DEPTH) {
fd_draw(ctx, DI_PT_RECTLIST, DI_SRC_SEL_AUTO_INDEX, 2,
INDEX_SIZE_IGN, 0, 0, NULL);
-
- OUT_WFI (ring);
}
void
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
OUT_RING(ring, 0x00000000);
-
- OUT_WFI (ring);
}
/* emit texture state for mem->gmem restore operation.. eventually it would
struct fd3_zsa_stateobj *zsa = fd3_zsa_stateobj(ctx->zsa);
struct pipe_stencil_ref *sr = &ctx->stencil_ref;
- fd3_emit_rbrc_draw_state(ring, zsa->rb_render_control);
+ fd3_emit_rbrc_draw_state(ctx, ring, zsa->rb_render_control);
OUT_PKT0(ring, REG_A3XX_RB_ALPHA_REF, 1);
OUT_RING(ring, zsa->rb_alpha_ref);
}
emit_cache_flush(ring);
+ fd_rmw_wfi(ctx, ring);
}
* GMEM/binning code is deciding on the bin-width (and whether to
* use binning) after the draw/clear state is emitted.
*/
-static inline void
-fd3_emit_rbrc_draw_state(struct fd_ringbuffer *ring, uint32_t val)
-{
- OUT_PKT3(ring, CP_REG_RMW, 3);
- OUT_RING(ring, REG_A3XX_RB_RENDER_CONTROL);
- OUT_RING(ring, A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK |
- A3XX_RB_RENDER_CONTROL_ENABLE_GMEM);
- OUT_RING(ring, val);
-}
+
+#define RBRC_DRAW_STATE (A3XX_RB_RENDER_CONTROL_ALPHA_TEST | \
+ A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC__MASK)
static inline void
-fd3_emit_rbrc_tile_state(struct fd_ringbuffer *ring, uint32_t val)
+fd3_emit_rbrc_draw_state(struct fd_context *ctx,
+ struct fd_ringbuffer *ring, uint32_t val)
{
- OUT_PKT3(ring, CP_REG_RMW, 3);
- OUT_RING(ring, REG_A3XX_RB_RENDER_CONTROL);
- OUT_RING(ring, ~(A3XX_RB_RENDER_CONTROL_BIN_WIDTH__MASK |
- A3XX_RB_RENDER_CONTROL_ENABLE_GMEM));
- OUT_RING(ring, val);
+ assert(!(val & ~RBRC_DRAW_STATE));
+ if (val != ctx->rmw.rbrc_draw) {
+ fd_rmw_wfi(ctx, ring);
+ OUT_PKT3(ring, CP_REG_RMW, 3);
+ OUT_RING(ring, REG_A3XX_RB_RENDER_CONTROL);
+ OUT_RING(ring, ~RBRC_DRAW_STATE);
+ OUT_RING(ring, val);
+ ctx->rmw.rbrc_draw = val;
+ }
}
#endif /* FD3_EMIT_H */
OUT_RING(ring, A3XX_RB_MODE_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE);
- fd3_emit_rbrc_draw_state(ring,
- A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
- A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER));
+ OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
+ OUT_RING(ring, A3XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE |
+ A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
+ A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
+ A3XX_RB_RENDER_CONTROL_BIN_WIDTH(ctx->gmem.bin_w));
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RESOLVE_PASS) |
A3XX_RB_MRT_BLEND_CONTROL_CLAMP_ENABLE);
}
- fd3_emit_rbrc_tile_state(ring,
+ OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
+ OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_ALWAYS) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w));
OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
A3XX_RB_STENCIL_CONTROL_ZPASS_BF(STENCIL_KEEP) |
A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(STENCIL_KEEP));
- fd3_emit_rbrc_draw_state(ring,
- A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_ALWAYS));
-
OUT_PKT0(ring, REG_A3XX_GRAS_SC_CONTROL, 1);
OUT_RING(ring, A3XX_GRAS_SC_CONTROL_RENDER_MODE(RB_RENDERING_PASS) |
A3XX_GRAS_SC_CONTROL_MSAA_SAMPLES(MSAA_ONE) |
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, 0);
- fd3_emit_rbrc_tile_state(ring,
+ OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
+ OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(pitch));
/* setup scissor/offset for current tile: */
emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL, gmem->bin_w);
- fd3_emit_rbrc_tile_state(ring,
- A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
+ OUT_PKT0(ring, REG_A3XX_RB_RENDER_CONTROL, 1);
+ OUT_RING(ring, A3XX_RB_RENDER_CONTROL_ENABLE_GMEM |
+ A3XX_RB_RENDER_CONTROL_ALPHA_TEST_FUNC(FUNC_NEVER) |
A3XX_RB_RENDER_CONTROL_BIN_WIDTH(gmem->bin_w));
/* setup scissor/offset for current tile: */
}
fd_context_next_rb(pctx);
+ fd_reset_rmw_state(ctx);
util_slab_create(&ctx->transfer_pool, sizeof(struct pipe_transfer),
16, UTIL_SLAB_SINGLETHREADED);
#include "freedreno_screen.h"
#include "freedreno_gmem.h"
+#include "freedreno_util.h"
struct fd_vertex_stateobj;
struct fd_ringbuffer *ring;
struct fd_ringmarker *draw_start, *draw_end;
+ /* Keep track if WAIT_FOR_IDLE is needed for registers we need
+ * to update via RMW:
+ */
+ struct {
+ bool need_wfi;
+ /* note: would be nicer to have in fd3_context, fd2_context,
+ * etc, because the registered modified via RMR differ across
+ * generation. But as long as it is a small set of registers
+ * that might be more hassle than it's worth.
+ */
+ /* state for RB_RENDER_CONTROL: */
+ uint32_t rbrc_draw;
+ } rmw;
+
struct pipe_scissor_state scissor;
/* we don't have a disable/enable bit for scissor, so instead we keep
return (1 << prim) & ctx->primtype_mask;
}
+static INLINE void
+fd_reset_rmw_state(struct fd_context *ctx)
+{
+ ctx->rmw.need_wfi = true;
+ ctx->rmw.rbrc_draw = ~0;
+}
+
+/* emit before a RMW a WAIT_FOR_IDLE only if needed: */
+static inline void
+fd_rmw_wfi(struct fd_context *ctx, struct fd_ringbuffer *ring)
+{
+ if (ctx->rmw.need_wfi) {
+ OUT_WFI(ring);
+ ctx->rmw.need_wfi = false;
+ }
+}
+
struct pipe_context * fd_context_init(struct fd_context *ctx,
struct pipe_screen *pscreen, const uint8_t *primtypes,
void *priv);
}
emit_marker(ring, 7);
+
+ ctx->rmw.need_wfi = true;
}
#endif /* FREEDRENO_DRAW_H_ */
/* mark start for next draw cmds: */
fd_ringmarker_mark(ctx->draw_start);
+ fd_reset_rmw_state(ctx);
+
/* update timestamps on render targets: */
timestamp = fd_ringbuffer_timestamp(ctx->ring);
if (pfb->cbufs[0])