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;
