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 nir_foreach_shader_in_variable(var
, b
->shader
) {
53 if (var
->data
.location
== VARYING_SLOT_POS
)
54 return nir_load_var(b
, var
);
57 nir_variable
*pos
= nir_variable_create(b
->shader
, nir_var_shader_in
,
58 glsl_vec4_type(), NULL
);
59 pos
->data
.location
= VARYING_SLOT_POS
;
60 pos
->data
.interpolation
= INTERP_MODE_NOPERSPECTIVE
;
61 pos
->data
.driver_location
= b
->shader
->num_inputs
++;
62 return nir_load_var(b
, pos
);
66 nir_lower_pstipple_block(nir_block
*block
,
67 lower_pstipple
*state
)
69 nir_builder
*b
= &state
->b
;
70 nir_ssa_def
*texcoord
;
72 b
->cursor
= nir_before_block(block
);
74 nir_ssa_def
*div32
= nir_imm_vec2(b
, 1.0/32.0, 1.0/32.0);
76 nir_ssa_def
*frag_coord
= state
->fs_pos_is_sysval
? nir_load_frag_coord(b
) : load_frag_coord(b
);
78 texcoord
= nir_fmul(b
, frag_coord
, div32
);
80 nir_tex_instr
*tex
= nir_tex_instr_create(b
->shader
, 1);
81 tex
->op
= nir_texop_tex
;
82 tex
->sampler_dim
= GLSL_SAMPLER_DIM_2D
;
83 tex
->coord_components
= 2;
84 tex
->dest_type
= nir_type_float
;
85 tex
->texture_index
= state
->stip_tex
->data
.binding
;
86 tex
->sampler_index
= state
->stip_tex
->data
.binding
;
87 tex
->src
[0].src_type
= nir_tex_src_coord
;
88 tex
->src
[0].src
= nir_src_for_ssa(texcoord
);
89 nir_ssa_dest_init(&tex
->instr
, &tex
->dest
, 4, 32, NULL
);
91 nir_builder_instr_insert(b
, &tex
->instr
);
93 nir_ssa_def
*condition
= nir_f2b32(b
, nir_channel(b
, &tex
->dest
.ssa
, 3));
94 nir_intrinsic_instr
*discard
= nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_discard_if
);
95 discard
->src
[0] = nir_src_for_ssa(condition
);
96 nir_builder_instr_insert(b
, &discard
->instr
);
97 b
->shader
->info
.fs
.uses_discard
= true;
101 nir_lower_pstipple_impl(nir_function_impl
*impl
,
102 lower_pstipple
*state
)
104 nir_builder
*b
= &state
->b
;
106 nir_builder_init(b
, impl
);
108 nir_block
*start
= nir_start_block(impl
);
109 nir_lower_pstipple_block(start
, state
);
113 nir_lower_pstipple_fs(struct nir_shader
*shader
,
114 unsigned *samplerUnitOut
,
116 bool fs_pos_is_sysval
)
118 lower_pstipple state
= {
120 .fs_pos_is_sysval
= fs_pos_is_sysval
,
122 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
126 nir_foreach_uniform_variable(var
, shader
) {
127 if (glsl_type_is_sampler(var
->type
)) {
128 if (var
->data
.binding
>= binding
)
129 binding
= var
->data
.binding
+ 1;
132 const struct glsl_type
*sampler2D
=
133 glsl_sampler_type(GLSL_SAMPLER_DIM_2D
, false, false, GLSL_TYPE_FLOAT
);
135 nir_variable
*tex_var
= nir_variable_create(shader
, nir_var_uniform
, sampler2D
, "stipple_tex");
136 tex_var
->data
.binding
= binding
;
137 tex_var
->data
.explicit_binding
= true;
138 tex_var
->data
.how_declared
= nir_var_hidden
;
140 shader
->info
.textures_used
|= (1 << binding
);
141 state
.stip_tex
= tex_var
;
143 nir_foreach_function(function
, shader
) {
144 if (function
->impl
) {
145 nir_lower_pstipple_impl(function
->impl
, &state
);
148 *samplerUnitOut
= binding
;
154 nir_variable
*line_width_input
;
158 nir_lower_aaline_block(nir_block
*block
,
161 nir_builder
*b
= &state
->b
;
162 nir_foreach_instr(instr
, block
) {
163 if (instr
->type
!= nir_instr_type_intrinsic
)
166 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
167 if (intrin
->intrinsic
!= nir_intrinsic_store_deref
)
170 nir_variable
*var
= nir_intrinsic_get_var(intrin
, 0);
171 if (var
->data
.mode
!= nir_var_shader_out
)
173 if (var
->data
.location
!= FRAG_RESULT_COLOR
)
176 nir_ssa_def
*out_input
= intrin
->src
[1].ssa
;
177 b
->cursor
= nir_before_instr(instr
);
178 nir_ssa_def
*lw
= nir_load_var(b
, state
->line_width_input
);
179 nir_ssa_def
*tmp
= nir_fsat(b
, nir_fadd(b
, nir_channel(b
, lw
, 1),
180 nir_fneg(b
, nir_fabs(b
, nir_channel(b
, lw
, 0)))));
181 nir_ssa_def
*tmp1
= nir_fsat(b
, nir_fadd(b
, nir_channel(b
, lw
, 3),
182 nir_fneg(b
, nir_fabs(b
, nir_channel(b
, lw
, 2)))));
184 tmp
= nir_fmul(b
, tmp
, tmp1
);
185 tmp
= nir_fmul(b
, nir_channel(b
, out_input
, 3), tmp
);
187 nir_ssa_def
*out
= nir_vec4(b
, nir_channel(b
, out_input
, 0),
188 nir_channel(b
, out_input
, 1),
189 nir_channel(b
, out_input
, 2),
191 nir_instr_rewrite_src(instr
, &intrin
->src
[1], nir_src_for_ssa(out
));
197 nir_lower_aaline_impl(nir_function_impl
*impl
,
200 nir_builder
*b
= &state
->b
;
202 nir_builder_init(b
, impl
);
204 nir_foreach_block(block
, impl
) {
205 nir_lower_aaline_block(block
, state
);
210 nir_lower_aaline_fs(struct nir_shader
*shader
, int *varying
)
212 lower_aaline state
= {
215 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
218 int highest_location
= -1, highest_drv_location
= -1;
219 nir_foreach_shader_in_variable(var
, shader
) {
220 if ((int)var
->data
.location
> highest_location
)
221 highest_location
= var
->data
.location
;
222 if ((int)var
->data
.driver_location
> highest_drv_location
)
223 highest_drv_location
= var
->data
.driver_location
;
226 nir_variable
*line_width
= nir_variable_create(shader
, nir_var_shader_in
,
227 glsl_vec4_type(), "aaline");
228 if (highest_location
== -1 || highest_location
< VARYING_SLOT_VAR0
) {
229 line_width
->data
.location
= VARYING_SLOT_VAR0
;
230 line_width
->data
.driver_location
= highest_drv_location
+ 1;
232 line_width
->data
.location
= highest_location
+ 1;
233 line_width
->data
.driver_location
= highest_drv_location
+ 1;
235 shader
->num_inputs
++;
236 *varying
= tgsi_get_generic_gl_varying_index(line_width
->data
.location
, true);
237 state
.line_width_input
= line_width
;
239 nir_foreach_function(function
, shader
) {
240 if (function
->impl
) {
241 nir_lower_aaline_impl(function
->impl
, &state
);
253 nir_lower_aapoint_block(nir_block
*block
,
254 lower_aapoint
*state
, nir_ssa_def
*sel
)
256 nir_builder
*b
= &state
->b
;
257 nir_foreach_instr(instr
, block
) {
258 if (instr
->type
!= nir_instr_type_intrinsic
)
261 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
262 if (intrin
->intrinsic
!= nir_intrinsic_store_deref
)
265 nir_variable
*var
= nir_intrinsic_get_var(intrin
, 0);
266 if (var
->data
.mode
!= nir_var_shader_out
)
268 if (var
->data
.location
!= FRAG_RESULT_COLOR
)
271 nir_ssa_def
*out_input
= intrin
->src
[1].ssa
;
272 b
->cursor
= nir_before_instr(instr
);
274 nir_ssa_def
*tmp
= nir_fmul(b
, nir_channel(b
, out_input
, 3), sel
);
275 nir_ssa_def
*out
= nir_vec4(b
, nir_channel(b
, out_input
, 0),
276 nir_channel(b
, out_input
, 1),
277 nir_channel(b
, out_input
, 2),
279 nir_instr_rewrite_src(instr
, &intrin
->src
[1], nir_src_for_ssa(out
));
285 nir_lower_aapoint_impl(nir_function_impl
*impl
,
286 lower_aapoint
*state
)
288 nir_builder
*b
= &state
->b
;
290 nir_builder_init(b
, impl
);
292 nir_block
*block
= nir_start_block(impl
);
293 b
->cursor
= nir_before_block(block
);
295 nir_ssa_def
*aainput
= nir_load_var(b
, state
->input
);
297 nir_ssa_def
*dist
= nir_fadd(b
, nir_fmul(b
, nir_channel(b
, aainput
, 0), nir_channel(b
, aainput
, 0)),
298 nir_fmul(b
, nir_channel(b
, aainput
, 1), nir_channel(b
, aainput
, 1)));
300 nir_ssa_def
*k
= nir_channel(b
, aainput
, 2);
301 nir_ssa_def
*chan_val_one
= nir_channel(b
, aainput
, 3);
302 nir_ssa_def
*comp
= nir_flt32(b
, chan_val_one
, dist
);
304 nir_intrinsic_instr
*discard
= nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_discard_if
);
305 discard
->src
[0] = nir_src_for_ssa(comp
);
306 nir_builder_instr_insert(b
, &discard
->instr
);
307 b
->shader
->info
.fs
.uses_discard
= true;
309 /* compute coverage factor = (1-d)/(1-k) */
311 nir_ssa_def
*tmp
= nir_fadd(b
, chan_val_one
, nir_fneg(b
, k
));
313 tmp
= nir_frcp(b
, tmp
);
316 nir_ssa_def
*tmp2
= nir_fadd(b
, chan_val_one
, nir_fneg(b
, dist
));
318 /* (1 - d) / (1 - k) */
319 nir_ssa_def
*coverage
= nir_fmul(b
, tmp
, tmp2
);
321 /* if (k >= distance)
326 nir_ssa_def
*sel
= nir_b32csel(b
, nir_fge32(b
, k
, dist
), coverage
, chan_val_one
);
328 nir_foreach_block(block
, impl
) {
329 nir_lower_aapoint_block(block
, state
, sel
);
334 nir_lower_aapoint_fs(struct nir_shader
*shader
, int *varying
)
336 lower_aapoint state
= {
339 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
)
342 int highest_location
= -1, highest_drv_location
= -1;
343 nir_foreach_shader_in_variable(var
, shader
) {
344 if ((int)var
->data
.location
> highest_location
)
345 highest_location
= var
->data
.location
;
346 if ((int)var
->data
.driver_location
> highest_drv_location
)
347 highest_drv_location
= var
->data
.driver_location
;
350 nir_variable
*aapoint_input
= nir_variable_create(shader
, nir_var_shader_in
,
351 glsl_vec4_type(), "aapoint");
352 if (highest_location
== -1 || highest_location
< VARYING_SLOT_VAR0
) {
353 aapoint_input
->data
.location
= VARYING_SLOT_VAR0
;
355 aapoint_input
->data
.location
= highest_location
+ 1;
357 aapoint_input
->data
.driver_location
= highest_drv_location
+ 1;
359 shader
->num_inputs
++;
360 *varying
= tgsi_get_generic_gl_varying_index(aapoint_input
->data
.location
, true);
361 state
.input
= aapoint_input
;
363 nir_foreach_function(function
, shader
) {
364 if (function
->impl
) {
365 nir_lower_aapoint_impl(function
->impl
, &state
);