panfrost: Fix indirect draws when vertex or instance count is 0

In that case we should just skip the vertex/tiler jobs as done in the
direct draw path.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Acked-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12589>
This commit is contained in:
Boris Brezillon 2021-08-24 10:48:40 +02:00 committed by Marge Bot
parent 7682a5de04
commit 43760a7b2f
2 changed files with 50 additions and 26 deletions

View File

@ -1,6 +1,5 @@
# The shader assisted indirect draw path is buggy. The shader assisted indirect
# draw path is disabled outside of CI due to these conformance issues.
KHR-GLES31.core.compute_shader.pipeline-gen-draw-commands,Crash
KHR-GLES31.core.draw_indirect.advanced-primitiveRestart-elements,Fail
KHR-GLES31.core.draw_indirect.advanced-twoPass-transformFeedback-arrays,Crash
KHR-GLES31.core.draw_indirect.advanced-twoPass-transformFeedback-arrays,Fail
KHR-GLES31.core.draw_indirect.advanced-twoPass-transformFeedback-elements,Fail

View File

@ -801,6 +801,21 @@ update_jobs(struct indirect_draw_shader_builder *builder)
update_job(builder, MALI_JOB_TYPE_TILER);
}
static void
set_null_job(struct indirect_draw_shader_builder *builder,
nir_ssa_def *job_ptr)
{
nir_builder *b = &builder->b;
nir_ssa_def *w4 = get_address_imm(b, job_ptr, WORD(4));
nir_ssa_def *val = load_global(b, w4, 1, 32);
/* Set job type to NULL (AKA NOOP) */
val = nir_ior(b, nir_iand_imm(b, val, 0xffffff01),
nir_imm_int(b, MALI_JOB_TYPE_NULL << 1));
store_global(b, w4, val, 1);
}
static void
get_instance_size(struct indirect_draw_shader_builder *builder)
{
@ -928,34 +943,44 @@ patch(struct indirect_draw_shader_builder *builder)
assert(builder->draw.vertex_count->num_components);
get_instance_size(builder);
nir_ssa_def *num_vertices =
nir_imul(b, builder->draw.vertex_count, builder->draw.instance_count);
builder->instance_size.padded =
get_padded_count(b, builder->instance_size.raw,
&builder->instance_size.packed);
IF (nir_ieq(b, num_vertices, nir_imm_int(b, 0))) {
/* If there's nothing to draw, turn the vertex/tiler jobs into
* null jobs.
*/
set_null_job(builder, builder->jobs.vertex_job);
set_null_job(builder, builder->jobs.tiler_job);
} ELSE {
get_instance_size(builder);
update_varyings(builder);
update_jobs(builder);
update_vertex_attribs(builder);
builder->instance_size.padded =
get_padded_count(b, builder->instance_size.raw,
&builder->instance_size.packed);
IF (nir_ine(b, builder->jobs.first_vertex_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.first_vertex_sysval,
builder->jobs.offset_start, 1);
update_varyings(builder);
update_jobs(builder);
update_vertex_attribs(builder);
IF (nir_ine(b, builder->jobs.first_vertex_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.first_vertex_sysval,
builder->jobs.offset_start, 1);
} ENDIF
IF (nir_ine(b, builder->jobs.base_vertex_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.base_vertex_sysval,
index_size ?
builder->draw.index_bias :
nir_imm_int(b, 0),
1);
} ENDIF
IF (nir_ine(b, builder->jobs.base_instance_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.base_instance_sysval,
builder->draw.start_instance, 1);
} ENDIF
} ENDIF
IF (nir_ine(b, builder->jobs.base_vertex_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.base_vertex_sysval,
index_size ?
builder->draw.index_bias :
nir_imm_int(b, 0),
1);
} ENDIF
IF (nir_ine(b, builder->jobs.base_instance_sysval, nir_imm_int64(b, 0))) {
store_global(b, builder->jobs.base_instance_sysval,
builder->draw.start_instance, 1);
} ENDIF
}
/* Search the min/max index in the range covered by the indirect draw call */