diff --git a/docs/gallium/screen.rst b/docs/gallium/screen.rst index 266e54cf82e..274b16e2bf7 100644 --- a/docs/gallium/screen.rst +++ b/docs/gallium/screen.rst @@ -248,6 +248,8 @@ The integer capabilities: * ``PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS``: Whether the driver supports taking the number of indirect draws from a separate parameter buffer, see pipe_draw_indirect_info::indirect_draw_count. +* ``PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE``: Whether the driver supports + indirect draws with an arbitrary stride. * ``PIPE_CAP_FS_FINE_DERIVATIVE``: Whether the fragment shader supports the FINE versions of DDX/DDY. * ``PIPE_CAP_VENDOR_ID``: The vendor ID of the underlying hardware. If it's diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c index 617a9dbf38a..6ab60a639e7 100644 --- a/src/gallium/auxiliary/util/u_screen.c +++ b/src/gallium/auxiliary/util/u_screen.c @@ -253,6 +253,8 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen, case PIPE_CAP_FS_POINT_IS_SYSVAL: case PIPE_CAP_FS_FACE_IS_INTEGER_SYSVAL: return 0; + case PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE: + return 1; case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: /* Enables GL_ARB_shader_storage_buffer_object */ diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 582d61a538c..50e0404a1e9 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -859,6 +859,7 @@ enum pipe_cap PIPE_CAP_SHADER_PACK_HALF_FLOAT, PIPE_CAP_MULTI_DRAW_INDIRECT, PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS, + PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE, PIPE_CAP_FS_POSITION_IS_SYSVAL, PIPE_CAP_FS_POINT_IS_SYSVAL, PIPE_CAP_FS_FACE_IS_INTEGER_SYSVAL, diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index b3a12d4a77e..a73cd0a0c6d 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -609,6 +609,8 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe, screen->get_param(screen, PIPE_CAP_SHADER_PACK_HALF_FLOAT); st->has_multi_draw_indirect = screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT); + st->has_indirect_partial_stride = + screen->get_param(screen, PIPE_CAP_MULTI_DRAW_INDIRECT_PARTIAL_STRIDE); st->has_single_pipe_stat = screen->get_param(screen, PIPE_CAP_QUERY_PIPELINE_STATISTICS_SINGLE); st->has_indep_blend_func = diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 4c8c838ad10..1498884b31e 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -150,6 +150,7 @@ struct st_context boolean has_shareable_shaders; boolean has_half_float_packing; boolean has_multi_draw_indirect; + boolean has_indirect_partial_stride; boolean has_single_pipe_stat; boolean has_indep_blend_func; boolean needs_rgb_dst_alpha_override; diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index e121564d3be..cd0b8d6e8b2 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -217,6 +217,21 @@ st_draw_gallium_multimode(struct gl_context *ctx, } } +static void +rewrite_partial_stride_indirect(struct st_context *st, + const struct pipe_draw_info *info, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count_bias draw) +{ + unsigned draw_count = 0; + struct u_indirect_params *new_draws = util_draw_indirect_read(st->pipe, info, indirect, &draw_count); + if (!new_draws) + return; + for (unsigned i = 0; i < draw_count; i++) + cso_draw_vbo(st->cso_context, &new_draws[i].info, i, NULL, new_draws[i].draw); + free(new_draws); +} + void st_indirect_draw_vbo(struct gl_context *ctx, GLuint mode, @@ -276,6 +291,15 @@ st_indirect_draw_vbo(struct gl_context *ctx, } else { indirect.draw_count = draw_count; indirect.stride = stride; + if (!st->has_indirect_partial_stride && stride && + (draw_count > 1 || indirect_draw_count)) { + /* DrawElementsIndirectCommand or DrawArraysIndirectCommand */ + const size_t struct_size = info.index_size ? sizeof(uint32_t) * 5 : sizeof(uint32_t) * 4; + if (indirect.stride && indirect.stride < struct_size) { + rewrite_partial_stride_indirect(st, &info, &indirect, draw); + return; + } + } if (indirect_draw_count) { indirect.indirect_draw_count = indirect_draw_count->buffer;