summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2017-11-24 21:40:50 -0800
committerEric Anholt <[email protected]>2017-12-01 15:37:28 -0800
commit84ab48c15c9373dfa4709f4f9e887c329286e5a1 (patch)
tree6ab3fc6e0478f5a54be55a3405fce1e8f8dcdd68 /src/gallium
parentbcb6ebe91a1bbbe6ad62f0e99707414fb91e488e (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')
-rw-r--r--src/gallium/drivers/vc4/vc4_draw.c43
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;
}
}