• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * 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 THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include "nir/nir.h"
25 #include "nir/nir_builder.h"
26 #include "nir/nir_search_helpers.h"
27 #include "rogue.h"
28 #include "util/macros.h"
29 
30 #include <assert.h>
31 #include <stdbool.h>
32 #include <stdint.h>
33 
34 /**
35  * \file rogue_nir_lower_io.c
36  *
37  * \brief Contains the rogue_nir_lower_io pass.
38  */
39 
lower_vulkan_resource_index(nir_builder * b,nir_intrinsic_instr * intr)40 static void lower_vulkan_resource_index(nir_builder *b,
41                                         nir_intrinsic_instr *intr)
42 {
43    /* Pass along the desc_set, binding, desc_type. */
44    unsigned desc_set = nir_intrinsic_desc_set(intr);
45    unsigned binding = nir_intrinsic_binding(intr);
46    unsigned desc_type = nir_intrinsic_desc_type(intr);
47 
48    nir_def *def = nir_vec3(b,
49                                nir_imm_int(b, desc_set),
50                                nir_imm_int(b, binding),
51                                nir_imm_int(b, desc_type));
52    nir_def_rewrite_uses(&intr->def, def);
53    nir_instr_remove(&intr->instr);
54 }
55 
lower_load_global_constant_to_scalar(nir_builder * b,nir_intrinsic_instr * intr)56 static void lower_load_global_constant_to_scalar(nir_builder *b,
57                                                  nir_intrinsic_instr *intr)
58 {
59    /* Scalarize the load_global_constant. */
60    b->cursor = nir_before_instr(&intr->instr);
61 
62    assert(intr->num_components > 1);
63 
64    nir_def *loads[NIR_MAX_VEC_COMPONENTS];
65 
66    for (uint8_t i = 0; i < intr->num_components; i++) {
67       nir_intrinsic_instr *chan_intr =
68          nir_intrinsic_instr_create(b->shader, intr->intrinsic);
69       nir_def_init(&chan_intr->instr, &chan_intr->def, 1,
70                    intr->def.bit_size);
71       chan_intr->num_components = 1;
72 
73       nir_intrinsic_set_access(chan_intr, nir_intrinsic_access(intr));
74       nir_intrinsic_set_align_mul(chan_intr, nir_intrinsic_align_mul(intr));
75       nir_intrinsic_set_align_offset(chan_intr,
76                                      nir_intrinsic_align_offset(intr));
77 
78       /* Address. */
79       chan_intr->src[0] =
80          nir_src_for_ssa(nir_iadd_imm(b, intr->src[0].ssa, i * 4));
81 
82       nir_builder_instr_insert(b, &chan_intr->instr);
83 
84       loads[i] = &chan_intr->def;
85    }
86 
87    nir_def_rewrite_uses(&intr->def,
88                             nir_vec(b, loads, intr->num_components));
89    nir_instr_remove(&intr->instr);
90 }
91 
lower_intrinsic(nir_builder * b,nir_intrinsic_instr * instr)92 static bool lower_intrinsic(nir_builder *b, nir_intrinsic_instr *instr)
93 {
94    switch (instr->intrinsic) {
95    case nir_intrinsic_vulkan_resource_index:
96       lower_vulkan_resource_index(b, instr);
97       return true;
98 
99    case nir_intrinsic_load_global_constant:
100       lower_load_global_constant_to_scalar(b, instr);
101       return true;
102 
103    default:
104       break;
105    }
106 
107    return false;
108 }
109 
lower_impl(nir_function_impl * impl)110 static bool lower_impl(nir_function_impl *impl)
111 {
112    bool progress = false;
113    nir_builder b = nir_builder_create(impl);
114 
115    nir_foreach_block (block, impl) {
116       nir_foreach_instr_safe (instr, block) {
117          b.cursor = nir_before_instr(instr);
118          switch (instr->type) {
119          case nir_instr_type_intrinsic:
120             progress |= lower_intrinsic(&b, nir_instr_as_intrinsic(instr));
121             break;
122 
123          default:
124             break;
125          }
126       }
127    }
128 
129    if (progress)
130       nir_metadata_preserve(impl, nir_metadata_none);
131    else
132       nir_metadata_preserve(impl, nir_metadata_all);
133 
134    return progress;
135 }
136 
137 PUBLIC
rogue_nir_lower_io(nir_shader * shader)138 bool rogue_nir_lower_io(nir_shader *shader)
139 {
140    bool progress = false;
141 
142    nir_foreach_function (function, shader) {
143       if (function->impl)
144          progress |= lower_impl(function->impl);
145    }
146 
147    if (progress)
148       nir_opt_dce(shader);
149 
150    return progress;
151 }
152