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_replace(&intrin->def, lowered);
82 return true;
83 }
84
85 /* Assume the fragment shader is single-sampled and lower accordingly
86 *
87 * This drops sample/centroid qualifiers from all input variables, forces
88 * barycentrics to pixel, and constant-folds various built-ins.
89 */
90 bool
nir_lower_single_sampled(nir_shader * shader)91 nir_lower_single_sampled(nir_shader *shader)
92 {
93 assert(shader->info.stage == MESA_SHADER_FRAGMENT);
94
95 bool progress = false;
96 nir_foreach_shader_in_variable(var, shader) {
97 if (var->data.sample) {
98 var->data.sample = false;
99 progress = true;
100 }
101 if (var->data.centroid) {
102 var->data.centroid = false;
103 progress = true;
104 }
105 }
106
107 /* We're going to get rid of any uses of these */
108 BITSET_CLEAR(shader->info.system_values_read,
109 SYSTEM_VALUE_BARYCENTRIC_PERSP_SAMPLE);
110 BITSET_CLEAR(shader->info.system_values_read,
111 SYSTEM_VALUE_BARYCENTRIC_PERSP_CENTROID);
112 BITSET_CLEAR(shader->info.system_values_read,
113 SYSTEM_VALUE_BARYCENTRIC_LINEAR_SAMPLE);
114 BITSET_CLEAR(shader->info.system_values_read,
115 SYSTEM_VALUE_BARYCENTRIC_LINEAR_CENTROID);
116
117 return nir_shader_intrinsics_pass(shader, lower_single_sampled_instr,
118 nir_metadata_control_flow,
119 NULL) ||
120 progress;
121 }
122