Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_lower_buffers.c
4545 views
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 "util/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
53
/* We're walking the deref from the tail so prepend the array index */
54
block_name = ralloc_asprintf(b->shader, "[%u]%s", arr_index,
55
block_name);
56
57
binding += arr_index * array_elements;
58
} else {
59
nir_ssa_def *arr_index = nir_ssa_for_src(b, deref->arr.index, 1);
60
arr_index = nir_umin(b, arr_index, nir_imm_int(b, arr_size - 1));
61
nir_ssa_def *arr_offset = nir_amul_imm(b, arr_index, array_elements);
62
if (nonconst_index)
63
nonconst_index = nir_iadd(b, nonconst_index, arr_offset);
64
else
65
nonconst_index = arr_offset;
66
67
/* We're walking the deref from the tail so prepend the array index */
68
block_name = ralloc_asprintf(b->shader, "[0]%s", block_name);
69
}
70
71
array_elements *= arr_size;
72
deref = parent;
73
}
74
75
assert(deref->deref_type == nir_deref_type_var);
76
binding += deref->var->data.binding;
77
block_name = ralloc_asprintf(b->shader, "%s%s",
78
glsl_get_type_name(deref->var->interface_type),
79
block_name);
80
81
struct gl_linked_shader *linked_shader =
82
shader_program->_LinkedShaders[b->shader->info.stage];
83
84
unsigned num_blocks;
85
struct gl_uniform_block **blocks;
86
if (nir_deref_mode_is(deref, nir_var_mem_ubo)) {
87
num_blocks = linked_shader->Program->info.num_ubos;
88
blocks = linked_shader->Program->sh.UniformBlocks;
89
} else {
90
assert(nir_deref_mode_is(deref, nir_var_mem_ssbo));
91
num_blocks = linked_shader->Program->info.num_ssbos;
92
blocks = linked_shader->Program->sh.ShaderStorageBlocks;
93
}
94
95
/* Block names are optional with ARB_gl_spirv so use the binding instead. */
96
bool use_bindings = shader_program->data->spirv;
97
98
for (unsigned i = 0; i < num_blocks; i++) {
99
if (( use_bindings && binding == blocks[i]->Binding) ||
100
(!use_bindings && strcmp(block_name, blocks[i]->Name) == 0)) {
101
if (nonconst_index)
102
return nir_iadd_imm(b, nonconst_index, i);
103
else
104
return nir_imm_int(b, i);
105
}
106
}
107
108
/* TODO: Investigate if we could change the code to assign Bindings to the
109
* blocks that were not explicitly assigned, so we can always compare
110
* bindings.
111
*/
112
113
if (use_bindings)
114
unreachable("Failed to find the block by binding");
115
else
116
unreachable("Failed to find the block by name");
117
}
118
119
static void
120
get_block_index_offset(nir_variable *var,
121
const struct gl_shader_program *shader_program,
122
gl_shader_stage stage,
123
unsigned *index, unsigned *offset)
124
{
125
126
struct gl_linked_shader *linked_shader =
127
shader_program->_LinkedShaders[stage];
128
129
unsigned num_blocks;
130
struct gl_uniform_block **blocks;
131
if (var->data.mode == nir_var_mem_ubo) {
132
num_blocks = linked_shader->Program->info.num_ubos;
133
blocks = linked_shader->Program->sh.UniformBlocks;
134
} else {
135
assert(var->data.mode == nir_var_mem_ssbo);
136
num_blocks = linked_shader->Program->info.num_ssbos;
137
blocks = linked_shader->Program->sh.ShaderStorageBlocks;
138
}
139
140
/* Block names are optional with ARB_gl_spirv so use the binding instead. */
141
bool use_bindings = shader_program->data->spirv;
142
143
for (unsigned i = 0; i < num_blocks; i++) {
144
const char *block_name = glsl_get_type_name(var->interface_type);
145
if (( use_bindings && blocks[i]->Binding == var->data.binding) ||
146
(!use_bindings && strcmp(block_name, blocks[i]->Name) == 0)) {
147
*index = i;
148
*offset = blocks[i]->Uniforms[var->data.location].Offset;
149
return;
150
}
151
}
152
153
if (use_bindings)
154
unreachable("Failed to find the block by binding");
155
else
156
unreachable("Failed to find the block by name");
157
}
158
159
static bool
160
lower_buffer_interface_derefs_impl(nir_function_impl *impl,
161
const struct gl_shader_program *shader_program)
162
{
163
bool progress = false;
164
165
nir_builder b;
166
nir_builder_init(&b, impl);
167
168
/* this must be a separate loop before the main pass in order to ensure that
169
* access info is fully propagated prior to the info being lost during rewrites
170
*/
171
nir_foreach_block(block, impl) {
172
nir_foreach_instr(instr, block) {
173
if (instr->type != nir_instr_type_intrinsic)
174
continue;
175
176
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
177
if (intrin->intrinsic == nir_intrinsic_load_deref ||
178
intrin->intrinsic == nir_intrinsic_store_deref) {
179
nir_variable *var = nir_intrinsic_get_var(intrin, 0);
180
assert(var);
181
nir_intrinsic_set_access(intrin, nir_intrinsic_access(intrin) | var->data.access);
182
}
183
}
184
}
185
186
nir_foreach_block(block, impl) {
187
nir_foreach_instr_safe(instr, block) {
188
switch (instr->type) {
189
case nir_instr_type_deref: {
190
nir_deref_instr *deref = nir_instr_as_deref(instr);
191
if (!nir_deref_mode_is_one_of(deref, nir_var_mem_ubo |
192
nir_var_mem_ssbo))
193
break;
194
195
/* We use nir_address_format_32bit_index_offset */
196
assert(deref->dest.is_ssa);
197
assert(deref->dest.ssa.bit_size == 32);
198
deref->dest.ssa.num_components = 2;
199
200
progress = true;
201
202
b.cursor = nir_before_instr(&deref->instr);
203
204
unsigned offset = 0;
205
nir_ssa_def *ptr;
206
if (deref->deref_type == nir_deref_type_var &&
207
!glsl_type_is_interface(glsl_without_array(deref->var->type))) {
208
/* This variable is contained in an interface block rather than
209
* containing one. We need the block index and its offset
210
* inside that block
211
*/
212
unsigned index;
213
get_block_index_offset(deref->var, shader_program,
214
b.shader->info.stage,
215
&index, &offset);
216
ptr = nir_imm_ivec2(&b, index, offset);
217
} else if (glsl_type_is_interface(deref->type)) {
218
/* This is the last deref before the block boundary.
219
* Everything after this point is a byte offset and will be
220
* handled by nir_lower_explicit_io().
221
*/
222
nir_ssa_def *index = get_block_array_index(&b, deref,
223
shader_program);
224
ptr = nir_vec2(&b, index, nir_imm_int(&b, offset));
225
} else {
226
/* This will get handled by nir_lower_explicit_io(). */
227
break;
228
}
229
230
nir_deref_instr *cast = nir_build_deref_cast(&b, ptr, deref->modes,
231
deref->type, 0);
232
/* Set the alignment on the cast so that we get good alignment out
233
* of nir_lower_explicit_io. Our offset to the start of the UBO
234
* variable is always a constant, so we can use the maximum
235
* align_mul.
236
*/
237
cast->cast.align_mul = NIR_ALIGN_MUL_MAX;
238
cast->cast.align_offset = offset % NIR_ALIGN_MUL_MAX;
239
240
nir_ssa_def_rewrite_uses(&deref->dest.ssa,
241
&cast->dest.ssa);
242
nir_deref_instr_remove_if_unused(deref);
243
break;
244
}
245
246
case nir_instr_type_intrinsic: {
247
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
248
switch (intrin->intrinsic) {
249
case nir_intrinsic_load_deref: {
250
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
251
if (!nir_deref_mode_is_one_of(deref, nir_var_mem_ubo |
252
nir_var_mem_ssbo))
253
break;
254
255
/* UBO and SSBO Booleans are 32-bit integers where any non-zero
256
* value is considered true. NIR Booleans, on the other hand
257
* are 1-bit values until you get to a very late stage of the
258
* compilation process. We need to turn those 1-bit loads into
259
* a 32-bit load wrapped in an i2b to get a proper NIR boolean
260
* from the SSBO.
261
*/
262
if (glsl_type_is_boolean(deref->type)) {
263
assert(intrin->dest.is_ssa);
264
b.cursor = nir_after_instr(&intrin->instr);
265
intrin->dest.ssa.bit_size = 32;
266
nir_ssa_def *bval = nir_i2b(&b, &intrin->dest.ssa);
267
nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa,
268
bval,
269
bval->parent_instr);
270
progress = true;
271
}
272
break;
273
}
274
275
case nir_intrinsic_store_deref: {
276
nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]);
277
if (!nir_deref_mode_is_one_of(deref, nir_var_mem_ubo |
278
nir_var_mem_ssbo))
279
break;
280
281
/* SSBO Booleans are 32-bit integers where any non-zero value
282
* is considered true. NIR Booleans, on the other hand are
283
* 1-bit values until you get to a very late stage of the
284
* compilation process. We need to turn those 1-bit stores
285
* into a b2i32 followed by a 32-bit store. Technically the
286
* value we write doesn't have to be 0/1 so once Booleans are
287
* lowered to 32-bit values, we have an unneeded sanitation
288
* step but in practice it doesn't cost much.
289
*/
290
if (glsl_type_is_boolean(deref->type)) {
291
assert(intrin->src[1].is_ssa);
292
b.cursor = nir_before_instr(&intrin->instr);
293
nir_ssa_def *ival = nir_b2i32(&b, intrin->src[1].ssa);
294
nir_instr_rewrite_src(&intrin->instr, &intrin->src[1],
295
nir_src_for_ssa(ival));
296
progress = true;
297
}
298
break;
299
}
300
301
case nir_intrinsic_copy_deref:
302
unreachable("copy_deref should be lowered by now");
303
break;
304
305
default:
306
/* Nothing to do */
307
break;
308
}
309
break;
310
}
311
312
default:
313
break; /* Nothing to do */
314
}
315
}
316
}
317
318
if (progress) {
319
nir_metadata_preserve(impl, nir_metadata_block_index |
320
nir_metadata_dominance);
321
}
322
323
return progress;
324
}
325
326
bool
327
gl_nir_lower_buffers(nir_shader *shader,
328
const struct gl_shader_program *shader_program)
329
{
330
bool progress = false;
331
332
/* First, we lower the derefs to turn block variable and array derefs into
333
* a nir_address_format_32bit_index_offset pointer. From there forward,
334
* we leave the derefs in place and let nir_lower_explicit_io handle them.
335
*/
336
nir_foreach_function(function, shader) {
337
if (function->impl &&
338
lower_buffer_interface_derefs_impl(function->impl, shader_program))
339
progress = true;
340
}
341
342
/* If that did something, we validate and then call nir_lower_explicit_io
343
* to finish the process.
344
*/
345
if (progress) {
346
nir_validate_shader(shader, "Lowering buffer interface derefs");
347
nir_lower_explicit_io(shader, nir_var_mem_ubo | nir_var_mem_ssbo,
348
nir_address_format_32bit_index_offset);
349
}
350
351
return progress;
352
}
353
354