radeonsi: implement multi_draw for compute-based primitive culling

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7056>
This commit is contained in:
Marek Olšák
2020-10-09 18:58:14 -04:00
committed by Marge Bot
parent cc24ec8c07
commit a44868beda
3 changed files with 58 additions and 18 deletions
@@ -956,7 +956,8 @@ static bool si_check_ring_space(struct si_context *sctx, unsigned out_indexbuf_s
enum si_prim_discard_outcome
si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe_draw_info *info,
const struct pipe_draw_start_count *draws,
unsigned num_draws, bool primitive_restart)
unsigned num_draws, bool primitive_restart,
unsigned total_count)
{
/* If the compute shader compilation isn't finished, this returns false. */
if (!si_shader_select_prim_discard_cs(sctx, info, primitive_restart))
@@ -967,7 +968,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe
struct radeon_cmdbuf *gfx_cs = sctx->gfx_cs;
unsigned prim = info->mode;
unsigned count = draws[0].count;
unsigned count = total_count;
unsigned instance_count = info->instance_count;
unsigned num_prims_per_instance = u_decomposed_prims_for_vertices(prim, count);
unsigned num_prims = num_prims_per_instance * instance_count;
@@ -981,16 +982,54 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe
if (ring_full && num_prims > split_prims_draw_level &&
instance_count == 1 && /* TODO: support splitting instanced draws */
(1 << prim) & ((1 << PIPE_PRIM_TRIANGLES) | (1 << PIPE_PRIM_TRIANGLE_STRIP))) {
/* Split draws. */
unsigned vert_count_per_subdraw = 0;
if (prim == PIPE_PRIM_TRIANGLES)
vert_count_per_subdraw = split_prims_draw_level * 3;
else if (prim == PIPE_PRIM_TRIANGLE_STRIP)
vert_count_per_subdraw = split_prims_draw_level;
else
unreachable("shouldn't get here");
/* Split multi draws first. */
if (num_draws > 1) {
unsigned count = 0;
unsigned first_draw = 0;
unsigned num_draws_split = 0;
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, draws + first_draw, num_draws_split);
count = 0;
first_draw = i;
num_draws_split = 0;
}
if (draws[i].count > vert_count_per_subdraw) {
/* Submit just 1 draw. It will be split. */
sctx->b.multi_draw(&sctx->b, info, draws + i, 1);
assert(count == 0);
assert(first_draw == i);
assert(num_draws_split == 0);
first_draw = i + 1;
continue;
}
count += draws[i].count;
num_draws_split++;
}
return SI_PRIM_DISCARD_MULTI_DRAW_SPLIT;
}
/* Split single draws if splitting multi draws isn't enough. */
struct pipe_draw_info split_draw = *info;
struct pipe_draw_start_count split_draw_range = draws[0];
unsigned base_start = split_draw_range.start;
split_draw.primitive_restart = primitive_restart;
unsigned base_start = split_draw_range.start;
if (prim == PIPE_PRIM_TRIANGLES) {
unsigned vert_count_per_subdraw = split_prims_draw_level * 3;
assert(vert_count_per_subdraw < count);
for (unsigned start = 0; start < count; start += vert_count_per_subdraw) {
@@ -1004,8 +1043,6 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe
* for odd primitives. */
STATIC_ASSERT(split_prims_draw_level % 2 == 0);
unsigned vert_count_per_subdraw = split_prims_draw_level;
for (unsigned start = 0; start < count - 2; start += vert_count_per_subdraw) {
split_draw_range.start = base_start + start;
split_draw_range.count = MIN2(count - start, vert_count_per_subdraw + 2);
@@ -1017,8 +1054,6 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe
sctx->preserve_prim_restart_gds_at_flush = true;
}
sctx->preserve_prim_restart_gds_at_flush = false;
} else {
assert(0);
}
return SI_PRIM_DISCARD_DRAW_SPLIT;
@@ -1031,7 +1066,7 @@ si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe
return SI_PRIM_DISCARD_DISABLED;
}
unsigned num_subdraws = DIV_ROUND_UP(num_prims, SPLIT_PRIMS_PACKET_LEVEL);
unsigned num_subdraws = DIV_ROUND_UP(num_prims, SPLIT_PRIMS_PACKET_LEVEL) * num_draws;
unsigned need_compute_dw = 11 /* shader */ + 34 /* first draw */ +
24 * (num_subdraws - 1) + /* subdraws */
30; /* leave some space at the end */
+3 -1
View File
@@ -1451,13 +1451,15 @@ enum si_prim_discard_outcome
SI_PRIM_DISCARD_ENABLED,
SI_PRIM_DISCARD_DISABLED,
SI_PRIM_DISCARD_DRAW_SPLIT,
SI_PRIM_DISCARD_MULTI_DRAW_SPLIT,
};
void si_build_prim_discard_compute_shader(struct si_shader_context *ctx);
enum si_prim_discard_outcome
si_prepare_prim_discard_or_split_draw(struct si_context *sctx, const struct pipe_draw_info *info,
const struct pipe_draw_start_count *draws,
unsigned num_draws, bool primitive_restart);
unsigned num_draws, bool primitive_restart,
unsigned total_count);
void si_compute_signal_gfx(struct si_context *sctx);
void si_dispatch_prim_discard_cs_and_draw(struct si_context *sctx,
const struct pipe_draw_info *info,
+9 -6
View File
@@ -941,12 +941,13 @@ static void si_emit_draw_packets(struct si_context *sctx, const struct pipe_draw
if (index_size) {
if (dispatch_prim_discard_cs) {
index_va += draws[0].start * original_index_size;
index_max_size = MIN2(index_max_size, draws[0].count);
for (unsigned i = 0; i < num_draws; i++) {
uint64_t va = index_va + draws[0].start * original_index_size;
si_dispatch_prim_discard_cs_and_draw(sctx, info, draws[0].count,
original_index_size, base_vertex,
index_va, index_max_size);
si_dispatch_prim_discard_cs_and_draw(sctx, info, draws[i].count,
original_index_size, base_vertex,
va, MIN2(index_max_size, draws[i].count));
}
return;
}
@@ -1998,7 +1999,7 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
(si_all_vs_resources_read_only(sctx, index_size ? indexbuf : NULL) ||
pd_msg("write reference"))) {
switch (si_prepare_prim_discard_or_split_draw(sctx, info, draws, num_draws,
primitive_restart)) {
primitive_restart, total_direct_count)) {
case SI_PRIM_DISCARD_ENABLED:
original_index_size = index_size;
prim_discard_cs_instancing = instance_count > 1;
@@ -2017,6 +2018,8 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
case SI_PRIM_DISCARD_DRAW_SPLIT:
sctx->compute_num_verts_rejected -= total_direct_count;
goto return_cleanup;
case SI_PRIM_DISCARD_MULTI_DRAW_SPLIT:
goto return_cleanup;
}
}