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

Author: Qiang Yu <[email protected]>
Date:   Sun Jan 29 17:12:18 2023 +0800

radv: use amd common force_vrs option

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

---

 src/amd/vulkan/radv_cmd_buffer.c  | 19 +++++++----
 src/amd/vulkan/radv_pipeline.c    | 27 ++++++++--------
 src/amd/vulkan/radv_private.h     |  1 +
 src/amd/vulkan/radv_shader.c      | 67 +--------------------------------------
 src/amd/vulkan/radv_shader.h      |  2 --
 src/amd/vulkan/radv_shader_args.c |  3 +-
 src/amd/vulkan/radv_shader_info.c | 33 +++++++++++++------
 7 files changed, 53 insertions(+), 99 deletions(-)

diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
index 4ecebb241e4..7f7ee238752 100644
--- a/src/amd/vulkan/radv_cmd_buffer.c
+++ b/src/amd/vulkan/radv_cmd_buffer.c
@@ -4966,11 +4966,6 @@ static void
 radv_flush_force_vrs_state(struct radv_cmd_buffer *cmd_buffer)
 {
    struct radv_graphics_pipeline *pipeline = 
cmd_buffer->state.graphics_pipeline;
-   enum amd_gfx_level gfx_level = 
pipeline->base.device->physical_device->rad_info.gfx_level;
-   const unsigned stage = pipeline->last_vgt_api_stage;
-   struct radv_userdata_info *loc = 
&pipeline->last_vgt_api_stage_locs[AC_UD_FORCE_VRS_RATES];
-   uint32_t vrs_rates = 0;
-   uint32_t base_reg;
 
    if (!pipeline->force_vrs_per_vertex) {
       /* Un-set the SGPR index so we know to re-emit it later. */
@@ -4978,9 +4973,21 @@ radv_flush_force_vrs_state(struct radv_cmd_buffer 
*cmd_buffer)
       return;
    }
 
+   struct radv_userdata_info *loc;
+   uint32_t base_reg;
+
+   if (radv_pipeline_has_gs_copy_shader(&pipeline->base)) {
+      loc = 
&pipeline->base.gs_copy_shader->info.user_sgprs_locs.shader_data[AC_UD_FORCE_VRS_RATES];
+      base_reg = R_00B130_SPI_SHADER_USER_DATA_VS_0;
+   } else {
+      loc = &pipeline->last_vgt_api_stage_locs[AC_UD_FORCE_VRS_RATES];
+      base_reg = pipeline->base.user_data_0[pipeline->last_vgt_api_stage];
+   }
+
    assert(loc->sgpr_idx != -1);
 
-   base_reg = pipeline->base.user_data_0[stage];
+   enum amd_gfx_level gfx_level = 
pipeline->base.device->physical_device->rad_info.gfx_level;
+   uint32_t vrs_rates = 0;
 
    switch (cmd_buffer->device->force_vrs) {
    case RADV_FORCE_VRS_2x2:
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index 7a0ded225e0..903bedbab2e 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -2545,17 +2545,22 @@ static void
 radv_fill_shader_info(struct radv_graphics_pipeline *pipeline,
                       struct radv_pipeline_layout *pipeline_layout,
                       const struct radv_pipeline_key *pipeline_key,
-                      struct radv_pipeline_stage *stages)
+                      struct radv_pipeline_stage *stages,
+                      bool noop_fs)
 {
    struct radv_device *device = pipeline->base.device;
 
+   bool consider_force_vrs = radv_consider_force_vrs(pipeline, noop_fs, 
stages);
+
    for (int i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
       if (!stages[i].nir)
          continue;
 
       radv_nir_shader_info_init(&stages[i].info);
       radv_nir_shader_info_pass(device, stages[i].nir, pipeline_layout, 
pipeline_key,
-                                pipeline->base.type, &stages[i].info);
+                                pipeline->base.type,
+                                i == pipeline->last_vgt_api_stage && 
consider_force_vrs,
+                                &stages[i].info);
    }
 
    radv_nir_shader_info_link(device, pipeline_key, stages);
@@ -3048,18 +3053,19 @@ radv_pipeline_create_gs_copy_shader(struct 
radv_pipeline *pipeline,
                                    gs_info->outinfo.clip_dist_mask | 
gs_info->outinfo.cull_dist_mask,
                                    gs_info->outinfo.vs_output_param_offset,
                                    gs_info->outinfo.param_exports,
-                                   false, false, false,
+                                   false, false, gs_info->force_vrs_per_vertex,
                                    &output_info);
 
    nir_validate_shader(nir, "after ac_nir_create_gs_copy_shader");
    nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
 
    struct radv_shader_info info = {0};
-   radv_nir_shader_info_pass(device, nir, pipeline_layout, pipeline_key, 
pipeline->type, &info);
+   radv_nir_shader_info_pass(device, nir, pipeline_layout, pipeline_key, 
pipeline->type, false, &info);
    info.wave_size = 64; /* Wave32 not supported. */
    info.workgroup_size = 64; /* HW VS: separate waves, no workgroups */
    info.so = gs_info->so;
    info.outinfo = gs_info->outinfo;
+   info.force_vrs_per_vertex = gs_info->force_vrs_per_vertex;
 
    struct radv_shader_args gs_copy_args = {0};
    gs_copy_args.is_gs_copy_shader = true;
@@ -3329,7 +3335,7 @@ radv_postprocess_nir(struct radv_pipeline *pipeline,
                     stage->info.outinfo.vs_output_param_offset,
                     stage->info.outinfo.param_exports,
                     stage->info.outinfo.export_prim_id,
-                    false, false, false);
+                    false, false, stage->info.force_vrs_per_vertex);
 
       } else {
          ac_nir_gs_output_info gs_out_info = {
@@ -3608,13 +3614,6 @@ radv_graphics_pipeline_compile(struct 
radv_graphics_pipeline *pipeline,
 
    radv_pipeline_get_nir(pipeline, stages, pipeline_key, retain_shaders);
 
-   /* Force per-vertex VRS. */
-   if (radv_consider_force_vrs(pipeline, noop_fs, stages)) {
-      assert(pipeline->last_vgt_api_stage != MESA_SHADER_MESH);
-      nir_shader *last_vgt_shader = stages[pipeline->last_vgt_api_stage].nir;
-      NIR_PASS(_, last_vgt_shader, radv_force_primitive_shading_rate, device);
-   }
-
    bool optimize_conservatively = pipeline_key->optimisations_disabled;
 
    /* Determine if shaders uses NGG before linking because it's needed for 
some NIR pass. */
@@ -3655,7 +3654,7 @@ radv_graphics_pipeline_compile(struct 
radv_graphics_pipeline *pipeline,
                pipeline_key);
    }
 
-   radv_fill_shader_info(pipeline, pipeline_layout, pipeline_key, stages);
+   radv_fill_shader_info(pipeline, pipeline_layout, pipeline_key, stages, 
noop_fs);
 
    radv_declare_pipeline_args(device, stages, pipeline_key);
 
@@ -5539,7 +5538,7 @@ radv_compute_pipeline_compile(struct 
radv_compute_pipeline *pipeline,
    /* Run the shader info pass. */
    radv_nir_shader_info_init(&cs_stage.info);
    radv_nir_shader_info_pass(device, cs_stage.nir, pipeline_layout, 
pipeline_key,
-                             pipeline->base.type, &cs_stage.info);
+                             pipeline->base.type, false, &cs_stage.info);
 
    /* Declare shader arguments. */
    cs_stage.args.explicit_scratch_args = !radv_use_llvm_for_stage(device, 
MESA_SHADER_COMPUTE);
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 7615013736f..afa9ae925ef 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -2936,6 +2936,7 @@ void radv_nir_shader_info_pass(struct radv_device 
*device, const struct nir_shad
                                const struct radv_pipeline_layout *layout,
                                const struct radv_pipeline_key *pipeline_key,
                                const enum radv_pipeline_type pipeline_type,
+                               bool consider_force_vrs,
                                struct radv_shader_info *info);
 
 void radv_nir_shader_info_init(struct radv_shader_info *info);
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index 6239408e574..29bbe045d3d 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -458,72 +458,6 @@ radv_lower_primitive_shading_rate(nir_shader *nir, enum 
amd_gfx_level gfx_level)
    return progress;
 }
 
-bool
-radv_force_primitive_shading_rate(nir_shader *nir, struct radv_device *device)
-{
-   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
-   bool progress = false;
-
-   nir_builder b;
-   nir_builder_init(&b, impl);
-
-   nir_foreach_block_reverse(block, impl) {
-      nir_foreach_instr_reverse(instr, block) {
-         if (instr->type != nir_instr_type_intrinsic)
-            continue;
-
-         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);
-
-         nir_ssa_scalar scalar_idx = nir_ssa_scalar_resolved(intr->src[1].ssa, 
3);
-
-         /* Use coarse shading if the value of Pos.W can't be determined or if 
its value is != 1
-          * (typical for non-GUI elements).
-          */
-         if (!nir_ssa_scalar_is_const(scalar_idx) ||
-             nir_ssa_scalar_as_uint(scalar_idx) != 0x3f800000u) {
-
-            var = nir_variable_create(nir, nir_var_shader_out, 
glsl_int_type(), "vrs rate");
-            var->data.location = VARYING_SLOT_PRIMITIVE_SHADING_RATE;
-            var->data.interpolation = INTERP_MODE_NONE;
-
-            nir_ssa_def *vrs_rates = nir_load_force_vrs_rates_amd(&b);
-
-            nir_ssa_def *pos_w = nir_channel(&b, intr->src[1].ssa, 3);
-            nir_ssa_def *val = nir_bcsel(&b, nir_fneu(&b, pos_w, 
nir_imm_float(&b, 1.0f)),
-                                             vrs_rates, nir_imm_int(&b, 0));
-
-            nir_deref_instr *deref = nir_build_deref_var(&b, var);
-            nir_store_deref(&b, deref, val, 0x1);
-
-            /* Update outputs_written to reflect that the pass added a new 
output. */
-            nir->info.outputs_written |= 
BITFIELD64_BIT(VARYING_SLOT_PRIMITIVE_SHADING_RATE);
-
-            progress = true;
-            if (nir->info.stage == MESA_SHADER_VERTEX)
-               break;
-         }
-      }
-      if (nir->info.stage == MESA_SHADER_VERTEX && progress)
-         break;
-   }
-
-   if (progress)
-      nir_metadata_preserve(impl, nir_metadata_block_index | 
nir_metadata_dominance);
-   else
-      nir_metadata_preserve(impl, nir_metadata_all);
-
-   return progress;
-}
-
 bool
 radv_lower_fs_intrinsics(nir_shader *nir, const struct radv_pipeline_stage 
*fs_stage,
                          const struct radv_pipeline_key *key)
@@ -1456,6 +1390,7 @@ void radv_lower_ngg(struct radv_device *device, struct 
radv_pipeline_stage *ngg_
    options.disable_streamout = !device->physical_device->use_ngg_streamout;
    options.has_gen_prim_query = info->has_ngg_prim_query;
    options.has_xfb_prim_query = info->has_ngg_xfb_query;
+   options.force_vrs = info->force_vrs_per_vertex;
 
    if (nir->info.stage == MESA_SHADER_VERTEX ||
        nir->info.stage == MESA_SHADER_TESS_EVAL) {
diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h
index 54727cbb7e9..e9ef95f07f2 100644
--- a/src/amd/vulkan/radv_shader.h
+++ b/src/amd/vulkan/radv_shader.h
@@ -749,8 +749,6 @@ bool radv_consider_culling(const struct 
radv_physical_device *pdevice, struct ni
 
 void radv_get_nir_options(struct radv_physical_device *device);
 
-bool radv_force_primitive_shading_rate(nir_shader *nir, struct radv_device 
*device);
-
 bool radv_lower_fs_intrinsics(nir_shader *nir, const struct 
radv_pipeline_stage *fs_stage,
                               const struct radv_pipeline_key *key);
 
diff --git a/src/amd/vulkan/radv_shader_args.c 
b/src/amd/vulkan/radv_shader_args.c
index 259a3da211a..936b38766ff 100644
--- a/src/amd/vulkan/radv_shader_args.c
+++ b/src/amd/vulkan/radv_shader_args.c
@@ -789,7 +789,8 @@ radv_declare_shader_args(enum amd_gfx_level gfx_level, 
const struct radv_pipelin
          if (previous_stage == MESA_SHADER_TESS_EVAL && 
key->dynamic_patch_control_points)
             ac_add_arg(&args->ac, AC_ARG_SGPR, 1, AC_ARG_INT, 
&args->tes_num_patches);
 
-         if (info->force_vrs_per_vertex) {
+         /* Legacy GS force vrs is handled by GS copy shader. */
+         if (info->force_vrs_per_vertex && info->is_ngg) {
             ac_add_arg(&args->ac, AC_ARG_SGPR, 1, AC_ARG_INT, 
&args->ac.force_vrs_rates);
          }
 
diff --git a/src/amd/vulkan/radv_shader_info.c 
b/src/amd/vulkan/radv_shader_info.c
index c04711673e0..f79ac212196 100644
--- a/src/amd/vulkan/radv_shader_info.c
+++ b/src/amd/vulkan/radv_shader_info.c
@@ -56,7 +56,7 @@ gather_intrinsic_load_input_info(const nir_shader *nir, const 
nir_intrinsic_inst
 
 static void
 gather_intrinsic_store_output_info(const nir_shader *nir, const 
nir_intrinsic_instr *instr,
-                                   struct radv_shader_info *info)
+                                   struct radv_shader_info *info, bool 
consider_force_vrs)
 {
    unsigned idx = nir_intrinsic_base(instr);
    unsigned num_slots = nir_intrinsic_io_semantics(instr).num_slots;
@@ -92,6 +92,19 @@ gather_intrinsic_store_output_info(const nir_shader *nir, 
const nir_intrinsic_in
       }
    }
 
+   if (consider_force_vrs && idx == VARYING_SLOT_POS) {
+      unsigned pos_w_chan = 3 - component;
+
+      if (write_mask & BITFIELD_BIT(pos_w_chan)) {
+         nir_ssa_scalar pos_w = nir_ssa_scalar_resolved(instr->src[0].ssa, 
pos_w_chan);
+         /* Use coarse shading if the value of Pos.W can't be determined or if 
its value is != 1
+          * (typical for non-GUI elements).
+          */
+         if (!nir_ssa_scalar_is_const(pos_w) || nir_ssa_scalar_as_uint(pos_w) 
!= 0x3f800000u)
+            info->force_vrs_per_vertex = true;
+      }
+   }
+
    if (nir->info.stage == MESA_SHADER_GEOMETRY) {
       uint8_t gs_streams = nir_intrinsic_io_semantics(instr).gs_streams;
       info->gs.output_streams[idx] |= gs_streams << (component * 2);
@@ -119,7 +132,7 @@ gather_push_constant_info(const nir_shader *nir, const 
nir_intrinsic_instr *inst
 
 static void
 gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
-                      struct radv_shader_info *info)
+                      struct radv_shader_info *info, bool consider_force_vrs)
 {
    switch (instr->intrinsic) {
    case nir_intrinsic_load_barycentric_sample:
@@ -208,14 +221,11 @@ gather_intrinsic_info(const nir_shader *nir, const 
nir_intrinsic_instr *instr,
       gather_intrinsic_load_input_info(nir, instr, info);
       break;
    case nir_intrinsic_store_output:
-      gather_intrinsic_store_output_info(nir, instr, info);
+      gather_intrinsic_store_output_info(nir, instr, info, consider_force_vrs);
       break;
    case nir_intrinsic_load_sbt_base_amd:
       info->cs.uses_sbt = true;
       break;
-   case nir_intrinsic_load_force_vrs_rates_amd:
-      info->force_vrs_per_vertex = true;
-      break;
    case nir_intrinsic_load_rt_dynamic_callable_stack_base_amd:
       info->cs.uses_dynamic_rt_callable_stack = true;
       break;
@@ -245,12 +255,13 @@ gather_tex_info(const nir_shader *nir, const 
nir_tex_instr *instr, struct radv_s
 }
 
 static void
-gather_info_block(const nir_shader *nir, const nir_block *block, struct 
radv_shader_info *info)
+gather_info_block(const nir_shader *nir, const nir_block *block, struct 
radv_shader_info *info,
+                  bool consider_force_vrs)
 {
    nir_foreach_instr (instr, block) {
       switch (instr->type) {
       case nir_instr_type_intrinsic:
-         gather_intrinsic_info(nir, nir_instr_as_intrinsic(instr), info);
+         gather_intrinsic_info(nir, nir_instr_as_intrinsic(instr), info, 
consider_force_vrs);
          break;
       case nir_instr_type_tex:
          gather_tex_info(nir, nir_instr_as_tex(instr), info);
@@ -688,6 +699,7 @@ radv_nir_shader_info_pass(struct radv_device *device, const 
struct nir_shader *n
                           const struct radv_pipeline_layout *layout,
                           const struct radv_pipeline_key *pipeline_key,
                           const enum radv_pipeline_type pipeline_type,
+                          bool consider_force_vrs,
                           struct radv_shader_info *info)
 {
    struct nir_function *func = (struct nir_function 
*)exec_list_get_head_const(&nir->functions);
@@ -699,7 +711,7 @@ radv_nir_shader_info_pass(struct radv_device *device, const 
struct nir_shader *n
    }
 
    nir_foreach_block (block, func->impl) {
-      gather_info_block(nir, block, info);
+      gather_info_block(nir, block, info, consider_force_vrs);
    }
 
    if (nir->info.stage == MESA_SHADER_VERTEX || nir->info.stage == 
MESA_SHADER_TESS_EVAL ||
@@ -729,7 +741,8 @@ radv_nir_shader_info_pass(struct radv_device *device, const 
struct nir_shader *n
       outinfo->writes_pointsize = per_vtx_mask & VARYING_BIT_PSIZ;
       outinfo->writes_viewport_index = per_vtx_mask & VARYING_BIT_VIEWPORT;
       outinfo->writes_layer = per_vtx_mask & VARYING_BIT_LAYER;
-      outinfo->writes_primitive_shading_rate = per_vtx_mask & 
VARYING_BIT_PRIMITIVE_SHADING_RATE;
+      outinfo->writes_primitive_shading_rate =
+         (per_vtx_mask & VARYING_BIT_PRIMITIVE_SHADING_RATE) || 
info->force_vrs_per_vertex;
 
       /* Per primitive outputs. */
       outinfo->writes_viewport_index_per_primitive = per_prim_mask & 
VARYING_BIT_VIEWPORT;

Reply via email to