2023-05-25 13:22:45 -04:00
|
|
|
/*
|
|
|
|
|
* Copyright 2023 Alyssa Rosenzweig
|
|
|
|
|
* Copyright 2021 Intel Corporation
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
2024-01-09 15:50:27 -04:00
|
|
|
#include "nir.h"
|
2023-05-25 13:22:45 -04:00
|
|
|
#include "nir_builder.h"
|
|
|
|
|
|
2025-04-14 22:53:46 +01:00
|
|
|
static nir_def *
|
|
|
|
|
alpha_to_coverage(nir_builder *b, nir_def *alpha, uint8_t nr_samples, bool has_intrinsic)
|
|
|
|
|
{
|
|
|
|
|
if (has_intrinsic)
|
|
|
|
|
return nir_alpha_to_coverage(b, alpha);
|
|
|
|
|
|
|
|
|
|
/* Calculate a coverage mask (alpha * nr_samples) bits set. The way we do
|
|
|
|
|
* this isn't particularly clever:
|
|
|
|
|
*
|
|
|
|
|
* # of bits = (unsigned int) (alpha * nr_samples)
|
|
|
|
|
* mask = (1 << (# of bits)) - 1
|
|
|
|
|
*/
|
|
|
|
|
nir_def *bits = nir_f2u32(b, nir_fmul_imm(b, alpha, nr_samples));
|
|
|
|
|
return nir_iadd_imm(b, nir_ishl(b, nir_imm_intN_t(b, 1, 16), bits), -1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-25 13:22:45 -04:00
|
|
|
/*
|
|
|
|
|
* Lower alpha-to-coverage to sample_mask and some math. May run on either a
|
|
|
|
|
* monolithic pixel shader or a fragment epilogue.
|
|
|
|
|
*/
|
2024-01-09 15:50:27 -04:00
|
|
|
bool
|
2025-08-28 17:14:20 +01:00
|
|
|
nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples, bool has_intrinsic, nir_def *dyn_enable)
|
2023-05-25 13:22:45 -04:00
|
|
|
{
|
2025-08-04 10:13:21 +01:00
|
|
|
/* If we are not using the intrinsic we need to know the sample count. */
|
|
|
|
|
assert(has_intrinsic || nr_samples);
|
|
|
|
|
|
2023-05-25 13:22:45 -04:00
|
|
|
/* nir_lower_io_to_temporaries ensures that stores are in the last block */
|
|
|
|
|
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
|
|
|
|
|
nir_block *block = nir_impl_last_block(impl);
|
|
|
|
|
|
|
|
|
|
/* The store is probably at the end of the block, so search in reverse. */
|
|
|
|
|
nir_intrinsic_instr *store = NULL;
|
|
|
|
|
nir_foreach_instr_reverse(instr, block) {
|
|
|
|
|
if (instr->type != nir_instr_type_intrinsic)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
|
|
|
|
if (intr->intrinsic != nir_intrinsic_store_output)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
|
|
|
|
|
if (sem.location != FRAG_RESULT_DATA0)
|
|
|
|
|
continue;
|
|
|
|
|
if (sem.dual_source_blend_index != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
store = intr;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If render target 0 isn't written, the alpha value input to
|
|
|
|
|
* alpha-to-coverage is undefined. We assume that the alpha would be 1.0,
|
|
|
|
|
* which would effectively disable alpha-to-coverage, skipping the lowering.
|
2024-01-09 15:50:27 -04:00
|
|
|
*
|
|
|
|
|
* Similarly, if there are less than 4 components, alpha is undefined.
|
2023-05-25 13:22:45 -04:00
|
|
|
*/
|
2024-01-09 15:50:27 -04:00
|
|
|
nir_def *rgba = store ? store->src[0].ssa : NULL;
|
|
|
|
|
if (!rgba || rgba->num_components < 4) {
|
treewide: Switch to nir_progress
Via the Coccinelle patch at the end of the commit message, followed by
sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
ninja -C ~/mesa/build clang-format
cd ~/mesa/src/compiler/nir && clang-format -i *.c
agxfmt
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-return true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
-}
+bool progress = prog_expr;
+return nir_progress(progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
+nir_progress(prog, impl, metadata);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-return true;
+return nir_progress(true, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
+return nir_no_progress(impl);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-other_prog |= prog;
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+nir_progress(prog, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-other_prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-other_prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+nir_progress(impl_progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-prog = true;
+prog = nir_progress(true, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
+nir_progress(prog, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
+nir_no_progress(impl);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
+nir_progress(true, impl, metadata);
squashme! sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Acked-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33722>
2025-02-24 15:10:33 -05:00
|
|
|
return nir_no_progress(impl);
|
2024-01-09 15:50:27 -04:00
|
|
|
}
|
2023-05-25 13:22:45 -04:00
|
|
|
|
2023-07-04 22:24:28 -04:00
|
|
|
nir_builder _b = nir_builder_at(nir_before_instr(&store->instr));
|
|
|
|
|
nir_builder *b = &_b;
|
2023-05-25 13:22:45 -04:00
|
|
|
|
2023-08-12 16:17:15 -04:00
|
|
|
nir_def *alpha = nir_channel(b, rgba, 3);
|
2025-08-28 17:14:20 +01:00
|
|
|
if (dyn_enable)
|
|
|
|
|
alpha = nir_bcsel(b, dyn_enable, alpha, nir_imm_floatN_t(b, 1.0f, alpha->bit_size));
|
2025-04-14 22:53:46 +01:00
|
|
|
nir_def *mask = alpha_to_coverage(b, alpha, nr_samples, has_intrinsic);
|
2023-05-25 13:22:45 -04:00
|
|
|
|
|
|
|
|
/* Discard samples that aren't covered */
|
2025-04-08 16:27:11 +01:00
|
|
|
nir_demote_samples(b, nir_inot(b, mask));
|
2023-06-14 12:34:34 -04:00
|
|
|
shader->info.fs.uses_discard = true;
|
treewide: Switch to nir_progress
Via the Coccinelle patch at the end of the commit message, followed by
sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
ninja -C ~/mesa/build clang-format
cd ~/mesa/src/compiler/nir && clang-format -i *.c
agxfmt
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-return true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
-}
+bool progress = prog_expr;
+return nir_progress(progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
+nir_progress(prog, impl, metadata);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-return true;
+return nir_progress(true, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
+return nir_no_progress(impl);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-other_prog |= prog;
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+nir_progress(prog, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-other_prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-other_prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+nir_progress(impl_progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-prog = true;
+prog = nir_progress(true, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
+nir_progress(prog, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
+nir_no_progress(impl);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
+nir_progress(true, impl, metadata);
squashme! sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Acked-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33722>
2025-02-24 15:10:33 -05:00
|
|
|
return nir_progress(true, impl, nir_metadata_control_flow);
|
2023-05-25 13:22:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Modify the inputs to store_output instructions in a pixel shader when
|
|
|
|
|
* alpha-to-one is used. May run on either a monolithic pixel shader or a
|
|
|
|
|
* fragment epilogue.
|
|
|
|
|
*/
|
2024-01-09 15:50:27 -04:00
|
|
|
bool
|
2025-04-08 16:27:11 +01:00
|
|
|
nir_lower_alpha_to_one(nir_shader *shader)
|
2023-05-25 13:22:45 -04:00
|
|
|
{
|
2024-01-09 15:50:27 -04:00
|
|
|
bool progress = false;
|
|
|
|
|
|
2023-05-25 13:22:45 -04:00
|
|
|
/* nir_lower_io_to_temporaries ensures that stores are in the last block */
|
|
|
|
|
nir_function_impl *impl = nir_shader_get_entrypoint(shader);
|
|
|
|
|
nir_block *block = nir_impl_last_block(impl);
|
|
|
|
|
|
|
|
|
|
nir_foreach_instr(instr, block) {
|
|
|
|
|
if (instr->type != nir_instr_type_intrinsic)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
|
|
|
|
if (intr->intrinsic != nir_intrinsic_store_output)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* The OpenGL spec is a bit confusing here, but seemingly alpha-to-one
|
|
|
|
|
* applies to all render targets. Piglit
|
|
|
|
|
* ext_framebuffer_multisample-draw-buffers-alpha-to-one checks this.
|
|
|
|
|
*
|
|
|
|
|
* Even more confusingly, it seems to apply to dual-source blending too.
|
|
|
|
|
* ext_framebuffer_multisample-alpha-to-one-dual-src-blend checks this.
|
|
|
|
|
*/
|
|
|
|
|
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
|
|
|
|
|
if (sem.location < FRAG_RESULT_DATA0)
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-08-12 16:17:15 -04:00
|
|
|
nir_def *rgba = intr->src[0].ssa;
|
2023-05-25 13:22:45 -04:00
|
|
|
if (rgba->num_components < 4)
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-07-04 22:24:28 -04:00
|
|
|
nir_builder b = nir_builder_at(nir_before_instr(instr));
|
2023-08-12 16:17:15 -04:00
|
|
|
nir_def *rgb1 = nir_vector_insert_imm(
|
2023-07-04 22:24:28 -04:00
|
|
|
&b, rgba, nir_imm_floatN_t(&b, 1.0, rgba->bit_size), 3);
|
2023-05-25 13:22:45 -04:00
|
|
|
|
2023-08-17 15:44:47 -05:00
|
|
|
nir_src_rewrite(&intr->src[0], rgb1);
|
2024-01-09 15:50:27 -04:00
|
|
|
progress = true;
|
2023-05-25 13:22:45 -04:00
|
|
|
}
|
2024-01-09 15:50:27 -04:00
|
|
|
|
treewide: Switch to nir_progress
Via the Coccinelle patch at the end of the commit message, followed by
sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
ninja -C ~/mesa/build clang-format
cd ~/mesa/src/compiler/nir && clang-format -i *.c
agxfmt
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-return true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
-}
+bool progress = prog_expr;
+return nir_progress(progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, prog ? (metadata) : nir_metadata_all);
+nir_progress(prog, impl, metadata);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-return true;
+return nir_progress(true, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
-return false;
+return nir_no_progress(impl);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
-other_prog |= prog;
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+nir_progress(prog, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-other_prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-prog = true;
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
identifier other_prog, prog;
expression impl, metadata;
@@
-if (prog) {
-other_prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+other_prog = other_prog | nir_progress(prog, impl, metadata);
@@
expression prog_expr, impl, metadata;
identifier prog;
@@
-if (prog_expr) {
-prog = true;
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+prog = prog | nir_progress(impl_progress, impl, metadata);
@@
expression prog_expr, impl, metadata;
@@
-if (prog_expr) {
-nir_metadata_preserve(impl, metadata);
-} else {
-nir_metadata_preserve(impl, nir_metadata_all);
-}
+bool impl_progress = prog_expr;
+nir_progress(impl_progress, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
-prog = true;
+prog = nir_progress(true, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
-return prog;
+return nir_progress(prog, impl, metadata);
@@
identifier prog;
expression impl, metadata;
@@
-if (prog) {
-nir_metadata_preserve(impl, metadata);
-}
+nir_progress(prog, impl, metadata);
@@
expression impl;
@@
-nir_metadata_preserve(impl, nir_metadata_all);
+nir_no_progress(impl);
@@
expression impl, metadata;
@@
-nir_metadata_preserve(impl, metadata);
+nir_progress(true, impl, metadata);
squashme! sed -ie 's/progress = progress | /progress |=/g' $(git grep -l 'progress = prog')
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Acked-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33722>
2025-02-24 15:10:33 -05:00
|
|
|
return nir_progress(progress, impl, nir_metadata_control_flow);
|
2023-05-25 13:22:45 -04:00
|
|
|
}
|