1 /**************************************************************************
3 * Copyright 2019 Red Hat.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 **************************************************************************/
27 * NIR lowering passes to handle the draw stages for
32 * These are all ported from the equivalent TGSI transforms.
36 #include "tgsi/tgsi_from_mesa.h"
37 #include "nir_builder.h"
39 #include "nir_draw_helpers.h"
44 bool fs_pos_is_sysval
;
45 nir_variable
*stip_tex
;
46 nir_ssa_def
*fragcoord
;
50 load_frag_coord(nir_builder
*b
)
52 int max_driver_loc
= -1;
53 nir_foreach_variable(var
, &b
->shader
->inputs
) {
54 if (var
->data
.location
== VARYING_SLOT_POS
)
55 return nir_load_var(b
, var
);
56 if (max_driver_loc
< (int)var
->data
.driver_location
)
57 max_driver_loc
= var
->data
.driver_location
;
60 nir_variable
*pos
= nir_variable_create(b
->shader
, nir_var_shader_in
,
61 glsl_vec4_type(), NULL
);
62 pos
->data
.location
= VARYING_SLOT_POS
;
63 pos
->data
.interpolation
= INTERP_MODE_NOPERSPECTIVE
;
64 pos
->data
.driver_location
= max_driver_loc
+ 1;
65 b
->shader
->num_inputs
++;
66 return nir_load_var(b
, pos
);
70 nir_lower_pstipple_block(nir_block
*block
,
71 lower_pstipple
*state
)
73 nir_builder
*b
= &state
->b
;
74 nir_ssa_def
*texcoord
;
76 b
->cursor
= nir_before_block(block
);
78 nir_ssa_def
*div32
= nir_imm_vec2(b
, 1.0/32.0, 1.0/32.0);
80 nir_ssa_def
*frag_coord
= state
->fs_pos_is_sysval
? nir_load_frag_coord(b
) : load_frag_coord(b
);
82 texcoord
= nir_fmul(b
, frag_coord
, div32
);
84 nir_tex_instr
*tex
= nir_tex_instr_create(b
->shader
, 1);
85 tex
->op
= nir_texop_tex
;
86 tex
->sampler_dim
= GLSL_SAMPLER_DIM_2D
;
87 tex
->coord_components
= 2;
88 tex
->dest_type
= nir_type_float
;
89 tex
->texture_index
= state
->stip_tex
->data
.binding
;
90 tex
->sampler_index
= state
->stip_tex
->data
.binding
;
91 tex
->src
[0].src_type
= nir_tex_src_coord
;
92 tex
->src
[0].src
= nir_src_for_ssa(texcoord
);
93 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, NULL
);
95 nir_builder_instr_insert(b
, &tex
->instr
);
97 nir_ssa_def
*condition
= nir_f2b32(b
, nir_channel(b
, &tex
->dest
.ssa
, 3));
98 nir_intrinsic_instr
*discard
= nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_discard_if
);
99 discard
->src
[0] = nir_src_for_ssa(condition
);
100 nir_builder_instr_insert(b
, &discard
->instr
);
101 b
->shader
->info
.fs
.uses_discard
= true;
105 nir_lower_pstipple_impl(nir_function_impl
*impl
,
106 lower_pstipple
*state
)
108 nir_builder
*b
= &state
->b
;
110 nir_builder_init(b
, impl
);
112 nir_block
*start
= nir_start_block(impl
);
113 nir_lower_pstipple_block(start
, state
);
117 nir_lower_pstipple_fs(struct nir_shader
*shader
,
118 unsigned *samplerUnitOut
,
120 bool fs_pos_is_sysval
)
122 lower_pstipple state
= {
124 .fs_pos_is_sysval
= fs_pos_is_sysval
,
126 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
130 nir_foreach_variable(var
, &shader
->uniforms
) {
131 if (glsl_type_is_sampler(var
->type
)) {
132 if (var
->data
.binding
>= binding
)
133 binding
= var
->data
.binding
+ 1;
136 const struct glsl_type
*sampler2D
=
137 glsl_sampler_type(GLSL_SAMPLER_DIM_2D
, false, false, GLSL_TYPE_FLOAT
);
139 nir_variable
*tex_var
= nir_variable_create(shader
, nir_var_uniform
, sampler2D
, "stipple_tex");
140 tex_var
->data
.binding
= binding
;
141 tex_var
->data
.explicit_binding
= true;
142 tex_var
->data
.how_declared
= nir_var_hidden
;
144 shader
->info
.textures_used
|= (1 << binding
);
145 state
.stip_tex
= tex_var
;
147 nir_foreach_function(function
, shader
) {
148 if (function
->impl
) {
149 nir_lower_pstipple_impl(function
->impl
, &state
);
152 *samplerUnitOut
= binding
;
158 nir_variable
*line_width_input
;
162 nir_lower_aaline_block(nir_block
*block
,
165 nir_builder
*b
= &state
->b
;
166 nir_foreach_instr(instr
, block
) {
167 if (instr
->type
!= nir_instr_type_intrinsic
)
170 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
171 if (intrin
->intrinsic
!= nir_intrinsic_store_deref
)
174 nir_variable
*var
= nir_intrinsic_get_var(intrin
, 0);
175 if (var
->data
.mode
!= nir_var_shader_out
)
177 if (var
->data
.location
!= FRAG_RESULT_COLOR
)
180 nir_ssa_def
*out_input
= intrin
->src
[1].ssa
;
181 b
->cursor
= nir_before_instr(instr
);
182 nir_ssa_def
*lw
= nir_load_var(b
, state
->line_width_input
);
183 nir_ssa_def
*tmp
= nir_fsat(b
, nir_fadd(b
, nir_channel(b
, lw
, 1),
184 nir_fneg(b
, nir_fabs(b
, nir_channel(b
, lw
, 0)))));
185 nir_ssa_def
*tmp1
= nir_fsat(b
, nir_fadd(b
, nir_channel(b
, lw
, 3),
186 nir_fneg(b
, nir_fabs(b
, nir_channel(b
, lw
, 2)))));
188 tmp
= nir_fmul(b
, tmp
, tmp1
);
189 tmp
= nir_fmul(b
, nir_channel(b
, out_input
, 3), tmp
);
191 nir_ssa_def
*out
= nir_vec4(b
, nir_channel(b
, out_input
, 0),
192 nir_channel(b
, out_input
, 1),
193 nir_channel(b
, out_input
, 2),
195 nir_instr_rewrite_src(instr
, &intrin
->src
[1], nir_src_for_ssa(out
));
201 nir_lower_aaline_impl(nir_function_impl
*impl
,
204 nir_builder
*b
= &state
->b
;
206 nir_builder_init(b
, impl
);
208 nir_foreach_block(block
, impl
) {
209 nir_lower_aaline_block(block
, state
);
214 nir_lower_aaline_fs(struct nir_shader
*shader
, int *varying
)
216 lower_aaline state
= {
219 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
222 int highest_location
= -1, highest_drv_location
= -1;
223 nir_foreach_variable(var
, &shader
->inputs
) {
224 if ((int)var
->data
.location
> highest_location
)
225 highest_location
= var
->data
.location
;
226 if ((int)var
->data
.driver_location
> highest_drv_location
)
227 highest_drv_location
= var
->data
.driver_location
;
230 nir_variable
*line_width
= nir_variable_create(shader
, nir_var_shader_in
,
231 glsl_vec4_type(), "aaline");
232 if (highest_location
== -1 || highest_location
< VARYING_SLOT_VAR0
) {
233 line_width
->data
.location
= VARYING_SLOT_VAR0
;
234 line_width
->data
.driver_location
= highest_drv_location
+ 1;
236 line_width
->data
.location
= highest_location
+ 1;
237 line_width
->data
.driver_location
= highest_drv_location
+ 1;
239 shader
->num_inputs
++;
240 *varying
= tgsi_get_generic_gl_varying_index(line_width
->data
.location
, true);
241 state
.line_width_input
= line_width
;
243 nir_foreach_function(function
, shader
) {
244 if (function
->impl
) {
245 nir_lower_aaline_impl(function
->impl
, &state
);
257 nir_lower_aapoint_block(nir_block
*block
,
258 lower_aapoint
*state
, nir_ssa_def
*sel
)
260 nir_builder
*b
= &state
->b
;
261 nir_foreach_instr(instr
, block
) {
262 if (instr
->type
!= nir_instr_type_intrinsic
)
265 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
266 if (intrin
->intrinsic
!= nir_intrinsic_store_deref
)
269 nir_variable
*var
= nir_intrinsic_get_var(intrin
, 0);
270 if (var
->data
.mode
!= nir_var_shader_out
)
272 if (var
->data
.location
!= FRAG_RESULT_COLOR
)
275 nir_ssa_def
*out_input
= intrin
->src
[1].ssa
;
276 b
->cursor
= nir_before_instr(instr
);
278 nir_ssa_def
*tmp
= nir_fmul(b
, nir_channel(b
, out_input
, 3), sel
);
279 nir_ssa_def
*out
= nir_vec4(b
, nir_channel(b
, out_input
, 0),
280 nir_channel(b
, out_input
, 1),
281 nir_channel(b
, out_input
, 2),
283 nir_instr_rewrite_src(instr
, &intrin
->src
[1], nir_src_for_ssa(out
));
289 nir_lower_aapoint_impl(nir_function_impl
*impl
,
290 lower_aapoint
*state
)
292 nir_builder
*b
= &state
->b
;
294 nir_builder_init(b
, impl
);
296 nir_block
*block
= nir_start_block(impl
);
297 b
->cursor
= nir_before_block(block
);
299 nir_ssa_def
*aainput
= nir_load_var(b
, state
->input
);
301 nir_ssa_def
*dist
= nir_fadd(b
, nir_fmul(b
, nir_channel(b
, aainput
, 0), nir_channel(b
, aainput
, 0)),
302 nir_fmul(b
, nir_channel(b
, aainput
, 1), nir_channel(b
, aainput
, 1)));
304 nir_ssa_def
*k
= nir_channel(b
, aainput
, 2);
305 nir_ssa_def
*chan_val_one
= nir_channel(b
, aainput
, 3);
306 nir_ssa_def
*comp
= nir_flt32(b
, chan_val_one
, dist
);
308 nir_intrinsic_instr
*discard
= nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_discard_if
);
309 discard
->src
[0] = nir_src_for_ssa(comp
);
310 nir_builder_instr_insert(b
, &discard
->instr
);
311 b
->shader
->info
.fs
.uses_discard
= true;
313 /* compute coverage factor = (1-d)/(1-k) */
315 nir_ssa_def
*tmp
= nir_fadd(b
, chan_val_one
, nir_fneg(b
, k
));
317 tmp
= nir_frcp(b
, tmp
);
320 nir_ssa_def
*tmp2
= nir_fadd(b
, chan_val_one
, nir_fneg(b
, dist
));
322 /* (1 - d) / (1 - k) */
323 nir_ssa_def
*coverage
= nir_fmul(b
, tmp
, tmp2
);
325 /* if (k >= distance)
330 nir_ssa_def
*sel
= nir_b32csel(b
, nir_fge32(b
, k
, dist
), coverage
, chan_val_one
);
332 nir_foreach_block(block
, impl
) {
333 nir_lower_aapoint_block(block
, state
, sel
);
338 nir_lower_aapoint_fs(struct nir_shader
*shader
, int *varying
)
340 lower_aapoint state
= {
343 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
346 int highest_location
= -1, highest_drv_location
= -1;
347 nir_foreach_variable(var
, &shader
->inputs
) {
348 if ((int)var
->data
.location
> highest_location
)
349 highest_location
= var
->data
.location
;
350 if ((int)var
->data
.driver_location
> highest_drv_location
)
351 highest_drv_location
= var
->data
.driver_location
;
354 nir_variable
*aapoint_input
= nir_variable_create(shader
, nir_var_shader_in
,
355 glsl_vec4_type(), "aapoint");
356 if (highest_location
== -1 || highest_location
< VARYING_SLOT_VAR0
) {
357 aapoint_input
->data
.location
= VARYING_SLOT_VAR0
;
359 aapoint_input
->data
.location
= highest_location
+ 1;
361 aapoint_input
->data
.driver_location
= highest_drv_location
+ 1;
363 shader
->num_inputs
++;
364 *varying
= tgsi_get_generic_gl_varying_index(aapoint_input
->data
.location
, true);
365 state
.input
= aapoint_input
;
367 nir_foreach_function(function
, shader
) {
368 if (function
->impl
) {
369 nir_lower_aapoint_impl(function
->impl
, &state
);