xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r300/compiler/r300_nir.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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