• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2021 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "nir.h"
25 #include "nir_builder.h"
26 
27 static bool
lower_single_sampled_instr(nir_builder * b,nir_intrinsic_instr * intrin,UNUSED void * cb_data)28 lower_single_sampled_instr(nir_builder *b,
29                            nir_intrinsic_instr *intrin,
30                            UNUSED void *cb_data)
31 {
32    nir_def *lowered;
33    switch (intrin->intrinsic) {
34    case nir_intrinsic_load_sample_id:
35       b->cursor = nir_before_instr(&intrin->instr);
36       lowered = nir_imm_int(b, 0);
37       break;
38 
39    case nir_intrinsic_load_sample_pos:
40       b->cursor = nir_before_instr(&intrin->instr);
41       lowered = nir_imm_vec2(b, 0.5, 0.5);
42       break;
43 
44    case nir_intrinsic_load_sample_mask_in:
45       /* Don't lower to helper invocations if helper invocations are going
46        * to be lowered right back to sample mask.
47        */
48       if (b->shader->options->lower_helper_invocation)
49          return false;
50 
51       b->cursor = nir_before_instr(&intrin->instr);
52       lowered = nir_b2i32(b, nir_inot(b, nir_load_helper_invocation(b, 1)));
53       break;
54 
55    case nir_intrinsic_interp_deref_at_centroid:
56    case nir_intrinsic_interp_deref_at_sample:
57       b->cursor = nir_before_instr(&intrin->instr);
58       lowered = nir_load_deref(b, nir_src_as_deref(intrin->src[0]));
59       break;
60 
61    case nir_intrinsic_load_barycentric_centroid:
62    case nir_intrinsic_load_barycentric_sample:
63    case nir_intrinsic_load_barycentric_at_sample:
64       b->cursor = nir_before_instr(&intrin->instr);
65       lowered = nir_load_barycentric(b, nir_intrinsic_load_barycentric_pixel,
66                                      nir_intrinsic_interp_mode(intrin));
67 
68       if (nir_intrinsic_interp_mode(intrin) == INTERP_MODE_NOPERSPECTIVE) {
69          BITSET_SET(b->shader->info.system_values_read,
70                     SYSTEM_VALUE_BARYCENTRIC_LINEAR_PIXEL);
71       } else {
72          BITSET_SET(b->shader->info.system_values_read,
73                     SYSTEM_VALUE_BARYCENTRIC_PERSP_PIXEL);
74       }
75       break;
76 
77    default:
78       return false;
79    }
80 
81    nir_def_rewrite_uses(&intrin->def, lowered);
82    nir_instr_remove(&intrin->instr);
83    return true;
84 }
85 
86 /* Assume the fragment shader is single-sampled and lower accordingly
87  *
88  * This drops sample/centroid qualifiers from all input variables, forces
89  * barycentrics to pixel, and constant-folds various built-ins.
90  */
91 bool
nir_lower_single_sampled(nir_shader * shader)92 nir_lower_single_sampled(nir_shader *shader)
93 {
94    assert(shader->info.stage == MESA_SHADER_FRAGMENT);
95 
96    bool progress = false;
97    nir_foreach_shader_in_variable(var, shader) {
98       if (var->data.sample) {
99          var->data.sample = false;
100          progress = true;
101       }
102       if (var->data.centroid) {
103          var->data.centroid = false;
104          progress = true;
105       }
106    }
107 
108    /* We're going to get rid of any uses of these */
109    BITSET_CLEAR(shader->info.system_values_read,
110                 SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE);
111    BITSET_CLEAR(shader->info.system_values_read,
112                 SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID);
113    BITSET_CLEAR(shader->info.system_values_read,
114                 SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE);
115    BITSET_CLEAR(shader->info.system_values_read,
116                 SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID);
117 
118    return nir_shader_intrinsics_pass(shader, lower_single_sampled_instr,
119                                        nir_metadata_block_index |
120                                           nir_metadata_dominance,
121                                        NULL) ||
122           progress;
123 }
124