From 99d7c130510206ac71b259c0a88620623da1bfd3 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 25 Jan 2022 09:24:38 +0100 Subject: [PATCH] radv: rework RADV_FORCE_VRS to make it more dynamic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VRS rates are now emitted from the command buffer via an user SGPR which will allow to change the rates dynamically in later changes. Signed-off-by: Samuel Pitoiset Reviewed-by: Timur Kristóf Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/amd/vulkan/radv_cmd_buffer.c | 35 ++++++++++++++++++++++++++++++++ src/amd/vulkan/radv_pipeline.c | 4 +++- src/amd/vulkan/radv_private.h | 3 +++ src/amd/vulkan/radv_shader.c | 31 +++------------------------- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 712fce200fa..0f84067dfe9 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -3628,6 +3628,40 @@ radv_flush_ngg_gs_state(struct radv_cmd_buffer *cmd_buffer) radeon_set_sh_reg(cmd_buffer->cs, base_reg + loc->sgpr_idx * 4, ngg_gs_state); } +static void +radv_flush_force_vrs_state(struct radv_cmd_buffer *cmd_buffer) +{ + struct radv_pipeline *pipeline = cmd_buffer->state.pipeline; + const unsigned stage = pipeline->graphics.last_vgt_api_stage; + struct radv_userdata_info *loc; + uint32_t vrs_rates = 0; + uint32_t base_reg; + + if (!pipeline->graphics.force_vrs_per_vertex) + return; + + loc = radv_lookup_user_sgpr(pipeline, stage, AC_UD_FORCE_VRS_RATES); + assert(loc->sgpr_idx != -1); + + base_reg = pipeline->user_data_0[stage]; + + switch (cmd_buffer->device->force_vrs) { + case RADV_FORCE_VRS_2x2: + vrs_rates = (1u << 2) | (1u << 4); + break; + case RADV_FORCE_VRS_2x1: + vrs_rates = (1u << 2) | (0u << 4); + break; + case RADV_FORCE_VRS_1x2: + vrs_rates = (0u << 2) | (1u << 4); + break; + default: + break; + } + + radeon_set_sh_reg(cmd_buffer->cs, base_reg + loc->sgpr_idx * 4, vrs_rates); +} + static void radv_upload_graphics_shader_descriptors(struct radv_cmd_buffer *cmd_buffer, bool pipeline_is_dirty) { @@ -3640,6 +3674,7 @@ radv_upload_graphics_shader_descriptors(struct radv_cmd_buffer *cmd_buffer, bool radv_flush_constants(cmd_buffer, stages, cmd_buffer->state.pipeline, VK_PIPELINE_BIND_POINT_GRAPHICS); radv_flush_ngg_gs_state(cmd_buffer); + radv_flush_force_vrs_state(cmd_buffer); } struct radv_draw_info { diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 3d8f625193f..761b10990a1 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -5783,7 +5783,7 @@ gfx103_pipeline_generate_vrs_state(struct radeon_cmdbuf *ctx_cs, mode = V_028064_VRS_COMB_MODE_OVERRIDE; rate_x = rate_y = 1; } else if (!vk_find_struct_const(pCreateInfo->pNext, PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR) && - pipeline->device->force_vrs != RADV_FORCE_VRS_NONE && + pipeline->graphics.force_vrs_per_vertex && get_vs_output_info(pipeline)->writes_primitive_shading_rate) { /* Otherwise, if per-draw VRS is not enabled statically, try forcing per-vertex VRS if * requested by the user. Note that vkd3d-proton always has to declare VRS as dynamic because @@ -6077,6 +6077,8 @@ radv_pipeline_init(struct radv_pipeline *pipeline, struct radv_device *device, pipeline->graphics.has_ngg_culling = pipeline->graphics.is_ngg && pipeline->shaders[pipeline->graphics.last_vgt_api_stage]->info.has_ngg_culling; + pipeline->graphics.force_vrs_per_vertex = + pipeline->shaders[pipeline->graphics.last_vgt_api_stage]->info.force_vrs_per_vertex; pipeline->push_constant_size = pipeline_layout->push_constant_size; pipeline->dynamic_offset_count = pipeline_layout->dynamic_offset_count; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index eca3c007137..2d40c48e3d9 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -1873,6 +1873,9 @@ struct radv_pipeline { /* Last pre-PS API stage */ gl_shader_stage last_vgt_api_stage; + + /* Whether the pipeline forces per-vertex VRS (GFX10.3+). */ + bool force_vrs_per_vertex; } graphics; struct { struct radv_pipeline_group_handle *rt_group_handles; diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 99094d907ec..debc02a4116 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -461,37 +461,10 @@ radv_force_primitive_shading_rate(nir_shader *nir, struct radv_device *device) { nir_function_impl *impl = nir_shader_get_entrypoint(nir); bool progress = false; - unsigned vrs_rate = 0; nir_builder b; nir_builder_init(&b, impl); - /* Bits [2:3] = VRS rate X - * Bits [4:5] = VRS rate Y - * - * The range is [-2, 1]. Values: - * 1: 2x coarser shading rate in that direction. - * 0: normal shading rate - * -1: 2x finer shading rate (sample shading, not directional) - * -2: 4x finer shading rate (sample shading, not directional) - * - * Sample shading can't go above 8 samples, so both numbers can't be -2 - * at the same time. - */ - switch (device->force_vrs) { - case RADV_FORCE_VRS_2x2: - vrs_rate = (1u << 2) | (1u << 4); - break; - case RADV_FORCE_VRS_2x1: - vrs_rate = (1u << 2) | (0u << 4); - break; - case RADV_FORCE_VRS_1x2: - vrs_rate = (0u << 2) | (1u << 4); - break; - default: - unreachable("Invalid RADV_FORCE_VRS value"); - } - nir_foreach_block_reverse(block, impl) { nir_foreach_instr_reverse(instr, block) { if (instr->type != nir_instr_type_intrinsic) @@ -520,9 +493,11 @@ radv_force_primitive_shading_rate(nir_shader *nir, struct radv_device *device) 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)), - nir_imm_int(&b, vrs_rate), nir_imm_int(&b, 0)); + vrs_rates, nir_imm_int(&b, 0)); nir_deref_instr *deref = nir_build_deref_var(&b, var); nir_store_deref(&b, deref, val, 0x1);