• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Red Hat.
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 "lvp_private.h"
25 #include "nir.h"
26 #include "nir_builder.h"
27 #include "lvp_lower_vulkan_resource.h"
28 
29 static bool
lower_vulkan_resource_index(const nir_instr * instr,const void * data_cb)30 lower_vulkan_resource_index(const nir_instr *instr, const void *data_cb)
31 {
32    if (instr->type == nir_instr_type_intrinsic) {
33       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
34       switch (intrin->intrinsic) {
35       case nir_intrinsic_vulkan_resource_index:
36       case nir_intrinsic_vulkan_resource_reindex:
37       case nir_intrinsic_load_vulkan_descriptor:
38       case nir_intrinsic_get_ssbo_size:
39          return true;
40       default:
41          return false;
42       }
43    }
44    if (instr->type == nir_instr_type_tex) {
45       return true;
46    }
47    return false;
48 }
49 
lower_vri_intrin_vri(struct nir_builder * b,nir_instr * instr,void * data_cb)50 static nir_ssa_def *lower_vri_intrin_vri(struct nir_builder *b,
51                                            nir_instr *instr, void *data_cb)
52 {
53    nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
54    unsigned desc_set_idx = nir_intrinsic_desc_set(intrin);
55    unsigned binding_idx = nir_intrinsic_binding(intrin);
56    struct lvp_pipeline_layout *layout = data_cb;
57    struct lvp_descriptor_set_binding_layout *binding = &layout->set[desc_set_idx].layout->binding[binding_idx];
58    int value = 0;
59    bool is_ubo = (binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
60                   binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC);
61 
62    for (unsigned s = 0; s < desc_set_idx; s++) {
63      if (is_ubo)
64        value += layout->set[s].layout->stage[b->shader->info.stage].const_buffer_count;
65      else
66        value += layout->set[s].layout->stage[b->shader->info.stage].shader_buffer_count;
67    }
68    if (is_ubo)
69      value += binding->stage[b->shader->info.stage].const_buffer_index + 1;
70    else
71      value += binding->stage[b->shader->info.stage].shader_buffer_index;
72 
73    /* The SSA size for indices is the same as for pointers.  We use
74     * nir_addr_format_32bit_index_offset so we need a vec2.  We don't need all
75     * that data so just stuff a 0 in the second component.
76     */
77    if (nir_src_is_const(intrin->src[0])) {
78       value += nir_src_comp_as_int(intrin->src[0], 0);
79       return nir_imm_ivec2(b, value, 0);
80    } else
81       return nir_vec2(b, nir_iadd_imm(b, intrin->src[0].ssa, value),
82                          nir_imm_int(b, 0));
83 }
84 
lower_vri_intrin_vrri(struct nir_builder * b,nir_instr * instr,void * data_cb)85 static nir_ssa_def *lower_vri_intrin_vrri(struct nir_builder *b,
86                                           nir_instr *instr, void *data_cb)
87 {
88    nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
89    nir_ssa_def *old_index = nir_ssa_for_src(b, intrin->src[0], 1);
90    nir_ssa_def *delta = nir_ssa_for_src(b, intrin->src[1], 1);
91    return nir_vec2(b, nir_iadd(b, old_index, delta),
92                       nir_imm_int(b, 0));
93 }
94 
lower_vri_intrin_lvd(struct nir_builder * b,nir_instr * instr,void * data_cb)95 static nir_ssa_def *lower_vri_intrin_lvd(struct nir_builder *b,
96                                          nir_instr *instr, void *data_cb)
97 {
98    nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
99    nir_ssa_def *index = nir_ssa_for_src(b, intrin->src[0], 1);
100    return nir_vec2(b, index, nir_imm_int(b, 0));
101 }
102 
103 static unsigned
lower_vri_instr_tex_deref(nir_tex_instr * tex,nir_tex_src_type deref_src_type,gl_shader_stage stage,struct lvp_pipeline_layout * layout)104 lower_vri_instr_tex_deref(nir_tex_instr *tex,
105                           nir_tex_src_type deref_src_type,
106                           gl_shader_stage stage,
107                           struct lvp_pipeline_layout *layout)
108 {
109    int deref_src_idx = nir_tex_instr_src_index(tex, deref_src_type);
110 
111    if (deref_src_idx < 0)
112       return 0;
113 
114    nir_deref_instr *deref_instr = nir_src_as_deref(tex->src[deref_src_idx].src);
115    nir_variable *var = nir_deref_instr_get_variable(deref_instr);
116    unsigned desc_set_idx = var->data.descriptor_set;
117    unsigned binding_idx = var->data.binding;
118    int value = 0;
119    struct lvp_descriptor_set_binding_layout *binding = &layout->set[desc_set_idx].layout->binding[binding_idx];
120    nir_tex_instr_remove_src(tex, deref_src_idx);
121    for (unsigned s = 0; s < desc_set_idx; s++) {
122       if (deref_src_type == nir_tex_src_sampler_deref)
123          value += layout->set[s].layout->stage[stage].sampler_count;
124       else
125          value += layout->set[s].layout->stage[stage].sampler_view_count;
126    }
127    if (deref_src_type == nir_tex_src_sampler_deref)
128       value += binding->stage[stage].sampler_index;
129    else
130       value += binding->stage[stage].sampler_view_index;
131 
132    if (deref_instr->deref_type == nir_deref_type_array) {
133       if (nir_src_is_const(deref_instr->arr.index))
134          value += nir_src_as_uint(deref_instr->arr.index);
135       else {
136          if (deref_src_type == nir_tex_src_sampler_deref)
137             nir_tex_instr_add_src(tex, nir_tex_src_sampler_offset, deref_instr->arr.index);
138          else
139             nir_tex_instr_add_src(tex, nir_tex_src_texture_offset, deref_instr->arr.index);
140       }
141    }
142    if (deref_src_type == nir_tex_src_sampler_deref)
143       tex->sampler_index = value;
144    else
145       tex->texture_index = value;
146 
147    if (deref_src_type == nir_tex_src_sampler_deref)
148       return 0;
149 
150    if (deref_instr->deref_type == nir_deref_type_array) {
151       assert(glsl_type_is_array(var->type));
152       assert(value >= 0);
153       unsigned size = glsl_get_aoa_size(var->type);
154       return u_bit_consecutive(value, size);
155    } else
156       return 1u << value;
157 }
158 
lower_vri_instr_tex(struct nir_builder * b,nir_tex_instr * tex,void * data_cb)159 static void lower_vri_instr_tex(struct nir_builder *b,
160                                 nir_tex_instr *tex, void *data_cb)
161 {
162    struct lvp_pipeline_layout *layout = data_cb;
163    unsigned textures_used;
164 
165    lower_vri_instr_tex_deref(tex, nir_tex_src_sampler_deref, b->shader->info.stage, layout);
166    textures_used = lower_vri_instr_tex_deref(tex, nir_tex_src_texture_deref, b->shader->info.stage, layout);
167    while (textures_used) {
168       int i = u_bit_scan(&textures_used);
169       BITSET_SET(b->shader->info.textures_used, i);
170    }
171 }
172 
lower_vri_instr(struct nir_builder * b,nir_instr * instr,void * data_cb)173 static nir_ssa_def *lower_vri_instr(struct nir_builder *b,
174                                     nir_instr *instr, void *data_cb)
175 {
176    if (instr->type == nir_instr_type_intrinsic) {
177       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
178       switch (intrin->intrinsic) {
179       case nir_intrinsic_vulkan_resource_index:
180          return lower_vri_intrin_vri(b, instr, data_cb);
181 
182       case nir_intrinsic_vulkan_resource_reindex:
183          return lower_vri_intrin_vrri(b, instr, data_cb);
184 
185       case nir_intrinsic_load_vulkan_descriptor:
186          return lower_vri_intrin_lvd(b, instr, data_cb);
187 
188       case nir_intrinsic_get_ssbo_size: {
189          /* The result of the load_vulkan_descriptor is a vec2(index, offset)
190           * but we only want the index in get_ssbo_size.
191           */
192          b->cursor = nir_before_instr(&intrin->instr);
193          nir_ssa_def *index = nir_ssa_for_src(b, intrin->src[0], 1);
194          nir_instr_rewrite_src(&intrin->instr, &intrin->src[0],
195                                nir_src_for_ssa(index));
196          return NULL;
197       }
198 
199       default:
200          return NULL;
201       }
202    }
203    if (instr->type == nir_instr_type_tex)
204       lower_vri_instr_tex(b, nir_instr_as_tex(instr), data_cb);
205    return NULL;
206 }
207 
lvp_lower_pipeline_layout(const struct lvp_device * device,struct lvp_pipeline_layout * layout,nir_shader * shader)208 void lvp_lower_pipeline_layout(const struct lvp_device *device,
209                                struct lvp_pipeline_layout *layout,
210                                nir_shader *shader)
211 {
212    nir_shader_lower_instructions(shader, lower_vulkan_resource_index, lower_vri_instr, layout);
213    nir_foreach_uniform_variable(var, shader) {
214       const struct glsl_type *type = var->type;
215       enum glsl_base_type base_type =
216          glsl_get_base_type(glsl_without_array(type));
217       unsigned desc_set_idx = var->data.descriptor_set;
218       unsigned binding_idx = var->data.binding;
219       struct lvp_descriptor_set_binding_layout *binding = &layout->set[desc_set_idx].layout->binding[binding_idx];
220       int value = 0;
221       var->data.descriptor_set = 0;
222       if (base_type == GLSL_TYPE_SAMPLER) {
223          if (binding->type == VK_DESCRIPTOR_TYPE_SAMPLER) {
224             for (unsigned s = 0; s < desc_set_idx; s++)
225                value += layout->set[s].layout->stage[shader->info.stage].sampler_count;
226             value += binding->stage[shader->info.stage].sampler_index;
227          } else {
228             for (unsigned s = 0; s < desc_set_idx; s++)
229                value += layout->set[s].layout->stage[shader->info.stage].sampler_view_count;
230             value += binding->stage[shader->info.stage].sampler_view_index;
231          }
232          var->data.binding = value;
233       }
234       if (base_type == GLSL_TYPE_IMAGE) {
235          var->data.descriptor_set = 0;
236          for (unsigned s = 0; s < desc_set_idx; s++)
237            value += layout->set[s].layout->stage[shader->info.stage].image_count;
238          value += binding->stage[shader->info.stage].image_index;
239          var->data.binding = value;
240       }
241    }
242 }
243