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

Author: Samuel Pitoiset <[email protected]>
Date:   Fri Mar 18 13:49:44 2022 +0100

radv: lower has_multiview_view_index in NIR

This lowering is done in a new NIR pass where the layer is written
before emit_vertex_with_counter for geometry shaders and after the
position for other vertex stages.

Signed-off-by: Samuel Pitoiset <[email protected]>
Reviewed-by: Rhys Perry <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15456>

---

 src/amd/compiler/aco_instruction_selection.cpp | 14 -----
 src/amd/vulkan/radv_nir_to_llvm.c              | 31 +---------
 src/amd/vulkan/radv_pipeline.c                 | 82 +++++++++++++++++++++++++-
 src/amd/vulkan/radv_shader.c                   |  3 +-
 src/amd/vulkan/radv_shader.h                   |  2 +-
 src/amd/vulkan/radv_shader_args.c              | 34 +----------
 src/amd/vulkan/radv_shader_info.c              |  8 ---
 7 files changed, 84 insertions(+), 90 deletions(-)

diff --git a/src/amd/compiler/aco_instruction_selection.cpp 
b/src/amd/compiler/aco_instruction_selection.cpp
index 90bb0a37a25..cc30bfbdcc6 100644
--- a/src/amd/compiler/aco_instruction_selection.cpp
+++ b/src/amd/compiler/aco_instruction_selection.cpp
@@ -10476,13 +10476,6 @@ create_vs_exports(isel_context* ctx)
             get_arg(ctx, ctx->args->ac.vs_prim_id);
    }
 
-   if (ctx->options->key.has_multiview_view_index &&
-       !outinfo->writes_layer_per_primitive) {
-      ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1;
-      ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] =
-         as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index));
-   }
-
    /* Hardware requires position data to always be exported, even if the
     * application did not write gl_Position.
     */
@@ -10531,13 +10524,6 @@ create_primitive_exports(isel_context *ctx, Temp 
prim_ch1)
 
    Builder bld(ctx->program, ctx->block);
 
-   if (ctx->options->key.has_multiview_view_index &&
-       outinfo->writes_layer_per_primitive) {
-      ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1;
-      ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] =
-         as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index));
-   }
-
    /* Use zeroes if the shader doesn't write these but they are needed by eg. 
PS. */
    if (outinfo->writes_layer_per_primitive && 
!ctx->outputs.mask[VARYING_SLOT_LAYER])
       ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = bld.copy(bld.def(v1), 
Operand::c32(0));
diff --git a/src/amd/vulkan/radv_nir_to_llvm.c 
b/src/amd/vulkan/radv_nir_to_llvm.c
index 8d242b8fd66..408ccc31970 100644
--- a/src/amd/vulkan/radv_nir_to_llvm.c
+++ b/src/amd/vulkan/radv_nir_to_llvm.c
@@ -1070,19 +1070,6 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, 
bool export_prim_id, boo
    struct radv_shader_output_values *outputs;
    unsigned noutput = 0;
 
-   if (ctx->options->key.has_multiview_view_index) {
-      LLVMValueRef *tmp_out = 
&ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
-      if (!*tmp_out) {
-         for (unsigned i = 0; i < 4; ++i)
-            ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, i)] =
-               ac_build_alloca_undef(&ctx->ac, ctx->ac.f32, "");
-      }
-
-      LLVMValueRef view_index = ac_get_arg(&ctx->ac, ctx->args->ac.view_index);
-      LLVMBuildStore(ctx->ac.builder, ac_to_float(&ctx->ac, view_index), 
*tmp_out);
-      ctx->output_mask |= 1ull << VARYING_SLOT_LAYER;
-   }
-
    if (ctx->shader_info->so.num_outputs && !ctx->args->is_gs_copy_shader) {
       /* The GS copy shader emission already emits streamout. */
       radv_emit_streamout(ctx, 0);
@@ -1177,9 +1164,6 @@ ngg_gs_get_vertex_storage(struct radv_shader_context *ctx)
 {
    unsigned num_outputs = util_bitcount64(ctx->output_mask);
 
-   if (ctx->options->key.has_multiview_view_index)
-      num_outputs++;
-
    LLVMTypeRef elements[2] = {
       LLVMArrayType(ctx->ac.i32, 4 * num_outputs),
       LLVMArrayType(ctx->ac.i8, 4),
@@ -1650,12 +1634,11 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context 
*ctx)
    ac_build_ifcc(&ctx->ac, tmp, 5145);
    {
       const struct radv_vs_output_info *outinfo = 
&ctx->shader_info->vs.outinfo;
-      bool export_view_index = ctx->options->key.has_multiview_view_index;
       struct radv_shader_output_values *outputs;
       unsigned noutput = 0;
 
       /* Allocate a temporary array for the output values. */
-      unsigned num_outputs = util_bitcount64(ctx->output_mask) + 
export_view_index;
+      unsigned num_outputs = util_bitcount64(ctx->output_mask);
       outputs = calloc(num_outputs, sizeof(outputs[0]));
 
       tmp = ngg_gs_vertex_ptr(ctx, tid);
@@ -1697,18 +1680,6 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context 
*ctx)
          noutput++;
       }
 
-      /* Export ViewIndex. */
-      if (export_view_index) {
-         outputs[noutput].slot_name = VARYING_SLOT_LAYER;
-         outputs[noutput].slot_index = 0;
-         outputs[noutput].usage_mask = 0x1;
-         outputs[noutput].values[0] =
-            ac_to_float(&ctx->ac, ac_get_arg(&ctx->ac, 
ctx->args->ac.view_index));
-         for (unsigned j = 1; j < 4; j++)
-            outputs[noutput].values[j] = ctx->ac.f32_0;
-         noutput++;
-      }
-
       radv_llvm_export_vs(ctx, outputs, noutput, outinfo, 
outinfo->export_clip_dists);
       FREE(outputs);
    }
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 83985f7bd5c..55fac2e375d 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -2511,6 +2511,77 @@ radv_lower_viewport_to_zero(nir_shader *nir)
    return false;
 }
 
+static nir_variable *
+find_layer_out_var(nir_shader *nir)
+{
+   nir_variable *var = nir_find_variable_with_location(nir, 
nir_var_shader_out, VARYING_SLOT_LAYER);
+   if (var != NULL)
+      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;
+
+   return var;
+}
+
+static bool
+radv_lower_multiview(nir_shader *nir)
+{
+   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
+   bool progress = false;
+
+   nir_builder b;
+   nir_builder_init(&b, impl);
+
+   /* Iterate in reverse order since there should be only one deref store to 
POS after
+    * lower_io_to_temporaries for vertex shaders and inject the layer there. 
For geometry shaders,
+    * the layer is injected right before every emit_vertex_with_counter.
+    */
+   nir_variable *layer = NULL;
+   nir_foreach_block_reverse(block, impl) {
+      nir_foreach_instr_reverse(instr, block) {
+         if (instr->type != nir_instr_type_intrinsic)
+            continue;
+
+         if (nir->info.stage == MESA_SHADER_GEOMETRY) {
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            if (intr->intrinsic != nir_intrinsic_emit_vertex_with_counter)
+               continue;
+
+            b.cursor = nir_before_instr(instr);
+         } else {
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            if (intr->intrinsic != nir_intrinsic_store_deref)
+               continue;
+
+            nir_variable *var = nir_intrinsic_get_var(intr, 0);
+            if (var->data.mode != nir_var_shader_out || var->data.location != 
VARYING_SLOT_POS)
+               continue;
+
+            b.cursor = nir_after_instr(instr);
+         }
+
+         if (!layer)
+            layer = find_layer_out_var(nir);
+
+         nir_store_var(&b, layer, nir_load_view_index(&b), 1);
+
+         /* 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)
+            return progress;
+      }
+   }
+
+   return progress;
+}
+
 static void
 radv_link_shaders(struct radv_pipeline *pipeline,
                   const struct radv_pipeline_key *pipeline_key,
@@ -2688,6 +2759,14 @@ radv_link_shaders(struct radv_pipeline *pipeline,
       radv_lower_viewport_to_zero(shaders[MESA_SHADER_FRAGMENT]);
    }
 
+   /* Export the layer in the last VGT stage if multiview is used. */
+   if (pipeline_key->has_multiview_view_index && 
pipeline->graphics.last_vgt_api_stage != -1 &&
+       !(shaders[pipeline->graphics.last_vgt_api_stage]->info.outputs_written &
+         VARYING_BIT_LAYER)) {
+      nir_shader *last_vgt_shader = 
shaders[pipeline->graphics.last_vgt_api_stage];
+      radv_lower_multiview(last_vgt_shader);
+   }
+
    for (int i = 1; !optimize_conservatively && (i < shader_count); ++i) {
       if (nir_link_opt_varyings(ordered_shaders[i], ordered_shaders[i - 1])) {
          nir_opt_constant_folding(ordered_shaders[i - 1]);
@@ -4377,8 +4456,7 @@ radv_create_shaders(struct radv_pipeline *pipeline, 
struct radv_pipeline_layout
 
       pipeline->gs_copy_shader = radv_create_gs_copy_shader(
          device, nir[MESA_SHADER_GEOMETRY], &info, &gs_copy_args, 
&gs_copy_binary,
-         keep_executable_info, keep_statistic_info, 
pipeline_key->has_multiview_view_index,
-         pipeline_key->optimisations_disabled);
+         keep_executable_info, keep_statistic_info, 
pipeline_key->optimisations_disabled);
    }
 
    if (nir[MESA_SHADER_FRAGMENT]) {
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index 8a7f9695e9a..5361a0349d3 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -2051,12 +2051,11 @@ struct radv_shader *
 radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader 
*shader,
                            struct radv_shader_info *info, const struct 
radv_shader_args *args,
                            struct radv_shader_binary **binary_out, bool 
keep_shader_info,
-                           bool keep_statistic_info, bool multiview, bool 
disable_optimizations)
+                           bool keep_statistic_info, bool 
disable_optimizations)
 {
    struct radv_nir_compiler_options options = {0};
    gl_shader_stage stage = MESA_SHADER_VERTEX;
 
-   options.key.has_multiview_view_index = multiview;
    options.key.optimisations_disabled = disable_optimizations;
 
    return shader_compile(device, NULL, &shader, 1, stage, info, args, 
&options, true, false,
diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
index 88cb617a148..212bc0eb2c9 100644
--- a/src/amd/vulkan/radv_shader.h
+++ b/src/amd/vulkan/radv_shader.h
@@ -553,7 +553,7 @@ void radv_free_shader_memory(struct radv_device *device, 
union radv_shader_arena
 struct radv_shader *
 radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *nir,
                            struct radv_shader_info *info, const struct 
radv_shader_args *args,
-                           struct radv_shader_binary **binary_out, bool 
multiview,
+                           struct radv_shader_binary **binary_out,
                            bool keep_shader_info, bool keep_statistic_info,
                            bool disable_optimizations);
 
diff --git a/src/amd/vulkan/radv_shader_args.c 
b/src/amd/vulkan/radv_shader_args.c
index bd40dfe8d3a..13397790dc8 100644
--- a/src/amd/vulkan/radv_shader_args.c
+++ b/src/amd/vulkan/radv_shader_args.c
@@ -74,38 +74,6 @@ struct user_sgpr_info {
    bool inlined_all_push_consts;
 };
 
-static bool
-needs_view_index_sgpr(const struct radv_pipeline_key *key, const struct 
radv_shader_info *info,
-                      gl_shader_stage stage)
-{
-   switch (stage) {
-   case MESA_SHADER_VERTEX:
-      if (info->uses_view_index ||
-          (!info->vs.as_es && !info->vs.as_ls && 
key->has_multiview_view_index))
-         return true;
-      break;
-   case MESA_SHADER_TESS_EVAL:
-      if (info->uses_view_index || (!info->tes.as_es && 
key->has_multiview_view_index))
-         return true;
-      break;
-   case MESA_SHADER_TESS_CTRL:
-      if (info->uses_view_index)
-         return true;
-      break;
-   case MESA_SHADER_GEOMETRY:
-      if (info->uses_view_index || (info->is_ngg && 
key->has_multiview_view_index))
-         return true;
-      break;
-   case MESA_SHADER_MESH:
-      if (info->uses_view_index || key->has_multiview_view_index)
-         return true;
-      break;
-   default:
-      break;
-   }
-   return false;
-}
-
 static uint8_t
 count_vs_user_sgprs(const struct radv_shader_info *info)
 {
@@ -554,7 +522,7 @@ radv_declare_shader_args(enum chip_class chip_class, const 
struct radv_pipeline_
                          struct radv_shader_args *args)
 {
    struct user_sgpr_info user_sgpr_info;
-   bool needs_view_index = needs_view_index_sgpr(key, info, stage);
+   bool needs_view_index = info->uses_view_index;
    bool has_api_gs = stage == MESA_SHADER_GEOMETRY;
 
    if (chip_class >= GFX10 && info->is_ngg && stage != MESA_SHADER_GEOMETRY) {
diff --git a/src/amd/vulkan/radv_shader_info.c 
b/src/amd/vulkan/radv_shader_info.c
index 4ff27c814c8..4196d97fa37 100644
--- a/src/amd/vulkan/radv_shader_info.c
+++ b/src/amd/vulkan/radv_shader_info.c
@@ -673,14 +673,6 @@ radv_nir_shader_info_pass(struct radv_device *device, 
const struct nir_shader *n
 
    struct radv_vs_output_info *outinfo = get_vs_output_info(nir, info);
    if (outinfo) {
-      /* Make sure to export the LayerID if the subpass has multiviews. */
-      if (pipeline_key->has_multiview_view_index) {
-         if (nir->info.stage == MESA_SHADER_MESH)
-            outinfo->writes_layer_per_primitive = true;
-         else
-            outinfo->writes_layer = true;
-      }
-
       int pos_written = 0x1;
 
       if (outinfo->writes_pointsize || outinfo->writes_viewport_index || 
outinfo->writes_layer ||

Reply via email to