diff --git a/src/gallium/drivers/crocus/crocus_state.c b/src/gallium/drivers/crocus/crocus_state.c index 2793ecfbd0f..6bf0f228e60 100644 --- a/src/gallium/drivers/crocus/crocus_state.c +++ b/src/gallium/drivers/crocus/crocus_state.c @@ -4836,7 +4836,8 @@ crocus_populate_fs_key(const struct crocus_context *ice, key->clamp_fragment_color = rast->cso.clamp_fragment_color; - key->alpha_to_coverage = blend->cso.alpha_to_coverage; + key->alpha_to_coverage = blend->cso.alpha_to_coverage ? + BRW_ALWAYS : BRW_NEVER; key->alpha_test_replicate_alpha = fb->nr_cbufs > 1 && zsa->cso.alpha_enabled; diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index ffda6797033..f168d2d3a5b 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -157,7 +157,7 @@ iris_to_brw_fs_key(const struct iris_screen *screen, .nr_color_regions = key->nr_color_regions, .flat_shade = key->flat_shade, .alpha_test_replicate_alpha = key->alpha_test_replicate_alpha, - .alpha_to_coverage = key->alpha_to_coverage, + .alpha_to_coverage = key->alpha_to_coverage ? BRW_ALWAYS : BRW_NEVER, .clamp_fragment_color = key->clamp_fragment_color, .persample_interp = key->persample_interp ? BRW_ALWAYS : BRW_NEVER, .multisample_fbo = key->multisample_fbo ? BRW_ALWAYS : BRW_NEVER, diff --git a/src/intel/compiler/brw_compiler.h b/src/intel/compiler/brw_compiler.h index 0efcaa1e224..dbfc5eabf07 100644 --- a/src/intel/compiler/brw_compiler.h +++ b/src/intel/compiler/brw_compiler.h @@ -487,9 +487,11 @@ struct brw_wm_prog_key { bool emit_alpha_test:1; enum compare_func alpha_test_func:3; /* < For Gfx4/5 MRT alpha test */ bool alpha_test_replicate_alpha:1; - bool alpha_to_coverage:1; + enum brw_sometimes alpha_to_coverage:2; bool clamp_fragment_color:1; + bool force_dual_color_blend:1; + /** Whether or inputs are interpolated at sample rate by default * * This corresponds to the sample shading API bit in Vulkan or OpenGL which @@ -504,12 +506,12 @@ struct brw_wm_prog_key { enum brw_sometimes multisample_fbo:2; enum brw_sometimes line_aa:2; - bool force_dual_color_blend:1; + bool coherent_fb_fetch:1; bool ignore_sample_mask_out:1; bool coarse_pixel:1; - uint64_t padding:56; + uint64_t padding:55; }; struct brw_cs_prog_key { @@ -863,6 +865,9 @@ enum brw_wm_msaa_flags { /** True if inputs should be interpolated per-sample by default */ BRW_WM_MSAA_FLAG_PERSAMPLE_INTERP = (1 << 3), + /** True if this shader has been dispatched with alpha-to-coverage */ + BRW_WM_MSAA_FLAG_ALPHA_TO_COVERAGE = (1 << 4), + /** True if this shader has been dispatched coarse * * This is intentionally chose to be bit 15 to correspond to the coarse bit @@ -949,6 +954,12 @@ struct brw_wm_prog_data { */ enum brw_sometimes coarse_pixel_dispatch; + /** + * Shader writes the SampleMask and this is AND-ed with the API's + * SampleMask to generate a new coverage mask. + */ + enum brw_sometimes alpha_to_coverage; + unsigned msaa_flags_param; /** diff --git a/src/intel/compiler/brw_fs.cpp b/src/intel/compiler/brw_fs.cpp index 792432ab9e5..181e08d8ce4 100644 --- a/src/intel/compiler/brw_fs.cpp +++ b/src/intel/compiler/brw_fs.cpp @@ -7303,6 +7303,14 @@ brw_nir_populate_wm_prog_data(const nir_shader *shader, prog_data->persample_dispatch = MIN2(prog_data->persample_dispatch, key->multisample_fbo); + /* Currently only the Vulkan API allows alpha_to_coverage to be dynamic. If + * persample_dispatch & multisample_fbo are not dynamic, Anv should be able + * to definitively tell whether alpha_to_coverage is on or off. + */ + prog_data->alpha_to_coverage = key->alpha_to_coverage; + assert(prog_data->alpha_to_coverage != BRW_SOMETIMES || + prog_data->persample_dispatch == BRW_SOMETIMES); + if (devinfo->ver >= 6) { prog_data->uses_sample_mask = BITSET_TEST(shader->info.system_values_read, SYSTEM_VALUE_SAMPLE_MASK_IN); @@ -7411,13 +7419,13 @@ brw_compile_fs(const struct brw_compiler *compiler, * "If Pixel Shader outputs oMask, AlphaToCoverage is disabled in * hardware, regardless of the state setting for this feature." */ - if (devinfo->ver > 6 && key->alpha_to_coverage) { + if (devinfo->ver > 6 && key->alpha_to_coverage != BRW_NEVER) { /* Run constant fold optimization in order to get the correct source * offset to determine render target 0 store instruction in * emit_alpha_to_coverage pass. */ NIR_PASS_V(nir, nir_opt_constant_folding); - NIR_PASS_V(nir, brw_nir_lower_alpha_to_coverage); + NIR_PASS_V(nir, brw_nir_lower_alpha_to_coverage, key, prog_data); } NIR_PASS_V(nir, brw_nir_move_interpolation_to_top); diff --git a/src/intel/compiler/brw_nir.h b/src/intel/compiler/brw_nir.h index b11a36a34e2..88844922424 100644 --- a/src/intel/compiler/brw_nir.h +++ b/src/intel/compiler/brw_nir.h @@ -109,7 +109,9 @@ brw_nir_link_shaders(const struct brw_compiler *compiler, nir_shader *producer, nir_shader *consumer); bool brw_nir_lower_cs_intrinsics(nir_shader *nir); -bool brw_nir_lower_alpha_to_coverage(nir_shader *shader); +bool brw_nir_lower_alpha_to_coverage(nir_shader *shader, + const struct brw_wm_prog_key *key, + const struct brw_wm_prog_data *prog_data); void brw_nir_lower_vs_inputs(nir_shader *nir, bool edgeflag_is_last, const uint8_t *vs_attrib_wa_flags); diff --git a/src/intel/compiler/brw_nir_lower_alpha_to_coverage.c b/src/intel/compiler/brw_nir_lower_alpha_to_coverage.c index 2f07ed451bb..55020616fd5 100644 --- a/src/intel/compiler/brw_nir_lower_alpha_to_coverage.c +++ b/src/intel/compiler/brw_nir_lower_alpha_to_coverage.c @@ -78,9 +78,13 @@ build_dither_mask(nir_builder *b, nir_ssa_def *color) } bool -brw_nir_lower_alpha_to_coverage(nir_shader *shader) +brw_nir_lower_alpha_to_coverage(nir_shader *shader, + const struct brw_wm_prog_key *key, + const struct brw_wm_prog_data *prog_data) { assert(shader->info.stage == MESA_SHADER_FRAGMENT); + assert(key->alpha_to_coverage != BRW_NEVER); + nir_function_impl *impl = nir_shader_get_entrypoint(shader); const uint64_t outputs_written = shader->info.outputs_written; @@ -168,8 +172,21 @@ brw_nir_lower_alpha_to_coverage(nir_shader *shader) /* Combine dither_mask and the gl_SampleMask value */ b.cursor = nir_before_instr(&sample_mask_write->instr); + nir_ssa_def *dither_mask = build_dither_mask(&b, color0); dither_mask = nir_iand(&b, sample_mask, dither_mask); + + if (key->alpha_to_coverage == BRW_SOMETIMES) { + nir_ssa_def *push_flags = + nir_load_uniform(&b, 1, 32, nir_imm_int(&b, prog_data->msaa_flags_param * 4)); + nir_ssa_def *alpha_to_coverage = + nir_i2b(&b, + nir_iadd_imm(&b, push_flags, + BRW_WM_MSAA_FLAG_ALPHA_TO_COVERAGE)); + dither_mask = nir_bcsel(&b, alpha_to_coverage, + dither_mask, sample_mask_write->src[0].ssa); + } + nir_instr_rewrite_src(&sample_mask_write->instr, &sample_mask_write->src[0], nir_src_for_ssa(dither_mask)); diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index c0e69cdc481..016f6355195 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -546,7 +546,8 @@ populate_wm_prog_key(const struct anv_graphics_pipeline *pipeline, * code to workaround the issue that hardware disables alpha to coverage * when there is SampleMask output. */ - key->alpha_to_coverage = ms != NULL && ms->alpha_to_coverage_enable; + key->alpha_to_coverage = ms != NULL && ms->alpha_to_coverage_enable ? + BRW_ALWAYS : BRW_NEVER; /* Vulkan doesn't support fixed-function alpha test */ key->alpha_test_replicate_alpha = false; diff --git a/src/intel/vulkan_hasvk/anv_pipeline.c b/src/intel/vulkan_hasvk/anv_pipeline.c index bf9cbbc41ce..03fda25acfc 100644 --- a/src/intel/vulkan_hasvk/anv_pipeline.c +++ b/src/intel/vulkan_hasvk/anv_pipeline.c @@ -363,7 +363,8 @@ populate_wm_prog_key(const struct anv_graphics_pipeline *pipeline, * code to workaround the issue that hardware disables alpha to coverage * when there is SampleMask output. */ - key->alpha_to_coverage = ms != NULL && ms->alpha_to_coverage_enable; + key->alpha_to_coverage = ms != NULL && ms->alpha_to_coverage_enable ? + BRW_ALWAYS : BRW_NEVER; /* Vulkan doesn't support fixed-function alpha test */ key->alpha_test_replicate_alpha = false;