summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Scheidegger <[email protected]>2018-07-22 01:05:39 +0200
committerRoland Scheidegger <[email protected]>2018-07-23 22:07:07 +0200
commit09828feab0bdcb1feb0865fc66e5304f6164c3b8 (patch)
tree8b2b89b49314a63813e00f8686be42530fd27749
parent51f67eeb213bb46b57e442c055e986cff839cb5c (diff)
draw: force draw pipeline if there's more than 65535 vertices
The pt emit path can only handle 65535 - the number of vertices is truncated to a ushort, resulting in a too small buffer allocation, which will crash. Forcing the pipeline path looks suboptimal, then again this bug is probably there ever since GS is supported, so it seems it's not happening often. (Note that the vertex_id in the vertex header is 16 bit too, however this is only used by the draw pipeline, and it denotes the emit vertex nr, and that uses vbuf code, which will only emit smaller chunks, so should be fine I think.) Other solutions would be to simply allow 32bit counts for vertex allocation, however 65535 is already larger than this was intended for (the idea being it should be more cache friendly). Or could try to teach the pt emit path to split the emit in smaller chunks (only the non-index path can be affected, since gs output is always linear), but it's a bit tricky (we don't know the primitive boundaries up-front). Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=107295 Cc: <[email protected]> Reviewed-by: Jose Fonseca <[email protected]>
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_emit.c2
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c10
-rw-r--r--src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c9
3 files changed, 21 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index 6fb630b5498..984c76fdf94 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -158,6 +158,7 @@ draw_pt_emit(struct pt_emit *emit,
*/
render->set_primitive(draw->render, prim_info->prim);
+ assert(vertex_count <= 65535);
render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)vertex_count);
@@ -229,6 +230,7 @@ draw_pt_emit_linear(struct pt_emit *emit,
*/
render->set_primitive(draw->render, prim_info->prim);
+ assert(count <= 65535);
if (!render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)count))
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index aa20b918f50..f76e022994a 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -299,6 +299,16 @@ fetch_pipeline_generic(struct draw_pt_middle_end *middle,
FREE(vert_info->verts);
vert_info = &gs_vert_info;
prim_info = &gs_prim_info;
+
+ /*
+ * pt emit can only handle ushort number of vertices (see
+ * render->allocate_vertices).
+ * vsplit guarantees there's never more than 4096, however GS can
+ * easily blow this up (by a factor of 256 (or even 1024) max).
+ */
+ if (vert_info->count > 65535) {
+ opt |= PT_PIPELINE;
+ }
} else {
if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
draw_prim_assembler_run(draw, prim_info, vert_info,
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
index 5e0c562256d..91c9360cced 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
@@ -428,6 +428,15 @@ llvm_pipeline_generic(struct draw_pt_middle_end *middle,
FREE(vert_info->verts);
vert_info = &gs_vert_info;
prim_info = &gs_prim_info;
+ /*
+ * pt emit can only handle ushort number of vertices (see
+ * render->allocate_vertices).
+ * vsplit guarantees there's never more than 4096, however GS can
+ * easily blow this up (by a factor of 256 (or even 1024) max).
+ */
+ if (vert_info->count > 65535) {
+ opt |= PT_PIPELINE;
+ }
} else {
if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
draw_prim_assembler_run(draw, prim_info, vert_info,