From 1cd455b17b7ac9260fb1e943c5993e8cf747abb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 1 Nov 2020 09:04:40 -0500 Subject: [PATCH] gallium: extend draw_vbo to support multi draws Essentially rename multi_draw to draw_vbo and remove start and count from pipe_draw_info. This is only an interface change. It doesn't add multi draw support anywhere. Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/gallium/auxiliary/cso_cache/cso_context.c | 23 ++-- src/gallium/auxiliary/cso_cache/cso_context.h | 3 +- src/gallium/auxiliary/draw/draw_context.h | 4 +- src/gallium/auxiliary/draw/draw_pt.c | 36 ++++--- src/gallium/auxiliary/driver_ddebug/dd_draw.c | 30 +++--- src/gallium/auxiliary/driver_ddebug/dd_pipe.h | 3 +- .../auxiliary/driver_noop/noop_state.c | 4 +- .../auxiliary/driver_rbug/rbug_context.c | 6 +- .../auxiliary/driver_trace/tr_context.c | 8 +- .../auxiliary/driver_trace/tr_dump_state.c | 15 ++- .../auxiliary/driver_trace/tr_dump_state.h | 2 + src/gallium/auxiliary/indices/u_primconvert.c | 24 +++-- src/gallium/auxiliary/indices/u_primconvert.h | 3 +- src/gallium/auxiliary/util/u_draw.c | 8 +- src/gallium/auxiliary/util/u_draw.h | 32 +++--- src/gallium/auxiliary/util/u_dump.h | 3 + src/gallium/auxiliary/util/u_dump_state.c | 11 +- src/gallium/auxiliary/util/u_helpers.c | 5 +- src/gallium/auxiliary/util/u_helpers.h | 1 + src/gallium/auxiliary/util/u_prim_restart.c | 22 ++-- src/gallium/auxiliary/util/u_prim_restart.h | 4 +- .../auxiliary/util/u_threaded_context.c | 47 +++++--- src/gallium/auxiliary/util/u_vbuf.c | 87 ++++++++------- src/gallium/auxiliary/util/u_vbuf.h | 4 +- src/gallium/drivers/d3d12/d3d12_context.h | 4 +- src/gallium/drivers/d3d12/d3d12_draw.cpp | 35 +++--- src/gallium/drivers/etnaviv/etnaviv_context.c | 20 ++-- src/gallium/drivers/freedreno/a2xx/fd2_draw.c | 26 ++--- src/gallium/drivers/freedreno/a3xx/fd3_draw.c | 6 +- src/gallium/drivers/freedreno/a3xx/fd3_emit.c | 2 +- src/gallium/drivers/freedreno/a3xx/fd3_emit.h | 1 + src/gallium/drivers/freedreno/a4xx/fd4_draw.c | 6 +- src/gallium/drivers/freedreno/a4xx/fd4_draw.h | 7 +- src/gallium/drivers/freedreno/a4xx/fd4_emit.c | 2 +- src/gallium/drivers/freedreno/a4xx/fd4_emit.h | 1 + src/gallium/drivers/freedreno/a5xx/fd5_draw.c | 6 +- src/gallium/drivers/freedreno/a5xx/fd5_draw.h | 5 +- src/gallium/drivers/freedreno/a5xx/fd5_emit.c | 2 +- src/gallium/drivers/freedreno/a5xx/fd5_emit.h | 1 + .../drivers/freedreno/a6xx/fd6_const.c | 2 +- src/gallium/drivers/freedreno/a6xx/fd6_draw.c | 19 ++-- src/gallium/drivers/freedreno/a6xx/fd6_emit.h | 1 + src/gallium/drivers/freedreno/a6xx/fd6_vsc.c | 15 +-- src/gallium/drivers/freedreno/a6xx/fd6_vsc.h | 3 +- .../drivers/freedreno/freedreno_blitter.c | 6 +- .../drivers/freedreno/freedreno_context.h | 1 + .../drivers/freedreno/freedreno_draw.c | 19 ++-- .../drivers/freedreno/freedreno_draw.h | 7 +- src/gallium/drivers/freedreno/ir3/ir3_const.h | 10 +- src/gallium/drivers/i915/i915_context.c | 8 +- src/gallium/drivers/iris/iris_context.h | 4 +- src/gallium/drivers/iris/iris_draw.c | 27 +++-- src/gallium/drivers/iris/iris_screen.h | 3 +- src/gallium/drivers/iris/iris_state.c | 9 +- src/gallium/drivers/lima/lima_draw.c | 75 +++++++------ src/gallium/drivers/llvmpipe/lp_draw_arrays.c | 6 +- .../drivers/nouveau/nv30/nv30_context.h | 6 +- src/gallium/drivers/nouveau/nv30/nv30_draw.c | 5 +- src/gallium/drivers/nouveau/nv30/nv30_push.c | 13 +-- src/gallium/drivers/nouveau/nv30/nv30_vbo.c | 16 +-- .../drivers/nouveau/nv50/nv50_context.h | 7 +- src/gallium/drivers/nouveau/nv50/nv50_push.c | 13 +-- src/gallium/drivers/nouveau/nv50/nv50_vbo.c | 12 ++- .../drivers/nouveau/nvc0/nvc0_context.h | 10 +- src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 14 +-- .../drivers/nouveau/nvc0/nvc0_vbo_translate.c | 53 ++++----- src/gallium/drivers/panfrost/pan_cmdstream.c | 15 +-- src/gallium/drivers/panfrost/pan_cmdstream.h | 1 + src/gallium/drivers/panfrost/pan_context.c | 28 ++--- src/gallium/drivers/r300/r300_render.c | 102 ++++++++++-------- .../drivers/r300/r300_render_stencilref.c | 14 ++- src/gallium/drivers/r600/r600_state_common.c | 24 +++-- .../radeonsi/si_compute_prim_discard.c | 8 +- src/gallium/drivers/radeonsi/si_state_draw.c | 29 ++--- src/gallium/drivers/softpipe/sp_draw_arrays.c | 6 +- src/gallium/drivers/softpipe/sp_state.h | 4 +- src/gallium/drivers/svga/svga_draw.h | 1 + src/gallium/drivers/svga/svga_draw_elements.c | 10 +- src/gallium/drivers/svga/svga_pipe_draw.c | 21 ++-- src/gallium/drivers/svga/svga_swtnl.h | 3 +- src/gallium/drivers/svga/svga_swtnl_backend.c | 5 +- src/gallium/drivers/svga/svga_swtnl_draw.c | 5 +- src/gallium/drivers/swr/swr_draw.cpp | 21 ++-- src/gallium/drivers/swr/swr_state.cpp | 5 +- src/gallium/drivers/swr/swr_state.h | 3 +- src/gallium/drivers/tegra/tegra_context.c | 6 +- src/gallium/drivers/v3d/v3dx_draw.c | 37 ++++--- src/gallium/drivers/vc4/vc4_draw.c | 28 ++--- src/gallium/drivers/virgl/virgl_context.c | 14 +-- src/gallium/drivers/virgl/virgl_encode.c | 7 +- src/gallium/drivers/virgl/virgl_encode.h | 3 +- src/gallium/drivers/zink/zink_context.h | 4 +- src/gallium/drivers/zink/zink_draw.c | 20 ++-- src/gallium/frontends/lavapipe/lvp_execute.c | 15 +-- src/gallium/frontends/nine/device9.c | 7 +- src/gallium/frontends/nine/nine_state.c | 37 ++++--- src/gallium/include/pipe/p_context.h | 53 ++++----- src/gallium/include/pipe/p_state.h | 8 -- src/gallium/tests/graw/tri-instanced.c | 7 +- src/mesa/state_tracker/st_draw.c | 31 +++--- src/mesa/state_tracker/st_draw_feedback.c | 15 +-- 101 files changed, 852 insertions(+), 618 deletions(-) diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index d63892f27bb..1f8e9c36924 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -1723,7 +1723,8 @@ cso_restore_state(struct cso_context *cso) void cso_draw_vbo(struct cso_context *cso, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count draw) { struct u_vbuf *vbuf = cso->vbuf_current; @@ -1738,10 +1739,10 @@ cso_draw_vbo(struct cso_context *cso, indirect->count_from_stream_output == NULL); if (vbuf) { - u_vbuf_draw_vbo(vbuf, info, indirect); + u_vbuf_draw_vbo(vbuf, info, indirect, draw); } else { struct pipe_context *pipe = cso->pipe; - pipe->draw_vbo(pipe, info, indirect); + pipe->draw_vbo(pipe, info, indirect, &draw, 1); } } @@ -1749,16 +1750,18 @@ void cso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.mode = mode; - info.start = start; - info.count = count; info.min_index = start; info.max_index = start + count - 1; - cso_draw_vbo(cso, &info, NULL); + draw.start = start; + draw.count = count; + + cso_draw_vbo(cso, &info, NULL, draw); } void @@ -1767,16 +1770,18 @@ cso_draw_arrays_instanced(struct cso_context *cso, uint mode, uint start_instance, uint instance_count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.mode = mode; - info.start = start; - info.count = count; info.min_index = start; info.max_index = start + count - 1; info.start_instance = start_instance; info.instance_count = instance_count; - cso_draw_vbo(cso, &info, NULL); + draw.start = start; + draw.count = count; + + cso_draw_vbo(cso, &info, NULL, draw); } diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 57dcccff8ae..6bbf536001a 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -218,7 +218,8 @@ cso_set_vertex_buffers_and_elements(struct cso_context *ctx, void cso_draw_vbo(struct cso_context *cso, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count draw); void cso_draw_arrays_instanced(struct cso_context *cso, uint mode, diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 13cbe1ea122..4dcc0d75624 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -324,7 +324,9 @@ draw_set_mapped_so_targets(struct draw_context *draw, void draw_vbo(struct draw_context *draw, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); /******************************************************************************* diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 5149a17acaa..5ce1eb85e55 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -382,11 +382,12 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count) */ static void draw_pt_arrays_restart(struct draw_context *draw, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw_info) { const unsigned prim = info->mode; - const unsigned start = info->start; - const unsigned count = info->count; + const unsigned start = draw_info->start; + const unsigned count = draw_info->count; const unsigned elt_max = draw->pt.user.eltMax; unsigned i, j, cur_start, cur_count; /* The largest index within a loop using the i variable as the index. @@ -441,21 +442,24 @@ draw_pt_arrays_restart(struct draw_context *draw, static void resolve_draw_info(const struct pipe_draw_info *raw_info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *raw_draw, struct pipe_draw_info *info, + struct pipe_draw_start_count *draw, struct pipe_vertex_buffer *vertex_buffer) { memcpy(info, raw_info, sizeof(struct pipe_draw_info)); + memcpy(draw, raw_draw, sizeof(struct pipe_draw_start_count)); if (indirect && indirect->count_from_stream_output) { struct draw_so_target *target = (struct draw_so_target *)indirect->count_from_stream_output; assert(vertex_buffer != NULL); - info->count = vertex_buffer->stride == 0 ? 0 : + draw->count = vertex_buffer->stride == 0 ? 0 : target->internal_offset / vertex_buffer->stride; /* Stream output draw can not be indexed */ debug_assert(!info->index_size); - info->max_index = info->count - 1; + info->max_index = draw->count - 1; } } @@ -468,13 +472,16 @@ resolve_draw_info(const struct pipe_draw_info *raw_info, void draw_vbo(struct draw_context *draw, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { unsigned instance; unsigned index_limit; unsigned count; unsigned fpstate = util_fpstate_get(); struct pipe_draw_info resolved_info; + struct pipe_draw_start_count resolved_draw; if (info->instance_count == 0) return; @@ -484,13 +491,16 @@ draw_vbo(struct draw_context *draw, */ util_fpstate_set_denorms_to_zero(fpstate); - resolve_draw_info(info, indirect, &resolved_info, &(draw->pt.vertex_buffer[0])); + resolve_draw_info(info, indirect, &draws[0], &resolved_info, + &resolved_draw, &(draw->pt.vertex_buffer[0])); info = &resolved_info; + draws = &resolved_draw; + num_draws = 1; if (info->index_size) assert(draw->pt.user.elts); - count = info->count; + count = draws[0].count; draw->pt.user.eltBias = info->index_bias; draw->pt.user.min_index = info->min_index; @@ -502,7 +512,7 @@ draw_vbo(struct draw_context *draw, if (0) debug_printf("draw_vbo(mode=%u start=%u count=%u):\n", - info->mode, info->start, count); + info->mode, draws[0].start, count); if (0) tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); @@ -530,7 +540,7 @@ draw_vbo(struct draw_context *draw, } if (0) - draw_print_arrays(draw, info->mode, info->start, MIN2(count, 20)); + draw_print_arrays(draw, info->mode, draws[0].start, MIN2(count, 20)); index_limit = util_draw_max_index(draw->pt.vertex_buffer, draw->pt.vertex_element, @@ -554,7 +564,7 @@ draw_vbo(struct draw_context *draw, } draw->pt.max_index = index_limit - 1; - draw->start_index = info->start; + draw->start_index = draws[0].start; /* * TODO: We could use draw->pt.max_index to further narrow @@ -575,10 +585,10 @@ draw_vbo(struct draw_context *draw, draw_new_instance(draw); if (info->primitive_restart) { - draw_pt_arrays_restart(draw, info); + draw_pt_arrays_restart(draw, info, &draws[0]); } else { - draw_pt_arrays(draw, info->mode, info->start, count); + draw_pt_arrays(draw, info->mode, draws[0].start, count); } } diff --git a/src/gallium/auxiliary/driver_ddebug/dd_draw.c b/src/gallium/auxiliary/driver_ddebug/dd_draw.c index ba398f6df5f..bcecf6191f9 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_draw.c +++ b/src/gallium/auxiliary/driver_ddebug/dd_draw.c @@ -352,11 +352,13 @@ dd_dump_flush(struct dd_draw_state *dstate, struct call_flush *info, FILE *f) static void dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect, FILE *f) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, FILE *f) { int sh, i; DUMP(draw_info, info); + DUMP(draw_start_count, draw); if (indirect) { if (indirect->buffer) DUMP_M(resource, indirect, buffer); @@ -633,8 +635,9 @@ dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call) dd_dump_flush(state, &call->info.flush, f); break; case CALL_DRAW_VBO: - dd_dump_draw_vbo(state, &call->info.draw_vbo.draw, - &call->info.draw_vbo.indirect, f); + dd_dump_draw_vbo(state, &call->info.draw_vbo.info, + &call->info.draw_vbo.indirect, + &call->info.draw_vbo.draw, f); break; case CALL_LAUNCH_GRID: dd_dump_launch_grid(state, &call->info.launch_grid, f); @@ -710,11 +713,11 @@ dd_unreference_copy_of_call(struct dd_call *dst) pipe_so_target_reference(&dst->info.draw_vbo.indirect.count_from_stream_output, NULL); pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL); pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL); - if (dst->info.draw_vbo.draw.index_size && - !dst->info.draw_vbo.draw.has_user_indices) - pipe_resource_reference(&dst->info.draw_vbo.draw.index.resource, NULL); + if (dst->info.draw_vbo.info.index_size && + !dst->info.draw_vbo.info.has_user_indices) + pipe_resource_reference(&dst->info.draw_vbo.info.index.resource, NULL); else - dst->info.draw_vbo.draw.index.user = NULL; + dst->info.draw_vbo.info.index.user = NULL; break; case CALL_LAUNCH_GRID: pipe_resource_reference(&dst->info.launch_grid.indirect, NULL); @@ -1300,17 +1303,20 @@ dd_context_flush(struct pipe_context *_pipe, static void dd_context_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct dd_context *dctx = dd_context(_pipe); struct pipe_context *pipe = dctx->pipe; struct dd_draw_record *record = dd_create_record(dctx); record->call.type = CALL_DRAW_VBO; - record->call.info.draw_vbo.draw = *info; + record->call.info.draw_vbo.info = *info; + record->call.info.draw_vbo.draw = draws[0]; if (info->index_size && !info->has_user_indices) { - record->call.info.draw_vbo.draw.index.resource = NULL; - pipe_resource_reference(&record->call.info.draw_vbo.draw.index.resource, + record->call.info.draw_vbo.info.index.resource = NULL; + pipe_resource_reference(&record->call.info.draw_vbo.info.index.resource, info->index.resource); } @@ -1330,7 +1336,7 @@ dd_context_draw_vbo(struct pipe_context *_pipe, } dd_before_draw(dctx, record); - pipe->draw_vbo(pipe, info, indirect); + pipe->draw_vbo(pipe, info, indirect, draws, num_draws); dd_after_draw(dctx, record); } diff --git a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h index cf5d879c2d8..25bfc74fb62 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h +++ b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h @@ -122,8 +122,9 @@ struct call_flush { }; struct call_draw_info { - struct pipe_draw_info draw; + struct pipe_draw_info info; struct pipe_draw_indirect_info indirect; + struct pipe_draw_start_count draw; }; struct call_get_query_result_resource { diff --git a/src/gallium/auxiliary/driver_noop/noop_state.c b/src/gallium/auxiliary/driver_noop/noop_state.c index 222cee45cd9..4a595302527 100644 --- a/src/gallium/auxiliary/driver_noop/noop_state.c +++ b/src/gallium/auxiliary/driver_noop/noop_state.c @@ -31,7 +31,9 @@ #include "util/u_transfer.h" static void noop_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { } diff --git a/src/gallium/auxiliary/driver_rbug/rbug_context.c b/src/gallium/auxiliary/driver_rbug/rbug_context.c index 0698f96256b..090f4a30547 100644 --- a/src/gallium/auxiliary/driver_rbug/rbug_context.c +++ b/src/gallium/auxiliary/driver_rbug/rbug_context.c @@ -115,7 +115,9 @@ rbug_draw_block_locked(struct rbug_context *rb_pipe, int flag) static void rbug_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *_info, - const struct pipe_draw_indirect_info *_indirect) + const struct pipe_draw_indirect_info *_indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct rbug_context *rb_pipe = rbug_context(_pipe); struct pipe_context *pipe = rb_pipe->pipe; @@ -133,7 +135,7 @@ rbug_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *_info, if (!(rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT] && rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT]->disabled) && !(rb_pipe->curr.shader[PIPE_SHADER_GEOMETRY] && rb_pipe->curr.shader[PIPE_SHADER_GEOMETRY]->disabled) && !(rb_pipe->curr.shader[PIPE_SHADER_VERTEX] && rb_pipe->curr.shader[PIPE_SHADER_VERTEX]->disabled)) - pipe->draw_vbo(pipe, &info, _indirect); + pipe->draw_vbo(pipe, &info, _indirect, draws, num_draws); mtx_unlock(&rb_pipe->call_mutex); rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c index 8f0d4262940..9c079031adc 100644 --- a/src/gallium/auxiliary/driver_trace/tr_context.c +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -90,7 +90,9 @@ trace_surface_unwrap(struct trace_context *tr_ctx, static void trace_context_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; @@ -100,10 +102,12 @@ trace_context_draw_vbo(struct pipe_context *_pipe, trace_dump_arg(ptr, pipe); trace_dump_arg(draw_info, info); trace_dump_arg(draw_indirect_info, indirect); + trace_dump_struct_array(draw_start_count, draws, num_draws); + trace_dump_arg(uint, num_draws); trace_dump_trace_flush(); - pipe->draw_vbo(pipe, info, indirect); + pipe->draw_vbo(pipe, info, indirect, draws, num_draws); trace_dump_call_end(); } diff --git a/src/gallium/auxiliary/driver_trace/tr_dump_state.c b/src/gallium/auxiliary/driver_trace/tr_dump_state.c index f747e9af82d..29c60e6fedf 100644 --- a/src/gallium/auxiliary/driver_trace/tr_dump_state.c +++ b/src/gallium/auxiliary/driver_trace/tr_dump_state.c @@ -775,11 +775,7 @@ void trace_dump_draw_info(const struct pipe_draw_info *state) trace_dump_member(uint, state, index_size); trace_dump_member(uint, state, has_user_indices); - trace_dump_member(uint, state, mode); - trace_dump_member(uint, state, start); - trace_dump_member(uint, state, count); - trace_dump_member(uint, state, start_instance); trace_dump_member(uint, state, instance_count); @@ -796,6 +792,17 @@ void trace_dump_draw_info(const struct pipe_draw_info *state) trace_dump_struct_end(); } +void trace_dump_draw_start_count(const struct pipe_draw_start_count *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_struct_begin("pipe_draw_start_count"); + trace_dump_member(uint, state, start); + trace_dump_member(uint, state, count); + trace_dump_struct_end(); +} + void trace_dump_draw_indirect_info(const struct pipe_draw_indirect_info *state) { if (!trace_dumping_enabled_locked()) diff --git a/src/gallium/auxiliary/driver_trace/tr_dump_state.h b/src/gallium/auxiliary/driver_trace/tr_dump_state.h index d7e624f5714..78895577710 100644 --- a/src/gallium/auxiliary/driver_trace/tr_dump_state.h +++ b/src/gallium/auxiliary/driver_trace/tr_dump_state.h @@ -82,6 +82,8 @@ void trace_dump_shader_buffer(const struct pipe_shader_buffer *buffer); void trace_dump_draw_info(const struct pipe_draw_info *state); +void trace_dump_draw_start_count(const struct pipe_draw_start_count *state); + void trace_dump_draw_indirect_info(const struct pipe_draw_indirect_info *state); void trace_dump_blit_info(const struct pipe_blit_info *); diff --git a/src/gallium/auxiliary/indices/u_primconvert.c b/src/gallium/auxiliary/indices/u_primconvert.c index 41d43031360..e7e4b4228cd 100644 --- a/src/gallium/auxiliary/indices/u_primconvert.c +++ b/src/gallium/auxiliary/indices/u_primconvert.c @@ -97,9 +97,11 @@ util_primconvert_save_rasterizer_state(struct primconvert_context *pc, void util_primconvert_draw_vbo(struct primconvert_context *pc, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct pipe_draw_info new_info; + struct pipe_draw_start_count new_draw; struct pipe_transfer *src_transfer = NULL; u_translate_func trans_func; u_generate_func gen_func; @@ -121,10 +123,10 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, unsigned index_size; u_index_translator(pc->cfg.primtypes_mask, - info->mode, info->index_size, info->count, + info->mode, info->index_size, draw->count, pc->api_pv, pc->api_pv, info->primitive_restart ? PR_ENABLE : PR_DISABLE, - &mode, &index_size, &new_info.count, + &mode, &index_size, &new_draw.count, &trans_func); new_info.mode = mode; new_info.index_size = index_size; @@ -140,31 +142,31 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, unsigned index_size; u_index_generator(pc->cfg.primtypes_mask, - info->mode, info->start, info->count, + info->mode, draw->start, draw->count, pc->api_pv, pc->api_pv, - &mode, &index_size, &new_info.count, + &mode, &index_size, &new_draw.count, &gen_func); new_info.mode = mode; new_info.index_size = index_size; } - u_upload_alloc(pc->pipe->stream_uploader, 0, new_info.index_size * new_info.count, 4, + u_upload_alloc(pc->pipe->stream_uploader, 0, new_info.index_size * new_draw.count, 4, &ib_offset, &new_info.index.resource, &dst); - new_info.start = ib_offset / new_info.index_size; + new_draw.start = ib_offset / new_info.index_size; if (info->index_size) { - trans_func(src, info->start, info->count, new_info.count, info->restart_index, dst); + trans_func(src, draw->start, draw->count, new_draw.count, info->restart_index, dst); if (pc->cfg.fixed_prim_restart && info->primitive_restart) { new_info.restart_index = (1ull << (new_info.index_size * 8)) - 1; if (info->restart_index != new_info.restart_index) util_translate_prim_restart_data(new_info.index_size, dst, dst, - new_info.count, + new_draw.count, info->restart_index); } } else { - gen_func(info->start, new_info.count, dst); + gen_func(draw->start, new_draw.count, dst); } if (src_transfer) @@ -173,7 +175,7 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, u_upload_unmap(pc->pipe->stream_uploader); /* to the translated draw: */ - pc->pipe->draw_vbo(pc->pipe, &new_info, NULL); + pc->pipe->draw_vbo(pc->pipe, &new_info, NULL, &new_draw, 1); pipe_resource_reference(&new_info.index.resource, NULL); } diff --git a/src/gallium/auxiliary/indices/u_primconvert.h b/src/gallium/auxiliary/indices/u_primconvert.h index 80d25a49313..0aa2ba15146 100644 --- a/src/gallium/auxiliary/indices/u_primconvert.h +++ b/src/gallium/auxiliary/indices/u_primconvert.h @@ -46,6 +46,7 @@ void util_primconvert_save_rasterizer_state(struct primconvert_context *pc, const struct pipe_rasterizer_state *rast); void util_primconvert_draw_vbo(struct primconvert_context *pc, - const struct pipe_draw_info *info); + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw); #endif /* U_PRIMCONVERT_H_ */ diff --git a/src/gallium/auxiliary/util/u_draw.c b/src/gallium/auxiliary/util/u_draw.c index 5481aa2ef32..c4f8cec53e1 100644 --- a/src/gallium/auxiliary/util/u_draw.c +++ b/src/gallium/auxiliary/util/u_draw.c @@ -176,14 +176,16 @@ util_draw_indirect(struct pipe_context *pipe, } for (unsigned i = 0; i < draw_count; i++) { - info.count = params[0]; + struct pipe_draw_start_count draw; + + draw.count = params[0]; info.instance_count = params[1]; - info.start = params[2]; + draw.start = params[2]; info.index_bias = info_in->index_size ? params[3] : 0; info.start_instance = info_in->index_size ? params[4] : params[3]; info.drawid = i; - pipe->draw_vbo(pipe, &info, NULL); + pipe->draw_vbo(pipe, &info, NULL, &draw, 1); params += indirect->stride / 4; } diff --git a/src/gallium/auxiliary/util/u_draw.h b/src/gallium/auxiliary/util/u_draw.h index af2cf5aef44..f05d49592fc 100644 --- a/src/gallium/auxiliary/util/u_draw.h +++ b/src/gallium/auxiliary/util/u_draw.h @@ -55,15 +55,17 @@ util_draw_arrays(struct pipe_context *pipe, uint count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.mode = mode; - info.start = start; - info.count = count; info.min_index = start; info.max_index = start + count - 1; - pipe->draw_vbo(pipe, &info, NULL); + draw.start = start; + draw.count = count; + + pipe->draw_vbo(pipe, &info, NULL, &draw, 1); } static inline void @@ -75,17 +77,19 @@ util_draw_elements(struct pipe_context *pipe, uint count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.index.user = indices; info.has_user_indices = true; info.index_size = index_size; info.mode = mode; - info.start = start; - info.count = count; info.index_bias = index_bias; - pipe->draw_vbo(pipe, &info, NULL); + draw.start = start; + draw.count = count; + + pipe->draw_vbo(pipe, &info, NULL, &draw, 1); } static inline void @@ -97,18 +101,20 @@ util_draw_arrays_instanced(struct pipe_context *pipe, uint instance_count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.mode = mode; - info.start = start; - info.count = count; info.start_instance = start_instance; info.instance_count = instance_count; info.index_bounds_valid = true; info.min_index = start; info.max_index = start + count - 1; - pipe->draw_vbo(pipe, &info, NULL); + draw.start = start; + draw.count = count; + + pipe->draw_vbo(pipe, &info, NULL, &draw, 1); } static inline void @@ -123,19 +129,21 @@ util_draw_elements_instanced(struct pipe_context *pipe, uint instance_count) { struct pipe_draw_info info; + struct pipe_draw_start_count draw; util_draw_init_info(&info); info.index.user = indices; info.has_user_indices = true; info.index_size = index_size; info.mode = mode; - info.start = start; - info.count = count; info.index_bias = index_bias; info.start_instance = start_instance; info.instance_count = instance_count; - pipe->draw_vbo(pipe, &info, NULL); + draw.start = start; + draw.count = count; + + pipe->draw_vbo(pipe, &info, NULL, &draw, 1); } diff --git a/src/gallium/auxiliary/util/u_dump.h b/src/gallium/auxiliary/util/u_dump.h index 2d0cac50a28..bac1d1237f9 100644 --- a/src/gallium/auxiliary/util/u_dump.h +++ b/src/gallium/auxiliary/util/u_dump.h @@ -200,6 +200,9 @@ util_dump_stream_output_target(FILE *stream, void util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state); +void +util_dump_draw_start_count(FILE *stream, const struct pipe_draw_start_count *state); + void util_dump_draw_indirect_info(FILE *stream, const struct pipe_draw_indirect_info *indirect); diff --git a/src/gallium/auxiliary/util/u_dump_state.c b/src/gallium/auxiliary/util/u_dump_state.c index 432b6567b51..40d1ac5a2a8 100644 --- a/src/gallium/auxiliary/util/u_dump_state.c +++ b/src/gallium/auxiliary/util/u_dump_state.c @@ -917,8 +917,6 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state) util_dump_member(stream, uint, state, has_user_indices); util_dump_member(stream, enum_prim_mode, state, mode); - util_dump_member(stream, uint, state, start); - util_dump_member(stream, uint, state, count); util_dump_member(stream, uint, state, start_instance); util_dump_member(stream, uint, state, instance_count); @@ -944,6 +942,15 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state) util_dump_struct_end(stream); } +void +util_dump_draw_start_count(FILE *stream, const struct pipe_draw_start_count *state) +{ + util_dump_struct_begin(stream, "pipe_draw_start_count"); + util_dump_member(stream, uint, state, start); + util_dump_member(stream, uint, state, count); + util_dump_struct_end(stream); +} + void util_dump_draw_indirect_info(FILE *stream, const struct pipe_draw_indirect_info *state) diff --git a/src/gallium/auxiliary/util/u_helpers.c b/src/gallium/auxiliary/util/u_helpers.c index 9856f1cf6d7..7e7b2560462 100644 --- a/src/gallium/auxiliary/util/u_helpers.c +++ b/src/gallium/auxiliary/util/u_helpers.c @@ -143,13 +143,14 @@ void util_set_shader_buffers_mask(struct pipe_shader_buffer *dst, bool util_upload_index_buffer(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, struct pipe_resource **out_buffer, unsigned *out_offset, unsigned alignment) { - unsigned start_offset = info->start * info->index_size; + unsigned start_offset = draw->start * info->index_size; u_upload_data(pipe->stream_uploader, start_offset, - info->count * info->index_size, alignment, + draw->count * info->index_size, alignment, (char*)info->index.user + start_offset, out_offset, out_buffer); u_upload_unmap(pipe->stream_uploader); diff --git a/src/gallium/auxiliary/util/u_helpers.h b/src/gallium/auxiliary/util/u_helpers.h index e5748f11edf..5c83f6caaa0 100644 --- a/src/gallium/auxiliary/util/u_helpers.h +++ b/src/gallium/auxiliary/util/u_helpers.h @@ -54,6 +54,7 @@ void util_set_shader_buffers_mask(struct pipe_shader_buffer *dst, bool util_upload_index_buffer(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, struct pipe_resource **out_buffer, unsigned *out_offset, unsigned alignment); diff --git a/src/gallium/auxiliary/util/u_prim_restart.c b/src/gallium/auxiliary/util/u_prim_restart.c index d3a5e634387..8d1640969f8 100644 --- a/src/gallium/auxiliary/util/u_prim_restart.c +++ b/src/gallium/auxiliary/util/u_prim_restart.c @@ -100,6 +100,7 @@ enum pipe_error util_translate_prim_restart_ib(struct pipe_context *context, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect_info, + const struct pipe_draw_start_count *draw, struct pipe_resource **dst_buffer) { struct pipe_screen *screen = context->screen; @@ -108,8 +109,8 @@ util_translate_prim_restart_ib(struct pipe_context *context, const unsigned src_index_size = info->index_size; unsigned dst_index_size; DrawElementsIndirectCommand indirect; - unsigned count = info->count; - unsigned start = info->start; + unsigned count = draw->count; + unsigned start = draw->start; /* 1-byte indexes are converted to 2-byte indexes, 4-byte stays 4-byte */ dst_index_size = MAX2(2, info->index_size); @@ -147,7 +148,7 @@ util_translate_prim_restart_ib(struct pipe_context *context, goto error; util_translate_prim_restart_data(src_index_size, src_map, dst_map, - info->count, info->restart_index); + draw->count, info->restart_index); if (src_transfer) pipe_buffer_unmap(context, src_transfer); @@ -222,16 +223,18 @@ add_range(struct range_info *info, unsigned start, unsigned count) enum pipe_error util_draw_vbo_without_prim_restart(struct pipe_context *context, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect_info) + const struct pipe_draw_indirect_info *indirect_info, + const struct pipe_draw_start_count *draw) { const void *src_map; struct range_info ranges = {0}; struct pipe_draw_info new_info; + struct pipe_draw_start_count new_draw; struct pipe_transfer *src_transfer = NULL; unsigned i, start, count; DrawElementsIndirectCommand indirect; - unsigned info_start = info->start; - unsigned info_count = info->count; + unsigned info_start = draw->start; + unsigned info_count = draw->count; unsigned info_instance_count = info->instance_count; assert(info->index_size); @@ -308,13 +311,14 @@ util_draw_vbo_without_prim_restart(struct pipe_context *context, /* draw ranges between the restart indexes */ new_info = *info; + new_draw = *draw; /* we've effectively remapped this to a direct draw */ new_info.instance_count = info_instance_count; new_info.primitive_restart = FALSE; for (i = 0; i < ranges.count; i++) { - new_info.start = ranges.ranges[i].start; - new_info.count = ranges.ranges[i].count; - context->draw_vbo(context, &new_info, NULL); + new_draw.start = ranges.ranges[i].start; + new_draw.count = ranges.ranges[i].count; + context->draw_vbo(context, &new_info, NULL, &new_draw, 1); } FREE(ranges.ranges); diff --git a/src/gallium/auxiliary/util/u_prim_restart.h b/src/gallium/auxiliary/util/u_prim_restart.h index de7d93303e7..5ba89de282e 100644 --- a/src/gallium/auxiliary/util/u_prim_restart.h +++ b/src/gallium/auxiliary/util/u_prim_restart.h @@ -50,12 +50,14 @@ enum pipe_error util_translate_prim_restart_ib(struct pipe_context *context, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, struct pipe_resource **dst_buffer); enum pipe_error util_draw_vbo_without_prim_restart(struct pipe_context *context, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); static inline unsigned util_prim_restart_index_from_size(unsigned index_size) diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index 9401c36d3f2..dbc0343326a 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -64,6 +64,7 @@ enum tc_call_id { * not needed. */ struct tc_draw_single { struct pipe_draw_info info; + struct pipe_draw_start_count draw; }; typedef void (*tc_execute)(struct pipe_context *pipe, union tc_payload *payload); @@ -124,9 +125,9 @@ is_next_call_a_mergeable_draw(struct tc_draw_single *first_info, simplify_draw_info(&(*next_info)->info); /* All fields must be the same except start and count. */ - return memcmp((uint32_t*)&first_info->info + 2, - (uint32_t*)&(*next_info)->info + 2, - sizeof(struct pipe_draw_info) - 8) == 0; + return memcmp((uint32_t*)&first_info->info, + (uint32_t*)&(*next_info)->info, + sizeof(struct pipe_draw_info)) == 0; } static void @@ -161,10 +162,10 @@ tc_batch_execute(void *job, UNUSED int thread_index) struct pipe_draw_start_count multi[256]; unsigned num_draws = 2; - multi[0].start = first_info->info.start; - multi[0].count = first_info->info.count; - multi[1].start = next_info->info.start; - multi[1].count = next_info->info.count; + multi[0].start = first_info->draw.start; + multi[0].count = first_info->draw.count; + multi[1].start = next_info->draw.start; + multi[1].count = next_info->draw.count; if (next_info->info.index_size) pipe_resource_reference(&next_info->info.index.resource, NULL); @@ -174,14 +175,14 @@ tc_batch_execute(void *job, UNUSED int thread_index) for (; next != last && num_draws < ARRAY_SIZE(multi) && is_next_call_a_mergeable_draw(first_info, next, &next_info); next += next->num_call_slots, num_draws++) { - multi[num_draws].start = next_info->info.start; - multi[num_draws].count = next_info->info.count; + multi[num_draws].start = next_info->draw.start; + multi[num_draws].count = next_info->draw.count; if (next_info->info.index_size) pipe_resource_reference(&next_info->info.index.resource, NULL); } - pipe->multi_draw(pipe, &first_info->info, NULL, multi, num_draws); + pipe->draw_vbo(pipe, &first_info->info, NULL, multi, num_draws); if (first_info->info.index_size) pipe_resource_reference(&first_info->info.index.resource, NULL); iter = next; @@ -2230,7 +2231,7 @@ tc_call_draw_single(struct pipe_context *pipe, union tc_payload *payload) { struct tc_draw_single *info = (struct tc_draw_single*)payload; - pipe->draw_vbo(pipe, &info->info, NULL); + pipe->draw_vbo(pipe, &info->info, NULL, &info->draw, 1); if (info->info.index_size) pipe_resource_reference(&info->info.index.resource, NULL); } @@ -2238,6 +2239,7 @@ tc_call_draw_single(struct pipe_context *pipe, union tc_payload *payload) struct tc_draw_indirect { struct pipe_draw_info info; struct pipe_draw_indirect_info indirect; + struct pipe_draw_start_count draw; }; static void @@ -2245,7 +2247,7 @@ tc_call_draw_indirect(struct pipe_context *pipe, union tc_payload *payload) { struct tc_draw_indirect *info = (struct tc_draw_indirect*)payload; - pipe->draw_vbo(pipe, &info->info, &info->indirect); + pipe->draw_vbo(pipe, &info->info, &info->indirect, &info->draw, 1); if (info->info.index_size) pipe_resource_reference(&info->info.index.resource, NULL); @@ -2256,7 +2258,9 @@ tc_call_draw_indirect(struct pipe_context *pipe, union tc_payload *payload) static void tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct threaded_context *tc = threaded_context(_pipe); unsigned index_size = info->index_size; @@ -2264,6 +2268,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, if (unlikely(indirect)) { assert(!has_user_indices); + assert(num_draws == 1); struct tc_draw_indirect *p = tc_add_struct_typed_call(tc, TC_CALL_draw_indirect, tc_draw_indirect); @@ -2280,8 +2285,14 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, pipe_so_target_reference(&p->indirect.count_from_stream_output, indirect->count_from_stream_output); memcpy(&p->indirect, indirect, sizeof(*indirect)); - } else if (index_size && has_user_indices) { - unsigned size = info->count * index_size; + p->draw.start = draws[0].start; + return; + } + + assert(num_draws == 1); /* TODO: implement multi draws */ + + if (index_size && has_user_indices) { + unsigned size = draws[0].count * index_size; struct pipe_resource *buffer = NULL; unsigned offset; @@ -2290,7 +2301,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, * to the driver if it was done afterwards. */ u_upload_data(tc->base.stream_uploader, 0, size, 4, - (uint8_t*)info->index.user + info->start * index_size, + (uint8_t*)info->index.user + draws[0].start * index_size, &offset, &buffer); if (unlikely(!buffer)) return; @@ -2300,7 +2311,8 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, memcpy(&p->info, info, sizeof(*info)); p->info.has_user_indices = false; p->info.index.resource = buffer; - p->info.start = offset >> util_logbase2(index_size); + p->draw.start = offset >> util_logbase2(index_size); + p->draw.count = draws[0].count; } else { /* Non-indexed call or indexed with a real index buffer. */ struct tc_draw_single *p = @@ -2310,6 +2322,7 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info, info->index.resource); } memcpy(&p->info, info, sizeof(*info)); + p->draw = draws[0]; } } diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c index c10041e2124..ba40f33a08e 100644 --- a/src/gallium/auxiliary/util/u_vbuf.c +++ b/src/gallium/auxiliary/util/u_vbuf.c @@ -409,6 +409,7 @@ void u_vbuf_destroy(struct u_vbuf *mgr) static enum pipe_error u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned vb_mask, unsigned out_vb, int start_vertex, unsigned num_vertices, int min_index, boolean unroll_indices) @@ -475,12 +476,12 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, /* Translate. */ if (unroll_indices) { struct pipe_transfer *transfer = NULL; - const unsigned offset = info->start * info->index_size; + const unsigned offset = draw->start * info->index_size; uint8_t *map; /* Create and map the output buffer. */ u_upload_alloc(mgr->pipe->stream_uploader, 0, - key->output_stride * info->count, 4, + key->output_stride * draw->count, 4, &out_offset, &out_buffer, (void**)&out_map); if (!out_buffer) @@ -490,19 +491,19 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, map = (uint8_t*)info->index.user + offset; } else { map = pipe_buffer_map_range(mgr->pipe, info->index.resource, offset, - info->count * info->index_size, + draw->count * info->index_size, PIPE_MAP_READ, &transfer); } switch (info->index_size) { case 4: - tr->run_elts(tr, (unsigned*)map, info->count, 0, 0, out_map); + tr->run_elts(tr, (unsigned*)map, draw->count, 0, 0, out_map); break; case 2: - tr->run_elts16(tr, (uint16_t*)map, info->count, 0, 0, out_map); + tr->run_elts16(tr, (uint16_t*)map, draw->count, 0, 0, out_map); break; case 1: - tr->run_elts8(tr, map, info->count, 0, 0, out_map); + tr->run_elts8(tr, map, draw->count, 0, 0, out_map); break; } @@ -611,6 +612,7 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr, static boolean u_vbuf_translate_begin(struct u_vbuf *mgr, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, int start_vertex, unsigned num_vertices, int min_index, boolean unroll_indices) { @@ -717,8 +719,8 @@ u_vbuf_translate_begin(struct u_vbuf *mgr, for (type = 0; type < VB_NUM; type++) { if (key[type].nr_elements) { enum pipe_error err; - err = u_vbuf_translate_buffers(mgr, &key[type], info, mask[type], - mgr->fallback_vbs[type], + err = u_vbuf_translate_buffers(mgr, &key[type], info, draw, + mask[type], mgr->fallback_vbs[type], start[type], num[type], min_index, unroll_indices && type == VB_VERTEX); if (err != PIPE_OK) @@ -1133,10 +1135,11 @@ static boolean u_vbuf_mapping_vertex_buffer_blocks(const struct u_vbuf *mgr) static void u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, + unsigned count, const void *indices, unsigned *out_min_index, unsigned *out_max_index) { - if (!info->count) { + if (!count) { *out_min_index = 0; *out_max_index = 0; return; @@ -1148,7 +1151,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, unsigned max = 0; unsigned min = ~0u; if (info->primitive_restart) { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (ui_indices[i] != info->restart_index) { if (ui_indices[i] > max) max = ui_indices[i]; if (ui_indices[i] < min) min = ui_indices[i]; @@ -1156,7 +1159,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, } } else { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (ui_indices[i] > max) max = ui_indices[i]; if (ui_indices[i] < min) min = ui_indices[i]; } @@ -1170,7 +1173,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, unsigned short max = 0; unsigned short min = ~((unsigned short)0); if (info->primitive_restart) { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (us_indices[i] != info->restart_index) { if (us_indices[i] > max) max = us_indices[i]; if (us_indices[i] < min) min = us_indices[i]; @@ -1178,7 +1181,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, } } else { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (us_indices[i] > max) max = us_indices[i]; if (us_indices[i] < min) min = us_indices[i]; } @@ -1192,7 +1195,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, unsigned char max = 0; unsigned char min = ~((unsigned char)0); if (info->primitive_restart) { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (ub_indices[i] != info->restart_index) { if (ub_indices[i] > max) max = ub_indices[i]; if (ub_indices[i] < min) min = ub_indices[i]; @@ -1200,7 +1203,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, } } else { - for (unsigned i = 0; i < info->count; i++) { + for (unsigned i = 0; i < count; i++) { if (ub_indices[i] > max) max = ub_indices[i]; if (ub_indices[i] < min) min = ub_indices[i]; } @@ -1216,6 +1219,7 @@ u_vbuf_get_minmax_index_mapped(const struct pipe_draw_info *info, void u_vbuf_get_minmax_index(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned *out_min_index, unsigned *out_max_index) { struct pipe_transfer *transfer = NULL; @@ -1223,15 +1227,16 @@ void u_vbuf_get_minmax_index(struct pipe_context *pipe, if (info->has_user_indices) { indices = (uint8_t*)info->index.user + - info->start * info->index_size; + draw->start * info->index_size; } else { indices = pipe_buffer_map_range(pipe, info->index.resource, - info->start * info->index_size, - info->count * info->index_size, + draw->start * info->index_size, + draw->count * info->index_size, PIPE_MAP_READ, &transfer); } - u_vbuf_get_minmax_index_mapped(info, indices, out_min_index, out_max_index); + u_vbuf_get_minmax_index_mapped(info, draw->count, indices, + out_min_index, out_max_index); if (transfer) { pipe_buffer_unmap(pipe, transfer); @@ -1259,24 +1264,26 @@ u_vbuf_split_indexed_multidraw(struct u_vbuf *mgr, struct pipe_draw_info *info, assert(info->index_size); for (unsigned i = 0; i < draw_count; i++) { + struct pipe_draw_start_count draw; unsigned offset = i * stride / 4; - info->count = indirect_data[offset + 0]; + draw.count = indirect_data[offset + 0]; info->instance_count = indirect_data[offset + 1]; - if (!info->count || !info->instance_count) + if (!draw.count || !info->instance_count) continue; - info->start = indirect_data[offset + 2]; + draw.start = indirect_data[offset + 2]; info->index_bias = indirect_data[offset + 3]; info->start_instance = indirect_data[offset + 4]; - u_vbuf_draw_vbo(mgr, info, NULL); + u_vbuf_draw_vbo(mgr, info, NULL, draw); } } void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count draw) { struct pipe_context *pipe = mgr->pipe; int start_vertex; @@ -1288,6 +1295,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, const uint32_t incompatible_vb_mask = mgr->incompatible_vb_mask & used_vb_mask; struct pipe_draw_info new_info; + struct pipe_draw_start_count new_draw; /* Normal draw. No fallback and no user buffers. */ if (!incompatible_vb_mask && @@ -1299,11 +1307,12 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, u_vbuf_set_driver_vertex_buffers(mgr); } - pipe->draw_vbo(pipe, info, indirect); + pipe->draw_vbo(pipe, info, indirect, &draw, 1); return; } new_info = *info; + new_draw = draw; /* Handle indirect (multi)draws. */ if (indirect && indirect->buffer) { @@ -1406,8 +1415,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, /* Update the index range. */ unsigned min, max; - new_info.count = count; /* only used by get_minmax_index */ - u_vbuf_get_minmax_index_mapped(&new_info, + u_vbuf_get_minmax_index_mapped(&new_info, count, indices + new_info.index_size * start, &min, &max); @@ -1435,7 +1443,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, * This efficiently processes the multidraw with the time complexity * equal to 1 draw call. */ - new_info.start = ~0u; + new_draw.start = ~0u; new_info.start_instance = ~0u; unsigned end_vertex = 0; unsigned end_instance = 0; @@ -1447,7 +1455,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, unsigned start_instance = data[offset + 3]; unsigned instance_count = data[offset + 1]; - new_info.start = MIN2(new_info.start, start); + new_draw.start = MIN2(new_draw.start, start); new_info.start_instance = MIN2(new_info.start_instance, start_instance); @@ -1457,10 +1465,10 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, free(data); /* Set the final counts. */ - new_info.count = end_vertex - new_info.start; + new_draw.count = end_vertex - new_draw.start; new_info.instance_count = end_instance - new_info.start_instance; - if (new_info.start == ~0u || !new_info.count || !new_info.instance_count) + if (new_draw.start == ~0u || !new_draw.count || !new_info.instance_count) return; } } @@ -1474,7 +1482,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, min_index = new_info.min_index; max_index = new_info.max_index; } else { - u_vbuf_get_minmax_index(mgr->pipe, &new_info, + u_vbuf_get_minmax_index(mgr->pipe, &new_info, &new_draw, &min_index, &max_index); } @@ -1489,7 +1497,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, * performance. */ if (!indirect && !new_info.primitive_restart && - util_is_vbo_upload_ratio_too_large(new_info.count, num_vertices) && + util_is_vbo_upload_ratio_too_large(new_draw.count, num_vertices) && !u_vbuf_mapping_vertex_buffer_blocks(mgr)) { unroll_indices = TRUE; user_vb_mask &= ~(mgr->nonzero_stride_vb_mask & @@ -1502,8 +1510,8 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, min_index = 0; } } else { - start_vertex = new_info.start; - num_vertices = new_info.count; + start_vertex = new_draw.start; + num_vertices = new_draw.count; min_index = 0; } @@ -1511,7 +1519,8 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, if (unroll_indices || incompatible_vb_mask || mgr->ve->incompatible_elem_mask) { - if (!u_vbuf_translate_begin(mgr, &new_info, start_vertex, num_vertices, + if (!u_vbuf_translate_begin(mgr, &new_info, &new_draw, + start_vertex, num_vertices, min_index, unroll_indices)) { debug_warn_once("u_vbuf_translate_begin() failed"); return; @@ -1521,8 +1530,8 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, new_info.index_size = 0; new_info.index_bias = 0; new_info.min_index = 0; - new_info.max_index = new_info.count - 1; - new_info.start = 0; + new_info.max_index = new_draw.count - 1; + new_draw.start = 0; } user_vb_mask &= ~(incompatible_vb_mask | @@ -1565,7 +1574,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, u_upload_unmap(pipe->stream_uploader); u_vbuf_set_driver_vertex_buffers(mgr); - pipe->draw_vbo(pipe, &new_info, indirect); + pipe->draw_vbo(pipe, &new_info, indirect, &draw, 1); if (mgr->using_translate) { u_vbuf_translate_end(mgr); diff --git a/src/gallium/auxiliary/util/u_vbuf.h b/src/gallium/auxiliary/util/u_vbuf.h index c2f21878aac..30d831d2656 100644 --- a/src/gallium/auxiliary/util/u_vbuf.h +++ b/src/gallium/auxiliary/util/u_vbuf.h @@ -78,9 +78,11 @@ void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned start_slot, unsigned count, const struct pipe_vertex_buffer *bufs); void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count draw); void u_vbuf_get_minmax_index(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned *out_min_index, unsigned *out_max_index); /* Save/restore functionality. */ diff --git a/src/gallium/drivers/d3d12/d3d12_context.h b/src/gallium/drivers/d3d12/d3d12_context.h index 0fec5415993..08d8b15df1a 100644 --- a/src/gallium/drivers/d3d12/d3d12_context.h +++ b/src/gallium/drivers/d3d12/d3d12_context.h @@ -320,7 +320,9 @@ d3d12_apply_resource_states(struct d3d12_context* ctx); void d3d12_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); void d3d12_blit(struct pipe_context *pctx, diff --git a/src/gallium/drivers/d3d12/d3d12_draw.cpp b/src/gallium/drivers/d3d12/d3d12_draw.cpp index af5506314ba..b78d144ff11 100644 --- a/src/gallium/drivers/d3d12/d3d12_draw.cpp +++ b/src/gallium/drivers/d3d12/d3d12_draw.cpp @@ -166,6 +166,7 @@ fill_sampler_descriptors(struct d3d12_context *ctx, static unsigned fill_state_vars(struct d3d12_context *ctx, const struct pipe_draw_info *dinfo, + const struct pipe_draw_start_count *draw, struct d3d12_shader *shader, uint32_t *values) { @@ -187,7 +188,7 @@ fill_state_vars(struct d3d12_context *ctx, size += 4; break; case D3D12_STATE_VAR_FIRST_VERTEX: - ptr[0] = dinfo->index_size ? dinfo->index_bias : dinfo->start; + ptr[0] = dinfo->index_size ? dinfo->index_bias : draw->start; size += 4; break; case D3D12_STATE_VAR_DEPTH_TRANSFORM: @@ -240,7 +241,8 @@ check_descriptors_left(struct d3d12_context *ctx) static void set_graphics_root_parameters(struct d3d12_context *ctx, - const struct pipe_draw_info *dinfo) + const struct pipe_draw_info *dinfo, + const struct pipe_draw_start_count *draw) { unsigned num_params = 0; @@ -269,7 +271,7 @@ set_graphics_root_parameters(struct d3d12_context *ctx, /* TODO Don't always update state vars */ if (shader->num_state_vars > 0) { uint32_t constants[D3D12_MAX_STATE_VARS * 4]; - unsigned size = fill_state_vars(ctx, dinfo, shader, constants); + unsigned size = fill_state_vars(ctx, dinfo, draw, shader, constants); ctx->cmdlist->SetGraphicsRoot32BitConstants(num_params, size, constants, 0); num_params++; } @@ -353,11 +355,12 @@ ib_format(unsigned index_size) static void twoface_emulation(struct d3d12_context *ctx, struct d3d12_rasterizer_state *rast, - const struct pipe_draw_info *dinfo) + const struct pipe_draw_info *dinfo, + const struct pipe_draw_start_count *draw) { /* draw backfaces */ ctx->base.bind_rasterizer_state(&ctx->base, rast->twoface_back); - d3d12_draw_vbo(&ctx->base, dinfo, NULL); + d3d12_draw_vbo(&ctx->base, dinfo, NULL, draw, 1); /* restore real state */ ctx->base.bind_rasterizer_state(&ctx->base, rast); @@ -417,7 +420,9 @@ d3d12_last_vertex_stage(struct d3d12_context *ctx) void d3d12_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct d3d12_context *ctx = d3d12_context(pctx); struct d3d12_batch *batch; @@ -431,12 +436,12 @@ d3d12_draw_vbo(struct pipe_context *pctx, dinfo->restart_index != 0xffffffff)) { if (!dinfo->primitive_restart && - !u_trim_pipe_prim(dinfo->mode, (unsigned *)&dinfo->count)) + !u_trim_pipe_prim(dinfo->mode, (unsigned *)&draws[0].count)) return; ctx->initial_api_prim = dinfo->mode; util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->gfx_pipeline_state.rast->base); - util_primconvert_draw_vbo(ctx->primconvert, dinfo); + util_primconvert_draw_vbo(ctx->primconvert, dinfo, &draws[0]); return; } @@ -452,7 +457,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, struct d3d12_rasterizer_state *rast = ctx->gfx_pipeline_state.rast; if (rast->twoface_back) { enum pipe_prim_type saved_mode = ctx->initial_api_prim; - twoface_emulation(ctx, rast, dinfo); + twoface_emulation(ctx, rast, dinfo, &draws[0]); ctx->initial_api_prim = saved_mode; } @@ -504,7 +509,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, assert(dinfo->index_size != 1); if (dinfo->has_user_indices) { - if (!util_upload_index_buffer(pctx, dinfo, &index_buffer, + if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, &index_offset, 4)) { debug_printf("util_upload_index_buffer() failed\n"); return; @@ -559,7 +564,7 @@ d3d12_draw_vbo(struct pipe_context *pctx, ctx->cmdlist->SetPipelineState(ctx->current_pso); } - set_graphics_root_parameters(ctx, dinfo); + set_graphics_root_parameters(ctx, dinfo, &draws[0]); bool need_zero_one_depth_range = d3d12_need_zero_one_depth_range(ctx); if (need_zero_one_depth_range != ctx->need_zero_one_depth_range) { @@ -698,12 +703,12 @@ d3d12_draw_vbo(struct pipe_context *pctx, d3d12_apply_resource_states(ctx); if (dinfo->index_size > 0) - ctx->cmdlist->DrawIndexedInstanced(dinfo->count, dinfo->instance_count, - dinfo->start, dinfo->index_bias, + ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count, + draws[0].start, dinfo->index_bias, dinfo->start_instance); else - ctx->cmdlist->DrawInstanced(dinfo->count, dinfo->instance_count, - dinfo->start, dinfo->start_instance); + ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count, + draws[0].start, dinfo->start_instance); ctx->state_dirty = 0; diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index 180ff95ee9b..58e5340ec0b 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -224,7 +224,9 @@ etna_get_fs(struct etna_context *ctx, struct etna_shader_key key) static void etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct etna_context *ctx = etna_context(pctx); struct etna_screen *screen = ctx->screen; @@ -234,7 +236,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (!indirect && !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; if (ctx->vertex_elements == NULL || ctx->vertex_elements->num_elements == 0) @@ -243,11 +245,11 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (!(ctx->prim_hwsupport & (1 << info->mode))) { struct primconvert_context *primconvert = ctx->primconvert; util_primconvert_save_rasterizer_state(primconvert, ctx->rasterizer); - util_primconvert_draw_vbo(primconvert, info); + util_primconvert_draw_vbo(primconvert, info, &draws[0]); return; } - int prims = u_decomposed_prims_for_vertices(info->mode, info->count); + int prims = u_decomposed_prims_for_vertices(info->mode, draws[0].count); if (unlikely(prims <= 0)) { DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode); return; @@ -266,12 +268,12 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (info->index_size) { indexbuf = info->has_user_indices ? NULL : info->index.resource; if (info->has_user_indices && - !util_upload_index_buffer(pctx, info, &indexbuf, &index_offset, 4)) { + !util_upload_index_buffer(pctx, info, &draws[0], &indexbuf, &index_offset, 4)) { BUG("Index buffer upload failed."); return; } /* Add start to index offset, when rendering indexed */ - index_offset += info->start * info->index_size; + index_offset += draws[0].start * info->index_size; ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.bo = etna_resource(indexbuf)->bo; ctx->index_buffer.FE_INDEX_STREAM_BASE_ADDR.offset = index_offset; @@ -356,7 +358,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, } } - ctx->stats.prims_generated += u_reduced_prims_for_vertices(info->mode, info->count); + ctx->stats.prims_generated += u_reduced_prims_for_vertices(info->mode, draws[0].count); ctx->stats.draw_calls++; /* Update state for this draw operation */ @@ -368,12 +370,12 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (screen->specs.halti >= 2) { /* On HALTI2+ (GC3000 and higher) only use instanced drawing commands, as the blob does */ etna_draw_instanced(ctx->stream, info->index_size, draw_mode, info->instance_count, - info->count, info->index_size ? info->index_bias : info->start); + draws[0].count, info->index_size ? info->index_bias : draws[0].start); } else { if (info->index_size) etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, info->index_bias); else - etna_draw_primitives(ctx->stream, draw_mode, info->start, prims); + etna_draw_primitives(ctx->stream, draw_mode, draws[0].start, prims); } if (DBG_ENABLED(ETNA_DBG_DRAW_STALL)) { diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_draw.c b/src/gallium/drivers/freedreno/a2xx/fd2_draw.c index 30130c92ea7..774dd98b2aa 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_draw.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_draw.c @@ -80,11 +80,12 @@ emit_vertexbufs(struct fd_context *ctx) static void draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, struct fd_ringbuffer *ring, unsigned index_offset, bool binning) { OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_VGT_INDX_OFFSET)); - OUT_RING(ring, info->index_size ? 0 : info->start); + OUT_RING(ring, info->index_size ? 0 : draw->start); OUT_PKT0(ring, REG_A2XX_TC_CNTL_STATUS, 1); OUT_RING(ring, A2XX_TC_CNTL_STATUS_L2_INVALIDATE); @@ -135,7 +136,7 @@ draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info, vismode = IGNORE_VISIBILITY; fd_draw_emit(ctx->batch, ring, ctx->primtypes[info->mode], - vismode, info, index_offset); + vismode, info, draw, index_offset); if (is_a20x(ctx->screen)) { /* not sure why this is required, but it fixes some hangs */ @@ -153,6 +154,7 @@ draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info, static bool fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *pinfo, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *pdraw, unsigned index_offset) { if (!ctx->prog.fs || !ctx->prog.vs) @@ -171,7 +173,7 @@ fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *pinfo, * using a limit of 32k because it fixes an unexplained hang * 32766 works for all primitives (multiple of 2 and 3) */ - if (pinfo->count > 32766) { + if (pdraw->count > 32766) { static const uint16_t step_tbl[PIPE_PRIM_MAX] = { [0 ... PIPE_PRIM_MAX - 1] = 32766, [PIPE_PRIM_LINE_STRIP] = 32765, @@ -182,26 +184,26 @@ fd2_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *pinfo, [PIPE_PRIM_LINE_LOOP] = 0, }; - struct pipe_draw_info info = *pinfo; - unsigned count = info.count; - unsigned step = step_tbl[info.mode]; + struct pipe_draw_start_count draw = *pdraw; + unsigned count = draw.count; + unsigned step = step_tbl[pinfo->mode]; unsigned num_vertices = ctx->batch->num_vertices; if (!step) return false; for (; count + step > 32766; count -= step) { - info.count = MIN2(count, 32766); - draw_impl(ctx, &info, ctx->batch->draw, index_offset, false); - draw_impl(ctx, &info, ctx->batch->binning, index_offset, true); - info.start += step; + draw.count = MIN2(count, 32766); + draw_impl(ctx, pinfo, &draw, ctx->batch->draw, index_offset, false); + draw_impl(ctx, pinfo, &draw, ctx->batch->binning, index_offset, true); + draw.start += step; ctx->batch->num_vertices += step; } /* changing this value is a hack, restore it */ ctx->batch->num_vertices = num_vertices; } else { - draw_impl(ctx, pinfo, ctx->batch->draw, index_offset, false); - draw_impl(ctx, pinfo, ctx->batch->binning, index_offset, true); + draw_impl(ctx, pinfo, pdraw, ctx->batch->draw, index_offset, false); + draw_impl(ctx, pinfo, pdraw, ctx->batch->binning, index_offset, true); } fd_context_all_clean(ctx); diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index 9e29dfd4b41..ecec325c392 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -70,7 +70,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, add_sat(info->min_index, info->index_bias)); /* VFD_INDEX_MIN */ OUT_RING(ring, add_sat(info->max_index, info->index_bias)); /* VFD_INDEX_MAX */ OUT_RING(ring, info->start_instance); /* VFD_INSTANCEID_OFFSET */ - OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */ + OUT_RING(ring, info->index_size ? info->index_bias : emit->draw->start); /* VFD_INDEX_OFFSET */ OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1); OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */ @@ -84,7 +84,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, fd_draw_emit(ctx->batch, ring, primtype, emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, - info, index_offset); + info, emit->draw, index_offset); } /* fixup dirty shader state in case some "unrelated" (from the state- @@ -115,6 +115,7 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) static bool fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct fd3_context *fd3_ctx = fd3_context(ctx); @@ -124,6 +125,7 @@ fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .prog = &ctx->prog, .info = info, .indirect = indirect, + .draw = draw, .key = { .color_two_side = ctx->rasterizer->light_twoside, .vclamp_color = ctx->rasterizer->clamp_vertex_color, diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index b6c22f609f0..c273b5e55ab 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -747,7 +747,7 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, HLSQ_FLUSH); if (emit->prog == &ctx->prog) { /* evil hack to deal sanely with clear path */ - ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect); + ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect, emit->draw); if (!emit->binning_pass) ir3_emit_fs_consts(fp, ring, ctx); } diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h index 8f88684f7c7..7e70cc58d1d 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h @@ -47,6 +47,7 @@ struct fd3_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; const struct pipe_draw_indirect_info *indirect; + const struct pipe_draw_start_count *draw; bool binning_pass; struct ir3_shader_key key; enum fd_dirty_3d_state dirty; diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c index 304fb6b075f..96189f821fd 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c @@ -53,7 +53,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, fd4_emit_vertex_bufs(ring, emit); OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2); - OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */ + OUT_RING(ring, info->index_size ? info->index_bias : emit->draw->start); /* VFD_INDEX_OFFSET */ OUT_RING(ring, info->start_instance); /* ??? UNKNOWN_2209 */ OUT_PKT0(ring, REG_A4XX_PC_RESTART_INDEX, 1); @@ -68,7 +68,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, fd4_draw_emit(ctx->batch, ring, primtype, emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, - info, emit->indirect, index_offset); + info, emit->indirect, emit->draw, index_offset); } /* fixup dirty shader state in case some "unrelated" (from the state- @@ -99,6 +99,7 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) static bool fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct fd4_context *fd4_ctx = fd4_context(ctx); @@ -108,6 +109,7 @@ fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .prog = &ctx->prog, .info = info, .indirect = indirect, + .draw = draw, .key = { .color_two_side = ctx->rasterizer->light_twoside, .vclamp_color = ctx->rasterizer->clamp_vertex_color, diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_draw.h b/src/gallium/drivers/freedreno/a4xx/fd4_draw.h index cadea8f9268..d7520e1d25c 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_draw.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_draw.h @@ -91,6 +91,7 @@ fd4_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, enum pc_di_vis_cull_mode vismode, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct pipe_resource *idx_buffer = NULL; @@ -132,8 +133,8 @@ fd4_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, idx_buffer = info->index.resource; idx_type = fd4_size2indextype(info->index_size); - idx_size = info->index_size * info->count; - idx_offset = index_offset + info->start * info->index_size; + idx_size = info->index_size * draw->count; + idx_offset = index_offset + draw->start * info->index_size; src_sel = DI_SRC_SEL_DMA; } else { idx_buffer = NULL; @@ -144,7 +145,7 @@ fd4_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, } fd4_draw(batch, ring, primtype, vismode, src_sel, - info->count, info->instance_count, + draw->count, info->instance_count, idx_type, idx_size, idx_offset, idx_buffer); } diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index fc1f54307f5..a1fd2b958fd 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -700,7 +700,7 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, } if (emit->prog == &ctx->prog) { /* evil hack to deal sanely with clear path */ - ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect); + ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect, emit->draw); if (!emit->binning_pass) ir3_emit_fs_consts(fp, ring, ctx); } diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h index a0f01eb9fd1..7cd275578a8 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h @@ -46,6 +46,7 @@ struct fd4_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; const struct pipe_draw_indirect_info *indirect; + const struct pipe_draw_start_count *draw; bool binning_pass; struct ir3_shader_key key; enum fd_dirty_3d_state dirty; diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c index 17a0a11eb18..5a68d788a69 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c @@ -53,7 +53,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, fd5_emit_vertex_bufs(ring, emit); OUT_PKT4(ring, REG_A5XX_VFD_INDEX_OFFSET, 2); - OUT_RING(ring, info->index_size ? info->index_bias : info->start); /* VFD_INDEX_OFFSET */ + OUT_RING(ring, info->index_size ? info->index_bias : emit->draw->start); /* VFD_INDEX_OFFSET */ OUT_RING(ring, info->start_instance); /* VFD_INSTANCE_START_OFFSET */ OUT_PKT4(ring, REG_A5XX_PC_RESTART_INDEX, 1); @@ -63,7 +63,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, fd5_emit_render_cntl(ctx, false, emit->binning_pass); fd5_draw_emit(ctx->batch, ring, primtype, emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, - info, emit->indirect, index_offset); + info, emit->indirect, emit->draw, index_offset); } /* fixup dirty shader state in case some "unrelated" (from the state- @@ -94,6 +94,7 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) static bool fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct fd5_context *fd5_ctx = fd5_context(ctx); @@ -103,6 +104,7 @@ fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .prog = &ctx->prog, .info = info, .indirect = indirect, + .draw = draw, .key = { .color_two_side = ctx->rasterizer->light_twoside, .vclamp_color = ctx->rasterizer->clamp_vertex_color, diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.h b/src/gallium/drivers/freedreno/a5xx/fd5_draw.h index 5160a11a7bd..47577fd8157 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.h +++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.h @@ -85,6 +85,7 @@ fd5_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, enum pc_di_vis_cull_mode vismode, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct pipe_resource *idx_buffer = NULL; @@ -128,7 +129,7 @@ fd5_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, idx_buffer = info->index.resource; idx_type = fd4_size2indextype(info->index_size); max_indices = idx_buffer->width0 / info->index_size; - idx_offset = index_offset + info->start * info->index_size; + idx_offset = index_offset + draw->start * info->index_size; src_sel = DI_SRC_SEL_DMA; } else { idx_buffer = NULL; @@ -139,7 +140,7 @@ fd5_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, } fd5_draw(batch, ring, primtype, vismode, src_sel, - info->count, info->instance_count, + draw->count, info->instance_count, idx_type, max_indices, idx_offset, idx_buffer); } diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c index 58a3c1022f7..1b6e276fd94 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c @@ -707,7 +707,7 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID(regid(63, 0))); } - ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect); + ir3_emit_vs_consts(vp, ring, ctx, emit->info, emit->indirect, emit->draw); if (!emit->binning_pass) ir3_emit_fs_consts(fp, ring, ctx); diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h index e2d4dad88d9..8c6c53a09de 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h @@ -46,6 +46,7 @@ struct fd5_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; const struct pipe_draw_indirect_info *indirect; + const struct pipe_draw_start_count *draw; bool binning_pass; struct ir3_shader_key key; enum fd_dirty_3d_state dirty; diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_const.c b/src/gallium/drivers/freedreno/a6xx/fd6_const.c index 8476353c596..3bd577380f5 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_const.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_const.c @@ -359,7 +359,7 @@ fd6_emit_consts(struct fd6_emit *emit) if (ir3_needs_vs_driver_params(vs)) { struct fd_ringbuffer *dpconstobj = fd_submit_new_ringbuffer( ctx->batch->submit, IR3_DP_VS_COUNT * 4, FD_RINGBUFFER_STREAMING); - ir3_emit_vs_driver_params(vs, dpconstobj, ctx, emit->info, emit->indirect); + ir3_emit_vs_driver_params(vs, dpconstobj, ctx, emit->info, emit->indirect, emit->draw); fd6_emit_take_group(emit, dpconstobj, FD6_GROUP_VS_DRIVER_PARAMS, ENABLE_ALL); fd6_ctx->has_dp_state = true; } else if (fd6_ctx->has_dp_state) { diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c index 5ca23828b19..5b6e5102717 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c @@ -77,6 +77,7 @@ static void draw_emit(struct fd_ringbuffer *ring, struct CP_DRAW_INDX_OFFSET_0 *draw0, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned index_offset) { if (info->index_size) { @@ -88,8 +89,8 @@ draw_emit(struct fd_ringbuffer *ring, OUT_PKT(ring, CP_DRAW_INDX_OFFSET, pack_CP_DRAW_INDX_OFFSET_0(*draw0), CP_DRAW_INDX_OFFSET_1(.num_instances = info->instance_count), - CP_DRAW_INDX_OFFSET_2(.num_indices = info->count), - CP_DRAW_INDX_OFFSET_3(.first_indx = info->start), + CP_DRAW_INDX_OFFSET_2(.num_indices = draw->count), + CP_DRAW_INDX_OFFSET_3(.first_indx = draw->start), A5XX_CP_DRAW_INDX_OFFSET_INDX_BASE( fd_resource(idx_buffer)->bo, index_offset), A5XX_CP_DRAW_INDX_OFFSET_6(.max_indices = max_indices) @@ -98,7 +99,7 @@ draw_emit(struct fd_ringbuffer *ring, OUT_PKT(ring, CP_DRAW_INDX_OFFSET, pack_CP_DRAW_INDX_OFFSET_0(*draw0), CP_DRAW_INDX_OFFSET_1(.num_instances = info->instance_count), - CP_DRAW_INDX_OFFSET_2(.num_indices = info->count) + CP_DRAW_INDX_OFFSET_2(.num_indices = draw->count) ); } } @@ -142,6 +143,7 @@ fixup_draw_state(struct fd_context *ctx, struct fd6_emit *emit) static bool fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct fd6_context *fd6_ctx = fd6_context(ctx); @@ -151,6 +153,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .vtx = &ctx->vtx, .info = info, .indirect = indirect, + .draw = draw, .key = { .vs = ctx->prog.vs, .gs = ctx->prog.gs, @@ -199,7 +202,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, emit.key.key.has_gs = true; if (!(emit.key.hs || emit.key.ds || emit.key.gs || (indirect && indirect->buffer))) - fd6_vsc_update_sizes(ctx->batch, info); + fd6_vsc_update_sizes(ctx->batch, info, draw); fixup_shader_state(ctx, &emit.key.key); @@ -270,9 +273,9 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, ctx->batch->tessellation = true; ctx->batch->tessparam_size = MAX2(ctx->batch->tessparam_size, - emit.hs->output_size * 4 * info->count); + emit.hs->output_size * 4 * draw->count); ctx->batch->tessfactor_size = MAX2(ctx->batch->tessfactor_size, - factor_stride * info->count); + factor_stride * draw->count); if (!ctx->batch->tess_addrs_constobj) { /* Reserve space for the bo address - we'll write them later in @@ -288,7 +291,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, } } - uint32_t index_start = info->index_size ? info->index_bias : info->start; + uint32_t index_start = info->index_size ? info->index_bias : draw->start; if (ctx->last.dirty || (ctx->last.index_start != index_start)) { OUT_PKT4(ring, REG_A6XX_VFD_INDEX_OFFSET, 1); OUT_RING(ring, index_start); /* VFD_INDEX_OFFSET */ @@ -321,7 +324,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, if (indirect && indirect->buffer) { draw_emit_indirect(ring, &draw0, info, indirect, index_offset); } else { - draw_emit(ring, &draw0, info, index_offset); + draw_emit(ring, &draw0, info, draw, index_offset); } emit_marker6(ring, 7); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h index bf7700f1a7b..2484ac21603 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h @@ -87,6 +87,7 @@ struct fd6_emit { const struct fd_vertex_state *vtx; const struct pipe_draw_info *info; const struct pipe_draw_indirect_info *indirect; + const struct pipe_draw_start_count *draw; struct ir3_cache_key key; enum fd_dirty_3d_state dirty; diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_vsc.c b/src/gallium/drivers/freedreno/a6xx/fd6_vsc.c index 43b8c2753a9..69a678e268d 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_vsc.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_vsc.c @@ -63,12 +63,13 @@ bitfield_size_bits(unsigned n) } static unsigned -prim_count(const struct pipe_draw_info *info) +prim_count(const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { /* PIPE_PRIM_MAX used internally for RECTLIST blits on 3d pipe: */ unsigned vtx_per_prim = (info->mode == PIPE_PRIM_MAX) ? 2 : u_vertices_per_prim(info->mode); - return (info->count * info->instance_count) / vtx_per_prim; + return (draw->count * info->instance_count) / vtx_per_prim; } /** @@ -87,9 +88,10 @@ prim_count(const struct pipe_draw_info *info) * https://github.com/freedreno/freedreno/wiki/Visibility-Stream-Format#primitive-streams */ static unsigned -primitive_stream_size_bits(const struct pipe_draw_info *info, unsigned num_bins) +primitive_stream_size_bits(const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned num_bins) { - unsigned num_prims = prim_count(info); + unsigned num_prims = prim_count(info, draw); unsigned nbits = (bitfield_size_bits(num_bins) /* bitfield of bins covered */ + number_size_bits(1) /* number of primitives with this bitset */ @@ -122,7 +124,8 @@ draw_stream_size_bits(const struct pipe_draw_info *info, unsigned num_bins, } void -fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info) +fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { if (!batch->num_bins_per_pipe) { batch->num_bins_per_pipe = fd_gmem_estimate_bins_per_pipe(batch); @@ -140,7 +143,7 @@ fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info) } unsigned prim_strm_bits = - primitive_stream_size_bits(info, batch->num_bins_per_pipe); + primitive_stream_size_bits(info, draw, batch->num_bins_per_pipe); unsigned draw_strm_bits = draw_stream_size_bits(info, batch->num_bins_per_pipe, prim_strm_bits); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_vsc.h b/src/gallium/drivers/freedreno/a6xx/fd6_vsc.h index 50470f683e0..3e1548efd02 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_vsc.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_vsc.h @@ -24,6 +24,7 @@ #ifndef FD6_VSC_H_ #define FD6_VSC_H_ -void fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info); +void fd6_vsc_update_sizes(struct fd_batch *batch, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw); #endif /* FD6_VSC_H_ */ diff --git a/src/gallium/drivers/freedreno/freedreno_blitter.c b/src/gallium/drivers/freedreno/freedreno_blitter.c index 55773af10bb..cefb8502640 100644 --- a/src/gallium/drivers/freedreno/freedreno_blitter.c +++ b/src/gallium/drivers/freedreno/freedreno_blitter.c @@ -234,11 +234,13 @@ fd_blitter_clear(struct pipe_context *pctx, unsigned buffers, struct pipe_draw_info info = { .mode = PIPE_PRIM_MAX, /* maps to DI_PT_RECTLIST */ - .count = 2, .max_index = 1, .instance_count = 1, }; - pctx->draw_vbo(pctx, &info, NULL); + struct pipe_draw_start_count draw = { + .count = 2, + }; + pctx->draw_vbo(pctx, &info, NULL, &draw, 1); /* We expect that this should not have triggered a change in pfb: */ assert(util_framebuffer_state_equal(pfb, &ctx->framebuffer)); diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index d3812279a49..948350a4f48 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -391,6 +391,7 @@ struct fd_context { /* draw: */ bool (*draw_vbo)(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, unsigned index_offset); bool (*clear)(struct fd_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil); diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index fdeb9ddc5c1..7154719359b 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -212,7 +212,9 @@ batch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info, static void fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct fd_context *ctx = fd_context(pctx); @@ -228,7 +230,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (info->mode != PIPE_PRIM_MAX && !indirect && !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; /* TODO: push down the region versions into the tiles */ @@ -240,7 +242,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (ctx->streamout.num_targets > 0) mesa_loge("stream-out with emulated prims"); util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer); - util_primconvert_draw_vbo(ctx->primconvert, info); + util_primconvert_draw_vbo(ctx->primconvert, info, &draws[0]); return; } @@ -250,7 +252,8 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, struct pipe_draw_info new_info; if (info->index_size) { if (info->has_user_indices) { - if (!util_upload_index_buffer(pctx, info, &indexbuf, &index_offset, 4)) + if (!util_upload_index_buffer(pctx, info, &draws[0], + &indexbuf, &index_offset, 4)) return; new_info = *info; new_info.index.resource = indexbuf; @@ -292,7 +295,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, unsigned prims; if ((info->mode != PIPE_PRIM_PATCHES) && (info->mode != PIPE_PRIM_MAX)) - prims = u_reduced_prims_for_vertices(info->mode, info->count); + prims = u_reduced_prims_for_vertices(info->mode, draws[0].count); else prims = 0; @@ -320,13 +323,13 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, util_format_short_name(pipe_surface_format(pfb->cbufs[0])), util_format_short_name(pipe_surface_format(pfb->zsbuf))); - if (ctx->draw_vbo(ctx, info, indirect, index_offset)) + if (ctx->draw_vbo(ctx, info, indirect, &draws[0], index_offset)) batch->needs_flush = true; - batch->num_vertices += info->count * info->instance_count; + batch->num_vertices += draws[0].count * info->instance_count; for (unsigned i = 0; i < ctx->streamout.num_targets; i++) - ctx->streamout.offsets[i] += info->count; + ctx->streamout.offsets[i] += draws[0].count; if (fd_mesa_debug & FD_DBG_DDRAW) fd_context_all_dirty(ctx); diff --git a/src/gallium/drivers/freedreno/freedreno_draw.h b/src/gallium/drivers/freedreno/freedreno_draw.h index b508f70f4ef..477b3088bf3 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.h +++ b/src/gallium/drivers/freedreno/freedreno_draw.h @@ -145,6 +145,7 @@ fd_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, enum pc_di_primtype primtype, enum pc_di_vis_cull_mode vismode, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned index_offset) { struct pipe_resource *idx_buffer = NULL; @@ -157,8 +158,8 @@ fd_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, idx_buffer = info->index.resource; idx_type = size2indextype(info->index_size); - idx_size = info->index_size * info->count; - idx_offset = index_offset + info->start * info->index_size; + idx_size = info->index_size * draw->count; + idx_offset = index_offset + draw->start * info->index_size; src_sel = DI_SRC_SEL_DMA; } else { idx_buffer = NULL; @@ -169,7 +170,7 @@ fd_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring, } fd_draw(batch, ring, primtype, vismode, src_sel, - info->count, info->instance_count - 1, + draw->count, info->instance_count - 1, idx_type, idx_size, idx_offset, idx_buffer); } diff --git a/src/gallium/drivers/freedreno/ir3/ir3_const.h b/src/gallium/drivers/freedreno/ir3/ir3_const.h index 4db055cd552..bae1062b4f2 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_const.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_const.h @@ -515,7 +515,8 @@ static inline void ir3_emit_vs_driver_params(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { debug_assert(ir3_needs_vs_driver_params(v)); @@ -524,7 +525,7 @@ ir3_emit_vs_driver_params(const struct ir3_shader_variant *v, uint32_t vertex_params[IR3_DP_VS_COUNT] = { [IR3_DP_DRAWID] = 0, /* filled by hw (CP_DRAW_INDIRECT_MULTI) */ [IR3_DP_VTXID_BASE] = info->index_size ? - info->index_bias : info->start, + info->index_bias : draw->start, [IR3_DP_INSTID_BASE] = info->start_instance, [IR3_DP_VTXCNT_MAX] = max_tf_vtx(ctx, v), }; @@ -597,7 +598,8 @@ ir3_emit_vs_driver_params(const struct ir3_shader_variant *v, static inline void ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { debug_assert(v->type == MESA_SHADER_VERTEX); @@ -606,7 +608,7 @@ ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *rin /* emit driver params every time: */ if (info && ir3_needs_vs_driver_params(v)) { ring_wfi(ctx->batch, ring); - ir3_emit_vs_driver_params(v, ring, ctx, info, indirect); + ir3_emit_vs_driver_params(v, ring, ctx, info, indirect, draw); } } diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 7750f906405..c778bb87c7e 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -52,14 +52,16 @@ DEBUG_GET_ONCE_BOOL_OPTION(i915_no_vbuf, "I915_NO_VBUF", FALSE) static void i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct i915_context *i915 = i915_context(pipe); struct draw_context *draw = i915->draw; const void *mapped_indices = NULL; unsigned i; - if (!u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; /* @@ -110,7 +112,7 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, /* * Do the drawing */ - draw_vbo(i915->draw, info, NULL); + draw_vbo(i915->draw, info, NULL, draws, num_draws); /* * unmap vertex/index buffers diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 05e8ae32d6a..6f165c9d775 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -823,7 +823,9 @@ void iris_copy_region(struct blorp_context *blorp, /* iris_draw.c */ void iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); void iris_launch_grid(struct pipe_context *, const struct pipe_grid_info *); /* iris_pipe_control.c */ diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c index 844887c3763..feec30bcabf 100644 --- a/src/gallium/drivers/iris/iris_draw.c +++ b/src/gallium/drivers/iris/iris_draw.c @@ -112,7 +112,8 @@ iris_update_draw_info(struct iris_context *ice, static void iris_update_draw_parameters(struct iris_context *ice, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { bool changed = false; @@ -127,7 +128,7 @@ iris_update_draw_parameters(struct iris_context *ice, changed = true; ice->draw.params_valid = false; } else { - int firstvertex = info->index_size ? info->index_bias : info->start; + int firstvertex = info->index_size ? info->index_bias : draw->start; if (!ice->draw.params_valid || ice->draw.params.firstvertex != firstvertex || @@ -173,7 +174,8 @@ iris_update_draw_parameters(struct iris_context *ice, static void iris_indirect_draw_vbo(struct iris_context *ice, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *dindirect) + const struct pipe_draw_indirect_info *dindirect, + const struct pipe_draw_start_count *draw) { struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; struct pipe_draw_info info = *dinfo; @@ -193,9 +195,9 @@ iris_indirect_draw_vbo(struct iris_context *ice, iris_batch_maybe_flush(batch, 1500); - iris_update_draw_parameters(ice, &info, &indirect); + iris_update_draw_parameters(ice, &info, &indirect, draw); - batch->screen->vtbl.upload_render_state(ice, batch, &info, &indirect); + batch->screen->vtbl.upload_render_state(ice, batch, &info, &indirect, draw); ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER; ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER; @@ -217,15 +219,16 @@ iris_indirect_draw_vbo(struct iris_context *ice, static void iris_simple_draw_vbo(struct iris_context *ice, const struct pipe_draw_info *draw, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *sc) { struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER]; iris_batch_maybe_flush(batch, 1500); - iris_update_draw_parameters(ice, draw, indirect); + iris_update_draw_parameters(ice, draw, indirect, sc); - batch->screen->vtbl.upload_render_state(ice, batch, draw, indirect); + batch->screen->vtbl.upload_render_state(ice, batch, draw, indirect, sc); } /** @@ -233,7 +236,9 @@ iris_simple_draw_vbo(struct iris_context *ice, */ void iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct iris_context *ice = (struct iris_context *) ctx; struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen; @@ -275,9 +280,9 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info, iris_handle_always_flush_cache(batch); if (indirect && indirect->buffer) - iris_indirect_draw_vbo(ice, info, indirect); + iris_indirect_draw_vbo(ice, info, indirect, &draws[0]); else - iris_simple_draw_vbo(ice, info, indirect); + iris_simple_draw_vbo(ice, info, indirect, &draws[0]); iris_handle_always_flush_cache(batch); diff --git a/src/gallium/drivers/iris/iris_screen.h b/src/gallium/drivers/iris/iris_screen.h index 420c347a7ce..ab5125b600b 100644 --- a/src/gallium/drivers/iris/iris_screen.h +++ b/src/gallium/drivers/iris/iris_screen.h @@ -61,7 +61,8 @@ struct iris_vtable { void (*upload_render_state)(struct iris_context *ice, struct iris_batch *batch, const struct pipe_draw_info *draw, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *sc); void (*update_surface_base_address)(struct iris_batch *batch, struct iris_binder *binder); void (*upload_compute_state)(struct iris_context *ice, diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index cc41a07f6d4..3b92121254b 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -6418,7 +6418,8 @@ static void iris_upload_render_state(struct iris_context *ice, struct iris_batch *batch, const struct pipe_draw_info *draw, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *sc) { bool use_predicate = ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT; @@ -6444,7 +6445,7 @@ iris_upload_render_state(struct iris_context *ice, if (draw->has_user_indices) { u_upload_data(ice->ctx.stream_uploader, 0, - draw->count * draw->index_size, 4, draw->index.user, + sc->count * draw->index_size, 4, draw->index.user, &offset, &ice->state.last_res.index_buffer); } else { struct iris_resource *res = (void *) draw->index.resource; @@ -6621,9 +6622,9 @@ iris_upload_render_state(struct iris_context *ice, } else { prim.StartInstanceLocation = draw->start_instance; prim.InstanceCount = draw->instance_count; - prim.VertexCountPerInstance = draw->count; + prim.VertexCountPerInstance = sc->count; - prim.StartVertexLocation = draw->start; + prim.StartVertexLocation = sc->start; if (draw->index_size) { prim.BaseVertexLocation += draw->index_bias; diff --git a/src/gallium/drivers/lima/lima_draw.c b/src/gallium/drivers/lima/lima_draw.c index a6165f397b4..3a89de4d142 100644 --- a/src/gallium/drivers/lima/lima_draw.c +++ b/src/gallium/drivers/lima/lima_draw.c @@ -265,7 +265,8 @@ lima_pipe_format_to_attrib_type(enum pipe_format format) } static void -lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) +lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_context_constant_buffer *ccb = ctx->const_buffer + PIPE_SHADER_VERTEX; @@ -302,7 +303,7 @@ lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) lima_ctx_buff_va(ctx, lima_ctx_buff_gp_varying_info), num_outputs); - unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : info->count; + unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count; VS_CMD_DRAW(num, info->index_size); VS_CMD_UNKNOWN2(); @@ -313,7 +314,8 @@ lima_pack_vs_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) } static void -lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) +lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_vs_shader_state *vs = ctx->vs; struct pipe_scissor_state *cscissor = &ctx->clipped_scissor; @@ -383,17 +385,17 @@ lima_pack_plbu_cmd(struct lima_context *ctx, const struct pipe_draw_info *info) if (vs->point_size_idx != -1) PLBU_CMD_INDEXED_PT_SIZE(ctx->gp_output->va + ctx->gp_output_point_size_offt); - PLBU_CMD_INDICES(ctx->index_res->bo->va + info->start * info->index_size + ctx->index_offset); + PLBU_CMD_INDICES(ctx->index_res->bo->va + draw->start * info->index_size + ctx->index_offset); } else { /* can this make the attribute info static? */ - PLBU_CMD_DRAW_ARRAYS(info->mode, info->start, info->count); + PLBU_CMD_DRAW_ARRAYS(info->mode, draw->start, draw->count); } PLBU_CMD_ARRAYS_SEMAPHORE_END(); if (info->index_size) - PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, info->count); + PLBU_CMD_DRAW_ELEMENTS(info->mode, ctx->min_index, draw->count); PLBU_CMD_END(); } @@ -799,7 +801,8 @@ lima_pack_render_state(struct lima_context *ctx, const struct pipe_draw_info *in } static void -lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info) +lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_job *job = lima_job_get(ctx); struct lima_vertex_element_state *ve = ctx->vertex_elements; @@ -821,7 +824,7 @@ lima_update_gp_attribute_info(struct lima_context *ctx, const struct pipe_draw_i lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ); - unsigned start = info->index_size ? (ctx->min_index + info->index_bias) : info->start; + unsigned start = info->index_size ? (ctx->min_index + info->index_bias) : draw->start; attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset + start * pvb->stride; attribute[n++] = (pvb->stride << 11) | @@ -914,13 +917,14 @@ lima_update_pp_uniform(struct lima_context *ctx) } static void -lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info) +lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_job *job = lima_job_get(ctx); struct lima_screen *screen = lima_screen(ctx->base.screen); struct lima_vs_shader_state *vs = ctx->vs; uint32_t gp_output_size; - unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : info->count; + unsigned num = info->index_size ? (ctx->max_index - ctx->min_index + 1) : draw->count; uint32_t *varying = lima_ctx_buff_alloc(ctx, lima_ctx_buff_gp_varying_info, @@ -998,7 +1002,8 @@ lima_update_varying(struct lima_context *ctx, const struct pipe_draw_info *info) static void lima_draw_vbo_update(struct pipe_context *pctx, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_context *ctx = lima_context(pctx); struct lima_context_framebuffer *fb = &ctx->framebuffer; @@ -1017,7 +1022,7 @@ lima_draw_vbo_update(struct pipe_context *pctx, lima_update_job_wb(ctx, buffers); - lima_update_gp_attribute_info(ctx, info); + lima_update_gp_attribute_info(ctx, info, draw); if ((ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF && ctx->const_buffer[PIPE_SHADER_VERTEX].dirty) || @@ -1027,9 +1032,9 @@ lima_draw_vbo_update(struct pipe_context *pctx, ctx->const_buffer[PIPE_SHADER_VERTEX].dirty = false; } - lima_update_varying(ctx, info); + lima_update_varying(ctx, info, draw); - lima_pack_vs_cmd(ctx, info); + lima_pack_vs_cmd(ctx, info, draw); if (ctx->dirty & LIMA_CONTEXT_DIRTY_CONST_BUFF && ctx->const_buffer[PIPE_SHADER_FRAGMENT].dirty) { @@ -1040,7 +1045,7 @@ lima_draw_vbo_update(struct pipe_context *pctx, lima_update_textures(ctx); lima_pack_render_state(ctx, info); - lima_pack_plbu_cmd(ctx, info); + lima_pack_plbu_cmd(ctx, info, draw); if (ctx->gp_output) { lima_bo_unreference(ctx->gp_output); /* held by job */ @@ -1052,7 +1057,8 @@ lima_draw_vbo_update(struct pipe_context *pctx, static void lima_draw_vbo_indexed(struct pipe_context *pctx, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct lima_context *ctx = lima_context(pctx); struct lima_job *job = lima_job_get(ctx); @@ -1068,26 +1074,26 @@ lima_draw_vbo_indexed(struct pipe_context *pctx, } if (info->has_user_indices) { - util_upload_index_buffer(&ctx->base, info, &indexbuf, &ctx->index_offset, 0x40); + util_upload_index_buffer(&ctx->base, info, draw, &indexbuf, &ctx->index_offset, 0x40); ctx->index_res = lima_resource(indexbuf); } else { ctx->index_res = lima_resource(info->index.resource); ctx->index_offset = 0; - needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, info->start, - info->count, &ctx->min_index, &ctx->max_index); + needs_indices = !panfrost_minmax_cache_get(ctx->index_res->index_cache, draw->start, + draw->count, &ctx->min_index, &ctx->max_index); } if (needs_indices) { - u_vbuf_get_minmax_index(pctx, info, &ctx->min_index, &ctx->max_index); + u_vbuf_get_minmax_index(pctx, info, draw, &ctx->min_index, &ctx->max_index); if (!info->has_user_indices) - panfrost_minmax_cache_add(ctx->index_res->index_cache, info->start, info->count, + panfrost_minmax_cache_add(ctx->index_res->index_cache, draw->start, draw->count, ctx->min_index, ctx->max_index); } lima_job_add_bo(job, LIMA_PIPE_GP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ); lima_job_add_bo(job, LIMA_PIPE_PP, ctx->index_res->bo, LIMA_SUBMIT_BO_READ); - lima_draw_vbo_update(pctx, info); + lima_draw_vbo_update(pctx, info, draw); if (indexbuf) pipe_resource_reference(&indexbuf, NULL); @@ -1095,13 +1101,14 @@ lima_draw_vbo_indexed(struct pipe_context *pctx, static void lima_draw_vbo_count(struct pipe_context *pctx, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { static const uint32_t max_verts = 65535; - struct pipe_draw_info local_info = *info; - unsigned start = info->start; - unsigned count = info->count; + struct pipe_draw_start_count local_draw = *draw; + unsigned start = draw->start; + unsigned count = draw->count; while (count) { unsigned this_count = count; @@ -1109,10 +1116,10 @@ lima_draw_vbo_count(struct pipe_context *pctx, u_split_draw(info, max_verts, &this_count, &step); - local_info.start = start; - local_info.count = this_count; + local_draw.start = start; + local_draw.count = this_count; - lima_draw_vbo_update(pctx, &local_info); + lima_draw_vbo_update(pctx, info, &local_draw); count -= step; start += step; @@ -1122,11 +1129,13 @@ lima_draw_vbo_count(struct pipe_context *pctx, static void lima_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { /* check if draw mode and vertex/index count match, * otherwise gp will hang */ - if (!u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) { + if (!u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) { debug_printf("draw mode and vertex/index count mismatch\n"); return; } @@ -1159,9 +1168,9 @@ lima_draw_vbo(struct pipe_context *pctx, lima_job_add_bo(job, LIMA_PIPE_PP, ctx->fs->bo, LIMA_SUBMIT_BO_READ); if (info->index_size) - lima_draw_vbo_indexed(pctx, info); + lima_draw_vbo_indexed(pctx, info, &draws[0]); else - lima_draw_vbo_count(pctx, info); + lima_draw_vbo_count(pctx, info, &draws[0]); } void diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c index c5e5ab0b671..1bcc7fd6f53 100644 --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c @@ -52,7 +52,9 @@ */ static void llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct llvmpipe_context *lp = llvmpipe_context(pipe); struct draw_context *draw = lp->draw; @@ -140,7 +142,7 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, !lp->queries_disabled); /* draw! */ - draw_vbo(draw, info, indirect); + draw_vbo(draw, info, indirect, draws, num_draws); /* * unmap vertex/index buffers diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.h b/src/gallium/drivers/nouveau/nv30/nv30_context.h index 1496b3760dd..0fea91d4b6b 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_context.h +++ b/src/gallium/drivers/nouveau/nv30/nv30_context.h @@ -195,13 +195,15 @@ nv30_fragtex_set_sampler_views(struct pipe_context *pipe, unsigned nr, struct pipe_sampler_view **views); void -nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info); +nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw); void nv30_draw_init(struct pipe_context *pipe); void -nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info); +nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw); bool nv30_state_validate(struct nv30_context *nv30, uint32_t mask, bool hwtnl); diff --git a/src/gallium/drivers/nouveau/nv30/nv30_draw.c b/src/gallium/drivers/nouveau/nv30/nv30_draw.c index 884fd56cc37..ce4e1911d77 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_draw.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_draw.c @@ -376,7 +376,8 @@ nv30_render_validate(struct nv30_context *nv30) } void -nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) +nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw_one) { struct nv30_context *nv30 = nv30_context(pipe); struct draw_context *draw = nv30->draw; @@ -443,7 +444,7 @@ nv30_render_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) draw_set_indexes(draw, NULL, 0, 0); } - draw_vbo(draw, info, NULL); + draw_vbo(draw, info, NULL, draw_one, 1); draw_flush(draw); if (info->index_size && transferi) diff --git a/src/gallium/drivers/nouveau/nv30/nv30_push.c b/src/gallium/drivers/nouveau/nv30/nv30_push.c index 13744c9dfa5..b0879461e31 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_push.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_push.c @@ -195,7 +195,8 @@ emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count) } void -nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info) +nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct push_context ctx; unsigned i, index_size; @@ -227,7 +228,7 @@ nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info) if (info->index_size) { if (!info->has_user_indices) ctx.idxbuf = nouveau_resource_map_offset(&nv30->base, - nv04_resource(info->index.resource), info->start * info->index_size, + nv04_resource(info->index.resource), draw->start * info->index_size, NOUVEAU_BO_RD); else ctx.idxbuf = info->index.user; @@ -259,16 +260,16 @@ nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info) PUSH_DATA (ctx.push, ctx.prim); switch (index_size) { case 0: - emit_vertices_seq(&ctx, info->start, info->count); + emit_vertices_seq(&ctx, draw->start, draw->count); break; case 1: - emit_vertices_i08(&ctx, info->start, info->count); + emit_vertices_i08(&ctx, draw->start, draw->count); break; case 2: - emit_vertices_i16(&ctx, info->start, info->count); + emit_vertices_i16(&ctx, draw->start, draw->count); break; case 4: - emit_vertices_i32(&ctx, info->start, info->count); + emit_vertices_i32(&ctx, draw->start, draw->count); break; default: assert(0); diff --git a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c index 6f941d07008..eb483a86f7d 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_vbo.c @@ -545,14 +545,16 @@ nv30_draw_elements(struct nv30_context *nv30, bool shorten, static void nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_pushbuf *push = nv30->base.pushbuf; int i; if (!info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; /* For picking only a few vertices from a large user buffer, push is better, @@ -560,7 +562,7 @@ nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, */ nv30->vbo_push_hint = /* the 64 is heuristic */ !(info->index_size && - ((info->max_index - info->min_index + 64) < info->count)); + ((info->max_index - info->min_index + 64) < draws[0].count)); nv30->vbo_min_index = info->min_index; nv30->vbo_max_index = info->max_index; @@ -574,11 +576,11 @@ nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, nv30_state_validate(nv30, ~0, true); if (nv30->draw_flags) { - nv30_render_vbo(pipe, info); + nv30_render_vbo(pipe, info, &draws[0]); return; } else if (nv30->vbo_fifo) { - nv30_push_vbo(nv30, info); + nv30_push_vbo(nv30, info, &draws[0]); return; } @@ -601,7 +603,7 @@ nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, if (!info->index_size) { nv30_draw_arrays(nv30, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count); } else { bool shorten = info->max_index <= 65535; @@ -629,7 +631,7 @@ nv30_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } nv30_draw_elements(nv30, shorten, info, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count, info->index_bias, info->index_size); } diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h index ff7edc67918..57b8599483f 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_context.h +++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h @@ -292,7 +292,9 @@ nv50_cb_push(struct nouveau_context *nv, /* nv50_vbo.c */ void nv50_draw_vbo(struct pipe_context *, const struct pipe_draw_info *, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); void * nv50_vertex_state_create(struct pipe_context *pipe, @@ -305,7 +307,8 @@ void nv50_vertex_arrays_validate(struct nv50_context *nv50); /* nv50_push.c */ void nv50_push_vbo(struct nv50_context *, const struct pipe_draw_info *, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); /* nv84_video.c */ struct pipe_video_codec * diff --git a/src/gallium/drivers/nouveau/nv50/nv50_push.c b/src/gallium/drivers/nouveau/nv50/nv50_push.c index 39798ee6ae0..a7ec021e882 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_push.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_push.c @@ -239,12 +239,13 @@ nv50_prim_gl(unsigned prim) void nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { struct push_context ctx; unsigned i, index_size; unsigned inst_count = info->instance_count; - unsigned vert_count = info->count; + unsigned vert_count = draw->count; bool apply_bias = info->index_size && info->index_bias; ctx.push = nv50->base.pushbuf; @@ -329,16 +330,16 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info, PUSH_DATA (ctx.push, ctx.prim); switch (index_size) { case 0: - emit_vertices_seq(&ctx, info->start, vert_count); + emit_vertices_seq(&ctx, draw->start, vert_count); break; case 1: - emit_vertices_i08(&ctx, info->start, vert_count); + emit_vertices_i08(&ctx, draw->start, vert_count); break; case 2: - emit_vertices_i16(&ctx, info->start, vert_count); + emit_vertices_i16(&ctx, draw->start, vert_count); break; case 4: - emit_vertices_i32(&ctx, info->start, vert_count); + emit_vertices_i32(&ctx, draw->start, vert_count); break; default: assert(0); diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c index 10906c7f564..351fd27d780 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c @@ -755,7 +755,9 @@ nv50_draw_vbo_kick_notify(struct nouveau_pushbuf *chan) void nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_pushbuf *push = nv50->base.pushbuf; @@ -775,7 +777,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, * if index count is larger and we expect repeated vertices, suggest upload. */ nv50->vbo_push_hint = /* the 64 is heuristic */ - !(info->index_size && ((nv50->vb_elt_limit + 64) < info->count)); + !(info->index_size && ((nv50->vb_elt_limit + 64) < draws[0].count)); if (nv50->vbo_user && !(nv50->dirty_3d & (NV50_NEW_3D_ARRAYS | NV50_NEW_3D_VERTEX))) { if (!!nv50->vbo_fifo != nv50->vbo_push_hint) @@ -828,7 +830,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } if (nv50->vbo_fifo) { - nv50_push_vbo(nv50, info, indirect); + nv50_push_vbo(nv50, info, indirect, &draws[0]); goto cleanup; } @@ -873,14 +875,14 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } nv50_draw_elements(nv50, shorten, info, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count, info->index_bias, info->index_size); } else if (unlikely(indirect && indirect->count_from_stream_output)) { nva0_draw_stream_output(nv50, info, indirect); } else { nv50_draw_arrays(nv50, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count); } diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h index 53e13cf82f8..92ef2699e0e 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h @@ -414,7 +414,9 @@ nvc0_cb_bo_push(struct nouveau_context *, /* nvc0_vbo.c */ void nvc0_draw_vbo(struct pipe_context *, const struct pipe_draw_info *, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); void * nvc0_vertex_state_create(struct pipe_context *pipe, @@ -438,9 +440,11 @@ nvc0_video_buffer_create(struct pipe_context *pipe, /* nvc0_push.c */ void nvc0_push_vbo(struct nvc0_context *, const struct pipe_draw_info *, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); void nvc0_push_vbo_indirect(struct nvc0_context *, const struct pipe_draw_info *, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); /* nve4_compute.c */ void nve4_launch_grid(struct pipe_context *, const struct pipe_grid_info *); diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c index 6e84c04cbc0..3270207c703 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c @@ -923,7 +923,9 @@ nvc0_update_prim_restart(struct nvc0_context *nvc0, bool en, uint32_t index) void nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct nvc0_context *nvc0 = nvc0_context(pipe); struct nouveau_pushbuf *push = nvc0->base.pushbuf; @@ -942,7 +944,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, */ nvc0->vbo_push_hint = (!indirect || indirect->count_from_stream_output) && info->index_size && - (nvc0->vb_elt_limit >= (info->count * 2)); + (nvc0->vb_elt_limit >= (draws[0].count * 2)); /* Check whether we want to switch vertex-submission mode. */ if (nvc0->vbo_user && !(nvc0->dirty_3d & (NVC0_NEW_3D_ARRAYS | NVC0_NEW_3D_VERTEX))) { @@ -1061,9 +1063,9 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, if (nvc0->state.vbo_mode) { if (indirect && indirect->buffer) - nvc0_push_vbo_indirect(nvc0, info, indirect); + nvc0_push_vbo_indirect(nvc0, info, indirect, &draws[0]); else - nvc0_push_vbo(nvc0, info, indirect); + nvc0_push_vbo(nvc0, info, indirect, &draws[0]); goto cleanup; } @@ -1104,11 +1106,11 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, shorten = false; nvc0_draw_elements(nvc0, shorten, info, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count, info->index_bias, info->index_size); } else { nvc0_draw_arrays(nvc0, - info->mode, info->start, info->count, + info->mode, draws[0].start, draws[0].count, info->instance_count); } diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c index abf10ac2f3c..5b9e003b267 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c @@ -36,7 +36,8 @@ struct push_context { static void nvc0_push_upload_vertex_ids(struct push_context *, struct nvc0_context *, - const struct pipe_draw_info *); + const struct pipe_draw_info *, + const struct pipe_draw_start_count *draw); static void nvc0_push_context_init(struct nvc0_context *nvc0, struct push_context *ctx) @@ -491,7 +492,8 @@ typedef struct { void nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { /* The strategy here is to just read the commands from the indirect buffer * and do the draws. This is suboptimal, but will only happen in the case @@ -514,18 +516,19 @@ nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *i uint8_t *buf_data = nouveau_resource_map_offset( &nvc0->base, buf, indirect->offset, NOUVEAU_BO_RD); struct pipe_draw_info single = *info; + struct pipe_draw_start_count sdraw = *draw; for (i = 0; i < draw_count; i++, buf_data += indirect->stride) { if (info->index_size) { DrawElementsIndirectCommand *cmd = (void *)buf_data; - single.start = info->start + cmd->firstIndex; - single.count = cmd->count; + sdraw.start = draw->start + cmd->firstIndex; + sdraw.count = cmd->count; single.start_instance = cmd->baseInstance; single.instance_count = cmd->primCount; single.index_bias = cmd->baseVertex; } else { DrawArraysIndirectCommand *cmd = (void *)buf_data; - single.start = cmd->first; - single.count = cmd->count; + sdraw.start = cmd->first; + sdraw.count = cmd->count; single.start_instance = cmd->baseInstance; single.instance_count = cmd->primCount; } @@ -543,7 +546,7 @@ nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *i PUSH_DATA (push, single.drawid + i); } - nvc0_push_vbo(nvc0, &single, NULL); + nvc0_push_vbo(nvc0, &single, NULL, &sdraw); } nouveau_resource_unmap(buf); @@ -553,12 +556,13 @@ nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *i void nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { struct push_context ctx; unsigned i, index_size; unsigned inst_count = info->instance_count; - unsigned vert_count = info->count; + unsigned vert_count = draw->count; unsigned prim; nvc0_push_context_init(nvc0, &ctx); @@ -619,7 +623,7 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info, break; if (unlikely(ctx.need_vertex_id)) - nvc0_push_upload_vertex_ids(&ctx, nvc0, info); + nvc0_push_upload_vertex_ids(&ctx, nvc0, info, draw); if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); @@ -627,17 +631,17 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info, PUSH_DATA (ctx.push, prim); switch (index_size) { case 1: - disp_vertices_i08(&ctx, info->start, vert_count); + disp_vertices_i08(&ctx, draw->start, vert_count); break; case 2: - disp_vertices_i16(&ctx, info->start, vert_count); + disp_vertices_i16(&ctx, draw->start, vert_count); break; case 4: - disp_vertices_i32(&ctx, info->start, vert_count); + disp_vertices_i32(&ctx, draw->start, vert_count); break; default: assert(index_size == 0); - disp_vertices_seq(&ctx, info->start, vert_count); + disp_vertices_seq(&ctx, draw->start, vert_count); break; } PUSH_SPACE(ctx.push, 1); @@ -705,7 +709,8 @@ copy_indices_u32(uint32_t *dst, const uint32_t *elts, uint32_t bias, unsigned n) static void nvc0_push_upload_vertex_ids(struct push_context *ctx, struct nvc0_context *nvc0, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct nouveau_pushbuf *push = ctx->push; @@ -720,7 +725,7 @@ nvc0_push_upload_vertex_ids(struct push_context *ctx, if (!index_size || info->index_bias) index_size = 4; data = (uint32_t *)nouveau_scratch_get(&nvc0->base, - info->count * index_size, &va, &bo); + draw->count * index_size, &va, &bo); BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, NOUVEAU_BO_GART | NOUVEAU_BO_RD, bo); @@ -728,23 +733,23 @@ nvc0_push_upload_vertex_ids(struct push_context *ctx, if (info->index_size) { if (!info->index_bias) { - memcpy(data, ctx->idxbuf, info->count * index_size); + memcpy(data, ctx->idxbuf, draw->count * index_size); } else { switch (info->index_size) { case 1: - copy_indices_u8(data, ctx->idxbuf, info->index_bias, info->count); + copy_indices_u8(data, ctx->idxbuf, info->index_bias, draw->count); break; case 2: - copy_indices_u16(data, ctx->idxbuf, info->index_bias, info->count); + copy_indices_u16(data, ctx->idxbuf, info->index_bias, draw->count); break; default: - copy_indices_u32(data, ctx->idxbuf, info->index_bias, info->count); + copy_indices_u32(data, ctx->idxbuf, info->index_bias, draw->count); break; } } } else { - for (i = 0; i < info->count; ++i) - data[i] = i + (info->start + info->index_bias); + for (i = 0; i < draw->count; ++i) + data[i] = i + (draw->start + info->index_bias); } format = (1 << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) | @@ -781,8 +786,8 @@ nvc0_push_upload_vertex_ids(struct push_context *ctx, BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(1)), 2); else BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(1)), 2); - PUSH_DATAh(push, va + info->count * index_size - 1); - PUSH_DATA (push, va + info->count * index_size - 1); + PUSH_DATAh(push, va + draw->count * index_size - 1); + PUSH_DATA (push, va + draw->count * index_size - 1); #define NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a) \ (((0x80 + (a) * 0x10) / 4) << NVC0_3D_VERTEX_ID_REPLACE_SOURCE__SHIFT) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 1a7a1cb6c91..113653bcc6f 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -61,11 +61,12 @@ panfrost_bo_access_for_stage(enum pipe_shader_type stage) mali_ptr panfrost_get_index_buffer_bounded(struct panfrost_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned *min_index, unsigned *max_index) { struct panfrost_resource *rsrc = pan_resource(info->index.resource); struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); - off_t offset = info->start * info->index_size; + off_t offset = draw->start * info->index_size; bool needs_indices = true; mali_ptr out = 0; @@ -85,8 +86,8 @@ panfrost_get_index_buffer_bounded(struct panfrost_context *ctx, /* Check the cache */ needs_indices = !panfrost_minmax_cache_get(rsrc->index_cache, - info->start, - info->count, + draw->start, + draw->count, min_index, max_index); } else { @@ -94,20 +95,20 @@ panfrost_get_index_buffer_bounded(struct panfrost_context *ctx, const uint8_t *ibuf8 = (const uint8_t *) info->index.user; struct panfrost_ptr T = panfrost_pool_alloc_aligned(&batch->pool, - info->count * info->index_size, + draw->count * info->index_size, info->index_size); - memcpy(T.cpu, ibuf8 + offset, info->count * info->index_size); + memcpy(T.cpu, ibuf8 + offset, draw->count * info->index_size); out = T.gpu; } if (needs_indices) { /* Fallback */ - u_vbuf_get_minmax_index(&ctx->base, info, min_index, max_index); + u_vbuf_get_minmax_index(&ctx->base, info, draw, min_index, max_index); if (!info->has_user_indices) panfrost_minmax_cache_add(rsrc->index_cache, - info->start, info->count, + draw->start, draw->count, *min_index, *max_index); } diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.h b/src/gallium/drivers/panfrost/pan_cmdstream.h index dfc67da876b..a1c5aea2537 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.h +++ b/src/gallium/drivers/panfrost/pan_cmdstream.h @@ -68,6 +68,7 @@ panfrost_emit_vertex_data(struct panfrost_batch *batch, mali_ptr panfrost_get_index_buffer_bounded(struct panfrost_context *ctx, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned *min_index, unsigned *max_index); void diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 2500226fb23..990cce8a2c3 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -228,12 +228,13 @@ panfrost_scissor_culls_everything(struct panfrost_context *ctx) static void panfrost_statistics_record( struct panfrost_context *ctx, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { if (!ctx->active_queries) return; - uint32_t prims = u_prims_for_vertices(info->mode, info->count); + uint32_t prims = u_prims_for_vertices(info->mode, draw->count); ctx->prims_generated += prims; if (!ctx->streamout.num_targets) @@ -331,6 +332,7 @@ static void panfrost_draw_emit_tiler(struct panfrost_batch *batch, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw, void *invocation_template, mali_ptr shared_mem, mali_ptr indices, mali_ptr fs_vary, mali_ptr varyings, @@ -362,7 +364,7 @@ panfrost_draw_emit_tiler(struct panfrost_batch *batch, cfg.index_type = panfrost_translate_index_size(info->index_size); cfg.indices = indices; cfg.base_vertex_offset = info->index_bias - ctx->offset_start; - cfg.index_count = info->count; + cfg.index_count = draw->count; } else { cfg.index_count = indirect && indirect->count_from_stream_output ? pan_so_target(indirect->count_from_stream_output)->offset : @@ -424,7 +426,9 @@ static void panfrost_draw_vbo( struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct panfrost_context *ctx = pan_context(pipe); struct panfrost_device *device = pan_device(ctx->base.screen); @@ -443,7 +447,7 @@ panfrost_draw_vbo( if (info->primitive_restart && info->index_size && info->restart_index != primitive_index) { - util_draw_vbo_without_prim_restart(pipe, info, indirect); + util_draw_vbo_without_prim_restart(pipe, info, indirect, &draws[0]); return; } @@ -452,13 +456,13 @@ panfrost_draw_vbo( assert(ctx->rasterizer != NULL); if (!(ctx->draw_modes & (1 << mode))) { - if (info->count < 4) { + if (draws[0].count < 4) { /* Degenerate case? */ return; } util_primconvert_save_rasterizer_state(ctx->primconvert, &ctx->rasterizer->base); - util_primconvert_draw_vbo(ctx->primconvert, info); + util_primconvert_draw_vbo(ctx->primconvert, info, &draws[0]); return; } @@ -468,7 +472,7 @@ panfrost_draw_vbo( panfrost_batch_set_requirements(batch); /* Take into account a negative bias */ - ctx->vertex_count = info->count + abs(info->index_bias); + ctx->vertex_count = draws[0].count + abs(info->index_bias); ctx->instance_count = info->instance_count; ctx->active_prim = info->mode; @@ -492,7 +496,7 @@ panfrost_draw_vbo( mali_ptr indices = 0; if (info->index_size) { - indices = panfrost_get_index_buffer_bounded(ctx, info, + indices = panfrost_get_index_buffer_bounded(ctx, info, &draws[0], &min_index, &max_index); @@ -500,7 +504,7 @@ panfrost_draw_vbo( vertex_count = max_index - min_index + 1; ctx->offset_start = min_index + info->index_bias; } else { - ctx->offset_start = info->start; + ctx->offset_start = draws[0].start; } /* Encode the padded vertex count */ @@ -510,7 +514,7 @@ panfrost_draw_vbo( else ctx->padded_count = vertex_count; - panfrost_statistics_record(ctx, info); + panfrost_statistics_record(ctx, info, &draws[0]); struct mali_invocation_packed invocation; panfrost_pack_work_groups_compute(&invocation, @@ -529,7 +533,7 @@ panfrost_draw_vbo( /* Fire off the draw itself */ panfrost_draw_emit_vertex(batch, info, &invocation, shared_mem, vs_vary, varyings, vertex.cpu); - panfrost_draw_emit_tiler(batch, info, indirect, &invocation, shared_mem, indices, + panfrost_draw_emit_tiler(batch, info, indirect, &draws[0], &invocation, shared_mem, indices, fs_vary, varyings, pos, psiz, tiler.cpu); panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index bec657022fb..c38a78e04e5 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -333,7 +333,8 @@ static boolean immd_is_good_idea(struct r300_context *r300, ****************************************************************************/ static void r300_draw_arrays_immediate(struct r300_context *r300, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; @@ -344,7 +345,7 @@ static void r300_draw_arrays_immediate(struct r300_context *r300, unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ - unsigned dwords = 4 + info->count * vertex_size; + unsigned dwords = 4 + draw->count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; @@ -375,21 +376,21 @@ static void r300_draw_arrays_immediate(struct r300_context *r300, map[vbi] = (uint32_t*)r300->rws->buffer_map( r300_resource(vbuf->buffer.resource)->buf, r300->cs, PIPE_MAP_READ | PIPE_MAP_UNSYNCHRONIZED); - map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * info->start; + map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * draw->start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } - r300_emit_draw_init(r300, info->mode, info->count-1); + r300_emit_draw_init(r300, info->mode, draw->count-1); BEGIN_CS(dwords); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, info->count * vertex_size); - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (info->count << 16) | + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, draw->count * vertex_size); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (draw->count << 16) | r300_translate_primitive(info->mode)); /* Emit vertices. */ - for (v = 0; v < info->count; v++) { + for (v = 0; v < draw->count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } @@ -496,14 +497,15 @@ static void r300_emit_draw_elements(struct r300_context *r300, } static void r300_draw_elements_immediate(struct r300_context *r300, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { const uint8_t *ptr1; const uint16_t *ptr2; const uint32_t *ptr4; unsigned index_size = info->index_size; - unsigned i, count_dwords = index_size == 4 ? info->count : - (info->count + 1) / 2; + unsigned i, count_dwords = index_size == 4 ? draw->count : + (draw->count + 1) / 2; CS_LOCALS(r300); /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ @@ -520,41 +522,41 @@ static void r300_draw_elements_immediate(struct r300_context *r300, switch (index_size) { case 1: ptr1 = (uint8_t*)info->index.user; - ptr1 += info->start; + ptr1 += draw->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { - for (i = 0; i < info->count-1; i += 2) + for (i = 0; i < draw->count-1; i += 2) OUT_CS(((ptr1[i+1] + info->index_bias) << 16) | (ptr1[i] + info->index_bias)); - if (info->count & 1) + if (draw->count & 1) OUT_CS(ptr1[i] + info->index_bias); } else { - for (i = 0; i < info->count-1; i += 2) + for (i = 0; i < draw->count-1; i += 2) OUT_CS(((ptr1[i+1]) << 16) | (ptr1[i] )); - if (info->count & 1) + if (draw->count & 1) OUT_CS(ptr1[i]); } break; case 2: ptr2 = (uint16_t*)info->index.user; - ptr2 += info->start; + ptr2 += draw->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { - for (i = 0; i < info->count-1; i += 2) + for (i = 0; i < draw->count-1; i += 2) OUT_CS(((ptr2[i+1] + info->index_bias) << 16) | (ptr2[i] + info->index_bias)); - if (info->count & 1) + if (draw->count & 1) OUT_CS(ptr2[i] + info->index_bias); } else { OUT_CS_TABLE(ptr2, count_dwords); @@ -563,14 +565,14 @@ static void r300_draw_elements_immediate(struct r300_context *r300, case 4: ptr4 = (uint32_t*)info->index.user; - ptr4 += info->start; + ptr4 += draw->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300_translate_primitive(info->mode)); if (info->index_bias && !r300->screen->caps.is_r500) { - for (i = 0; i < info->count; i++) + for (i = 0; i < draw->count; i++) OUT_CS(ptr4[i] + info->index_bias); } else { OUT_CS_TABLE(ptr4, count_dwords); @@ -582,14 +584,15 @@ static void r300_draw_elements_immediate(struct r300_context *r300, static void r300_draw_elements(struct r300_context *r300, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, int instance_id) { struct pipe_resource *indexBuffer = info->has_user_indices ? NULL : info->index.resource; unsigned indexSize = info->index_size; struct pipe_resource* orgIndexBuffer = indexBuffer; - unsigned start = info->start; - unsigned count = info->count; + unsigned start = draw->start; + unsigned count = draw->count; boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536; unsigned short_count; @@ -673,12 +676,13 @@ done: static void r300_draw_arrays(struct r300_context *r300, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, int instance_id) { boolean alt_num_verts = r300->screen->caps.is_r500 && - info->count > 65536; - unsigned start = info->start; - unsigned count = info->count; + draw->count > 65536; + unsigned start = draw->start; + unsigned count = draw->count; unsigned short_count; /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */ @@ -713,21 +717,23 @@ static void r300_draw_arrays(struct r300_context *r300, } static void r300_draw_arrays_instanced(struct r300_context *r300, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { int i; for (i = 0; i < info->instance_count; i++) - r300_draw_arrays(r300, info, i); + r300_draw_arrays(r300, info, draw, i); } static void r300_draw_elements_instanced(struct r300_context *r300, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { int i; for (i = 0; i < info->instance_count; i++) - r300_draw_elements(r300, info, i); + r300_draw_elements(r300, info, draw, i); } static unsigned r300_max_vertex_count(struct r300_context *r300) @@ -781,13 +787,16 @@ static unsigned r300_max_vertex_count(struct r300_context *r300) static void r300_draw_vbo(struct pipe_context* pipe, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct r300_context* r300 = r300_context(pipe); struct pipe_draw_info info = *dinfo; + struct pipe_draw_start_count draw = draws[0]; if (r300->skip_rendering || - !u_trim_pipe_prim(info.mode, &info.count)) { + !u_trim_pipe_prim(info.mode, &draw.count)) { return; } @@ -811,23 +820,23 @@ static void r300_draw_vbo(struct pipe_context* pipe, info.max_index = max_count - 1; if (info.instance_count <= 1) { - if (info.count <= 8 && info.has_user_indices) { - r300_draw_elements_immediate(r300, &info); + if (draw.count <= 8 && info.has_user_indices) { + r300_draw_elements_immediate(r300, &info, &draw); } else { - r300_draw_elements(r300, &info, -1); + r300_draw_elements(r300, &info, &draw, -1); } } else { - r300_draw_elements_instanced(r300, &info); + r300_draw_elements_instanced(r300, &info, &draw); } } else { if (info.instance_count <= 1) { - if (immd_is_good_idea(r300, info.count)) { - r300_draw_arrays_immediate(r300, &info); + if (immd_is_good_idea(r300, draw.count)) { + r300_draw_arrays_immediate(r300, &info, &draw); } else { - r300_draw_arrays(r300, &info, -1); + r300_draw_arrays(r300, &info, &draw, -1); } } else { - r300_draw_arrays_instanced(r300, &info); + r300_draw_arrays_instanced(r300, &info, &draw); } } } @@ -840,15 +849,18 @@ static void r300_draw_vbo(struct pipe_context* pipe, /* SW TCL elements, using Draw. */ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct r300_context* r300 = r300_context(pipe); + struct pipe_draw_start_count draw = draws[0]; if (r300->skip_rendering) { return; } - if (!u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + if (!u_trim_pipe_prim(info->mode, &draw.count)) return; if (info->index_size) { @@ -861,7 +873,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, r300_update_derived_state(r300); - draw_vbo(r300->draw, info, NULL); + draw_vbo(r300->draw, info, NULL, &draw, 1); draw_flush(r300->draw); } diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c index d0261a251f7..5135ce7765e 100644 --- a/src/gallium/drivers/r300/r300_render_stencilref.c +++ b/src/gallium/drivers/r300/r300_render_stencilref.c @@ -36,7 +36,9 @@ struct r300_stencilref_context { void (*draw_vbo)(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); uint32_t rs_cull_mode; uint32_t zb_stencilrefmask; @@ -103,18 +105,20 @@ static void r300_stencilref_end(struct r300_context *r300) static void r300_stencilref_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct r300_context *r300 = r300_context(pipe); struct r300_stencilref_context *sr = r300->stencilref_fallback; if (!r300_stencilref_needed(r300)) { - sr->draw_vbo(pipe, info, NULL); + sr->draw_vbo(pipe, info, NULL, draws, num_draws); } else { r300_stencilref_begin(r300); - sr->draw_vbo(pipe, info, NULL); + sr->draw_vbo(pipe, info, NULL, draws, num_draws); r300_stencilref_switch_side(r300); - sr->draw_vbo(pipe, info, NULL); + sr->draw_vbo(pipe, info, NULL, draws, num_draws); r300_stencilref_end(r300); } } diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 4772b448434..7b0696eaefb 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -2053,7 +2053,9 @@ static inline void r600_emit_rasterizer_prim_state(struct r600_context *rctx) } static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_resource *indexbuf = info->has_user_indices ? NULL : info->index.resource; @@ -2073,7 +2075,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info indirect = NULL; } - if (!indirect && !info->count && (index_size || !count_from_so)) { + if (!indirect && !draws[0].count && (index_size || !count_from_so)) { return; } @@ -2135,7 +2137,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info } if (index_size) { - index_offset += info->start * index_size; + index_offset += draws[0].start * index_size; /* Translate 8-bit indices to 16-bit. */ if (unlikely(index_size == 1)) { @@ -2146,7 +2148,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info if (likely(!indirect)) { start = 0; - count = info->count; + count = draws[0].count; } else { /* Have to get start/count from indirect buffer, slow path ahead... */ @@ -2185,16 +2187,16 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info * Note: Instanced rendering in combination with immediate indices hangs. */ if (has_user_indices && (R600_BIG_ENDIAN || indirect || info->instance_count > 1 || - info->count*index_size > 20)) { + draws[0].count*index_size > 20)) { indexbuf = NULL; u_upload_data(ctx->stream_uploader, 0, - info->count * index_size, 256, + draws[0].count * index_size, 256, info->index.user, &index_offset, &indexbuf); has_user_indices = false; } index_bias = info->index_bias; } else { - index_bias = info->start; + index_bias = draws[0].start; } /* Set the index offset and primitive restart. */ @@ -2326,10 +2328,10 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info (VGT_INDEX_16 | (R600_BIG_ENDIAN ? VGT_DMA_SWAP_16_BIT : 0))); if (has_user_indices) { - unsigned size_bytes = info->count*index_size; + unsigned size_bytes = draws[0].count*index_size; unsigned size_dw = align(size_bytes, 4) / 4; radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_IMMD, 1 + size_dw, render_cond_bit)); - radeon_emit(cs, info->count); + radeon_emit(cs, draws[0].count); radeon_emit(cs, V_0287F0_DI_SRC_SEL_IMMEDIATE); radeon_emit_array(cs, info->index.user, size_dw); } else { @@ -2339,7 +2341,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info radeon_emit(cs, PKT3(PKT3_DRAW_INDEX, 3, render_cond_bit)); radeon_emit(cs, va); radeon_emit(cs, (va >> 32UL) & 0xFF); - radeon_emit(cs, info->count); + radeon_emit(cs, draws[0].count); radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA); radeon_emit(cs, PKT3(PKT3_NOP, 0, 0)); radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, @@ -2390,7 +2392,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info if (likely(!indirect)) { radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_AUTO, 1, render_cond_bit)); - radeon_emit(cs, info->count); + radeon_emit(cs, draws[0].count); } else { radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDIRECT, 1, render_cond_bit)); diff --git a/src/gallium/drivers/radeonsi/si_compute_prim_discard.c b/src/gallium/drivers/radeonsi/si_compute_prim_discard.c index e989590121c..01bf52c5a6b 100644 --- a/src/gallium/drivers/radeonsi/si_compute_prim_discard.c +++ b/src/gallium/drivers/radeonsi/si_compute_prim_discard.c @@ -1000,7 +1000,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe for (unsigned i = 0; i < num_draws; i++) { if (count && count + draws[i].count > vert_count_per_subdraw) { /* Submit previous draws. */ - sctx->b.multi_draw(&sctx->b, info, NULL, draws + first_draw, num_draws_split); + sctx->b.draw_vbo(&sctx->b, info, NULL, draws + first_draw, num_draws_split); count = 0; first_draw = i; num_draws_split = 0; @@ -1008,7 +1008,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe if (draws[i].count > vert_count_per_subdraw) { /* Submit just 1 draw. It will be split. */ - sctx->b.multi_draw(&sctx->b, info, NULL, draws + i, 1); + sctx->b.draw_vbo(&sctx->b, info, NULL, draws + i, 1); assert(count == 0); assert(first_draw == i); assert(num_draws_split == 0); @@ -1036,7 +1036,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe split_draw_range.start = base_start + start; split_draw_range.count = MIN2(count - start, vert_count_per_subdraw); - sctx->b.multi_draw(&sctx->b, &split_draw, NULL, &split_draw_range, 1); + sctx->b.draw_vbo(&sctx->b, &split_draw, NULL, &split_draw_range, 1); } } else if (prim == PIPE_PRIM_TRIANGLE_STRIP) { /* No primitive pair can be split, because strips reverse orientation @@ -1047,7 +1047,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe split_draw_range.start = base_start + start; split_draw_range.count = MIN2(count - start, vert_count_per_subdraw + 2); - sctx->b.multi_draw(&sctx->b, &split_draw, NULL, &split_draw_range, 1); + sctx->b.draw_vbo(&sctx->b, &split_draw, NULL, &split_draw_range, 1); if (start == 0 && primitive_restart && sctx->cs_prim_discard_state.current->key.opt.cs_need_correct_orientation) diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index 5b0a72b7886..1a694086733 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -1768,11 +1768,11 @@ static ALWAYS_INLINE bool pd_msg(const char *s) return false; } -static void si_multi_draw_vbo(struct pipe_context *ctx, - const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect, - const struct pipe_draw_start_count *draws, - unsigned num_draws) +static void si_draw_vbo(struct pipe_context *ctx, + const struct pipe_draw_info *info, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct si_context *sctx = (struct si_context *)ctx; struct si_state_rasterizer *rs = sctx->queued.named.rasterizer; @@ -2247,15 +2247,6 @@ return_cleanup: pipe_resource_reference(&indexbuf, NULL); } -static void si_draw_vbo(struct pipe_context *ctx, - const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) -{ - struct pipe_draw_start_count draw = {info->start, info->count}; - - si_multi_draw_vbo(ctx, info, indirect, &draw, 1); -} - static void si_draw_rectangle(struct blitter_context *blitter, void *vertex_elements_cso, blitter_get_vs_func get_vs, int x1, int y1, int x2, int y2, float depth, unsigned num_instances, enum blitter_attrib_type type, @@ -2283,16 +2274,20 @@ static void si_draw_rectangle(struct blitter_context *blitter, void *vertex_elem pipe->bind_vs_state(pipe, si_get_blitter_vs(sctx, type, num_instances)); struct pipe_draw_info info = {}; + struct pipe_draw_start_count draw; + info.mode = SI_PRIM_RECTANGLE_LIST; - info.count = 3; info.instance_count = num_instances; + draw.start = 0; + draw.count = 3; + /* Don't set per-stage shader pointers for VS. */ sctx->shader_pointers_dirty &= ~SI_DESCS_SHADER_MASK(VERTEX); sctx->vertex_buffer_pointer_dirty = false; sctx->vertex_buffer_user_sgprs_dirty = false; - si_draw_vbo(pipe, &info, NULL); + si_draw_vbo(pipe, &info, NULL, &draw, 1); } void si_trace_emit(struct si_context *sctx) @@ -2312,8 +2307,6 @@ void si_trace_emit(struct si_context *sctx) void si_init_draw_functions(struct si_context *sctx) { sctx->b.draw_vbo = si_draw_vbo; - sctx->b.multi_draw = si_multi_draw_vbo; - sctx->blitter->draw_rectangle = si_draw_rectangle; si_init_ia_multi_vgt_param_table(sctx); diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index dd8d9f266fe..ea6262ef717 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -60,7 +60,9 @@ void softpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; @@ -130,7 +132,7 @@ softpipe_draw_vbo(struct pipe_context *pipe, sp->active_statistics_queries > 0); /* draw! */ - draw_vbo(draw, info, indirect); + draw_vbo(draw, info, indirect, draws, num_draws); /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 2c43a4aeea7..a9ae401de80 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -181,7 +181,9 @@ softpipe_set_sampler_views(struct pipe_context *pipe, void softpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); void softpipe_map_texture_surfaces(struct softpipe_context *sp); diff --git a/src/gallium/drivers/svga/svga_draw.h b/src/gallium/drivers/svga/svga_draw.h index 56d5127051d..a353f6a7a1c 100644 --- a/src/gallium/drivers/svga/svga_draw.h +++ b/src/gallium/drivers/svga/svga_draw.h @@ -66,6 +66,7 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl, enum pipe_error svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned count); boolean diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c index b17e301793b..336a1182c39 100644 --- a/src/gallium/drivers/svga/svga_draw_elements.c +++ b/src/gallium/drivers/svga/svga_draw_elements.c @@ -61,6 +61,7 @@ static enum pipe_error translate_indices(struct svga_hwtnl *hwtnl, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, enum pipe_prim_type gen_prim, unsigned orig_nr, unsigned gen_nr, unsigned gen_size, @@ -74,7 +75,7 @@ translate_indices(struct svga_hwtnl *hwtnl, struct pipe_transfer *src_transfer = NULL; struct pipe_transfer *dst_transfer = NULL; const unsigned size = gen_size * gen_nr; - const unsigned offset = info->start * info->index_size; + const unsigned offset = draw->start * info->index_size; const void *src_map = NULL; struct pipe_resource *dst = NULL; void *dst_map = NULL; @@ -215,6 +216,7 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl, enum pipe_error svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned count) { struct pipe_context *pipe = &hwtnl->svga->pipe; @@ -257,7 +259,7 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, if ((gen_type == U_TRANSLATE_MEMCPY) && (info->index_size == gen_size)) { /* No need for translation, just pass through to hardware: */ - unsigned start_offset = info->start * info->index_size; + unsigned start_offset = draw->start * info->index_size; struct pipe_resource *index_buffer = NULL; unsigned index_offset; @@ -269,7 +271,7 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, index_offset /= info->index_size; } else { pipe_resource_reference(&index_buffer, info->index.resource); - index_offset = info->start; + index_offset = draw->start; } assert(index_buffer != NULL); @@ -296,7 +298,7 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, * GL though, as index buffers are typically used only once * there. */ - ret = translate_indices(hwtnl, info, gen_prim, + ret = translate_indices(hwtnl, info, draw, gen_prim, count, gen_nr, gen_size, gen_func, &gen_buf, &gen_offset); if (ret == PIPE_OK) { diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 363661aae1d..61cd75ba169 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -45,11 +45,12 @@ static enum pipe_error retry_draw_range_elements(struct svga_context *svga, const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw, unsigned count) { SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS); - SVGA_RETRY(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, info, count)); + SVGA_RETRY(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, info, draw, count)); SVGA_STATS_TIME_POP(svga_sws(svga)); return PIPE_OK; @@ -217,11 +218,13 @@ get_vcount_from_stream_output(struct svga_context *svga, static void svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct svga_context *svga = svga_context(pipe); enum pipe_prim_type reduced_prim = u_reduced_prim(info->mode); - unsigned count = info->count; + unsigned count = draws[0].count; enum pipe_error ret = 0; boolean needed_swtnl; @@ -251,8 +254,8 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, * always start from 0 for DrawArrays and does not include baseVertex for * DrawIndexed. */ - if (svga->curr.vertex_id_bias != (info->start + info->index_bias)) { - svga->curr.vertex_id_bias = info->start + info->index_bias; + if (svga->curr.vertex_id_bias != (draws[0].start + info->index_bias)) { + svga->curr.vertex_id_bias = draws[0].start + info->index_bias; svga->dirty |= SVGA_NEW_VS_CONSTS; } @@ -270,7 +273,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, if (need_fallback_prim_restart(svga, info)) { enum pipe_error r; - r = util_draw_vbo_without_prim_restart(pipe, info, indirect); + r = util_draw_vbo_without_prim_restart(pipe, info, indirect, &draws[0]); assert(r == PIPE_OK); (void) r; goto done; @@ -299,7 +302,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, /* Avoid leaking the previous hwtnl bias to swtnl */ svga_hwtnl_set_index_bias(svga->hwtnl, 0); - ret = svga_swtnl_draw_vbo(svga, info, indirect); + ret = svga_swtnl_draw_vbo(svga, info, indirect, &draws[0]); } else { if (!svga_update_state_retry(svga, SVGA_STATE_HW_DRAW)) { @@ -351,10 +354,10 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, ret = retry_draw_indirect(svga, info, indirect); } else if (info->index_size) { - ret = retry_draw_range_elements(svga, info, count); + ret = retry_draw_range_elements(svga, info, &draws[0], count); } else { - ret = retry_draw_arrays(svga, info->mode, info->start, count, + ret = retry_draw_arrays(svga, info->mode, draws[0].start, count, info->start_instance, info->instance_count, info->vertices_per_patch); } diff --git a/src/gallium/drivers/svga/svga_swtnl.h b/src/gallium/drivers/svga/svga_swtnl.h index 6bffe95d471..8712b40e18e 100644 --- a/src/gallium/drivers/svga/svga_swtnl.h +++ b/src/gallium/drivers/svga/svga_swtnl.h @@ -40,7 +40,8 @@ void svga_destroy_swtnl( struct svga_context *svga ); enum pipe_error svga_swtnl_draw_vbo(struct svga_context *svga, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); #endif diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c index 4f0319d9bb0..01e9736af13 100644 --- a/src/gallium/drivers/svga/svga_swtnl_backend.c +++ b/src/gallium/drivers/svga/svga_swtnl_backend.c @@ -332,8 +332,10 @@ svga_vbuf_render_draw_elements(struct vbuf_render *render, .index_bias = bias, .min_index = svga_render->min_index, .max_index = svga_render->max_index, + }; + const struct pipe_draw_start_count draw = { .start = 0, - .count = nr_indices + .count = nr_indices, }; assert((svga_render->vbuf_offset - svga_render->vdecl_offset) @@ -350,6 +352,7 @@ svga_vbuf_render_draw_elements(struct vbuf_render *render, */ svga_update_state_retry(svga, SVGA_STATE_HW_DRAW); SVGA_RETRY_CHECK(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, &info, + &draw, nr_indices), retried); if (retried) { svga->swtnl.new_vbuf = TRUE; diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 46fb83502e7..30761d1ae1a 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -39,7 +39,8 @@ enum pipe_error svga_swtnl_draw_vbo(struct svga_context *svga, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw_one) { struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = { 0 }; struct pipe_transfer *ib_transfer = NULL; @@ -113,7 +114,7 @@ svga_swtnl_draw_vbo(struct svga_context *svga, svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer->width0); } - draw_vbo(draw, info, indirect); + draw_vbo(draw, info, indirect, draw_one, 1); draw_flush(svga->swtnl.draw); diff --git a/src/gallium/drivers/swr/swr_draw.cpp b/src/gallium/drivers/swr/swr_draw.cpp index c8765900d32..1fa045326f2 100644 --- a/src/gallium/drivers/swr/swr_draw.cpp +++ b/src/gallium/drivers/swr/swr_draw.cpp @@ -38,13 +38,15 @@ */ static void swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct swr_context *ctx = swr_context(pipe); if (!indirect && !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; if (!swr_check_render_cond(pipe)) @@ -66,14 +68,17 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, swr_update_draw_context(ctx); struct pipe_draw_info resolved_info; + struct pipe_draw_start_count resolved_draw; /* DrawTransformFeedback */ if (indirect && indirect->count_from_stream_output) { // trick copied from softpipe to modify const struct *info memcpy(&resolved_info, (void*)info, sizeof(struct pipe_draw_info)); - resolved_info.count = ctx->so_primCounter * resolved_info.vertices_per_patch; - resolved_info.max_index = resolved_info.count - 1; + resolved_draw.start = draws[0].start; + resolved_draw.count = ctx->so_primCounter * resolved_info.vertices_per_patch; + resolved_info.max_index = resolved_draw.count - 1; info = &resolved_info; indirect = NULL; + draws = &resolved_draw; } if (ctx->vs->pipe.stream_output.num_outputs) { @@ -232,17 +237,17 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, if (info->index_size) ctx->api.pfnSwrDrawIndexedInstanced(ctx->swrContext, swr_convert_prim_topology(info->mode, info->vertices_per_patch), - info->count, + draws[0].count, info->instance_count, - info->start, + draws[0].start, info->index_bias, info->start_instance); else ctx->api.pfnSwrDrawInstanced(ctx->swrContext, swr_convert_prim_topology(info->mode, info->vertices_per_patch), - info->count, + draws[0].count, info->instance_count, - info->start, + draws[0].start, info->start_instance); /* On client-buffer draw, we used client buffer directly, without diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp index 01758f5f910..2318e91ad99 100644 --- a/src/gallium/drivers/swr/swr_state.cpp +++ b/src/gallium/drivers/swr/swr_state.cpp @@ -1158,7 +1158,8 @@ swr_get_last_fe(const struct swr_context *ctx) void swr_update_derived(struct pipe_context *pipe, - const struct pipe_draw_info *p_draw_info) + const struct pipe_draw_info *p_draw_info, + const struct pipe_draw_start_count *draw) { struct swr_context *ctx = swr_context(pipe); struct swr_screen *screen = swr_screen(pipe->screen); @@ -1496,7 +1497,7 @@ swr_update_derived(struct pipe_context *pipe, * revalidate on each draw */ post_update_dirty_flags |= SWR_NEW_VERTEX; - size = info.count * pitch; + size = draw->count * pitch; size = AlignUp(size, 4); /* If size of client memory copy is too large, don't copy. The diff --git a/src/gallium/drivers/swr/swr_state.h b/src/gallium/drivers/swr/swr_state.h index 128b85a892b..50dad0bb07b 100644 --- a/src/gallium/drivers/swr/swr_state.h +++ b/src/gallium/drivers/swr/swr_state.h @@ -130,7 +130,8 @@ struct swr_derived_state { }; void swr_update_derived(struct pipe_context *, - const struct pipe_draw_info * = nullptr); + const struct pipe_draw_info * = nullptr, + const struct pipe_draw_start_count *draw = nullptr); /* * Conversion functions: Convert mesa state defines to SWR. diff --git a/src/gallium/drivers/tegra/tegra_context.c b/src/gallium/drivers/tegra/tegra_context.c index 59313a218f4..9f331e919a5 100644 --- a/src/gallium/drivers/tegra/tegra_context.c +++ b/src/gallium/drivers/tegra/tegra_context.c @@ -47,7 +47,9 @@ tegra_destroy(struct pipe_context *pcontext) static void tegra_draw_vbo(struct pipe_context *pcontext, const struct pipe_draw_info *pinfo, - const struct pipe_draw_indirect_info *pindirect) + const struct pipe_draw_indirect_info *pindirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct tegra_context *context = to_tegra_context(pcontext); struct pipe_draw_indirect_info indirect; @@ -68,7 +70,7 @@ tegra_draw_vbo(struct pipe_context *pcontext, pindirect = &indirect; } - context->gpu->draw_vbo(context->gpu, pinfo, pindirect); + context->gpu->draw_vbo(context->gpu, pinfo, pindirect, draws, num_draws); } static void diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 54ef02a7bbd..95773c8f5bd 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -977,14 +977,15 @@ v3d_emit_gl_shader_state(struct v3d_context *v3d, */ static void v3d_update_primitives_generated_counter(struct v3d_context *v3d, - const struct pipe_draw_info *info) + const struct pipe_draw_info *info, + const struct pipe_draw_start_count *draw) { assert(!v3d->prog.gs); if (!v3d->active_queries) return; - uint32_t prims = u_prims_for_vertices(info->mode, info->count); + uint32_t prims = u_prims_for_vertices(info->mode, draw->count); v3d->prims_generated += prims; } @@ -1085,13 +1086,15 @@ v3d_check_compiled_shaders(struct v3d_context *v3d) static void v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct v3d_context *v3d = v3d_context(pctx); if (!indirect && !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; /* Fall back for weird desktop GL primitive restart values. */ @@ -1109,16 +1112,16 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, } if (info->restart_index != mask) { - util_draw_vbo_without_prim_restart(pctx, info, indirect); + util_draw_vbo_without_prim_restart(pctx, info, indirect, &draws[0]); return; } } if (info->mode >= PIPE_PRIM_QUADS && info->mode <= PIPE_PRIM_POLYGON) { util_primconvert_save_rasterizer_state(v3d->primconvert, &v3d->rasterizer->base); - util_primconvert_draw_vbo(v3d->primconvert, info); + util_primconvert_draw_vbo(v3d->primconvert, info, &draws[0]); perf_debug("Fallback conversion for %d %s vertices\n", - info->count, u_prim_name(info->mode)); + draws[0].count, u_prim_name(info->mode)); return; } @@ -1260,17 +1263,17 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, #endif if (!v3d->prog.gs) - v3d_update_primitives_generated_counter(v3d, info); + v3d_update_primitives_generated_counter(v3d, info, &draws[0]); uint32_t hw_prim_type = v3d_hw_prim_type(info->mode); if (info->index_size) { uint32_t index_size = info->index_size; - uint32_t offset = info->start * index_size; + uint32_t offset = draws[0].start * index_size; struct pipe_resource *prsc; if (info->has_user_indices) { prsc = NULL; u_upload_data(v3d->uploader, 0, - info->count * info->index_size, 4, + draws[0].count * info->index_size, 4, info->index.user, &offset, &prsc); } else { @@ -1315,12 +1318,12 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, prim.enable_primitive_restarts = info->primitive_restart; prim.number_of_instances = info->instance_count; - prim.instance_length = info->count; + prim.instance_length = draws[0].count; } } else { cl_emit(&job->bcl, INDEXED_PRIM_LIST, prim) { prim.index_type = ffs(info->index_size) - 1; - prim.length = info->count; + prim.length = draws[0].count; #if V3D_VERSION >= 40 prim.index_offset = offset; #else /* V3D_VERSION < 40 */ @@ -1351,10 +1354,10 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, indirect->count_from_stream_output : NULL; uint32_t vert_count = so ? v3d_stream_output_target_get_vertex_count(so) : - info->count; + draws[0].count; cl_emit(&job->bcl, VERTEX_ARRAY_INSTANCED_PRIMS, prim) { prim.mode = hw_prim_type | prim_tf_enable; - prim.index_of_first_vertex = info->start; + prim.index_of_first_vertex = draws[0].start; prim.number_of_instances = info->instance_count; prim.instance_length = vert_count; } @@ -1364,11 +1367,11 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, indirect->count_from_stream_output : NULL; uint32_t vert_count = so ? v3d_stream_output_target_get_vertex_count(so) : - info->count; + draws[0].count; cl_emit(&job->bcl, VERTEX_ARRAY_PRIMS, prim) { prim.mode = hw_prim_type | prim_tf_enable; prim.length = vert_count; - prim.index_of_first_vertex = info->start; + prim.index_of_first_vertex = draws[0].start; } } } @@ -1387,7 +1390,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, * needs some clamping to the buffer size. */ for (int i = 0; i < v3d->streamout.num_targets; i++) - v3d->streamout.offsets[i] += info->count; + v3d->streamout.offsets[i] += draws[0].count; if (v3d->zsa && job->zsbuf && v3d->zsa->base.depth.enabled) { struct v3d_resource *rsc = v3d_resource(job->zsbuf->texture); diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c index 6a1c0e36694..7cf73328277 100644 --- a/src/gallium/drivers/vc4/vc4_draw.c +++ b/src/gallium/drivers/vc4/vc4_draw.c @@ -287,28 +287,30 @@ vc4_hw_2116_workaround(struct pipe_context *pctx, int vert_count) static void vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct vc4_context *vc4 = vc4_context(pctx); struct pipe_draw_info local_info; if (!indirect && !info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&info->count)) + !u_trim_pipe_prim(info->mode, (unsigned*)&draws[0].count)) return; if (info->mode >= PIPE_PRIM_QUADS) { if (info->mode == PIPE_PRIM_QUADS && - info->count == 4 && + draws[0].count == 4 && !vc4->rasterizer->base.flatshade) { local_info = *info; local_info.mode = PIPE_PRIM_TRIANGLE_FAN; info = &local_info; } else { util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base); - util_primconvert_draw_vbo(vc4->primconvert, info); + util_primconvert_draw_vbo(vc4->primconvert, info, &draws[0]); perf_debug("Fallback conversion for %d %s vertices\n", - info->count, u_prim_name(info->mode)); + draws[0].count, u_prim_name(info->mode)); return; } } @@ -317,7 +319,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, vc4_predraw_check_textures(pctx, &vc4->verttex); vc4_predraw_check_textures(pctx, &vc4->fragtex); - vc4_hw_2116_workaround(pctx, info->count); + vc4_hw_2116_workaround(pctx, draws[0].count); struct vc4_job *job = vc4_get_job_for_fbo(vc4); @@ -329,7 +331,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, job = vc4_get_job_for_fbo(vc4); } - vc4_get_draw_cl_space(job, info->count); + vc4_get_draw_cl_space(job, draws[0].count); if (vc4->prim_mode != info->mode) { vc4->prim_mode = info->mode; @@ -370,18 +372,18 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, */ if (info->index_size) { uint32_t index_size = info->index_size; - uint32_t offset = info->start * index_size; + uint32_t offset = draws[0].start * index_size; struct pipe_resource *prsc; if (info->index_size == 4) { prsc = vc4_get_shadow_index_buffer(pctx, info, offset, - info->count, &offset); + draws[0].count, &offset); index_size = 2; } else { if (info->has_user_indices) { prsc = NULL; u_upload_data(vc4->uploader, 0, - info->count * index_size, 4, + draws[0].count * index_size, 4, info->index.user, &offset, &prsc); } else { @@ -416,7 +418,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, (index_size == 2 ? VC4_INDEX_BUFFER_U16: VC4_INDEX_BUFFER_U8)); - cl_u32(&bcl, info->count); + cl_u32(&bcl, draws[0].count); cl_u32(&bcl, offset); cl_u32(&bcl, vc4->max_index); @@ -426,8 +428,8 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, if (info->index_size == 4 || info->has_user_indices) pipe_resource_reference(&prsc, NULL); } else { - uint32_t count = info->count; - uint32_t start = info->start; + uint32_t count = draws[0].count; + uint32_t start = draws[0].start; uint32_t extra_index_bias = 0; static const uint32_t max_verts = 65535; diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index 5769e301040..40ba18badba 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -849,7 +849,9 @@ static void virgl_clear_texture(struct pipe_context *ctx, static void virgl_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct virgl_context *vctx = virgl_context(ctx); struct virgl_screen *rs = virgl_screen(ctx->screen); @@ -858,22 +860,22 @@ static void virgl_draw_vbo(struct pipe_context *ctx, if (!indirect && !dinfo->primitive_restart && - !u_trim_pipe_prim(dinfo->mode, (unsigned*)&dinfo->count)) + !u_trim_pipe_prim(dinfo->mode, (unsigned*)&draws[0].count)) return; if (!(rs->caps.caps.v1.prim_mask & (1 << dinfo->mode))) { util_primconvert_save_rasterizer_state(vctx->primconvert, &vctx->rs_state.rs); - util_primconvert_draw_vbo(vctx->primconvert, dinfo); + util_primconvert_draw_vbo(vctx->primconvert, dinfo, &draws[0]); return; } if (info.index_size) { pipe_resource_reference(&ib.buffer, info.has_user_indices ? NULL : info.index.resource); ib.user_buffer = info.has_user_indices ? info.index.user : NULL; ib.index_size = dinfo->index_size; - ib.offset = info.start * ib.index_size; + ib.offset = draws[0].start * ib.index_size; if (ib.user_buffer) { - u_upload_data(vctx->uploader, 0, info.count * ib.index_size, 4, + u_upload_data(vctx->uploader, 0, draws[0].count * ib.index_size, 4, ib.user_buffer, &ib.offset, &ib.buffer); ib.user_buffer = NULL; } @@ -887,7 +889,7 @@ static void virgl_draw_vbo(struct pipe_context *ctx, if (info.index_size) virgl_hw_set_index_buffer(vctx, &ib); - virgl_encoder_draw_vbo(vctx, &info, indirect); + virgl_encoder_draw_vbo(vctx, &info, indirect, &draws[0]); pipe_resource_reference(&ib.buffer, NULL); diff --git a/src/gallium/drivers/virgl/virgl_encode.c b/src/gallium/drivers/virgl/virgl_encode.c index 494eedafa51..f58cc62e53e 100644 --- a/src/gallium/drivers/virgl/virgl_encode.c +++ b/src/gallium/drivers/virgl/virgl_encode.c @@ -708,7 +708,8 @@ int virgl_encoder_set_index_buffer(struct virgl_context *ctx, int virgl_encoder_draw_vbo(struct virgl_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect) + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw) { uint32_t length = VIRGL_DRAW_VBO_SIZE; if (info->mode == PIPE_PRIM_PATCHES) @@ -716,8 +717,8 @@ int virgl_encoder_draw_vbo(struct virgl_context *ctx, if (indirect && indirect->buffer) length = VIRGL_DRAW_VBO_SIZE_INDIRECT; virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_DRAW_VBO, 0, length)); - virgl_encoder_write_dword(ctx->cbuf, info->start); - virgl_encoder_write_dword(ctx->cbuf, info->count); + virgl_encoder_write_dword(ctx->cbuf, draw->start); + virgl_encoder_write_dword(ctx->cbuf, draw->count); virgl_encoder_write_dword(ctx->cbuf, info->mode); virgl_encoder_write_dword(ctx->cbuf, !!info->index_size); virgl_encoder_write_dword(ctx->cbuf, info->instance_count); diff --git a/src/gallium/drivers/virgl/virgl_encode.h b/src/gallium/drivers/virgl/virgl_encode.h index b80d0bcef7d..a1f9a884d48 100644 --- a/src/gallium/drivers/virgl/virgl_encode.h +++ b/src/gallium/drivers/virgl/virgl_encode.h @@ -136,7 +136,8 @@ int virgl_encoder_set_viewport_states(struct virgl_context *ctx, int virgl_encoder_draw_vbo(struct virgl_context *ctx, const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draw); int virgl_encoder_create_surface(struct virgl_context *ctx, diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 2d8502daa1c..7e5350324a5 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -188,6 +188,8 @@ zink_blit(struct pipe_context *pctx, void zink_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *indirect); + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); #endif diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index 0dbe7c73ebe..f359098cb24 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -209,7 +209,9 @@ restart_supported(enum pipe_prim_type mode) void zink_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *dinfo, - const struct pipe_draw_indirect_info *dindirect) + const struct pipe_draw_indirect_info *dindirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws) { struct zink_context *ctx = zink_context(pctx); struct zink_screen *screen = zink_screen(pctx->screen); @@ -224,7 +226,7 @@ zink_draw_vbo(struct pipe_context *pctx, if (dinfo->primitive_restart && !restart_supported(dinfo->mode)) { - util_draw_vbo_without_prim_restart(pctx, dinfo, dindirect); + util_draw_vbo_without_prim_restart(pctx, dinfo, dindirect, &draws[0]); return; } if (dinfo->mode == PIPE_PRIM_QUADS || @@ -232,11 +234,11 @@ zink_draw_vbo(struct pipe_context *pctx, dinfo->mode == PIPE_PRIM_POLYGON || (dinfo->mode == PIPE_PRIM_TRIANGLE_FAN && !screen->have_triangle_fans) || dinfo->mode == PIPE_PRIM_LINE_LOOP) { - if (!u_trim_pipe_prim(dinfo->mode, (unsigned *)&dinfo->count)) + if (!u_trim_pipe_prim(dinfo->mode, (unsigned *)&draws[0].count)) return; util_primconvert_save_rasterizer_state(ctx->primconvert, &rast_state->base); - util_primconvert_draw_vbo(ctx->primconvert, dinfo); + util_primconvert_draw_vbo(ctx->primconvert, dinfo, &draws[0]); return; } @@ -278,11 +280,11 @@ zink_draw_vbo(struct pipe_context *pctx, uint32_t restart_index = util_prim_restart_index_from_size(dinfo->index_size); if ((dinfo->primitive_restart && (dinfo->restart_index != restart_index)) || (!screen->info.have_EXT_index_type_uint8 && dinfo->index_size == 8)) { - util_translate_prim_restart_ib(pctx, dinfo, dindirect, &index_buffer); + util_translate_prim_restart_ib(pctx, dinfo, dindirect, &draws[0], &index_buffer); need_index_buffer_unref = true; } else { if (dinfo->has_user_indices) { - if (!util_upload_index_buffer(pctx, dinfo, &index_buffer, &index_offset, 4)) { + if (!util_upload_index_buffer(pctx, dinfo, &draws[0], &index_buffer, &index_offset, 4)) { debug_printf("util_upload_index_buffer() failed\n"); return; } @@ -523,8 +525,8 @@ zink_draw_vbo(struct pipe_context *pctx, vkCmdDrawIndexedIndirect(batch->cmdbuf, indirect->buffer, dindirect->offset, dindirect->draw_count, dindirect->stride); } else vkCmdDrawIndexed(batch->cmdbuf, - dinfo->count, dinfo->instance_count, - need_index_buffer_unref ? 0 : dinfo->start, dinfo->index_bias, dinfo->start_instance); + draws[0].count, dinfo->instance_count, + need_index_buffer_unref ? 0 : draws[0].start, dinfo->index_bias, dinfo->start_instance); } else { if (so_target && screen->info.tf_props.transformFeedbackDraw) { zink_batch_reference_resource_rw(batch, zink_resource(so_target->counter_buffer), true); @@ -536,7 +538,7 @@ zink_draw_vbo(struct pipe_context *pctx, zink_batch_reference_resource_rw(batch, indirect, false); vkCmdDrawIndirect(batch->cmdbuf, indirect->buffer, dindirect->offset, dindirect->draw_count, dindirect->stride); } else - vkCmdDraw(batch->cmdbuf, dinfo->count, dinfo->instance_count, dinfo->start, dinfo->start_instance); + vkCmdDraw(batch->cmdbuf, draws[0].count, dinfo->instance_count, draws[0].start, dinfo->start_instance); } if (dinfo->index_size > 0 && (dinfo->has_user_indices || need_index_buffer_unref)) diff --git a/src/gallium/frontends/lavapipe/lvp_execute.c b/src/gallium/frontends/lavapipe/lvp_execute.c index 7513312c668..d2bec928089 100644 --- a/src/gallium/frontends/lavapipe/lvp_execute.c +++ b/src/gallium/frontends/lavapipe/lvp_execute.c @@ -60,6 +60,7 @@ struct rendering_state { bool min_samples_dirty; struct pipe_draw_indirect_info indirect_info; struct pipe_draw_info info; + struct pipe_draw_start_count draw; struct pipe_grid_info dispatch_info; struct pipe_framebuffer_state framebuffer; @@ -1302,11 +1303,11 @@ static void handle_draw(struct lvp_cmd_buffer_entry *cmd, { state->info.index_size = 0; state->info.index.resource = NULL; - state->info.start = cmd->u.draw.first_vertex; - state->info.count = cmd->u.draw.vertex_count; + state->draw.start = cmd->u.draw.first_vertex; + state->draw.count = cmd->u.draw.vertex_count; state->info.start_instance = cmd->u.draw.first_instance; state->info.instance_count = cmd->u.draw.instance_count; - state->pctx->draw_vbo(state->pctx, &state->info, NULL); + state->pctx->draw_vbo(state->pctx, &state->info, NULL, &state->draw, 1); } static void handle_set_viewport(struct lvp_cmd_buffer_entry *cmd, @@ -1845,8 +1846,8 @@ static void handle_draw_indexed(struct lvp_cmd_buffer_entry *cmd, state->info.max_index = ~0; state->info.index_size = state->index_size; state->info.index.resource = state->index_buffer; - state->info.start = (state->index_offset / state->index_size) + cmd->u.draw_indexed.first_index; - state->info.count = cmd->u.draw_indexed.index_count; + state->draw.start = (state->index_offset / state->index_size) + cmd->u.draw_indexed.first_index; + state->draw.count = cmd->u.draw_indexed.index_count; state->info.start_instance = cmd->u.draw_indexed.first_instance; state->info.instance_count = cmd->u.draw_indexed.instance_count; state->info.index_bias = cmd->u.draw_indexed.vertex_offset; @@ -1858,7 +1859,7 @@ static void handle_draw_indexed(struct lvp_cmd_buffer_entry *cmd, state->info.restart_index = 0xffff; } - state->pctx->draw_vbo(state->pctx, &state->info, NULL); + state->pctx->draw_vbo(state->pctx, &state->info, NULL, &state->draw, 1); } static void handle_draw_indirect(struct lvp_cmd_buffer_entry *cmd, @@ -1875,7 +1876,7 @@ static void handle_draw_indirect(struct lvp_cmd_buffer_entry *cmd, state->indirect_info.stride = cmd->u.draw_indirect.stride; state->indirect_info.draw_count = cmd->u.draw_indirect.draw_count; state->indirect_info.buffer = cmd->u.draw_indirect.buffer->bo; - state->pctx->draw_vbo(state->pctx, &state->info, &state->indirect_info); + state->pctx->draw_vbo(state->pctx, &state->info, &state->indirect_info, &state->draw, 1); } static void handle_index_buffer(struct lvp_cmd_buffer_entry *cmd, diff --git a/src/gallium/frontends/nine/device9.c b/src/gallium/frontends/nine/device9.c index 3f8643ef793..30791ab914a 100644 --- a/src/gallium/frontends/nine/device9.c +++ b/src/gallium/frontends/nine/device9.c @@ -3090,6 +3090,7 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This, struct pipe_stream_output_info so; struct pipe_stream_output_target *target; struct pipe_draw_info draw; + struct pipe_draw_start_count sc; struct pipe_box box; bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t); unsigned offsets[1] = {0}; @@ -3170,13 +3171,13 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This, } draw.mode = PIPE_PRIM_POINTS; - draw.count = VertexCount; + sc.count = VertexCount; draw.start_instance = 0; draw.primitive_restart = FALSE; draw.restart_index = 0; draw.instance_count = 1; draw.index_size = 0; - draw.start = 0; + sc.start = 0; draw.index_bias = 0; draw.min_index = 0; draw.max_index = VertexCount - 1; @@ -3184,7 +3185,7 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This, pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets); - pipe_sw->draw_vbo(pipe_sw, &draw, NULL); + pipe_sw->draw_vbo(pipe_sw, &draw, NULL, &sc, 1); pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0); pipe_sw->stream_output_target_destroy(pipe_sw, target); diff --git a/src/gallium/frontends/nine/nine_state.c b/src/gallium/frontends/nine/nine_state.c index c6c44bbba7b..5fa90aaad21 100644 --- a/src/gallium/frontends/nine/nine_state.c +++ b/src/gallium/frontends/nine/nine_state.c @@ -2307,10 +2307,11 @@ CSMT_ITEM_NO_WAIT(nine_context_clear_fb, static inline void init_draw_info(struct pipe_draw_info *info, + struct pipe_draw_start_count *draw, struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count) { info->mode = d3dprimitivetype_to_pipe_prim(type); - info->count = prim_count_to_vertex_count(type, count); + draw->count = prim_count_to_vertex_count(type, count); info->start_instance = 0; info->instance_count = 1; if (dev->context.stream_instancedata_mask & dev->context.stream_usage_mask) @@ -2327,18 +2328,19 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_primitive, { struct nine_context *context = &device->context; struct pipe_draw_info info; + struct pipe_draw_start_count draw; nine_update_state(device); - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); info.index_size = 0; - info.start = StartVertex; + draw.start = StartVertex; info.index_bias = 0; - info.min_index = info.start; - info.max_index = info.count - 1; + info.min_index = draw.start; + info.max_index = draw.count - 1; info.index.resource = NULL; - context->pipe->draw_vbo(context->pipe, &info, NULL); + context->pipe->draw_vbo(context->pipe, &info, NULL, &draw, 1); } CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, @@ -2351,12 +2353,13 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, { struct nine_context *context = &device->context; struct pipe_draw_info info; + struct pipe_draw_start_count draw; nine_update_state(device); - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); info.index_size = context->index_size; - info.start = context->index_offset / context->index_size + StartIndex; + draw.start = context->index_offset / context->index_size + StartIndex; info.index_bias = BaseVertexIndex; info.index_bounds_valid = true; /* These don't include index bias: */ @@ -2364,7 +2367,7 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive, info.max_index = MinVertexIndex + NumVertices - 1; info.index.resource = context->idxbuf; - context->pipe->draw_vbo(context->pipe, &info, NULL); + context->pipe->draw_vbo(context->pipe, &info, NULL, &draw, 1); } CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf, @@ -2374,20 +2377,21 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_primitive_from_vtxbuf, { struct nine_context *context = &device->context; struct pipe_draw_info info; + struct pipe_draw_start_count draw; nine_update_state(device); - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); info.index_size = 0; - info.start = 0; + draw.start = 0; info.index_bias = 0; info.min_index = 0; - info.max_index = info.count - 1; + info.max_index = draw.count - 1; info.index.resource = NULL; context->pipe->set_vertex_buffers(context->pipe, 0, 1, vtxbuf); - context->pipe->draw_vbo(context->pipe, &info, NULL); + context->pipe->draw_vbo(context->pipe, &info, NULL, &draw, 1); } CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, @@ -2403,12 +2407,13 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, { struct nine_context *context = &device->context; struct pipe_draw_info info; + struct pipe_draw_start_count draw; nine_update_state(device); - init_draw_info(&info, device, PrimitiveType, PrimitiveCount); + init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount); info.index_size = index_size; - info.start = index_offset / info.index_size; + draw.start = index_offset / info.index_size; info.index_bias = 0; info.index_bounds_valid = true; info.min_index = MinVertexIndex; @@ -2421,7 +2426,7 @@ CSMT_ITEM_NO_WAIT(nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf, context->pipe->set_vertex_buffers(context->pipe, 0, 1, vbuf); - context->pipe->draw_vbo(context->pipe, &info, NULL); + context->pipe->draw_vbo(context->pipe, &info, NULL, &draw, 1); } CSMT_ITEM_NO_WAIT(nine_context_resource_copy_region, diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 05aca7ef033..74a3d49d2dd 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -108,45 +108,38 @@ struct pipe_context { * VBO drawing */ /*@{*/ - void (*draw_vbo)(struct pipe_context *pipe, - const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect); - /** - * Direct multi draw specifying "start" and "count" for each draw. + * Multi draw. * - * For indirect multi draws, use draw_vbo, which supports them through - * "info->indirect". + * For indirect multi draws, num_draws is 1 and indirect->draw_count + * is used instead. * - * Differences against draw_vbo: - * - "start" and "count" are taken from "draws", not "info" - * - "info->has_user_indices" is always false - * - "info->indirect" and "info->count_from_stream_output" are always NULL + * Caps: + * - PIPE_CAP_MULTI_DRAW: Direct multi draws + * - PIPE_CAP_MULTI_DRAW_INDIRECT: Indirect multi draws + * - PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: Indirect draw count * - * Differences against glMultiDraw: - * - "info->draw_id" is 0 and should be 0 for every draw - * (we could make this configurable) - * - "info->index_bias" is always constant due to hardware performance - * concerns (this is very important) and the lack of apps using - * glMultiDrawElementsBaseVertex. + * Differences against glMultiDraw and glMultiMode: + * - "info->mode" and "info->index_bias" are always constant due to the lack + * of hardware support and CPU performance concerns. Only start and count + * vary. + * - if "info->increment_draw_id" is false, draw_id doesn't change between + * draws * - * The main use case is to optimize applications that submit many - * back-to-back draws or when mesa/main or st/mesa eliminates redundant - * state changes, resulting in back-to-back draws in the driver. It requires - * DrawID = 0 for every draw. u_threaded_context is the module that converts - * back-to-back draws into a multi draw. It's done trivially by looking - * ahead within a gallium command buffer and collapsing draws. + * Direct multi draws are also generated by u_threaded_context, which looks + * ahead in gallium command buffers and merges single draws. * * \param pipe context * \param info draw info - * \param draws array of (start, count) pairs - * \param num_draws number of draws + * \param indirect indirect multi draws + * \param draws array of (start, count) pairs for direct draws + * \param num_draws number of direct draws; 1 for indirect multi draws */ - void (*multi_draw)(struct pipe_context *pipe, - const struct pipe_draw_info *info, - const struct pipe_draw_indirect_info *indirect, - const struct pipe_draw_start_count *draws, - unsigned num_draws); + void (*draw_vbo)(struct pipe_context *pipe, + const struct pipe_draw_info *info, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count *draws, + unsigned num_draws); /*@}*/ /** diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 705541ae823..2f4678b0a7d 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -749,14 +749,6 @@ struct pipe_draw_start_count { */ struct pipe_draw_info { - /** - * Direct draws: start is the index of the first vertex - * Non-indexed indirect draws: not used - * Indexed indirect draws: start is added to the indirect start. - */ - unsigned start; - unsigned count; /**< number of vertices */ - enum pipe_prim_type mode:8; /**< the mode of the primitive */ ubyte vertices_per_patch; /**< the number of vertices per patch */ ubyte index_size; /**< if 0, the draw is not indexed. */ diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c index dae7b45a9d6..a11286cc31f 100644 --- a/src/gallium/tests/graw/tri-instanced.c +++ b/src/gallium/tests/graw/tri-instanced.c @@ -187,6 +187,7 @@ static void draw( void ) { union pipe_color_union clear_color = { {1,0,1,1} }; struct pipe_draw_info info; + struct pipe_draw_start_count draw; ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0); @@ -194,8 +195,8 @@ static void draw( void ) util_draw_init_info(&info); info.index_size = draw_elements ? 2 : 0; info.mode = PIPE_PRIM_TRIANGLES; - info.start = 0; - info.count = 3; + draw.start = 0; + draw.count = 3; /* draw NUM_INST triangles */ info.instance_count = NUM_INST; @@ -209,7 +210,7 @@ static void draw( void ) indices); } - ctx->draw_vbo(ctx, &info, NULL); + ctx->draw_vbo(ctx, &info, NULL, &draw, 1); pipe_resource_reference(&info.index.resource, NULL); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index b80052ce186..9f66614dafc 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -223,31 +223,34 @@ st_draw_vbo(struct gl_context *ctx, /* do actual drawing */ for (i = 0; i < nr_prims; i++) { - info.count = prims[i].count; + struct pipe_draw_start_count draw; + + draw.count = prims[i].count; /* Skip no-op draw calls. */ - if (!info.count) + if (!draw.count) continue; + draw.start = start + prims[i].start; + info.mode = translate_prim(ctx, prims[i].mode); - info.start = start + prims[i].start; info.index_bias = prims[i].basevertex; info.drawid = prims[i].draw_id; if (!ib) { - info.min_index = info.start; - info.max_index = info.start + info.count - 1; + info.min_index = draw.start; + info.max_index = draw.start + draw.count - 1; } if (ST_DEBUG & DEBUG_DRAW) { debug_printf("st/draw: mode %s start %u count %u index_size %d\n", u_prim_name(info.mode), - info.start, - info.count, + draw.start, + draw.count, info.index_size); } /* Don't call u_trim_pipe_prim. Drivers should do it if they need it. */ - cso_draw_vbo(st->cso_context, &info, NULL); + cso_draw_vbo(st->cso_context, &info, NULL, draw); } } @@ -265,13 +268,13 @@ st_indirect_draw_vbo(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_draw_info info; struct pipe_draw_indirect_info indirect; + struct pipe_draw_start_count draw = {0}; assert(stride); prepare_draw(st, ctx); memset(&indirect, 0, sizeof(indirect)); util_draw_init_info(&info); - info.start = 0; /* index offset / index size */ info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ if (ib) { @@ -282,7 +285,7 @@ st_indirect_draw_vbo(struct gl_context *ctx, info.index_size = 1 << ib->index_size_shift; info.index.resource = st_buffer_object(bufobj)->buffer; - info.start = pointer_to_offset(ib->ptr) >> ib->index_size_shift; + draw.start = pointer_to_offset(ib->ptr) >> ib->index_size_shift; /* Primitive restart is not handled by the VBO module in this case. */ setup_primitive_restart(ctx, &info); @@ -307,7 +310,7 @@ st_indirect_draw_vbo(struct gl_context *ctx, indirect.draw_count = 1; for (i = 0; i < draw_count; i++) { info.drawid = i; - cso_draw_vbo(st->cso_context, &info, &indirect); + cso_draw_vbo(st->cso_context, &info, &indirect, draw); indirect.offset += stride; } } else { @@ -318,7 +321,7 @@ st_indirect_draw_vbo(struct gl_context *ctx, st_buffer_object(indirect_draw_count)->buffer; indirect.indirect_draw_count_offset = indirect_draw_count_offset; } - cso_draw_vbo(st->cso_context, &info, &indirect); + cso_draw_vbo(st->cso_context, &info, &indirect, draw); } } @@ -330,12 +333,12 @@ st_draw_transform_feedback(struct gl_context *ctx, GLenum mode, struct st_context *st = st_context(ctx); struct pipe_draw_info info; struct pipe_draw_indirect_info indirect; + struct pipe_draw_start_count draw = {0}; prepare_draw(st, ctx); memset(&indirect, 0, sizeof(indirect)); util_draw_init_info(&info); - info.start = 0; /* index offset / index size */ info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */ info.mode = translate_prim(ctx, mode); info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; @@ -351,7 +354,7 @@ st_draw_transform_feedback(struct gl_context *ctx, GLenum mode, if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &indirect)) return; - cso_draw_vbo(st->cso_context, &info, &indirect); + cso_draw_vbo(st->cso_context, &info, &indirect, draw); } void diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 4441e683049..ef78f824139 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -425,21 +425,24 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* draw here */ for (i = 0; i < nr_prims; i++) { - info.count = prims[i].count; + struct pipe_draw_start_count d; - if (!info.count) + d.count = prims[i].count; + + if (!d.count) continue; + d.start = start + prims[i].start; + info.mode = prims[i].mode; - info.start = start + prims[i].start; info.index_bias = prims[i].basevertex; info.drawid = prims[i].draw_id; if (!ib) { - info.min_index = info.start; - info.max_index = info.start + info.count - 1; + info.min_index = d.start; + info.max_index = d.start + d.count - 1; } - draw_vbo(draw, &info, NULL); + draw_vbo(draw, &info, NULL, &d, 1); } /* unmap images */