nir: Print array deref indices as decimal
[mesa.git] / src / compiler / glsl / gl_nir_lower_buffers.c
1 /*
2 * Copyright © 2019 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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "compiler/nir/nir.h"
25 #include "compiler/nir/nir_builder.h"
26 #include "gl_nir.h"
27 #include "ir_uniform.h"
28
29 #include "main/compiler.h"
30 #include "main/mtypes.h"
31
32 static nir_ssa_def *
33 get_block_array_index(nir_builder *b, nir_deref_instr *deref,
34 const struct gl_shader_program *shader_program)
35 {
36 unsigned array_elements = 1;
37
38 /* Build a block name such as "block[2][0]" for finding in the list of
39 * blocks later on as well as an optional dynamic index which gets added
40 * to the block index later.
41 */
42 int binding = 0;
43 const char *block_name = "";
44 nir_ssa_def *nonconst_index = NULL;
45 while (deref->deref_type == nir_deref_type_array) {
46 nir_deref_instr *parent = nir_deref_instr_parent(deref);
47 assert(parent && glsl_type_is_array(parent->type));
48 unsigned arr_size = glsl_get_length(parent->type);
49
50 if (nir_src_is_const(deref->arr.index)) {
51 unsigned arr_index = nir_src_as_uint(deref->arr.index);
52 arr_index = MIN2(arr_index, arr_size - 1);
53
54 /* We're walking the deref from the tail so prepend the array index */
55 block_name = ralloc_asprintf(b->shader, "[%u]%s", arr_index,
56 block_name);
57
58 binding += arr_index * array_elements;
59 } else {
60 nir_ssa_def *arr_index = nir_ssa_for_src(b, deref->arr.index, 1);
61 arr_index = nir_umin(b, arr_index, nir_imm_int(b, arr_size - 1));
62 nir_ssa_def *arr_offset = nir_imul_imm(b, arr_index, array_elements);
63 if (nonconst_index)
64 nonconst_index = nir_iadd(b, nonconst_index, arr_offset);
65 else
66 nonconst_index = arr_offset;
67
68 /* We're walking the deref from the tail so prepend the array index */
69 block_name = ralloc_asprintf(b->shader, "[0]%s", block_name);
70 }
71
72 array_elements *= arr_size;
73 deref = parent;
74 }
75
76 assert(deref->deref_type == nir_deref_type_var);
77 binding += deref->var->data.binding;
78 block_name = ralloc_asprintf(b->shader, "%s%s",
79 glsl_get_type_name(deref->var->interface_type),
80 block_name);
81
82 struct gl_linked_shader *linked_shader =
83 shader_program->_LinkedShaders[b->shader->info.stage];
84
85 unsigned num_blocks;
86 struct gl_uniform_block **blocks;
87 if (deref->mode == nir_var_mem_ubo) {
88 num_blocks = linked_shader->Program->info.num_ubos;
89 blocks = linked_shader->Program->sh.UniformBlocks;
90 } else {
91 assert(deref->mode == nir_var_mem_ssbo);
92 num_blocks = linked_shader->Program->info.num_ssbos;
93 blocks = linked_shader->Program->sh.ShaderStorageBlocks;
94 }
95
96 /* Block names are optional with ARB_gl_spirv so use the binding instead. */
97 bool use_bindings = shader_program->data->spirv;
98
99 for (unsigned i = 0; i < num_blocks; i++) {
100 if (( use_bindings && binding == blocks[i]->Binding) ||
101 (!use_bindings && strcmp(block_name, blocks[i]->Name) == 0)) {
102 if (nonconst_index)
103 return nir_iadd_imm(b, nonconst_index, i);
104 else
105 return nir_imm_int(b, i);
106 }
107 }
108
109 /* TODO: Investigate if we could change the code to assign Bindings to the
110 * blocks that were not explicitly assigned, so we can always compare
111 * bindings.
112 */
113
114 if (use_bindings)
115 unreachable("Failed to find the block by binding");
116 else
117 unreachable("Failed to find the block by name");
118 }
119
120 static void
121 get_block_index_offset(nir_variable *var,
122 const struct gl_shader_program *shader_program,
123 gl_shader_stage stage,
124 unsigned *index, unsigned *offset)
125 {
126
127 struct gl_linked_shader *linked_shader =
128 shader_program->_LinkedShaders[stage];
129
130 unsigned num_blocks;
131 struct gl_uniform_block **blocks;
132 if (var->data.mode == nir_var_mem_ubo) {
133 num_blocks = linked_shader->Program->info.num_ubos;
134 blocks = linked_shader->Program->sh.UniformBlocks;
135 } else {
136 assert(var->data.mode == nir_var_mem_ssbo);
137 num_blocks = linked_shader->Program->info.num_ssbos;
138 blocks = linked_shader->Program->sh.ShaderStorageBlocks;
139 }
140
141 /* Block names are optional with ARB_gl_spirv so use the binding instead. */
142 bool use_bindings = shader_program->data->spirv;
143
144 for (unsigned i = 0; i < num_blocks; i++) {
145 const char *block_name = glsl_get_type_name(var->interface_type);
146 if (( use_bindings && blocks[i]->Binding == var->data.binding) ||
147 (!use_bindings && strcmp(block_name, blocks[i]->Name) == 0)) {
148 *index = i;
149 *offset = blocks[i]->Uniforms[var->data.location].Offset;
150 return;
151 }
152 }
153
154 if (use_bindings)
155 unreachable("Failed to find the block by binding");
156 else
157 unreachable("Failed to find the block by name");
158 }
159
160 static bool
161 lower_buffer_interface_derefs_impl(nir_function_impl *impl,
162 const struct gl_shader_program *shader_program)
163 {
164 bool progress = false;
165
166 nir_builder b;
167 nir_builder_init(&b, impl);
168
169 nir_foreach_block(block, impl) {
170 nir_foreach_instr_safe(instr, block) {
171 switch (instr->type) {
172 case nir_instr_type_deref: {
173 nir_deref_instr *deref = nir_instr_as_deref(instr);
174 if (!(deref->mode & (nir_var_mem_ubo | nir_var_mem_ssbo)))
175 break;
176
177 /* We use nir_address_format_32bit_index_offset */
178 assert(deref->dest.is_ssa);
179 assert(deref->dest.ssa.bit_size == 32);
180 deref->dest.ssa.num_components = 2;
181
182 progress = true;
183
184 b.cursor = nir_before_instr(&deref->instr);
185
186 nir_ssa_def *ptr;
187 if (deref->deref_type == nir_deref_type_var &&
188 !glsl_type_is_interface(glsl_without_array(deref->var->type))) {
189 /* This variable is contained in an interface block rather than
190 * containing one. We need the block index and its offset
191 * inside that block
192 */
193 unsigned index, offset;
194 get_block_index_offset(deref->var, shader_program,
195 b.shader->info.stage,
196 &index, &offset);
197 ptr = nir_imm_ivec2(&b, index, offset);
198 } else if (glsl_type_is_interface(deref->type)) {
199 /* This is the last deref before the block boundary.
200 * Everything after this point is a byte offset and will be
201 * handled by nir_lower_explicit_io().
202 */
203 nir_ssa_def *index = get_block_array_index(&b, deref,
204 shader_program);
205 ptr = nir_vec2(&b, index, nir_imm_int(&b, 0));
206 } else {
207 /* This will get handled by nir_lower_explicit_io(). */
208 break;
209 }
210
211 nir_deref_instr *cast = nir_build_deref_cast(&b, ptr, deref->mode,
212 deref->type, 0);
213 nir_ssa_def_rewrite_uses(&deref->dest.ssa,
214 nir_src_for_ssa(&cast->dest.ssa));
215 nir_deref_instr_remove_if_unused(deref);
216 break;
217 }
218
219 case nir_instr_type_intrinsic: {
220 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
221 switch (intrin->intrinsic) {
222 case nir_intrinsic_load_deref: {
223 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
224 if (!(deref->mode & (nir_var_mem_ubo | nir_var_mem_ssbo)))
225 break;
226
227 /* UBO and SSBO Booleans are 32-bit integers where any non-zero
228 * value is considered true. NIR Booleans, on the other hand
229 * are 1-bit values until you get to a very late stage of the
230 * compilation process. We need to turn those 1-bit loads into
231 * a 32-bit load wrapped in an i2b to get a proper NIR boolean
232 * from the SSBO.
233 */
234 if (glsl_type_is_boolean(deref->type)) {
235 assert(intrin->dest.is_ssa);
236 b.cursor = nir_after_instr(&intrin->instr);
237 intrin->dest.ssa.bit_size = 32;
238 nir_ssa_def *bval = nir_i2b(&b, &intrin->dest.ssa);
239 nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa,
240 nir_src_for_ssa(bval),
241 bval->parent_instr);
242 progress = true;
243 }
244 break;
245 }
246
247 case nir_intrinsic_store_deref: {
248 nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
249 if (!(deref->mode & (nir_var_mem_ubo | nir_var_mem_ssbo)))
250 break;
251
252 /* SSBO Booleans are 32-bit integers where any non-zero value
253 * is considered true. NIR Booleans, on the other hand are
254 * 1-bit values until you get to a very late stage of the
255 * compilation process. We need to turn those 1-bit stores
256 * into a b2i32 followed by a 32-bit store. Technically the
257 * value we write doesn't have to be 0/1 so once Booleans are
258 * lowered to 32-bit values, we have an unneeded sanitation
259 * step but in practice it doesn't cost much.
260 */
261 if (glsl_type_is_boolean(deref->type)) {
262 assert(intrin->src[1].is_ssa);
263 b.cursor = nir_before_instr(&intrin->instr);
264 nir_ssa_def *ival = nir_b2i32(&b, intrin->src[1].ssa);
265 nir_instr_rewrite_src(&intrin->instr, &intrin->src[1],
266 nir_src_for_ssa(ival));
267 progress = true;
268 }
269 break;
270 }
271
272 case nir_intrinsic_copy_deref:
273 unreachable("copy_deref should be lowered by now");
274 break;
275
276 default:
277 /* Nothing to do */
278 break;
279 }
280 break;
281 }
282
283 default:
284 break; /* Nothing to do */
285 }
286 }
287 }
288
289 if (progress) {
290 nir_metadata_preserve(impl, nir_metadata_block_index |
291 nir_metadata_dominance);
292 }
293
294 return progress;
295 }
296
297 bool
298 gl_nir_lower_buffers(nir_shader *shader,
299 const struct gl_shader_program *shader_program)
300 {
301 bool progress = false;
302
303 /* First, we lower the derefs to turn block variable and array derefs into
304 * a nir_address_format_32bit_index_offset pointer. From there forward,
305 * we leave the derefs in place and let nir_lower_explicit_io handle them.
306 */
307 nir_foreach_function(function, shader) {
308 if (function->impl &&
309 lower_buffer_interface_derefs_impl(function->impl, shader_program))
310 progress = true;
311 }
312
313 /* If that did something, we validate and then call nir_lower_explicit_io
314 * to finish the process.
315 */
316 if (progress) {
317 nir_validate_shader(shader, "Lowering buffer interface derefs");
318 nir_lower_explicit_io(shader, nir_var_mem_ubo | nir_var_mem_ssbo,
319 nir_address_format_32bit_index_offset);
320 }
321
322 return progress;
323 }