diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index 26d362b7d13..d00b9ad9087 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -1576,6 +1576,8 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f) 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, " prolog.force_samplemask_to_helper_invocation = %u\n", + key->ps.part.prolog.force_samplemask_to_helper_invocation); 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); @@ -2302,6 +2304,7 @@ static bool run_pre_link_optimization_passes(struct si_nir_shader_ctx *ctx) ac_nir_lower_ps_early_options early_options = { .force_center_interp_no_msaa = key->ps.part.prolog.force_persp_center_interp || key->ps.part.prolog.force_linear_center_interp || + key->ps.part.prolog.force_samplemask_to_helper_invocation || 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, @@ -2331,7 +2334,11 @@ static bool run_pre_link_optimization_passes(struct si_nir_shader_ctx *ctx) NIR_PASS(progress, nir, ac_nir_lower_ps_early, &early_options); - /* This adds gl_SampleMaskIn. */ + /* This adds gl_SampleMaskIn. It must be after ac_nir_lower_ps_early that lowers + * sample_mask_in to load_helper_invocation because we only want to do that for user + * shaders while keeping the real sample mask for smoothing, which is produced using + * MSAA overrasterization over a single-sample color buffer. + */ if (key->ps.mono.poly_line_smoothing) NIR_PASS(progress, nir, nir_lower_poly_line_smooth, SI_NUM_SMOOTH_AA_SAMPLES); @@ -2704,6 +2711,12 @@ static void si_set_spi_ps_input_config_for_separate_prolog(struct si_shader *sha if (key->ps.part.prolog.samplemask_log_ps_iter) shader->config.spi_ps_input_ena |= S_0286CC_ANCILLARY_ENA(1); + if (key->ps.part.prolog.force_samplemask_to_helper_invocation) { + assert(key->ps.part.prolog.samplemask_log_ps_iter == 0); + assert(!key->ps.mono.poly_line_smoothing); + shader->config.spi_ps_input_ena &= C_0286CC_SAMPLE_COVERAGE_ENA; + } + /* 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; @@ -3342,7 +3355,8 @@ static void si_get_ps_prolog_key(struct si_shader *shader, union si_shader_part_ 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.get_frag_coord_from_pixel_coord); + key->ps_prolog.states.get_frag_coord_from_pixel_coord || + key->ps_prolog.states.force_samplemask_to_helper_invocation); 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) | @@ -3451,7 +3465,8 @@ static bool si_need_ps_prolog(const union si_shader_part_key *key) 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.get_frag_coord_from_pixel_coord; + key->ps_prolog.states.get_frag_coord_from_pixel_coord || + key->ps_prolog.states.force_samplemask_to_helper_invocation; } /** diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h index 6e5596e6c98..480af85add9 100644 --- a/src/gallium/drivers/radeonsi/si_shader.h +++ b/src/gallium/drivers/radeonsi/si_shader.h @@ -677,6 +677,7 @@ struct si_ps_prolog_bits { unsigned bc_optimize_for_linear : 1; unsigned samplemask_log_ps_iter : 2; unsigned get_frag_coord_from_pixel_coord : 1; + unsigned force_samplemask_to_helper_invocation : 1; }; /* Common PS bits between the shader key and the epilog key. */ diff --git a/src/gallium/drivers/radeonsi/si_shader_aco.c b/src/gallium/drivers/radeonsi/si_shader_aco.c index 70ab0794b01..e0f64f0bcb4 100644 --- a/src/gallium/drivers/radeonsi/si_shader_aco.c +++ b/src/gallium/drivers/radeonsi/si_shader_aco.c @@ -270,6 +270,7 @@ si_aco_build_ps_prolog(struct aco_compiler_options *options, .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, + .force_samplemask_to_helper_invocation = key->ps_prolog.states.force_samplemask_to_helper_invocation, .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], diff --git a/src/gallium/drivers/radeonsi/si_shader_llvm_ps.c b/src/gallium/drivers/radeonsi/si_shader_llvm_ps.c index b555d17e604..8788df3be28 100644 --- a/src/gallium/drivers/radeonsi/si_shader_llvm_ps.c +++ b/src/gallium/drivers/radeonsi/si_shader_llvm_ps.c @@ -655,6 +655,13 @@ void si_llvm_build_ps_prolog(struct si_shader_context *ctx, union si_shader_part sample_mask_in = ac_to_float(&ctx->ac, sample_mask_in); ret = insert_ret_of_arg(ctx, ret, sample_mask_in, args->ac.sample_coverage.arg_index); + } else if (key->ps_prolog.states.force_samplemask_to_helper_invocation) { + LLVMValueRef sample_mask_in = + LLVMBuildZExt(ctx->ac.builder, + LLVMBuildNot(ctx->ac.builder, ac_build_load_helper_invocation(&ctx->ac), ""), + ctx->ac.i32, ""); + ret = insert_ret_of_arg(ctx, ret, ac_to_float(&ctx->ac, sample_mask_in), + args->ac.sample_coverage.arg_index); } if (key->ps_prolog.states.get_frag_coord_from_pixel_coord) { diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.cpp b/src/gallium/drivers/radeonsi/si_state_shaders.cpp index 20dd6844a90..1b7c6140744 100644 --- a/src/gallium/drivers/radeonsi/si_state_shaders.cpp +++ b/src/gallium/drivers/radeonsi/si_state_shaders.cpp @@ -2864,6 +2864,7 @@ void si_ps_key_update_framebuffer_rasterizer_sample_shading(struct si_context *s key->ps.part.prolog.force_linear_center_interp = 0; key->ps.part.prolog.bc_optimize_for_persp = 0; key->ps.part.prolog.bc_optimize_for_linear = 0; + key->ps.part.prolog.force_samplemask_to_helper_invocation = 0; key->ps.mono.interpolate_at_sample_force_center = 0; } else if (rs->multisample_enable && sctx->framebuffer.nr_samples > 1) { key->ps.part.prolog.force_persp_sample_interp = 0; @@ -2876,6 +2877,7 @@ void si_ps_key_update_framebuffer_rasterizer_sample_shading(struct si_context *s 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.part.prolog.force_samplemask_to_helper_invocation = 0; key->ps.mono.interpolate_at_sample_force_center = 0; } else { key->ps.part.prolog.force_persp_sample_interp = 0; @@ -2894,6 +2896,7 @@ void si_ps_key_update_framebuffer_rasterizer_sample_shading(struct si_context *s 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.part.prolog.force_samplemask_to_helper_invocation = sel->info.reads_samplemask; key->ps.mono.interpolate_at_sample_force_center = sel->info.uses_interp_at_sample; }