xref: /aosp_15_r20/external/mesa3d/src/compiler/nir/nir_lower_vec3_to_vec4.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2020 Intel Corporation
3  *
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, sublicense,
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:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
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 NONINFRINGEMENT.  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 DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "nir_builder.h"
25 
26 static bool
lower_vec3_to_vec4_instr(nir_builder * b,nir_instr * instr,void * data)27 lower_vec3_to_vec4_instr(nir_builder *b, nir_instr *instr, void *data)
28 {
29    nir_variable_mode modes = *((nir_variable_mode *)data);
30 
31    switch (instr->type) {
32    case nir_instr_type_deref: {
33       nir_deref_instr *deref = nir_instr_as_deref(instr);
34       if (!nir_deref_mode_is_in_set(deref, modes))
35          return false;
36 
37       const struct glsl_type *vec4_type =
38          glsl_type_replace_vec3_with_vec4(deref->type);
39       if (deref->type != vec4_type) {
40          deref->type = vec4_type;
41          return true;
42       }
43       break;
44    }
45 
46    case nir_instr_type_intrinsic: {
47       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
48       switch (intrin->intrinsic) {
49       case nir_intrinsic_load_deref: {
50          if (intrin->num_components != 3)
51             break;
52 
53          nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
54          if (!nir_deref_mode_is_in_set(deref, modes))
55             break;
56 
57          intrin->num_components = 4;
58          intrin->def.num_components = 4;
59 
60          b->cursor = nir_after_instr(&intrin->instr);
61          nir_def *vec3 = nir_trim_vector(b, &intrin->def, 3);
62          nir_def_rewrite_uses_after(&intrin->def,
63                                     vec3,
64                                     vec3->parent_instr);
65          return true;
66       }
67 
68       case nir_intrinsic_store_deref: {
69          if (intrin->num_components != 3)
70             break;
71 
72          nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
73          if (!nir_deref_mode_is_in_set(deref, modes))
74             break;
75 
76          nir_def *data = intrin->src[1].ssa;
77 
78          b->cursor = nir_before_instr(&intrin->instr);
79          unsigned swiz[] = { 0, 1, 2, 2 };
80          data = nir_swizzle(b, data, swiz, 4);
81 
82          intrin->num_components = 4;
83          nir_src_rewrite(&intrin->src[1], data);
84          return true;
85       }
86 
87       case nir_intrinsic_copy_deref: {
88          nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]);
89          nir_deref_instr *src = nir_src_as_deref(intrin->src[0]);
90          /* If we convert once side of a copy and not the other, that
91           * would be very bad.
92           */
93          if (nir_deref_mode_may_be(dst, modes) ||
94              nir_deref_mode_may_be(src, modes)) {
95             assert(nir_deref_mode_must_be(dst, modes));
96             assert(nir_deref_mode_must_be(src, modes));
97          }
98          break;
99       }
100 
101       default:
102          break;
103       }
104       break;
105    }
106 
107    default:
108       break;
109    }
110 
111    return false;
112 }
113 
114 bool
nir_lower_vec3_to_vec4(nir_shader * shader,nir_variable_mode modes)115 nir_lower_vec3_to_vec4(nir_shader *shader, nir_variable_mode modes)
116 {
117    bool progress = false;
118 
119    if (modes & ~nir_var_function_temp) {
120       nir_foreach_variable_in_shader(var, shader) {
121          if (!(var->data.mode & modes))
122             continue;
123 
124          const struct glsl_type *vec4_type =
125             glsl_type_replace_vec3_with_vec4(var->type);
126          if (var->type != vec4_type) {
127             var->type = vec4_type;
128             progress = true;
129          }
130       }
131    }
132 
133    if (modes & nir_var_function_temp) {
134       nir_foreach_function_impl(impl, shader) {
135          nir_foreach_function_temp_variable(var, impl) {
136             const struct glsl_type *vec4_type =
137                glsl_type_replace_vec3_with_vec4(var->type);
138             if (var->type != vec4_type) {
139                var->type = vec4_type;
140                progress = true;
141             }
142          }
143       }
144    }
145 
146    progress |= nir_shader_instructions_pass(shader,
147                                             lower_vec3_to_vec4_instr,
148                                             nir_metadata_control_flow,
149                                             &modes);
150 
151    return progress;
152 }
153