vbo: Use alloca for _vbo_draw_indirect.

Avoid using malloc in the draw path of mesa.
Since the draw_count is a user api input, fall back to malloc if
the amount of consumed stack space may get too high.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
This commit is contained in:
Mathias Fröhlich 2018-03-28 07:19:02 +02:00 committed by Mathias Fröhlich
parent 3f1cd957d3
commit 1da345e569
1 changed files with 56 additions and 25 deletions

View File

@ -233,26 +233,20 @@ _vbo_DestroyContext(struct gl_context *ctx)
}
void
_vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
struct gl_buffer_object *indirect_data,
GLsizeiptr indirect_offset, unsigned draw_count,
unsigned stride,
struct gl_buffer_object *indirect_draw_count_buffer,
GLsizeiptr indirect_draw_count_offset,
const struct _mesa_index_buffer *ib)
/*
* Helper function for _vbo_draw_indirect below that additionally takes a zero
* initialized array of _mesa_prim scratch space memory as the last argument.
*/
static void
draw_indirect(struct gl_context *ctx, GLuint mode,
struct gl_buffer_object *indirect_data,
GLsizeiptr indirect_offset, unsigned draw_count,
unsigned stride,
struct gl_buffer_object *indirect_draw_count_buffer,
GLsizeiptr indirect_draw_count_offset,
const struct _mesa_index_buffer *ib,
struct _mesa_prim *prim)
{
struct _mesa_prim *prim;
prim = calloc(draw_count, sizeof(*prim));
if (prim == NULL) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
(draw_count > 1) ? "Multi" : "",
ib ? "Elements" : "Arrays",
indirect_data ? "CountARB" : "");
return;
}
prim[0].begin = 1;
prim[draw_count - 1].end = 1;
for (unsigned i = 0; i < draw_count; ++i, indirect_offset += stride) {
@ -266,10 +260,47 @@ _vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
/* This should always be true at this time */
assert(indirect_data == ctx->DrawIndirectBuffer);
ctx->Driver.Draw(ctx, prim, draw_count,
ib, false, 0, ~0,
NULL, 0,
indirect_data);
free(prim);
ctx->Driver.Draw(ctx, prim, draw_count, ib, false, 0u, ~0u,
NULL, 0, indirect_data);
}
/*
* Function to be put into dd_function_table::DrawIndirect as fallback.
* Calls into dd_function_table::Draw past adapting call arguments.
* See dd_function_table::DrawIndirect for call argument documentation.
*/
void
_vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
struct gl_buffer_object *indirect_data,
GLsizeiptr indirect_offset, unsigned draw_count,
unsigned stride,
struct gl_buffer_object *indirect_draw_count_buffer,
GLsizeiptr indirect_draw_count_offset,
const struct _mesa_index_buffer *ib)
{
/* Use alloca for the prim space if we are somehow in bounds. */
if (draw_count*sizeof(struct _mesa_prim) < 1024) {
struct _mesa_prim *space = alloca(draw_count*sizeof(struct _mesa_prim));
memset(space, 0, draw_count*sizeof(struct _mesa_prim));
draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count,
stride, indirect_draw_count_buffer,
indirect_draw_count_offset, ib, space);
} else {
struct _mesa_prim *space = calloc(draw_count, sizeof(struct _mesa_prim));
if (space == NULL) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
(draw_count > 1) ? "Multi" : "",
ib ? "Elements" : "Arrays",
indirect_data ? "CountARB" : "");
return;
}
draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count,
stride, indirect_draw_count_buffer,
indirect_draw_count_offset, ib, space);
free(space);
}
}