1 /*
2 * Copyright 2023 Pavel Ondračka <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef R300_NIR_H
7 #define R300_NIR_H
8
9 #include <math.h>
10
11 #include "pipe/p_screen.h"
12 #include "compiler/nir/nir.h"
13
14 static inline bool
is_ubo_or_input(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)15 is_ubo_or_input(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
16 unsigned src, unsigned num_components,
17 const uint8_t *swizzle)
18 {
19 nir_instr *parent = instr->src[src].src.ssa->parent_instr;
20 if (parent->type != nir_instr_type_intrinsic)
21 return false;
22
23 nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(parent);
24
25 switch (intrinsic->intrinsic) {
26 case nir_intrinsic_load_ubo_vec4:
27 case nir_intrinsic_load_input:
28 case nir_intrinsic_load_interpolated_input:
29 return true;
30 default:
31 return false;
32 }
33 }
34
35 static inline bool
is_not_used_in_single_if(const nir_alu_instr * instr)36 is_not_used_in_single_if(const nir_alu_instr *instr)
37 {
38 unsigned if_uses = 0;
39 nir_foreach_use(src, &instr->def) {
40 if (nir_src_is_if(src))
41 if_uses++;
42 else
43 return true;
44 }
45 return if_uses != 1;
46 }
47
48 static inline bool
is_only_used_by_load_ubo_vec4(const nir_alu_instr * instr)49 is_only_used_by_load_ubo_vec4(const nir_alu_instr *instr)
50 {
51 nir_foreach_use(src, &instr->def) {
52 if (nir_src_is_if(src))
53 return false;
54 nir_instr *user_instr = nir_src_parent_instr(src);
55 if (user_instr->type != nir_instr_type_intrinsic)
56 return false;
57
58 const nir_intrinsic_instr *const user_intrinsic = nir_instr_as_intrinsic(user_instr);
59
60 if (user_intrinsic->intrinsic != nir_intrinsic_load_ubo_vec4)
61 return false;
62 }
63 return true;
64 }
65
66 static inline bool
check_instr_and_src_value(nir_op op,nir_instr ** instr,double value)67 check_instr_and_src_value(nir_op op, nir_instr **instr, double value)
68 {
69 if ((*instr)->type != nir_instr_type_alu)
70 return false;
71 nir_alu_instr *alu = nir_instr_as_alu(*instr);
72 if (alu->op != op)
73 return false;
74 unsigned i;
75 for (i = 0; i <= 2; i++) {
76 if (i == 2) {
77 return false;
78 }
79 nir_alu_src src = alu->src[i];
80 if (nir_src_is_const(src.src)) {
81 /* All components must be reading the same value. */
82 for (unsigned j = 0; j < alu->def.num_components - 1; j++) {
83 if (src.swizzle[j] != src.swizzle[j + 1]) {
84 return false;
85 }
86 }
87 if (fabs(nir_src_comp_as_float(src.src, src.swizzle[0]) - value) < 1e-5) {
88 break;
89 }
90 }
91 }
92 *instr = alu->src[1 - i].src.ssa->parent_instr;
93 return true;
94 }
95
96 static inline bool
needs_vs_trig_input_fixup(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)97 needs_vs_trig_input_fixup(UNUSED struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
98 unsigned num_components, const uint8_t *swizzle)
99 {
100 /* We are checking for fadd(fmul(ffract(a), 2*pi), -pi) pattern
101 * emitted by us and also some wined3d shaders.
102 * Start with check for fadd(a, -pi).
103 */
104 nir_instr *parent = instr->src[src].src.ssa->parent_instr;
105 if (!check_instr_and_src_value(nir_op_fadd, &parent, -3.141592))
106 return true;
107 /* Now check for fmul(a, 2 * pi). */
108 if (!check_instr_and_src_value(nir_op_fmul, &parent, 6.283185))
109 return true;
110
111 /* Finally check for ffract(a). */
112 if (parent->type != nir_instr_type_alu)
113 return true;
114 nir_alu_instr *fract = nir_instr_as_alu(parent);
115 if (fract->op != nir_op_ffract)
116 return true;
117 return false;
118 }
119
120 static inline bool
needs_fs_trig_input_fixup(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)121 needs_fs_trig_input_fixup(UNUSED struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
122 unsigned num_components, const uint8_t *swizzle)
123 {
124 /* We are checking for ffract(a * (1 / 2 * pi)) pattern. */
125 nir_instr *parent = instr->src[src].src.ssa->parent_instr;
126 if (parent->type != nir_instr_type_alu)
127 return true;
128 nir_alu_instr *fract = nir_instr_as_alu(parent);
129 if (fract->op != nir_op_ffract)
130 return true;
131 parent = fract->src[0].src.ssa->parent_instr;
132
133 /* Now check for fmul(a, 1 / (2 * pi)). */
134 if (!check_instr_and_src_value(nir_op_fmul, &parent, 0.1591549))
135 return true;
136
137 return false;
138 }
139
140 bool r300_is_only_used_as_float(const nir_alu_instr *instr);
141
142 char *r300_finalize_nir(struct pipe_screen *pscreen, void *nir);
143
144 extern bool r300_transform_vs_trig_input(struct nir_shader *shader);
145
146 extern bool r300_transform_fs_trig_input(struct nir_shader *shader);
147
148 extern bool r300_nir_fuse_fround_d3d9(struct nir_shader *shader);
149
150 extern bool r300_nir_lower_bool_to_float(struct nir_shader *shader);
151
152 extern bool r300_nir_lower_bool_to_float_fs(struct nir_shader *shader);
153
154 extern bool r300_nir_prepare_presubtract(struct nir_shader *shader);
155
156 extern bool r300_nir_opt_algebraic_late(struct nir_shader *shader);
157
158 extern bool r300_nir_post_integer_lowering(struct nir_shader *shader);
159
160 extern bool r300_nir_lower_fcsel_r500(nir_shader *shader);
161
162 extern bool r300_nir_lower_fcsel_r300(nir_shader *shader);
163
164 extern bool r300_nir_lower_flrp(nir_shader *shader);
165
166 extern bool r300_nir_lower_comparison_fs(nir_shader *shader);
167
168 #endif /* R300_NIR_H */
169