2 * Copyright (c) 2019 Zodiac Inflight Innovations
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, sub license,
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
12 * next paragraph) shall be included in all copies or substantial portions
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 NON-INFRINGEMENT. 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
21 * DEALINGS IN THE SOFTWARE.
24 * Jonathan Marek <jonathan@marek.ca>
27 #include "etnaviv_nir.h"
29 /* io related lowering
30 * run after lower_int_to_float because it adds i2f/f2i ops
33 etna_lower_io(nir_shader
*shader
, struct etna_shader_variant
*v
)
35 nir_foreach_function(function
, shader
) {
37 nir_builder_init(&b
, function
->impl
);
39 nir_foreach_block(block
, function
->impl
) {
40 nir_foreach_instr_safe(instr
, block
) {
41 if (instr
->type
== nir_instr_type_intrinsic
) {
42 nir_intrinsic_instr
*intr
= nir_instr_as_intrinsic(instr
);
44 switch (intr
->intrinsic
) {
45 case nir_intrinsic_load_front_face
: {
46 /* HW front_face is 0.0/1.0, not 0/~0u for bool
47 * lower with a comparison with 0
49 intr
->dest
.ssa
.bit_size
= 32;
51 b
.cursor
= nir_after_instr(instr
);
53 nir_ssa_def
*ssa
= nir_ine(&b
, &intr
->dest
.ssa
, nir_imm_int(&b
, 0));
55 nir_instr_as_alu(ssa
->parent_instr
)->op
= nir_op_ieq
;
57 nir_ssa_def_rewrite_uses_after(&intr
->dest
.ssa
,
61 case nir_intrinsic_store_deref
: {
62 nir_deref_instr
*deref
= nir_src_as_deref(intr
->src
[0]);
63 if (shader
->info
.stage
!= MESA_SHADER_FRAGMENT
|| !v
->key
.frag_rb_swap
)
66 assert(deref
->deref_type
== nir_deref_type_var
);
68 if (deref
->var
->data
.location
!= FRAG_RESULT_COLOR
&&
69 deref
->var
->data
.location
!= FRAG_RESULT_DATA0
)
72 b
.cursor
= nir_before_instr(instr
);
74 nir_ssa_def
*ssa
= nir_mov(&b
, intr
->src
[1].ssa
);
75 nir_alu_instr
*alu
= nir_instr_as_alu(ssa
->parent_instr
);
76 alu
->src
[0].swizzle
[0] = 2;
77 alu
->src
[0].swizzle
[2] = 0;
78 nir_instr_rewrite_src(instr
, &intr
->src
[1], nir_src_for_ssa(ssa
));
80 case nir_intrinsic_load_uniform
: {
81 /* convert indirect load_uniform to load_ubo when possible
82 * this is required on HALTI5+ because address register is not implemented
83 * address register loads also arent done optimally
85 if (v
->shader
->specs
->halti
< 2 || nir_src_is_const(intr
->src
[0]))
88 nir_intrinsic_instr
*load_ubo
=
89 nir_intrinsic_instr_create(b
.shader
, nir_intrinsic_load_ubo
);
90 load_ubo
->num_components
= intr
->num_components
;
91 nir_ssa_dest_init(&load_ubo
->instr
, &load_ubo
->dest
,
92 load_ubo
->num_components
, 32, NULL
);
94 b
.cursor
= nir_before_instr(instr
);
95 load_ubo
->src
[0] = nir_src_for_ssa(nir_imm_int(&b
, 0));
96 load_ubo
->src
[1] = nir_src_for_ssa(nir_iadd(&b
,
97 nir_imul(&b
, intr
->src
[0].ssa
, nir_imm_int(&b
, 16)),
98 nir_imm_int(&b
, nir_intrinsic_base(intr
) * 16)));
99 nir_builder_instr_insert(&b
, &load_ubo
->instr
);
100 nir_ssa_def_rewrite_uses(&intr
->dest
.ssa
,
101 nir_src_for_ssa(&load_ubo
->dest
.ssa
));
102 nir_instr_remove(&intr
->instr
);
104 case nir_intrinsic_load_ubo
: {
105 nir_const_value
*idx
= nir_src_as_const_value(intr
->src
[0]);
107 /* offset index by 1, index 0 is used for converted load_uniform */
108 b
.cursor
= nir_before_instr(instr
);
109 nir_instr_rewrite_src(instr
, &intr
->src
[0],
110 nir_src_for_ssa(nir_imm_int(&b
, idx
[0].u32
+ 1)));
112 case nir_intrinsic_load_vertex_id
:
113 case nir_intrinsic_load_instance_id
:
114 /* detect use of vertex_id/instance_id */
115 v
->vs_id_in_reg
= v
->infile
.num_reg
;
122 if (instr
->type
!= nir_instr_type_tex
)
125 nir_tex_instr
*tex
= nir_instr_as_tex(instr
);
126 nir_src
*coord
= NULL
;
127 nir_src
*lod_bias
= NULL
;
128 unsigned lod_bias_idx
;
130 assert(tex
->sampler_index
== tex
->texture_index
);
132 for (unsigned i
= 0; i
< tex
->num_srcs
; i
++) {
133 switch (tex
->src
[i
].src_type
) {
134 case nir_tex_src_coord
:
135 coord
= &tex
->src
[i
].src
;
137 case nir_tex_src_bias
:
138 case nir_tex_src_lod
:
140 lod_bias
= &tex
->src
[i
].src
;
143 case nir_tex_src_comparator
:
151 if (tex
->sampler_dim
== GLSL_SAMPLER_DIM_RECT
) {
152 /* use a dummy load_uniform here to represent texcoord scale */
153 b
.cursor
= nir_before_instr(instr
);
154 nir_intrinsic_instr
*load
=
155 nir_intrinsic_instr_create(b
.shader
, nir_intrinsic_load_uniform
);
156 nir_intrinsic_set_base(load
, ~tex
->sampler_index
);
157 load
->num_components
= 2;
158 load
->src
[0] = nir_src_for_ssa(nir_imm_float(&b
, 0.0f
));
159 nir_ssa_dest_init(&load
->instr
, &load
->dest
, 2, 32, NULL
);
160 nir_intrinsic_set_type(load
, nir_type_float
);
162 nir_builder_instr_insert(&b
, &load
->instr
);
164 nir_ssa_def
*new_coord
= nir_fmul(&b
, coord
->ssa
, &load
->dest
.ssa
);
165 nir_instr_rewrite_src(&tex
->instr
, coord
, nir_src_for_ssa(new_coord
));
168 /* pre HALTI5 needs texture sources in a single source */
170 if (!lod_bias
|| v
->shader
->specs
->halti
>= 5)
173 assert(coord
&& lod_bias
&& tex
->coord_components
< 4);
175 nir_alu_instr
*vec
= nir_alu_instr_create(shader
, nir_op_vec4
);
176 for (unsigned i
= 0; i
< tex
->coord_components
; i
++) {
177 vec
->src
[i
].src
= nir_src_for_ssa(coord
->ssa
);
178 vec
->src
[i
].swizzle
[0] = i
;
180 for (unsigned i
= tex
->coord_components
; i
< 4; i
++)
181 vec
->src
[i
].src
= nir_src_for_ssa(lod_bias
->ssa
);
183 vec
->dest
.write_mask
= 0xf;
184 nir_ssa_dest_init(&vec
->instr
, &vec
->dest
.dest
, 4, 32, NULL
);
186 nir_tex_instr_remove_src(tex
, lod_bias_idx
);
187 nir_instr_rewrite_src(&tex
->instr
, coord
, nir_src_for_ssa(&vec
->dest
.dest
.ssa
));
188 tex
->coord_components
= 4;
190 nir_instr_insert_before(&tex
->instr
, &vec
->instr
);