2 * Copyright © 2019 Intel Corporation
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:
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
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.
24 #include "compiler/nir/nir.h"
25 #include "compiler/nir/nir_builder.h"
27 #include "ir_uniform.h"
29 #include "main/compiler.h"
30 #include "main/mtypes.h"
33 get_block_array_index(nir_builder
*b
, nir_deref_instr
*deref
,
34 const struct gl_shader_program
*shader_program
)
36 unsigned array_elements
= 1;
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.
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
);
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);
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
,
58 binding
+= arr_index
* array_elements
;
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
);
64 nonconst_index
= nir_iadd(b
, nonconst_index
, arr_offset
);
66 nonconst_index
= arr_offset
;
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
);
72 array_elements
*= arr_size
;
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
),
82 struct gl_linked_shader
*linked_shader
=
83 shader_program
->_LinkedShaders
[b
->shader
->info
.stage
];
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
;
91 assert(deref
->mode
== nir_var_mem_ssbo
);
92 num_blocks
= linked_shader
->Program
->info
.num_ssbos
;
93 blocks
= linked_shader
->Program
->sh
.ShaderStorageBlocks
;
96 /* Block names are optional with ARB_gl_spirv so use the binding instead. */
97 bool use_bindings
= shader_program
->data
->spirv
;
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)) {
103 return nir_iadd_imm(b
, nonconst_index
, i
);
105 return nir_imm_int(b
, i
);
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
115 unreachable("Failed to find the block by binding");
117 unreachable("Failed to find the block by name");
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
)
127 struct gl_linked_shader
*linked_shader
=
128 shader_program
->_LinkedShaders
[stage
];
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
;
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
;
141 /* Block names are optional with ARB_gl_spirv so use the binding instead. */
142 bool use_bindings
= shader_program
->data
->spirv
;
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)) {
149 *offset
= blocks
[i
]->Uniforms
[var
->data
.location
].Offset
;
155 unreachable("Failed to find the block by binding");
157 unreachable("Failed to find the block by name");
161 lower_buffer_interface_derefs_impl(nir_function_impl
*impl
,
162 const struct gl_shader_program
*shader_program
)
164 bool progress
= false;
167 nir_builder_init(&b
, impl
);
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
)))
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;
184 b
.cursor
= nir_before_instr(&deref
->instr
);
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
193 unsigned index
, offset
;
194 get_block_index_offset(deref
->var
, shader_program
,
195 b
.shader
->info
.stage
,
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().
203 nir_ssa_def
*index
= get_block_array_index(&b
, deref
,
205 ptr
= nir_vec2(&b
, index
, nir_imm_int(&b
, 0));
207 /* This will get handled by nir_lower_explicit_io(). */
211 nir_deref_instr
*cast
= nir_build_deref_cast(&b
, ptr
, deref
->mode
,
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
);
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
)))
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
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
),
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
)))
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.
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
));
272 case nir_intrinsic_copy_deref
:
273 unreachable("copy_deref should be lowered by now");
284 break; /* Nothing to do */
290 nir_metadata_preserve(impl
, nir_metadata_block_index
|
291 nir_metadata_dominance
);
298 gl_nir_lower_buffers(nir_shader
*shader
,
299 const struct gl_shader_program
*shader_program
)
301 bool progress
= false;
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.
307 nir_foreach_function(function
, shader
) {
308 if (function
->impl
&&
309 lower_buffer_interface_derefs_impl(function
->impl
, shader_program
))
313 /* If that did something, we validate and then call nir_lower_explicit_io
314 * to finish the process.
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
);