From 85b6ba136bdc2db570265a26c3a00919e0893ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 3 Nov 2020 13:04:03 -0500 Subject: [PATCH] st/mesa: implement Driver.DrawGallium callbacks This is the new fast path replacing the _mesa_prim path. Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/gallium/auxiliary/cso_cache/cso_context.c | 24 ++++ src/gallium/auxiliary/cso_cache/cso_context.h | 7 ++ src/mesa/state_tracker/st_draw.c | 113 +++++++++++++++++- 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index b651cd4b28a..69077fcf2be 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -1685,6 +1685,30 @@ cso_draw_vbo(struct cso_context *cso, } } +/* info->draw_id can be changed by the callee if increment_draw_id is true. */ +void +cso_multi_draw(struct cso_context *cso, + struct pipe_draw_info *info, + const struct pipe_draw_start_count *draws, + unsigned num_draws) +{ + struct u_vbuf *vbuf = cso->vbuf_current; + + if (vbuf) { + for (unsigned i = 0; i < num_draws; i++) { + if (draws[i].count) + u_vbuf_draw_vbo(vbuf, info, NULL, draws[i]); + + if (info->increment_draw_id) + info->drawid++; + } + } else { + struct pipe_context *pipe = cso->pipe; + + pipe->draw_vbo(pipe, info, NULL, draws, num_draws); + } +} + void cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count) { diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 8b856d07426..1f55097ecf4 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -217,6 +217,13 @@ cso_draw_vbo(struct cso_context *cso, const struct pipe_draw_indirect_info *indirect, const struct pipe_draw_start_count draw); +/* info->draw_id can be changed by the callee if increment_draw_id is true. */ +void +cso_multi_draw(struct cso_context *cso, + struct pipe_draw_info *info, + const struct pipe_draw_start_count *draws, + unsigned num_draws); + void cso_draw_arrays_instanced(struct cso_context *cso, uint mode, uint start, uint count, diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 27ff6b4777f..2f5802f8227 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -227,6 +227,115 @@ st_draw_vbo(struct gl_context *ctx, } } +static bool ALWAYS_INLINE +prepare_indexed_draw(/* pass both st and ctx to reduce dereferences */ + struct st_context *st, + struct gl_context *ctx, + struct pipe_draw_info *info, + const struct pipe_draw_start_count *draws, + unsigned num_draws) +{ + if (info->index_size) { + /* Get index bounds for user buffers. */ + if (!info->index_bounds_valid && + st->draw_needs_minmax_index) { + vbo_get_minmax_indices_gallium(ctx, info, draws, num_draws); + info->index_bounds_valid = true; + } + + if (!info->has_user_indices) { + info->index.resource = st_buffer_object(info->index.gl_bo)->buffer; + + /* Return if the bound element array buffer doesn't have any backing + * storage. (nothing to do) + */ + if (unlikely(!info->index.resource)) + return false; + } + } + return true; +} + +static void +st_draw_gallium(struct gl_context *ctx, + struct pipe_draw_info *info, + const struct pipe_draw_start_count *draws, + unsigned num_draws) +{ + struct st_context *st = st_context(ctx); + + prepare_draw(st, ctx); + + if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) + return; + + cso_multi_draw(st->cso_context, info, draws, num_draws); +} + +static void +st_draw_gallium_complex(struct gl_context *ctx, + struct pipe_draw_info *info, + const struct pipe_draw_start_count *draws, + const unsigned char *mode, + const int *base_vertex, + unsigned num_draws) +{ + struct st_context *st = st_context(ctx); + + prepare_draw(st, ctx); + + if (!prepare_indexed_draw(st, ctx, info, draws, num_draws)) + return; + + enum { + MODE = 1, + BASE_VERTEX = 2, + }; + unsigned mask = (mode ? MODE : 0) | (base_vertex ? BASE_VERTEX : 0); + unsigned i, first; + struct cso_context *cso = st->cso_context; + + /* Find consecutive draws where mode and base_vertex don't vary. */ + switch (mask) { + case MODE: + for (i = 0, first = 0; i <= num_draws; i++) { + if (i == num_draws || mode[i] != mode[first]) { + info->mode = mode[first]; + cso_multi_draw(cso, info, &draws[first], i - first); + first = i; + } + } + break; + + case BASE_VERTEX: + for (i = 0, first = 0; i <= num_draws; i++) { + if (i == num_draws || base_vertex[i] != base_vertex[first]) { + info->index_bias = base_vertex[first]; + cso_multi_draw(cso, info, &draws[first], i - first); + first = i; + } + } + break; + + case MODE | BASE_VERTEX: + for (i = 0, first = 0; i <= num_draws; i++) { + if (i == num_draws || + mode[i] != mode[first] || + base_vertex[i] != base_vertex[first]) { + info->mode = mode[first]; + info->index_bias = base_vertex[first]; + cso_multi_draw(cso, info, &draws[first], i - first); + first = i; + } + } + break; + + default: + assert(!"invalid parameters in DrawGalliumComplex"); + break; + } +} + static void st_indirect_draw_vbo(struct gl_context *ctx, GLuint mode, @@ -324,8 +433,8 @@ void st_init_draw_functions(struct dd_function_table *functions) { functions->Draw = st_draw_vbo; - functions->DrawGallium = _mesa_draw_gallium_fallback; - functions->DrawGalliumComplex = _mesa_draw_gallium_complex_fallback; + functions->DrawGallium = st_draw_gallium; + functions->DrawGalliumComplex = st_draw_gallium_complex; functions->DrawIndirect = st_indirect_draw_vbo; functions->DrawTransformFeedback = st_draw_transform_feedback; }