2 * Copyright © 2019 Google, Inc.
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:
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
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
25 * This lower pass lowers load_interpolated_input for various interpolation
26 * modes (as configured via nir_lower_interpolation_options bitmask) into
27 * load_attribute_deltas plus alu instructions:
29 * vec3 ad = load_attribute_deltas(varying_slot)
30 * float result = ad.x + ad.y * j + ad.z * i
35 #include "nir_builder.h"
38 nir_lower_interpolation_block(nir_block
*block
, nir_builder
*b
,
39 nir_lower_interpolation_options options
)
41 bool progress
= false;
43 nir_foreach_instr_safe(instr
, block
) {
44 if (instr
->type
!= nir_instr_type_intrinsic
)
47 nir_intrinsic_instr
*intr
= nir_instr_as_intrinsic(instr
);
49 if (intr
->intrinsic
!= nir_intrinsic_load_interpolated_input
)
52 assert(intr
->dest
.is_ssa
);
53 assert(intr
->src
[0].is_ssa
);
54 assert(intr
->src
[1].is_ssa
);
56 nir_intrinsic_instr
*bary_intrinsic
=
57 nir_instr_as_intrinsic(intr
->src
[0].ssa
->parent_instr
);
59 /* Leave VARYING_SLOT_POS alone */
60 if (nir_intrinsic_base(intr
) == VARYING_SLOT_POS
)
63 const enum glsl_interp_mode interp_mode
=
64 nir_intrinsic_interp_mode(bary_intrinsic
);
66 /* We need actual interpolation modes by the time we get here */
67 assert(interp_mode
!= INTERP_MODE_NONE
);
69 /* Only lower for inputs that need interpolation */
70 if (interp_mode
!= INTERP_MODE_SMOOTH
&&
71 interp_mode
!= INTERP_MODE_NOPERSPECTIVE
)
74 nir_intrinsic_op op
= bary_intrinsic
->intrinsic
;
77 case nir_intrinsic_load_barycentric_at_sample
:
78 if (options
& nir_lower_interpolation_at_sample
)
81 case nir_intrinsic_load_barycentric_at_offset
:
82 if (options
& nir_lower_interpolation_at_offset
)
85 case nir_intrinsic_load_barycentric_centroid
:
86 if (options
& nir_lower_interpolation_centroid
)
89 case nir_intrinsic_load_barycentric_pixel
:
90 if (options
& nir_lower_interpolation_pixel
)
93 case nir_intrinsic_load_barycentric_sample
:
94 if (options
& nir_lower_interpolation_sample
)
101 b
->cursor
= nir_before_instr(instr
);
103 nir_ssa_def
*comps
[NIR_MAX_VEC_COMPONENTS
];
104 for (int i
= 0; i
< intr
->num_components
; i
++) {
105 nir_intrinsic_instr
*load_iid
=
106 nir_intrinsic_instr_create(b
->shader
,
107 nir_intrinsic_load_fs_input_interp_deltas
);
108 load_iid
->src
[0] = nir_src_for_ssa(intr
->src
[1].ssa
);
109 nir_ssa_dest_init(&load_iid
->instr
, &load_iid
->dest
,
111 nir_intrinsic_set_base(load_iid
, nir_intrinsic_base(intr
));
112 nir_intrinsic_set_component(load_iid
,
113 nir_intrinsic_component(intr
) + i
);
114 nir_builder_instr_insert(b
, &load_iid
->instr
);
116 nir_ssa_def
*iid
= &load_iid
->dest
.ssa
;
117 nir_ssa_def
*bary
= intr
->src
[0].ssa
;
120 val
= nir_ffma(b
, nir_channel(b
, bary
, 1),
121 nir_channel(b
, iid
, 1),
122 nir_channel(b
, iid
, 0));
123 val
= nir_ffma(b
, nir_channel(b
, bary
, 0),
124 nir_channel(b
, iid
, 2),
129 nir_ssa_def
*vec
= nir_vec(b
, comps
, intr
->num_components
);
130 nir_ssa_def_rewrite_uses(&intr
->dest
.ssa
, nir_src_for_ssa(vec
));
139 nir_lower_interpolation_impl(nir_function_impl
*impl
,
140 nir_lower_interpolation_options options
)
142 bool progress
= false;
144 nir_builder_init(&builder
, impl
);
146 nir_foreach_block(block
, impl
) {
147 progress
|= nir_lower_interpolation_block(block
, &builder
, options
);
150 nir_metadata_preserve(impl
, nir_metadata_block_index
|
151 nir_metadata_dominance
);
156 nir_lower_interpolation(nir_shader
*shader
, nir_lower_interpolation_options options
)
158 bool progress
= false;
160 nir_foreach_function(function
, shader
) {
162 progress
|= nir_lower_interpolation_impl(function
->impl
, options
);