From 6d46d0e82b5214120aaa4d600e9fa0a502050c56 Mon Sep 17 00:00:00 2001 From: Erico Nunes Date: Tue, 12 Nov 2019 14:56:33 +0100 Subject: [PATCH] vc4: move the draw splitting routine to shared code This can also be useful for other hardware which has similar limitations on vertex count per single draw. The Mali400 has a similar limitation and can reuse this. Signed-off-by: Erico Nunes Reviewed-by: Eric Anholt Part-of: --- src/gallium/auxiliary/Makefile.sources | 2 + src/gallium/auxiliary/meson.build | 2 + src/gallium/auxiliary/util/u_split_draw.c | 67 +++++++++++++++++++++++ src/gallium/auxiliary/util/u_split_draw.h | 48 ++++++++++++++++ src/gallium/drivers/vc4/vc4_draw.c | 36 +----------- 5 files changed, 122 insertions(+), 33 deletions(-) create mode 100644 src/gallium/auxiliary/util/u_split_draw.c create mode 100644 src/gallium/auxiliary/util/u_split_draw.h diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources index 46c443b5747..9951fe94a48 100644 --- a/src/gallium/auxiliary/Makefile.sources +++ b/src/gallium/auxiliary/Makefile.sources @@ -285,6 +285,8 @@ C_SOURCES := \ util/u_screen.h \ util/u_simple_shaders.c \ util/u_simple_shaders.h \ + util/u_split_draw.c \ + util/u_split_draw.h \ util/u_split_prim.h \ util/u_sse.h \ util/u_suballoc.c \ diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index 65e4eda87ef..d9e91216211 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -305,6 +305,8 @@ files_libgallium = files( 'util/u_screen.h', 'util/u_simple_shaders.c', 'util/u_simple_shaders.h', + 'util/u_split_draw.c', + 'util/u_split_draw.h', 'util/u_split_prim.h', 'util/u_sse.h', 'util/u_suballoc.c', diff --git a/src/gallium/auxiliary/util/u_split_draw.c b/src/gallium/auxiliary/util/u_split_draw.c new file mode 100644 index 00000000000..39989aad00e --- /dev/null +++ b/src/gallium/auxiliary/util/u_split_draw.c @@ -0,0 +1,67 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "pipe/p_defines.h" +#include "util/u_debug.h" +#include "util/u_split_draw.h" + +bool +u_split_draw(const struct pipe_draw_info *info, uint32_t max_verts, + uint32_t *count, uint32_t *step) +{ + if (*count <= max_verts) { + *step = *count; + return false; + } + + switch (info->mode) { + case PIPE_PRIM_POINTS: + *count = *step = max_verts; + break; + case PIPE_PRIM_LINES: + *count = *step = max_verts - (max_verts % 2); + break; + case PIPE_PRIM_LINE_STRIP: + *count = max_verts; + *step = max_verts - 1; + break; + case PIPE_PRIM_LINE_LOOP: + *count = max_verts; + *step = max_verts - 1; + debug_warn_once("unhandled line loop " + "looping behavior with " + ">max vert count\n"); + break; + case PIPE_PRIM_TRIANGLES: + *count = *step = max_verts - (max_verts % 3); + break; + case PIPE_PRIM_TRIANGLE_STRIP: + *count = max_verts; + *step = max_verts - 2; + break; + default: + debug_warn_once("unhandled primitive " + "max vert count, truncating\n"); + *count = *step = max_verts; + } + + return true; +} diff --git a/src/gallium/auxiliary/util/u_split_draw.h b/src/gallium/auxiliary/util/u_split_draw.h new file mode 100644 index 00000000000..b3236a23be8 --- /dev/null +++ b/src/gallium/auxiliary/util/u_split_draw.h @@ -0,0 +1,48 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef U_SPLIT_DRAW_H +#define U_SPLIT_DRAW_H + +#include "pipe/p_state.h" + +/** + * For non-indexed drawing, this function helps work around hardware + * limits on the number of verts in a single draw. + * + * For the given mode of primitive from info, calculate the count and + * step in the buffer so the draw can be split into multiple draws. + * + * \param info pointer to the original pipe_draw_info from draw_vbo + * \param max_verts max number of vertices that can be handled by the hardware + * \param count number of vertices remaining in the draw call. It is also + * used as a return parameter, containing how many vertices + * should be sent in the next job to the hardware. + * \param step return parameter, will contain how many vertices should be + * skipped from the original count on the next call to this + * function (may differ from count if the primitive mode + * requires the last vertices to be reused in the next draw) + */ +bool +u_split_draw(const struct pipe_draw_info *info, uint32_t max_verts, + uint32_t *count, uint32_t *step); + +#endif diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c index 3d931807aec..3da60ff64a8 100644 --- a/src/gallium/drivers/vc4/vc4_draw.c +++ b/src/gallium/drivers/vc4/vc4_draw.c @@ -26,6 +26,7 @@ #include "util/u_prim.h" #include "util/format/u_format.h" #include "util/u_pack_color.h" +#include "util/u_split_draw.h" #include "util/u_upload_mgr.h" #include "indices/u_primconvert.h" @@ -448,45 +449,14 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) while (count) { uint32_t this_count = count; - uint32_t step = count; + uint32_t step; if (needs_drawarrays_shader_state) { vc4_emit_gl_shader_state(vc4, info, extra_index_bias); } - if (count > max_verts) { - switch (info->mode) { - case PIPE_PRIM_POINTS: - this_count = step = max_verts; - break; - case PIPE_PRIM_LINES: - this_count = step = max_verts - (max_verts % 2); - break; - case PIPE_PRIM_LINE_STRIP: - this_count = max_verts; - step = max_verts - 1; - break; - case PIPE_PRIM_LINE_LOOP: - this_count = max_verts; - step = max_verts - 1; - debug_warn_once("unhandled line loop " - "looping behavior with " - ">65535 verts\n"); - break; - case PIPE_PRIM_TRIANGLES: - this_count = step = max_verts - (max_verts % 3); - break; - case PIPE_PRIM_TRIANGLE_STRIP: - this_count = max_verts; - step = max_verts - 2; - break; - default: - debug_warn_once("unhandled primitive " - "max vert count, truncating\n"); - this_count = step = max_verts; - } - } + u_split_draw(info, max_verts, &this_count, &step); cl_emit(&job->bcl, VERTEX_ARRAY_PRIMITIVES, array) { array.primitive_mode = info->mode; -- 2.30.2