Module: Mesa
Branch: main
Commit: 43760a7b2f26ac040cf300435a73dd3d436d83fe
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=43760a7b2f26ac040cf300435a73dd3d436d83fe

Author: Boris Brezillon <[email protected]>
Date:   Tue Aug 24 10:48:40 2021 +0200

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 <[email protected]>
Acked-by: Alyssa Rosenzweig <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12589>

---

 .../panfrost/ci/deqp-panfrost-g52-fails.txt        |  3 +-
 src/panfrost/lib/pan_indirect_draw.c               | 73 +++++++++++++++-------
 2 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/src/gallium/drivers/panfrost/ci/deqp-panfrost-g52-fails.txt 
b/src/gallium/drivers/panfrost/ci/deqp-panfrost-g52-fails.txt
index 9998751ea0b..c9c0d68cf06 100644
--- a/src/gallium/drivers/panfrost/ci/deqp-panfrost-g52-fails.txt
+++ b/src/gallium/drivers/panfrost/ci/deqp-panfrost-g52-fails.txt
@@ -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
diff --git a/src/panfrost/lib/pan_indirect_draw.c 
b/src/panfrost/lib/pan_indirect_draw.c
index 531d3f4e43c..cd99ad4a2b1 100644
--- a/src/panfrost/lib/pan_indirect_draw.c
+++ b/src/panfrost/lib/pan_indirect_draw.c
@@ -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);
-
-        builder->instance_size.padded =
-                get_padded_count(b, builder->instance_size.raw,
-                                 &builder->instance_size.packed);
+        nir_ssa_def *num_vertices =
+                nir_imul(b, builder->draw.vertex_count, 
builder->draw.instance_count);
 
-        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_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);
+
+                builder->instance_size.padded =
+                        get_padded_count(b, builder->instance_size.raw,
+                                         &builder->instance_size.packed);
+
+                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_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);
+                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
-
 }
 
 /* Search the min/max index in the range covered by the indirect draw call */

Reply via email to