radeonsi: implement replacing frag_coord with pixel_coord at draw time
This adds an option into the prolog key to replace frag_coord.xy with pixel_coord when sample shading is disabled, which is most of the time. This reduces the number of input VGPRs. It's already implement in ac_nir_lower_ps_early for monolithic shaders and the PS prolog in ACO, so this just implements it for the PS prolog in LLVM IR. Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32910>
This commit is contained in:
@@ -1572,6 +1572,8 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
|
||||
key->ps.part.prolog.bc_optimize_for_linear);
|
||||
fprintf(f, " prolog.samplemask_log_ps_iter = %u\n",
|
||||
key->ps.part.prolog.samplemask_log_ps_iter);
|
||||
fprintf(f, " prolog.get_frag_coord_from_pixel_coord = %u\n",
|
||||
key->ps.part.prolog.get_frag_coord_from_pixel_coord);
|
||||
fprintf(f, " epilog.spi_shader_col_format = 0x%x\n",
|
||||
key->ps.part.epilog.spi_shader_col_format);
|
||||
fprintf(f, " epilog.color_is_int8 = 0x%X\n", key->ps.part.epilog.color_is_int8);
|
||||
@@ -2491,11 +2493,13 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
|
||||
key->ps.mono.interpolate_at_sample_force_center,
|
||||
.load_sample_positions_always_loads_current_ones = true,
|
||||
.force_front_face = key->ps.opt.force_front_face_input,
|
||||
.optimize_frag_coord = true,
|
||||
/* This does a lot of things. See the description in ac_nir_lower_ps_early_options. */
|
||||
.ps_iter_samples = key->ps.part.prolog.samplemask_log_ps_iter ?
|
||||
(1 << key->ps.part.prolog.samplemask_log_ps_iter) :
|
||||
(key->ps.part.prolog.force_persp_sample_interp ||
|
||||
key->ps.part.prolog.force_linear_sample_interp ? 2 : 0),
|
||||
key->ps.part.prolog.force_linear_sample_interp ? 2 :
|
||||
(key->ps.part.prolog.get_frag_coord_from_pixel_coord ? 1 : 0)),
|
||||
|
||||
.fbfetch_is_1D = key->ps.mono.fbfetch_is_1D,
|
||||
.fbfetch_layered = key->ps.mono.fbfetch_layered,
|
||||
@@ -2538,6 +2542,7 @@ static struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_
|
||||
}
|
||||
} else if (nir->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
ac_nir_lower_ps_early_options early_options = {
|
||||
.optimize_frag_coord = true,
|
||||
.alpha_func = COMPARE_FUNC_ALWAYS,
|
||||
.spi_shader_col_format_hint = ~0,
|
||||
};
|
||||
@@ -2908,6 +2913,12 @@ static void si_fixup_spi_ps_input_config(struct si_shader *shader)
|
||||
/* The sample mask fixup has an optimization that replaces the sample mask with the sample ID. */
|
||||
if (key->ps.part.prolog.samplemask_log_ps_iter == 3)
|
||||
shader->config.spi_ps_input_ena &= C_0286CC_SAMPLE_COVERAGE_ENA;
|
||||
|
||||
if (key->ps.part.prolog.get_frag_coord_from_pixel_coord) {
|
||||
shader->config.spi_ps_input_ena &= C_0286CC_POS_X_FLOAT_ENA;
|
||||
shader->config.spi_ps_input_ena &= C_0286CC_POS_Y_FLOAT_ENA;
|
||||
shader->config.spi_ps_input_ena |= S_0286CC_POS_FIXED_PT_ENA(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2921,6 +2932,8 @@ si_set_spi_ps_input_config(struct si_shader *shader)
|
||||
* otherwise LLVM will have a performance advantage here because it determines
|
||||
* VGPR inputs for each shader variant after LLVM optimizations.
|
||||
*/
|
||||
uint8_t frag_coord_mask = info->reads_frag_coord_mask | info->reads_sample_pos_mask;
|
||||
|
||||
shader->config.spi_ps_input_ena =
|
||||
S_0286CC_PERSP_CENTER_ENA(info->uses_persp_center) |
|
||||
S_0286CC_PERSP_CENTROID_ENA(info->uses_persp_centroid) |
|
||||
@@ -2928,14 +2941,16 @@ si_set_spi_ps_input_config(struct si_shader *shader)
|
||||
S_0286CC_LINEAR_CENTER_ENA(info->uses_linear_center) |
|
||||
S_0286CC_LINEAR_CENTROID_ENA(info->uses_linear_centroid) |
|
||||
S_0286CC_LINEAR_SAMPLE_ENA(info->uses_linear_sample) |
|
||||
S_0286CC_POS_X_FLOAT_ENA(!!(frag_coord_mask & 0x1) &&
|
||||
!key->ps.part.prolog.get_frag_coord_from_pixel_coord) |
|
||||
S_0286CC_POS_Y_FLOAT_ENA(!!(frag_coord_mask & 0x2) &&
|
||||
!key->ps.part.prolog.get_frag_coord_from_pixel_coord) |
|
||||
S_0286CC_POS_Z_FLOAT_ENA(!!(frag_coord_mask & 0x4)) |
|
||||
S_0286CC_POS_W_FLOAT_ENA(!!(frag_coord_mask & 0x8)) |
|
||||
S_0286CC_FRONT_FACE_ENA(info->uses_frontface && !key->ps.opt.force_front_face_input) |
|
||||
S_0286CC_SAMPLE_COVERAGE_ENA(info->reads_samplemask) |
|
||||
S_0286CC_ANCILLARY_ENA(info->uses_sampleid || info->uses_layer_id);
|
||||
|
||||
uint8_t mask = info->reads_frag_coord_mask | info->reads_sample_pos_mask;
|
||||
u_foreach_bit(i, mask) {
|
||||
shader->config.spi_ps_input_ena |= S_0286CC_POS_X_FLOAT_ENA(1) << i;
|
||||
}
|
||||
S_0286CC_ANCILLARY_ENA(info->uses_sampleid || info->uses_layer_id) |
|
||||
S_0286CC_POS_FIXED_PT_ENA(key->ps.part.prolog.get_frag_coord_from_pixel_coord);
|
||||
|
||||
if (key->ps.part.prolog.color_two_side)
|
||||
shader->config.spi_ps_input_ena |= S_0286CC_FRONT_FACE_ENA(1);
|
||||
@@ -3316,12 +3331,15 @@ static void si_get_ps_prolog_key(struct si_shader *shader, union si_shader_part_
|
||||
key->ps_prolog.states.force_persp_center_interp ||
|
||||
key->ps_prolog.states.force_linear_center_interp ||
|
||||
key->ps_prolog.states.bc_optimize_for_persp || key->ps_prolog.states.bc_optimize_for_linear ||
|
||||
key->ps_prolog.states.samplemask_log_ps_iter);
|
||||
key->ps_prolog.states.samplemask_log_ps_iter ||
|
||||
key->ps_prolog.states.get_frag_coord_from_pixel_coord);
|
||||
key->ps_prolog.fragcoord_usage_mask =
|
||||
G_0286CC_POS_X_FLOAT_ENA(shader->config.spi_ps_input_ena) |
|
||||
(G_0286CC_POS_Y_FLOAT_ENA(shader->config.spi_ps_input_ena) << 1) |
|
||||
(G_0286CC_POS_Z_FLOAT_ENA(shader->config.spi_ps_input_ena) << 2) |
|
||||
(G_0286CC_POS_W_FLOAT_ENA(shader->config.spi_ps_input_ena) << 3);
|
||||
key->ps_prolog.pixel_center_integer = key->ps_prolog.fragcoord_usage_mask &&
|
||||
shader->selector->info.base.fs.pixel_center_integer;
|
||||
|
||||
if (shader->key.ps.part.prolog.poly_stipple)
|
||||
shader->info.uses_vmem_load_other = true;
|
||||
@@ -3422,7 +3440,8 @@ static bool si_need_ps_prolog(const union si_shader_part_key *key)
|
||||
key->ps_prolog.states.force_linear_center_interp ||
|
||||
key->ps_prolog.states.bc_optimize_for_persp ||
|
||||
key->ps_prolog.states.bc_optimize_for_linear || key->ps_prolog.states.poly_stipple ||
|
||||
key->ps_prolog.states.samplemask_log_ps_iter;
|
||||
key->ps_prolog.states.samplemask_log_ps_iter ||
|
||||
key->ps_prolog.states.get_frag_coord_from_pixel_coord;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -676,6 +676,7 @@ struct si_ps_prolog_bits {
|
||||
unsigned bc_optimize_for_persp : 1;
|
||||
unsigned bc_optimize_for_linear : 1;
|
||||
unsigned samplemask_log_ps_iter : 2;
|
||||
unsigned get_frag_coord_from_pixel_coord : 1;
|
||||
};
|
||||
|
||||
/* Common PS bits between the shader key and the epilog key. */
|
||||
@@ -705,6 +706,7 @@ union si_shader_part_key {
|
||||
unsigned colors_read : 8; /* color input components read */
|
||||
unsigned num_interp_inputs : 5; /* BCOLOR is at this location */
|
||||
unsigned fragcoord_usage_mask : 4;
|
||||
unsigned pixel_center_integer : 1;
|
||||
unsigned wqm : 1;
|
||||
char color_attr_index[2];
|
||||
signed char color_interp_vgpr_index[2]; /* -1 == constant */
|
||||
|
||||
@@ -278,6 +278,8 @@ si_aco_build_ps_prolog(struct aco_compiler_options *options,
|
||||
.force_linear_center_interp = key->ps_prolog.states.force_linear_center_interp,
|
||||
|
||||
.samplemask_log_ps_iter = key->ps_prolog.states.samplemask_log_ps_iter,
|
||||
.get_frag_coord_from_pixel_coord = key->ps_prolog.states.get_frag_coord_from_pixel_coord,
|
||||
.pixel_center_integer = key->ps_prolog.pixel_center_integer,
|
||||
.num_interp_inputs = key->ps_prolog.num_interp_inputs,
|
||||
.colors_read = key->ps_prolog.colors_read,
|
||||
.color_interp_vgpr_index[0] = key->ps_prolog.color_interp_vgpr_index[0],
|
||||
|
||||
@@ -656,6 +656,28 @@ void si_llvm_build_ps_prolog(struct si_shader_context *ctx, union si_shader_part
|
||||
ret = insert_ret_of_arg(ctx, ret, sample_mask_in, args->ac.sample_coverage.arg_index);
|
||||
}
|
||||
|
||||
if (key->ps_prolog.states.get_frag_coord_from_pixel_coord) {
|
||||
LLVMValueRef pixel_coord = ac_get_arg(&ctx->ac, args->ac.pos_fixed_pt);
|
||||
pixel_coord = LLVMBuildBitCast(ctx->ac.builder, pixel_coord, ctx->ac.v2i16, "");
|
||||
pixel_coord = LLVMBuildUIToFP(ctx->ac.builder, pixel_coord, ctx->ac.v2f32, "");
|
||||
|
||||
if (!key->ps_prolog.pixel_center_integer) {
|
||||
LLVMValueRef vec2_half = LLVMConstVector((LLVMValueRef[]){LLVMConstReal(ctx->ac.f32, 0.5),
|
||||
LLVMConstReal(ctx->ac.f32, 0.5)}, 2);
|
||||
pixel_coord = LLVMBuildFAdd(ctx->ac.builder, pixel_coord, vec2_half, "");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
if (!args->ac.frag_pos[i].used)
|
||||
continue;
|
||||
|
||||
ret = insert_ret_of_arg(ctx, ret,
|
||||
LLVMBuildExtractElement(ctx->ac.builder, pixel_coord,
|
||||
LLVMConstInt(ctx->ac.i32, i, 0), ""),
|
||||
args->ac.frag_pos[i].arg_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tell LLVM to insert WQM instruction sequence when needed. */
|
||||
if (key->ps_prolog.wqm) {
|
||||
LLVMAddTargetDependentFunctionAttr(func, "amdgpu-ps-wqm-outputs", "");
|
||||
@@ -754,4 +776,3 @@ void si_llvm_build_ps_epilog(struct si_shader_context *ctx, union si_shader_part
|
||||
/* Compile. */
|
||||
LLVMBuildRetVoid(ctx->ac.builder);
|
||||
}
|
||||
|
||||
|
||||
@@ -2874,6 +2874,8 @@ void si_ps_key_update_framebuffer_rasterizer_sample_shading(struct si_context *s
|
||||
uses_persp_center && uses_persp_centroid;
|
||||
key->ps.part.prolog.bc_optimize_for_linear =
|
||||
sel->info.uses_linear_center && sel->info.uses_linear_centroid;
|
||||
key->ps.part.prolog.get_frag_coord_from_pixel_coord =
|
||||
!sel->info.base.fs.uses_sample_shading && sel->info.reads_frag_coord_mask & 0x3;
|
||||
key->ps.mono.interpolate_at_sample_force_center = 0;
|
||||
} else {
|
||||
key->ps.part.prolog.force_persp_sample_interp = 0;
|
||||
@@ -2890,6 +2892,8 @@ void si_ps_key_update_framebuffer_rasterizer_sample_shading(struct si_context *s
|
||||
sel->info.uses_linear_sample > 1;
|
||||
key->ps.part.prolog.bc_optimize_for_persp = 0;
|
||||
key->ps.part.prolog.bc_optimize_for_linear = 0;
|
||||
key->ps.part.prolog.get_frag_coord_from_pixel_coord =
|
||||
!!(sel->info.reads_frag_coord_mask & 0x3);
|
||||
key->ps.mono.interpolate_at_sample_force_center = sel->info.uses_interp_at_sample;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user