Mesa (main): radv, ac/nir: Fix multiview layer export for mesh shaders.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue May 31 08:24:00 UTC 2022


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

Author: Timur Kristóf <timur.kristof at gmail.com>
Date:   Fri May 13 21:32:12 2022 +0200

radv, ac/nir: Fix multiview layer export for mesh shaders.

Unfortunately, radv_lower_multiview is not suitable for mesh shaders
because it can't know the mapping between API mesh shader
invocations and output primitives.

Additionally, when lowering view id to layer, it must be created
as a per-primitive PS input.

Fixes: d32656bc65a7c0165e53d551e23462d626bbf870
Signed-off-by: Timur Kristóf <timur.kristof at gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16504>

---

 src/amd/common/ac_nir.h           |  3 ++-
 src/amd/common/ac_nir_lower_ngg.c | 16 +++++++++++++++-
 src/amd/vulkan/radv_pipeline.c    | 12 ++++++++----
 src/amd/vulkan/radv_shader.c      | 11 +++++++----
 src/amd/vulkan/radv_shader.h      |  2 +-
 src/amd/vulkan/radv_shader_info.c |  6 ++++++
 6 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/src/amd/common/ac_nir.h b/src/amd/common/ac_nir.h
index 3ef13c79687..61f9fc18af2 100644
--- a/src/amd/common/ac_nir.h
+++ b/src/amd/common/ac_nir.h
@@ -125,7 +125,8 @@ ac_nir_lower_ngg_gs(nir_shader *shader,
 
 void
 ac_nir_lower_ngg_ms(nir_shader *shader,
-                    unsigned wave_size);
+                    unsigned wave_size,
+                    bool multiview);
 
 void
 ac_nir_apply_first_task_to_task_shader(nir_shader *shader);
diff --git a/src/amd/common/ac_nir_lower_ngg.c b/src/amd/common/ac_nir_lower_ngg.c
index 49abaa99b4f..8ab79e4580e 100644
--- a/src/amd/common/ac_nir_lower_ngg.c
+++ b/src/amd/common/ac_nir_lower_ngg.c
@@ -112,6 +112,9 @@ typedef struct
 
    nir_ssa_def *workgroup_index;
 
+   /* True if the lowering needs to insert the layer output. */
+   bool insert_layer_output;
+
    struct {
       /* Bitmask of components used: 4 bits per slot, 1 bit per component. */
       uint32_t components_mask;
@@ -2535,6 +2538,15 @@ emit_ms_finale(nir_builder *b, lower_ngg_ms_state *s)
       ms_emit_arrayed_outputs(b, invocation_index, s->per_primitive_outputs,
                               s->num_per_primitive_outputs, s->prim_attr_lds_addr, s);
 
+      /* Insert layer output store if the pipeline uses multiview but the API shader doesn't write it. */
+      if (s->insert_layer_output) {
+         nir_ssa_def *layer = nir_load_view_index(b);
+         const nir_io_semantics io_sem = { .location = VARYING_SLOT_LAYER, .num_slots = 1 };
+         nir_store_output(b, layer, nir_imm_int(b, 0), .base = VARYING_SLOT_LAYER, .component = 0, .io_semantics = io_sem);
+         b->shader->info.outputs_written |= VARYING_BIT_LAYER;
+         b->shader->info.per_primitive_outputs |= VARYING_BIT_LAYER;
+      }
+
       /* Primitive connectivity data: describes which vertices the primitive uses. */
       nir_ssa_def *prim_idx_addr = nir_imul_imm(b, invocation_index, s->vertices_per_prim);
       nir_ssa_def *indices_loaded = nir_load_shared(b, s->vertices_per_prim, 8, prim_idx_addr, .base = s->prim_vtx_indices_addr);
@@ -2697,7 +2709,8 @@ handle_smaller_ms_api_workgroup(nir_builder *b,
 
 void
 ac_nir_lower_ngg_ms(nir_shader *shader,
-                    unsigned wave_size)
+                    unsigned wave_size,
+                    bool multiview)
 {
    unsigned vertices_per_prim =
       num_mesh_vertices_per_primitive(shader->info.mesh.primitive_type);
@@ -2761,6 +2774,7 @@ ac_nir_lower_ngg_ms(nir_shader *shader,
       .numprims_lds_addr = numprims_lds_addr,
       .api_workgroup_size = api_workgroup_size,
       .hw_workgroup_size = hw_workgroup_size,
+      .insert_layer_output = multiview && !(shader->info.outputs_written & VARYING_BIT_LAYER),
    };
 
    nir_function_impl *impl = nir_shader_get_entrypoint(shader);
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 8093c08d8da..ce4f5efe78a 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -2873,7 +2873,6 @@ find_layer_out_var(nir_shader *nir)
       return var;
 
    var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "layer id");
-   var->data.per_primitive = nir->info.stage == MESA_SHADER_MESH;
    var->data.location = VARYING_SLOT_LAYER;
    var->data.interpolation = INTERP_MODE_NONE;
 
@@ -2883,6 +2882,13 @@ find_layer_out_var(nir_shader *nir)
 static bool
 radv_lower_multiview(nir_shader *nir)
 {
+   /* This pass is not suitable for mesh shaders, because it can't know
+    * the mapping between API mesh shader invocations and output primitives.
+    * Needs to be handled in ac_nir_lower_ngg.
+    */
+   if (nir->info.stage == MESA_SHADER_MESH)
+      return false;
+
    nir_function_impl *impl = nir_shader_get_entrypoint(nir);
    bool progress = false;
 
@@ -2924,8 +2930,6 @@ radv_lower_multiview(nir_shader *nir)
 
          /* Update outputs_written to reflect that the pass added a new output. */
          nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_LAYER);
-         if (nir->info.stage == MESA_SHADER_MESH)
-            nir->info.per_primitive_outputs |= BITFIELD64_BIT(VARYING_SLOT_LAYER);
 
          progress = true;
          if (nir->info.stage == MESA_SHADER_VERTEX)
@@ -4764,7 +4768,7 @@ radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout
 
          /* Gather info again, information such as outputs_read can be out-of-date. */
          nir_shader_gather_info(stages[i].nir, nir_shader_get_entrypoint(stages[i].nir));
-         radv_lower_io(device, stages[i].nir);
+         radv_lower_io(device, stages[i].nir, stages[MESA_SHADER_MESH].nir);
 
          stages[i].feedback.duration += os_time_get_nano() - stage_start;
       }
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index d4867958e1f..27b35f98b3f 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -991,7 +991,7 @@ find_layer_in_var(nir_shader *nir)
  */
 
 static bool
-lower_view_index(nir_shader *nir)
+lower_view_index(nir_shader *nir, bool per_primitive)
 {
    bool progress = false;
    nir_function_impl *entry = nir_shader_get_entrypoint(nir);
@@ -1011,12 +1011,15 @@ lower_view_index(nir_shader *nir)
          if (!layer)
             layer = find_layer_in_var(nir);
 
+         layer->data.per_primitive = per_primitive;
          b.cursor = nir_before_instr(instr);
          nir_ssa_def *def = nir_load_var(&b, layer);
          nir_ssa_def_rewrite_uses(&load->dest.ssa, def);
 
          /* Update inputs_read to reflect that the pass added a new input. */
          nir->info.inputs_read |= VARYING_BIT_LAYER;
+         if (per_primitive)
+            nir->info.per_primitive_inputs |= VARYING_BIT_LAYER;
 
          nir_instr_remove(instr);
          progress = true;
@@ -1032,13 +1035,13 @@ lower_view_index(nir_shader *nir)
 }
 
 void
-radv_lower_io(struct radv_device *device, nir_shader *nir)
+radv_lower_io(struct radv_device *device, nir_shader *nir, bool is_mesh_shading)
 {
    if (nir->info.stage == MESA_SHADER_COMPUTE)
       return;
 
    if (nir->info.stage == MESA_SHADER_FRAGMENT) {
-      NIR_PASS(_, nir, lower_view_index);
+      NIR_PASS(_, nir, lower_view_index, is_mesh_shading);
       nir_assign_io_var_locations(nir, nir_var_shader_in, &nir->num_inputs, MESA_SHADER_FRAGMENT);
    }
 
@@ -1239,7 +1242,7 @@ void radv_lower_ngg(struct radv_device *device, struct radv_pipeline_stage *ngg_
                  info->ngg_info.esgs_ring_size, info->gs.gsvs_vertex_size,
                  info->ngg_info.ngg_emit_size * 4u, pl_key->vs.provoking_vtx_last);
    } else if (nir->info.stage == MESA_SHADER_MESH) {
-      NIR_PASS_V(nir, ac_nir_lower_ngg_ms, info->wave_size);
+      NIR_PASS_V(nir, ac_nir_lower_ngg_ms, info->wave_size, pl_key->has_multiview_view_index);
    } else {
       unreachable("invalid SW stage passed to radv_lower_ngg");
    }
diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
index 68744bde46c..0044d1e98d6 100644
--- a/src/amd/vulkan/radv_shader.h
+++ b/src/amd/vulkan/radv_shader.h
@@ -678,7 +678,7 @@ get_tcs_num_patches(unsigned tcs_num_input_vertices, unsigned tcs_num_output_ver
    return num_patches;
 }
 
-void radv_lower_io(struct radv_device *device, nir_shader *nir);
+void radv_lower_io(struct radv_device *device, nir_shader *nir, bool is_mesh_shading);
 
 bool radv_lower_io_to_mem(struct radv_device *device, struct radv_pipeline_stage *stage,
                           const struct radv_pipeline_key *pl_key);
diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c
index 6fcd773b4df..01278686367 100644
--- a/src/amd/vulkan/radv_shader_info.c
+++ b/src/amd/vulkan/radv_shader_info.c
@@ -509,6 +509,12 @@ radv_nir_shader_info_pass(struct radv_device *device, const struct nir_shader *n
       uint64_t per_vtx_mask =
          nir->info.outputs_written & ~nir->info.per_primitive_outputs & ~special_mask;
 
+      /* Mesh multivew is only lowered in ac_nir_lower_ngg, so we have to fake it here. */
+      if (nir->info.stage == MESA_SHADER_MESH && pipeline_key->has_multiview_view_index) {
+         per_prim_mask |= VARYING_BIT_LAYER;
+         info->uses_view_index = true;
+      }
+
       /* Per vertex outputs. */
       outinfo->writes_pointsize = per_vtx_mask & VARYING_BIT_PSIZ;
       outinfo->writes_viewport_index = per_vtx_mask & VARYING_BIT_VIEWPORT;



More information about the mesa-commit mailing list