draw: force draw pipeline if there's more than 65535 vertices
authorRoland Scheidegger <sroland@vmware.com>
Sat, 21 Jul 2018 23:05:39 +0000 (01:05 +0200)
committerRoland Scheidegger <sroland@vmware.com>
Mon, 23 Jul 2018 20:07:07 +0000 (22:07 +0200)
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: <mesa-stable@lists.freedesktop.org>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/draw/draw_pt_emit.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c

index 6fb630b5498397a73eb604247163cf958ea15e8c..984c76fdf9452b7059ec0fe3f38ede7e9bea37cd 100644 (file)
@@ -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))
index aa20b918f50a321db4397e791f48b9ff2d79a7fd..f76e022994a2d8a1db309cd17afcbda9f058b034 100644 (file)
@@ -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,
index 5e0c562256d414d9006b1abd4cdd7f5f6b23e37a..91c9360cced5daf7ff1ca194b4051651af93e550 100644 (file)
@@ -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,