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