From 4c5cd113b82b798634f9a71ef98241d8917c05e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 12 Feb 2020 15:30:30 -0500 Subject: [PATCH] mesa: clean up glMultiDrawElements code, use alloca for small draw count (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit v2: use calloc, add reusable macros Reviewed-by: Mathias Fröhlich (v1) Reviewed-by: Pierre-Eric Pelloux-Prayer (v1) Reviewed-by: Ian Romanick Part-of: --- src/mesa/main/draw.c | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/mesa/main/draw.c b/src/mesa/main/draw.c index 02efab74db1..3a7c390784d 100644 --- a/src/mesa/main/draw.c +++ b/src/mesa/main/draw.c @@ -608,6 +608,28 @@ _mesa_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, } +#define MAX_ALLOCA_PRIMS (50000 / sizeof(*prim)) + +/* Use calloc for large allocations and alloca for small allocations. */ +/* We have to use a macro because alloca is local within the function. */ +#define ALLOC_PRIMS(prim, primcount, func) do { \ + if (unlikely(primcount > MAX_ALLOCA_PRIMS)) { \ + prim = calloc(primcount, sizeof(*prim)); \ + if (!prim) { \ + _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \ + return; \ + } \ + } else { \ + prim = alloca(primcount * sizeof(*prim)); \ + } \ +} while (0) + +#define FREE_PRIMS(prim, primcount) do { \ + if (primcount > MAX_ALLOCA_PRIMS) \ + free(prim); \ +} while (0) + + /** * Called from glMultiDrawArrays when in immediate mode. */ @@ -1158,7 +1180,6 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, GLsizei primcount, const GLint *basevertex) { struct _mesa_index_buffer ib; - struct _mesa_prim *prim; unsigned int index_type_size = sizeof_ib_type(type); uintptr_t min_index_ptr, max_index_ptr; GLboolean fallback = GL_FALSE; @@ -1167,12 +1188,6 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, if (primcount == 0) return; - prim = calloc(primcount, sizeof(*prim)); - if (prim == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); - return; - } - min_index_ptr = (uintptr_t) indices[0]; max_index_ptr = 0; for (i = 0; i < primcount; i++) { @@ -1215,6 +1230,10 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, fallback = GL_TRUE; if (!fallback) { + struct _mesa_prim *prim; + + ALLOC_PRIMS(prim, primcount, "glMultiDrawElements"); + ib.count = (max_index_ptr - min_index_ptr) / index_type_size; ib.index_size = sizeof_ib_type(type); ib.obj = ctx->Array.VAO->IndexBufferObj; @@ -1236,34 +1255,35 @@ _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode, ctx->Driver.Draw(ctx, prim, primcount, &ib, false, 0, ~0, 1, 0, NULL, 0); + FREE_PRIMS(prim, primcount); } else { /* render one prim at a time */ for (i = 0; i < primcount; i++) { if (count[i] == 0) continue; + ib.count = count[i]; ib.index_size = sizeof_ib_type(type); ib.obj = ctx->Array.VAO->IndexBufferObj; ib.ptr = indices[i]; - prim[0].begin = 1; - prim[0].end = 1; - prim[0].mode = mode; - prim[0].start = 0; - prim[0].count = count[i]; - prim[0].draw_id = i; + struct _mesa_prim prim; + prim.begin = 1; + prim.end = 1; + prim.mode = mode; + prim.start = 0; + prim.count = count[i]; + prim.draw_id = i; if (basevertex != NULL) - prim[0].basevertex = basevertex[i]; + prim.basevertex = basevertex[i]; else - prim[0].basevertex = 0; + prim.basevertex = 0; - ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0); + ctx->Driver.Draw(ctx, &prim, 1, &ib, false, 0, ~0, 1, 0, NULL, 0); } } - free(prim); - if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) { _mesa_flush(ctx); } -- 2.30.2