freedreno/a3xx: enable hw primitive-restart
authorRob Clark <robclark@freedesktop.org>
Tue, 9 Sep 2014 15:20:40 +0000 (11:20 -0400)
committerRob Clark <robclark@freedesktop.org>
Tue, 9 Sep 2014 23:42:18 +0000 (19:42 -0400)
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 <robclark@freedesktop.org>
src/gallium/drivers/freedreno/a3xx/fd3_draw.c
src/gallium/drivers/freedreno/a3xx/fd3_emit.c
src/gallium/drivers/freedreno/a3xx/fd3_emit.h
src/gallium/drivers/freedreno/freedreno_screen.c

index 89af740c07c6e0eba6221b1fe340dd6fe0736c4d..394277cf6b91b0a694282d15f35ad12c0a481a9b 100644 (file)
@@ -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) |
index aae8ff13d19f65bf8f9578d087b0f66aa0e37787..f5bdea2d00b279ce6c735f33273a92d1daf7d0bc 100644 (file)
@@ -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);
index 5735c9f873d9f9bbf294d5c58cb153e6e0d48144..81ff06275bcd5aaf674df115a70b3346c3240411 100644 (file)
@@ -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 */
index 34594aebc4fff11e546ad1472c0bd4116dc23fbd..74cbd9676c49393361c65ebe4a5cfd4830e18352 100644 (file)
@@ -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;