diff options
author | Rob Clark <[email protected]> | 2015-11-16 15:07:29 -0500 |
---|---|---|
committer | Rob Clark <[email protected]> | 2015-11-18 14:31:13 -0500 |
commit | 8106fec74c4d8548974fcf64e052a6bac07e926f (patch) | |
tree | 1c1fdd5152d6f020bd9cf2a4879c5bdf51fadf11 /src/gallium/drivers/freedreno/a4xx | |
parent | b24c9a8aeef6fbad06d7982aee8bdb55679289f3 (diff) |
freedreno/a3xx+a4xx: fix for stk binning pass hang
We'd end up in a state where shader uses no inputs, yet num_elements is
greater than zero. Triggered by a TF vertex shader which did:
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
resulting in a binning pass variant with no inputs.
Includes equiv fix in a4xx, even though we don't have binning-pass
enabled yet on a4xx.
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/a4xx')
-rw-r--r-- | src/gallium/drivers/freedreno/a4xx/fd4_emit.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index 26b58718cd8..5a7b192f79d 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -332,7 +332,10 @@ fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit) unsigned instance_regid = regid(63, 0); unsigned vtxcnt_regid = regid(63, 0); + /* Note that sysvals come *after* normal inputs: */ for (i = 0; i < vp->inputs_count; i++) { + if (!vp->inputs[i].compmask) + continue; if (vp->inputs[i].sysval) { switch(vp->inputs[i].slot) { case SYSTEM_VALUE_BASE_VERTEX: @@ -351,19 +354,11 @@ fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit) unreachable("invalid system value"); break; } - } else if (i < vtx->vtx->num_elements && vp->inputs[i].compmask) { + } else if (i < vtx->vtx->num_elements) { last = i; } } - - /* hw doesn't like to be configured for zero vbo's, it seems: */ - if ((vtx->vtx->num_elements == 0) && - (vertex_regid == regid(63, 0)) && - (instance_regid == regid(63, 0)) && - (vtxcnt_regid == regid(63, 0))) - return; - for (i = 0, j = 0; i <= last; i++) { assert(!vp->inputs[i].sysval); if (vp->inputs[i].compmask) { @@ -408,6 +403,38 @@ fd4_emit_vertex_bufs(struct fd_ringbuffer *ring, struct fd4_emit *emit) } } + /* hw doesn't like to be configured for zero vbo's, it seems: */ + if (last < 0) { + /* just recycle the shader bo, we just need to point to *something* + * valid: + */ + struct fd_bo *dummy_vbo = vp->bo; + bool switchnext = (vertex_regid != regid(63, 0)) || + (instance_regid != regid(63, 0)) || + (vtxcnt_regid != regid(63, 0)); + + OUT_PKT0(ring, REG_A4XX_VFD_FETCH(0), 4); + OUT_RING(ring, A4XX_VFD_FETCH_INSTR_0_FETCHSIZE(0) | + A4XX_VFD_FETCH_INSTR_0_BUFSTRIDE(0) | + COND(switchnext, A4XX_VFD_FETCH_INSTR_0_SWITCHNEXT)); + OUT_RELOC(ring, dummy_vbo, 0, 0, 0); + OUT_RING(ring, A4XX_VFD_FETCH_INSTR_2_SIZE(1)); + OUT_RING(ring, A4XX_VFD_FETCH_INSTR_3_STEPRATE(1)); + + OUT_PKT0(ring, REG_A4XX_VFD_DECODE_INSTR(0), 1); + OUT_RING(ring, A4XX_VFD_DECODE_INSTR_CONSTFILL | + A4XX_VFD_DECODE_INSTR_WRITEMASK(0x1) | + A4XX_VFD_DECODE_INSTR_FORMAT(VFMT4_8_UNORM) | + A4XX_VFD_DECODE_INSTR_SWAP(XYZW) | + A4XX_VFD_DECODE_INSTR_REGID(regid(0,0)) | + A4XX_VFD_DECODE_INSTR_SHIFTCNT(1) | + A4XX_VFD_DECODE_INSTR_LASTCOMPVALID | + COND(switchnext, A4XX_VFD_DECODE_INSTR_SWITCHNEXT)); + + total_in = 1; + j = 1; + } + OUT_PKT0(ring, REG_A4XX_VFD_CONTROL_0, 5); OUT_RING(ring, A4XX_VFD_CONTROL_0_TOTALATTRTOVS(total_in) | 0xa0000 | /* XXX */ |