• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Alyssa Rosenzweig
3  * Copyright 2021 Intel Corporation
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "agx_tilebuffer.h"
8 #include "nir.h"
9 #include "nir_builder.h"
10 
11 /*
12  * Lower alpha-to-coverage to sample_mask and some math. May run on either a
13  * monolithic pixel shader or a fragment epilogue.
14  */
15 bool
agx_nir_lower_alpha_to_coverage(nir_shader * shader,uint8_t nr_samples)16 agx_nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples)
17 {
18    /* nir_lower_io_to_temporaries ensures that stores are in the last block */
19    nir_function_impl *impl = nir_shader_get_entrypoint(shader);
20    nir_block *block = nir_impl_last_block(impl);
21 
22    /* The store is probably at the end of the block, so search in reverse. */
23    nir_intrinsic_instr *store = NULL;
24    nir_foreach_instr_reverse(instr, block) {
25       if (instr->type != nir_instr_type_intrinsic)
26          continue;
27 
28       nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
29       if (intr->intrinsic != nir_intrinsic_store_output)
30          continue;
31 
32       nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
33       if (sem.location != FRAG_RESULT_DATA0)
34          continue;
35       if (sem.dual_source_blend_index != 0)
36          continue;
37 
38       store = intr;
39       break;
40    }
41 
42    /* If render target 0 isn't written, the alpha value input to
43     * alpha-to-coverage is undefined. We assume that the alpha would be 1.0,
44     * which would effectively disable alpha-to-coverage, skipping the lowering.
45     *
46     * Similarly, if there are less than 4 components, alpha is undefined.
47     */
48    nir_def *rgba = store ? store->src[0].ssa : NULL;
49    if (!rgba || rgba->num_components < 4) {
50       nir_metadata_preserve(impl, nir_metadata_all);
51       return false;
52    }
53 
54    nir_builder _b = nir_builder_at(nir_before_instr(&store->instr));
55    nir_builder *b = &_b;
56 
57    /* Calculate a coverage mask (alpha * nr_samples) bits set. The way we do
58     * this isn't particularly clever:
59     *
60     *    # of bits = (unsigned int) (alpha * nr_samples)
61     *    mask = (1 << (# of bits)) - 1
62     */
63    nir_def *alpha = nir_channel(b, rgba, 3);
64    nir_def *bits = nir_f2u32(b, nir_fmul_imm(b, alpha, nr_samples));
65    nir_def *mask =
66       nir_iadd_imm(b, nir_ishl(b, nir_imm_intN_t(b, 1, 16), bits), -1);
67 
68    /* Discard samples that aren't covered */
69    nir_discard_agx(b, nir_inot(b, mask));
70    shader->info.fs.uses_discard = true;
71    nir_metadata_preserve(impl,
72                          nir_metadata_dominance | nir_metadata_block_index);
73    return true;
74 }
75 
76 /*
77  * Modify the inputs to store_output instructions in a pixel shader when
78  * alpha-to-one is used. May run on either a monolithic pixel shader or a
79  * fragment epilogue.
80  */
81 bool
agx_nir_lower_alpha_to_one(nir_shader * shader)82 agx_nir_lower_alpha_to_one(nir_shader *shader)
83 {
84    bool progress = false;
85 
86    /* nir_lower_io_to_temporaries ensures that stores are in the last block */
87    nir_function_impl *impl = nir_shader_get_entrypoint(shader);
88    nir_block *block = nir_impl_last_block(impl);
89 
90    nir_foreach_instr(instr, block) {
91       if (instr->type != nir_instr_type_intrinsic)
92          continue;
93 
94       nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
95       if (intr->intrinsic != nir_intrinsic_store_output)
96          continue;
97 
98       /* The OpenGL spec is a bit confusing here, but seemingly alpha-to-one
99        * applies to all render targets. Piglit
100        * ext_framebuffer_multisample-draw-buffers-alpha-to-one checks this.
101        *
102        * Even more confusingly, it seems to apply to dual-source blending too.
103        * ext_framebuffer_multisample-alpha-to-one-dual-src-blend checks this.
104        */
105       nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
106       if (sem.location < FRAG_RESULT_DATA0)
107          continue;
108 
109       nir_def *rgba = intr->src[0].ssa;
110       if (rgba->num_components < 4)
111          continue;
112 
113       nir_builder b = nir_builder_at(nir_before_instr(instr));
114       nir_def *rgb1 = nir_vector_insert_imm(
115          &b, rgba, nir_imm_floatN_t(&b, 1.0, rgba->bit_size), 3);
116 
117       nir_src_rewrite(&intr->src[0], rgb1);
118       progress = true;
119    }
120 
121    if (progress) {
122       nir_metadata_preserve(impl,
123                             nir_metadata_block_index | nir_metadata_dominance);
124    } else {
125       nir_metadata_preserve(impl, nir_metadata_all);
126    }
127 
128    return progress;
129 }
130