From 720cfb6fe9a3dafadf3bc034008f7c5c15973866 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 9 Sep 2014 11:20:40 -0400 Subject: freedreno/a3xx: enable hw primitive-restart Since software primitive-restart emulation is going to be removed (and anyways, mostly seemed to be crash prone in combination with u_primconvert and oddball scenarios (like PIPE_PRIM_POLYGON with only a single vertex), might as well do it in hardware (which fortunately didn't turn out to be too hard to figure out). Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a3xx/fd3_draw.c | 6 +++--- src/gallium/drivers/freedreno/a3xx/fd3_emit.c | 15 ++++++++++++--- src/gallium/drivers/freedreno/a3xx/fd3_emit.h | 4 ++-- src/gallium/drivers/freedreno/freedreno_screen.c | 4 +++- 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'src/gallium/drivers') diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index 89af740c07c..394277cf6b9 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -72,7 +72,7 @@ static void draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info, struct fd_ringbuffer *ring, unsigned dirty, struct ir3_shader_key key) { - fd3_emit_state(ctx, ring, &ctx->prog, dirty, key); + fd3_emit_state(ctx, ring, info, &ctx->prog, key, dirty); if (dirty & FD_DIRTY_VTXBUF) emit_vertexbufs(ctx, ring, key); @@ -132,7 +132,7 @@ fd3_clear_binning(struct fd_context *ctx, unsigned dirty) .half_precision = true, }; - fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, key); + fd3_emit_state(ctx, ring, NULL, &ctx->solid_prog, key, dirty); fd3_emit_vertex_bufs(ring, fd3_shader_variant(ctx->solid_prog.vp, key), (struct fd3_vertex_buf[]) {{ @@ -178,7 +178,7 @@ fd3_clear(struct fd_context *ctx, unsigned buffers, fd3_clear_binning(ctx, dirty); /* emit generic state now: */ - fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, key); + fd3_emit_state(ctx, ring, NULL, &ctx->solid_prog, key, dirty); OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1); OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) | diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index aae8ff13d19..f5bdea2d00b 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -354,8 +354,8 @@ fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, - struct fd_program_stateobj *prog, uint32_t dirty, - struct ir3_shader_key key) + const struct pipe_draw_info *info, struct fd_program_stateobj *prog, + struct ir3_shader_key key, uint32_t dirty) { struct ir3_shader_variant *vp; struct ir3_shader_variant *fp; @@ -444,7 +444,12 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, val); } - if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) { + /* NOTE: since primitive_restart is not actually part of any + * state object, we need to make sure that we always emit + * PRIM_VTX_CNTL.. either that or be more clever and detect + * when it changes. + */ + if (info) { uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer) ->pc_prim_vtx_cntl; @@ -455,6 +460,10 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, val |= A3XX_PC_PRIM_VTX_CNTL_STRIDE_IN_VPC(stride_in_vpc); } + if (info && info->indexed && info->primitive_restart) { + val |= A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART; + } + val |= COND(vp->writes_psize, A3XX_PC_PRIM_VTX_CNTL_PSIZE); OUT_PKT0(ring, REG_A3XX_PC_PRIM_VTX_CNTL, 1); diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h index 5735c9f873d..81ff06275bc 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h @@ -59,8 +59,8 @@ void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring, struct ir3_shader_variant *vp, struct fd3_vertex_buf *vbufs, uint32_t n); void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, - struct fd_program_stateobj *prog, uint32_t dirty, - struct ir3_shader_key key); + const struct pipe_draw_info *info, struct fd_program_stateobj *prog, + struct ir3_shader_key key, uint32_t dirty); void fd3_emit_restore(struct fd_context *ctx); #endif /* FD3_EMIT_H */ diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 34594aebc4f..74cbd9676c4 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -181,12 +181,14 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: case PIPE_CAP_CONDITIONAL_RENDER: - case PIPE_CAP_PRIMITIVE_RESTART: case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_SM3: return 0; + case PIPE_CAP_PRIMITIVE_RESTART: + return (screen->gpu_id >= 300) ? 1 : 0; + case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 256; -- cgit v1.2.3