From c658ed5136119d78842f818b33bed5dd1cd3d8ac Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 2 May 2024 12:33:47 +0200 Subject: [PATCH] radv: precompute vertex shader register values To make emission faster. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/radv_pipeline_graphics.c | 67 ++++----------------- src/amd/vulkan/radv_shader.c | 79 ++++++++++++++++++++++++- src/amd/vulkan/radv_shader_info.h | 13 +++- 3 files changed, 100 insertions(+), 59 deletions(-) diff --git a/src/amd/vulkan/radv_pipeline_graphics.c b/src/amd/vulkan/radv_pipeline_graphics.c index 6169cd9fa87..7b6088fe6b4 100644 --- a/src/amd/vulkan/radv_pipeline_graphics.c +++ b/src/amd/vulkan/radv_pipeline_graphics.c @@ -2791,67 +2791,24 @@ radv_emit_hw_vs(const struct radv_device *device, struct radeon_cmdbuf *ctx_cs, radeon_emit(cs, shader->config.rsrc1); radeon_emit(cs, shader->config.rsrc2); - const struct radv_vs_output_info *outinfo = &shader->info.outinfo; - unsigned clip_dist_mask, cull_dist_mask, total_mask; - clip_dist_mask = outinfo->clip_dist_mask; - cull_dist_mask = outinfo->cull_dist_mask; - total_mask = clip_dist_mask | cull_dist_mask; - - bool misc_vec_ena = outinfo->writes_pointsize || outinfo->writes_layer || outinfo->writes_viewport_index || - outinfo->writes_primitive_shading_rate; - unsigned spi_vs_out_config, nparams; - - /* VS is required to export at least one param. */ - nparams = MAX2(outinfo->param_exports, 1); - spi_vs_out_config = S_0286C4_VS_EXPORT_COUNT(nparams - 1); - - if (pdev->info.gfx_level >= GFX10) { - spi_vs_out_config |= S_0286C4_NO_PC_EXPORT(outinfo->param_exports == 0); - } - - radeon_set_context_reg(ctx_cs, R_0286C4_SPI_VS_OUT_CONFIG, spi_vs_out_config); - - radeon_set_context_reg( - ctx_cs, R_02870C_SPI_SHADER_POS_FORMAT, - S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) | - S_02870C_POS1_EXPORT_FORMAT(outinfo->pos_exports > 1 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE) | - S_02870C_POS2_EXPORT_FORMAT(outinfo->pos_exports > 2 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE) | - S_02870C_POS3_EXPORT_FORMAT(outinfo->pos_exports > 3 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE)); - - radeon_set_context_reg( - ctx_cs, R_02881C_PA_CL_VS_OUT_CNTL, - S_02881C_USE_VTX_POINT_SIZE(outinfo->writes_pointsize) | - S_02881C_USE_VTX_RENDER_TARGET_INDX(outinfo->writes_layer) | - S_02881C_USE_VTX_VIEWPORT_INDX(outinfo->writes_viewport_index) | - S_02881C_USE_VTX_VRS_RATE(outinfo->writes_primitive_shading_rate) | - S_02881C_VS_OUT_MISC_VEC_ENA(misc_vec_ena) | - S_02881C_VS_OUT_MISC_SIDE_BUS_ENA(misc_vec_ena || - (pdev->info.gfx_level >= GFX10_3 && outinfo->pos_exports > 1)) | - S_02881C_VS_OUT_CCDIST0_VEC_ENA((total_mask & 0x0f) != 0) | - S_02881C_VS_OUT_CCDIST1_VEC_ENA((total_mask & 0xf0) != 0) | total_mask << 8 | clip_dist_mask); + radeon_set_context_reg(ctx_cs, R_0286C4_SPI_VS_OUT_CONFIG, shader->info.regs.vs.spi_vs_out_config); + radeon_set_context_reg(ctx_cs, R_02870C_SPI_SHADER_POS_FORMAT, shader->info.regs.vs.spi_shader_pos_format); + radeon_set_context_reg(ctx_cs, R_02881C_PA_CL_VS_OUT_CNTL, shader->info.regs.vs.pa_cl_vs_out_cntl); if (pdev->info.gfx_level <= GFX8) - radeon_set_context_reg(ctx_cs, R_028AB4_VGT_REUSE_OFF, outinfo->writes_viewport_index); - - unsigned late_alloc_wave64, cu_mask; - ac_compute_late_alloc(&pdev->info, false, false, shader->config.scratch_bytes_per_wave > 0, &late_alloc_wave64, - &cu_mask); + radeon_set_context_reg(ctx_cs, R_028AB4_VGT_REUSE_OFF, shader->info.regs.vs.vgt_reuse_off); if (pdev->info.gfx_level >= GFX7) { - radeon_set_sh_reg_idx( - pdev, cs, R_00B118_SPI_SHADER_PGM_RSRC3_VS, 3, - ac_apply_cu_en(S_00B118_CU_EN(cu_mask) | S_00B118_WAVE_LIMIT(0x3F), C_00B118_CU_EN, 0, &pdev->info)); - radeon_set_sh_reg(cs, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, S_00B11C_LIMIT(late_alloc_wave64)); + radeon_set_sh_reg_idx(pdev, cs, R_00B118_SPI_SHADER_PGM_RSRC3_VS, 3, + shader->info.regs.vs.spi_shader_pgm_rsrc3_vs); + radeon_set_sh_reg(cs, R_00B11C_SPI_SHADER_LATE_ALLOC_VS, shader->info.regs.vs.spi_shader_late_alloc_vs); } - if (pdev->info.gfx_level >= GFX10) { - uint32_t oversub_pc_lines = late_alloc_wave64 ? pdev->info.pc_lines / 4 : 0; - gfx10_emit_ge_pc_alloc(cs, oversub_pc_lines); - /* Required programming for tessellation (legacy pipeline only). */ + if (pdev->info.gfx_level >= GFX10) { + radeon_set_uconfig_reg(cs, R_030980_GE_PC_ALLOC, shader->info.regs.vs.ge_pc_alloc); + if (shader->info.stage == MESA_SHADER_TESS_EVAL) { - radeon_set_context_reg(ctx_cs, R_028A44_VGT_GS_ONCHIP_CNTL, - S_028A44_ES_VERTS_PER_SUBGRP(250) | S_028A44_GS_PRIMS_PER_SUBGRP(126) | - S_028A44_GS_INST_PRIMS_IN_SUBGRP(126)); + radeon_set_context_reg(ctx_cs, R_028A44_VGT_GS_ONCHIP_CNTL, shader->info.regs.vgt_gs_onchip_cntl); } } } @@ -3219,7 +3176,7 @@ radv_emit_hw_gs(const struct radv_device *device, struct radeon_cmdbuf *ctx_cs, radeon_emit(cs, gs->config.rsrc2 | S_00B22C_LDS_SIZE(gs_state->lds_size)); } - radeon_set_context_reg(ctx_cs, R_028A44_VGT_GS_ONCHIP_CNTL, gs->info.regs.gs.vgt_gs_onchip_cntl); + radeon_set_context_reg(ctx_cs, R_028A44_VGT_GS_ONCHIP_CNTL, gs->info.regs.vgt_gs_onchip_cntl); radeon_set_context_reg(ctx_cs, R_028A94_VGT_GS_MAX_PRIMS_PER_SUBGROUP, gs->info.regs.gs.vgt_gs_max_prims_per_subgroup); } else { diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index 0dbd80037f0..f2d1ad8bf9f 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -1461,6 +1461,71 @@ radv_open_rtld_binary(struct radv_device *device, const struct radv_shader_binar } #endif +static void +radv_precompute_registers_hw_vs(struct radv_device *device, struct radv_shader_binary *binary) +{ + const struct radv_physical_device *pdev = radv_device_physical(device); + struct radv_shader_info *info = &binary->info; + + /* VS is required to export at least one param. */ + const uint32_t nparams = MAX2(info->outinfo.param_exports, 1); + info->regs.vs.spi_vs_out_config = S_0286C4_VS_EXPORT_COUNT(nparams - 1); + if (pdev->info.gfx_level >= GFX10) { + info->regs.vs.spi_vs_out_config |= S_0286C4_NO_PC_EXPORT(info->outinfo.param_exports == 0); + } + + info->regs.vs.spi_shader_pos_format = + S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) | + S_02870C_POS1_EXPORT_FORMAT(info->outinfo.pos_exports > 1 ? V_02870C_SPI_SHADER_4COMP + : V_02870C_SPI_SHADER_NONE) | + S_02870C_POS2_EXPORT_FORMAT(info->outinfo.pos_exports > 2 ? V_02870C_SPI_SHADER_4COMP + : V_02870C_SPI_SHADER_NONE) | + S_02870C_POS3_EXPORT_FORMAT(info->outinfo.pos_exports > 3 ? V_02870C_SPI_SHADER_4COMP : V_02870C_SPI_SHADER_NONE); + + const bool misc_vec_ena = info->outinfo.writes_pointsize || info->outinfo.writes_layer || + info->outinfo.writes_viewport_index || info->outinfo.writes_primitive_shading_rate; + const unsigned clip_dist_mask = info->outinfo.clip_dist_mask; + const unsigned cull_dist_mask = info->outinfo.cull_dist_mask; + const unsigned total_mask = clip_dist_mask | cull_dist_mask; + + info->regs.vs.pa_cl_vs_out_cntl = + S_02881C_USE_VTX_POINT_SIZE(info->outinfo.writes_pointsize) | + S_02881C_USE_VTX_RENDER_TARGET_INDX(info->outinfo.writes_layer) | + S_02881C_USE_VTX_VIEWPORT_INDX(info->outinfo.writes_viewport_index) | + S_02881C_USE_VTX_VRS_RATE(info->outinfo.writes_primitive_shading_rate) | + S_02881C_VS_OUT_MISC_VEC_ENA(misc_vec_ena) | + S_02881C_VS_OUT_MISC_SIDE_BUS_ENA(misc_vec_ena || + (pdev->info.gfx_level >= GFX10_3 && info->outinfo.pos_exports > 1)) | + S_02881C_VS_OUT_CCDIST0_VEC_ENA((total_mask & 0x0f) != 0) | + S_02881C_VS_OUT_CCDIST1_VEC_ENA((total_mask & 0xf0) != 0) | total_mask << 8 | clip_dist_mask; + + if (pdev->info.gfx_level <= GFX8) + info->regs.vs.vgt_reuse_off = info->outinfo.writes_viewport_index; + + unsigned late_alloc_wave64, cu_mask; + ac_compute_late_alloc(&pdev->info, false, false, binary->config.scratch_bytes_per_wave > 0, &late_alloc_wave64, + &cu_mask); + + if (pdev->info.gfx_level >= GFX7) { + info->regs.vs.spi_shader_pgm_rsrc3_vs = + ac_apply_cu_en(S_00B118_CU_EN(cu_mask) | S_00B118_WAVE_LIMIT(0x3F), C_00B118_CU_EN, 0, &pdev->info); + info->regs.vs.spi_shader_late_alloc_vs = S_00B11C_LIMIT(late_alloc_wave64); + + if (pdev->info.gfx_level >= GFX10) { + const uint32_t oversub_pc_lines = late_alloc_wave64 ? pdev->info.pc_lines / 4 : 0; + + info->regs.vs.ge_pc_alloc = + S_030980_OVERSUB_EN(oversub_pc_lines > 0) | S_030980_NUM_PC_LINES(oversub_pc_lines - 1); + + /* Required programming for tessellation (legacy pipeline only). */ + if (binary->info.stage == MESA_SHADER_TESS_EVAL) { + info->regs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(250) | S_028A44_GS_PRIMS_PER_SUBGRP(126) | + S_028A44_GS_INST_PRIMS_IN_SUBGRP(126); + } + } + } +} + static void radv_precompute_registers_hw_gs(struct radv_device *device, struct radv_shader_binary *binary) { @@ -1472,9 +1537,9 @@ radv_precompute_registers_hw_gs(struct radv_device *device, struct radv_shader_b info->regs.gs.vgt_gs_max_prims_per_subgroup = S_028A94_MAX_PRIMS_PER_SUBGROUP(info->gs_ring_info.gs_inst_prims_in_subgroup); - info->regs.gs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(info->gs_ring_info.es_verts_per_subgroup) | - S_028A44_GS_PRIMS_PER_SUBGRP(info->gs_ring_info.gs_prims_per_subgroup) | - S_028A44_GS_INST_PRIMS_IN_SUBGRP(info->gs_ring_info.gs_inst_prims_in_subgroup); + info->regs.vgt_gs_onchip_cntl = S_028A44_ES_VERTS_PER_SUBGRP(info->gs_ring_info.es_verts_per_subgroup) | + S_028A44_GS_PRIMS_PER_SUBGRP(info->gs_ring_info.gs_prims_per_subgroup) | + S_028A44_GS_INST_PRIMS_IN_SUBGRP(info->gs_ring_info.gs_inst_prims_in_subgroup); const uint32_t gs_max_out_vertices = info->gs.vertices_out; const uint8_t max_stream = info->gs.max_stream; @@ -1566,6 +1631,14 @@ radv_precompute_registers(struct radv_device *device, struct radv_shader_binary struct radv_shader_info *info = &binary->info; switch (info->stage) { + case MESA_SHADER_VERTEX: + if (!info->vs.as_ls && !info->vs.as_es && !info->is_ngg) + radv_precompute_registers_hw_vs(device, binary); + break; + case MESA_SHADER_TESS_EVAL: + if (!info->is_ngg && !info->tes.as_es) + radv_precompute_registers_hw_vs(device, binary); + break; case MESA_SHADER_GEOMETRY: if (!info->is_ngg) radv_precompute_registers_hw_gs(device, binary); diff --git a/src/amd/vulkan/radv_shader_info.h b/src/amd/vulkan/radv_shader_info.h index 20a2724b1ba..5341d89bf98 100644 --- a/src/amd/vulkan/radv_shader_info.h +++ b/src/amd/vulkan/radv_shader_info.h @@ -253,13 +253,23 @@ struct radv_shader_info { /* Precomputed register values. */ struct { + struct { + uint32_t ge_pc_alloc; + uint32_t pa_cl_vs_out_cntl; + uint32_t spi_shader_late_alloc_vs; + uint32_t spi_shader_pgm_rsrc3_vs; + uint32_t spi_shader_pos_format; + uint32_t spi_vs_out_config; + uint32_t vgt_gs_instance_cnt; + uint32_t vgt_reuse_off; + } vs; + struct { uint32_t spi_shader_pgm_rsrc3_gs; uint32_t spi_shader_pgm_rsrc4_gs; uint32_t vgt_esgs_ring_itemsize; uint32_t vgt_gs_instance_cnt; uint32_t vgt_gs_max_prims_per_subgroup; - uint32_t vgt_gs_onchip_cntl; uint32_t vgt_gs_vert_itemsize[4]; uint32_t vgt_gsvs_ring_itemsize; uint32_t vgt_gsvs_ring_offset[3]; @@ -285,6 +295,7 @@ struct radv_shader_info { /* Common registers between stages. */ uint32_t vgt_gs_max_vert_out; + uint32_t vgt_gs_onchip_cntl; } regs; };