diff options
author | Eric Anholt <[email protected]> | 2017-11-24 21:40:50 -0800 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2017-12-01 15:37:28 -0800 |
commit | 84ab48c15c9373dfa4709f4f9e887c329286e5a1 (patch) | |
tree | 6ab3fc6e0478f5a54be55a3405fce1e8f8dcdd68 /src/gallium/drivers/vc4 | |
parent | bcb6ebe91a1bbbe6ad62f0e99707414fb91e488e (diff) |
broadcom/vc4: Fix handling of GFXH-515 workaround with a start vertex count.
We failed to take the start into account for how many vertices to draw in
this round, so we would end up decrementing count below 0, which as an
unsigned number meant we would loop until the CLs soon ran out of space.
When I wrote the code I was thinking about how to use the previously
emitted shader state (no index bias baked into the elements) by emitting
up to 65535 and then only re-emitting with bias for the second wround, but
that doesn't work if the start is over 65535. Instead, just delay
emitting shader state until we get into the drawarrays GFXH-515 loop and
always bake the bias in when we're doing the workaround.
Diffstat (limited to 'src/gallium/drivers/vc4')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_draw.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c index 0df22931410..6fd25b45b98 100644 --- a/src/gallium/drivers/vc4/vc4_draw.c +++ b/src/gallium/drivers/vc4/vc4_draw.c @@ -331,6 +331,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) vc4_emit_state(pctx); + bool needs_drawarrays_shader_state = false; if ((vc4->dirty & (VC4_DIRTY_VTXBUF | VC4_DIRTY_VTXSTATE | VC4_DIRTY_PRIM_MODE | @@ -342,7 +343,10 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) vc4->prog.vs->uniform_dirty_bits | vc4->prog.fs->uniform_dirty_bits)) || vc4->last_index_bias != info->index_bias) { - vc4_emit_gl_shader_state(vc4, info, 0); + if (info->index_size) + vc4_emit_gl_shader_state(vc4, info, 0); + else + needs_drawarrays_shader_state = true; } vc4->dirty = 0; @@ -392,29 +396,35 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) uint32_t count = info->count; uint32_t start = info->start; uint32_t extra_index_bias = 0; + static const uint32_t max_verts = 65535; + + /* GFXH-515 / SW-5891: The binner emits 16 bit indices for + * drawarrays, which means that if start + count > 64k it + * would truncate the top bits. Work around this by emitting + * a limited number of primitives at a time and reemitting the + * shader state pointing farther down the vertex attribute + * arrays. + * + * To do this properly for line loops or trifans, we'd need to + * make a new VB containing the first vertex plus whatever + * remainder. + */ + if (start + count > max_verts) { + extra_index_bias = start; + start = 0; + needs_drawarrays_shader_state = true; + } while (count) { uint32_t this_count = count; uint32_t step = count; - static const uint32_t max_verts = 65535; - - /* GFXH-515 / SW-5891: The binner emits 16 bit indices - * for drawarrays, which means that if start + count > - * 64k it would truncate the top bits. Work around - * this by emitting a limited number of primitives at - * a time and reemitting the shader state pointing - * farther down the vertex attribute arrays. - * - * To do this properly for line loops or trifans, we'd - * need to make a new VB containing the first vertex - * plus whatever remainder. - */ - if (extra_index_bias) { + + if (needs_drawarrays_shader_state) { vc4_emit_gl_shader_state(vc4, info, extra_index_bias); } - if (start + count > max_verts) { + if (count > max_verts) { switch (info->mode) { case PIPE_PRIM_POINTS: this_count = step = max_verts; @@ -457,6 +467,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) count -= step; extra_index_bias += start + step; start = 0; + needs_drawarrays_shader_state = true; } } |