~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/compiler/nir/nir_lower_io_to_scalar.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2016 Broadcom
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 "nir.h"
25
 
#include "nir_builder.h"
26
 
#include "nir_deref.h"
27
 
 
28
 
/** @file nir_lower_io_to_scalar.c
29
 
 *
30
 
 * Replaces nir_load_input/nir_store_output operations with num_components !=
31
 
 * 1 with individual per-channel operations.
32
 
 */
33
 
 
34
 
static void
35
 
set_io_semantics(nir_intrinsic_instr *scalar_intr,
36
 
                 nir_intrinsic_instr *vec_intr, unsigned component)
37
 
{
38
 
   nir_io_semantics sem = nir_intrinsic_io_semantics(vec_intr);
39
 
   sem.gs_streams = (sem.gs_streams >> (component * 2)) & 0x3;
40
 
   nir_intrinsic_set_io_semantics(scalar_intr, sem);
41
 
}
42
 
 
43
 
static void
44
 
lower_load_input_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
45
 
{
46
 
   b->cursor = nir_before_instr(&intr->instr);
47
 
 
48
 
   assert(intr->dest.is_ssa);
49
 
 
50
 
   nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
51
 
 
52
 
   for (unsigned i = 0; i < intr->num_components; i++) {
53
 
      nir_intrinsic_instr *chan_intr =
54
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
55
 
      nir_ssa_dest_init(&chan_intr->instr, &chan_intr->dest,
56
 
                        1, intr->dest.ssa.bit_size, NULL);
57
 
      chan_intr->num_components = 1;
58
 
 
59
 
      nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
60
 
      nir_intrinsic_set_component(chan_intr, nir_intrinsic_component(intr) + i);
61
 
      nir_intrinsic_set_dest_type(chan_intr, nir_intrinsic_dest_type(intr));
62
 
      set_io_semantics(chan_intr, intr, i);
63
 
      /* offset */
64
 
      nir_src_copy(&chan_intr->src[0], &intr->src[0]);
65
 
 
66
 
      nir_builder_instr_insert(b, &chan_intr->instr);
67
 
 
68
 
      loads[i] = &chan_intr->dest.ssa;
69
 
   }
70
 
 
71
 
   nir_ssa_def_rewrite_uses(&intr->dest.ssa,
72
 
                            nir_vec(b, loads, intr->num_components));
73
 
   nir_instr_remove(&intr->instr);
74
 
}
75
 
 
76
 
static void
77
 
lower_load_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
78
 
{
79
 
   b->cursor = nir_before_instr(&intr->instr);
80
 
 
81
 
   assert(intr->dest.is_ssa);
82
 
 
83
 
   nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
84
 
   unsigned offset_idx = intr->intrinsic == nir_intrinsic_load_shared ? 0 : 1;
85
 
   nir_ssa_def *base_offset = intr->src[offset_idx].ssa;
86
 
 
87
 
   for (unsigned i = 0; i < intr->num_components; i++) {
88
 
      nir_intrinsic_instr *chan_intr =
89
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
90
 
      nir_ssa_dest_init(&chan_intr->instr, &chan_intr->dest,
91
 
                        1, intr->dest.ssa.bit_size, NULL);
92
 
      chan_intr->num_components = 1;
93
 
 
94
 
      nir_intrinsic_set_align_offset(chan_intr,
95
 
                                     (nir_intrinsic_align_offset(intr) +
96
 
                                      i * (intr->dest.ssa.bit_size / 8)) % nir_intrinsic_align_mul(intr));
97
 
      nir_intrinsic_set_align_mul(chan_intr, nir_intrinsic_align_mul(intr));
98
 
      if (nir_intrinsic_has_access(intr))
99
 
         nir_intrinsic_set_access(chan_intr, nir_intrinsic_access(intr));
100
 
      if (nir_intrinsic_has_range(intr))
101
 
         nir_intrinsic_set_range(chan_intr, nir_intrinsic_range(intr));
102
 
      if (nir_intrinsic_has_range_base(intr))
103
 
         nir_intrinsic_set_range_base(chan_intr, nir_intrinsic_range_base(intr));
104
 
      if (nir_intrinsic_has_base(intr))
105
 
         nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
106
 
      for (unsigned j = 0; j < nir_intrinsic_infos[intr->intrinsic].num_srcs - 1; j++)
107
 
         nir_src_copy(&chan_intr->src[j], &intr->src[j]);
108
 
 
109
 
      /* increment offset per component */
110
 
      nir_ssa_def *offset = nir_iadd_imm(b, base_offset, i * (intr->dest.ssa.bit_size / 8));
111
 
      chan_intr->src[offset_idx] = nir_src_for_ssa(offset);
112
 
 
113
 
      nir_builder_instr_insert(b, &chan_intr->instr);
114
 
 
115
 
      loads[i] = &chan_intr->dest.ssa;
116
 
   }
117
 
 
118
 
   nir_ssa_def_rewrite_uses(&intr->dest.ssa,
119
 
                            nir_vec(b, loads, intr->num_components));
120
 
   nir_instr_remove(&intr->instr);
121
 
}
122
 
 
123
 
static void
124
 
lower_store_output_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
125
 
{
126
 
   b->cursor = nir_before_instr(&intr->instr);
127
 
 
128
 
   nir_ssa_def *value = nir_ssa_for_src(b, intr->src[0], intr->num_components);
129
 
 
130
 
   for (unsigned i = 0; i < intr->num_components; i++) {
131
 
      if (!(nir_intrinsic_write_mask(intr) & (1 << i)))
132
 
         continue;
133
 
 
134
 
      nir_intrinsic_instr *chan_intr =
135
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
136
 
      chan_intr->num_components = 1;
137
 
 
138
 
      nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
139
 
      nir_intrinsic_set_write_mask(chan_intr, 0x1);
140
 
      nir_intrinsic_set_component(chan_intr, nir_intrinsic_component(intr) + i);
141
 
      nir_intrinsic_set_src_type(chan_intr, nir_intrinsic_src_type(intr));
142
 
      set_io_semantics(chan_intr, intr, i);
143
 
 
144
 
      /* Scalarize transform feedback info. */
145
 
      unsigned component = nir_intrinsic_component(chan_intr);
146
 
 
147
 
      for (unsigned c = 0; c <= component; c++) {
148
 
         nir_io_xfb xfb = c < 2 ? nir_intrinsic_io_xfb(intr) :
149
 
                                  nir_intrinsic_io_xfb2(intr);
150
 
 
151
 
         if (component < c + xfb.out[c % 2].num_components) {
152
 
            nir_io_xfb scalar_xfb;
153
 
 
154
 
            memset(&scalar_xfb, 0, sizeof(scalar_xfb));
155
 
            scalar_xfb.out[component % 2].num_components = 1;
156
 
            scalar_xfb.out[component % 2].buffer = xfb.out[c % 2].buffer;
157
 
            scalar_xfb.out[component % 2].offset = xfb.out[c % 2].offset +
158
 
                                                   component - c;
159
 
            if (component < 2)
160
 
               nir_intrinsic_set_io_xfb(chan_intr, scalar_xfb);
161
 
            else
162
 
               nir_intrinsic_set_io_xfb2(chan_intr, scalar_xfb);
163
 
            break;
164
 
         }
165
 
      }
166
 
 
167
 
      /* value */
168
 
      chan_intr->src[0] = nir_src_for_ssa(nir_channel(b, value, i));
169
 
      /* offset */
170
 
      nir_src_copy(&chan_intr->src[1], &intr->src[1]);
171
 
 
172
 
      nir_builder_instr_insert(b, &chan_intr->instr);
173
 
   }
174
 
 
175
 
   nir_instr_remove(&intr->instr);
176
 
}
177
 
 
178
 
static void
179
 
lower_store_to_scalar(nir_builder *b, nir_intrinsic_instr *intr)
180
 
{
181
 
   b->cursor = nir_before_instr(&intr->instr);
182
 
 
183
 
   nir_ssa_def *value = nir_ssa_for_src(b, intr->src[0], intr->num_components);
184
 
   unsigned offset_idx = intr->intrinsic == nir_intrinsic_store_shared ? 1 : 2;
185
 
   nir_ssa_def *base_offset = intr->src[offset_idx].ssa;
186
 
 
187
 
   /* iterate wrmask instead of num_components to handle split components */
188
 
   u_foreach_bit(i, nir_intrinsic_write_mask(intr)) {
189
 
      nir_intrinsic_instr *chan_intr =
190
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
191
 
      chan_intr->num_components = 1;
192
 
 
193
 
      nir_intrinsic_set_write_mask(chan_intr, 0x1);
194
 
      nir_intrinsic_set_align_offset(chan_intr,
195
 
                                     (nir_intrinsic_align_offset(intr) +
196
 
                                      i * (value->bit_size / 8)) % nir_intrinsic_align_mul(intr));
197
 
      nir_intrinsic_set_align_mul(chan_intr, nir_intrinsic_align_mul(intr));
198
 
      if (nir_intrinsic_has_access(intr))
199
 
         nir_intrinsic_set_access(chan_intr, nir_intrinsic_access(intr));
200
 
      if (nir_intrinsic_has_base(intr))
201
 
         nir_intrinsic_set_base(chan_intr, nir_intrinsic_base(intr));
202
 
 
203
 
      /* value */
204
 
      chan_intr->src[0] = nir_src_for_ssa(nir_channel(b, value, i));
205
 
      for (unsigned j = 1; j < nir_intrinsic_infos[intr->intrinsic].num_srcs - 1; j++)
206
 
         nir_src_copy(&chan_intr->src[j], &intr->src[j]);
207
 
 
208
 
      /* increment offset per component */
209
 
      nir_ssa_def *offset = nir_iadd_imm(b, base_offset, i * (value->bit_size / 8));
210
 
      chan_intr->src[offset_idx] = nir_src_for_ssa(offset);
211
 
 
212
 
      nir_builder_instr_insert(b, &chan_intr->instr);
213
 
   }
214
 
 
215
 
   nir_instr_remove(&intr->instr);
216
 
}
217
 
 
218
 
static bool
219
 
nir_lower_io_to_scalar_instr(nir_builder *b, nir_instr *instr, void *data)
220
 
{
221
 
   nir_variable_mode mask = *(nir_variable_mode *)data;
222
 
 
223
 
   if (instr->type != nir_instr_type_intrinsic)
224
 
      return false;
225
 
 
226
 
   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
227
 
 
228
 
   if (intr->num_components == 1)
229
 
      return false;
230
 
 
231
 
   if (intr->intrinsic == nir_intrinsic_load_input &&
232
 
       (mask & nir_var_shader_in)) {
233
 
      lower_load_input_to_scalar(b, intr);
234
 
      return true;
235
 
   }
236
 
 
237
 
   if ((intr->intrinsic == nir_intrinsic_load_ubo && (mask & nir_var_mem_ubo)) ||
238
 
       (intr->intrinsic == nir_intrinsic_load_ssbo && (mask & nir_var_mem_ssbo)) ||
239
 
       (intr->intrinsic == nir_intrinsic_load_shared && (mask & nir_var_mem_shared))) {
240
 
      lower_load_to_scalar(b, intr);
241
 
      return true;
242
 
   }
243
 
 
244
 
   if (intr->intrinsic == nir_intrinsic_store_output &&
245
 
       mask & nir_var_shader_out) {
246
 
      lower_store_output_to_scalar(b, intr);
247
 
      return true;
248
 
   }
249
 
 
250
 
   if ((intr->intrinsic == nir_intrinsic_store_ssbo && (mask & nir_var_mem_ssbo)) ||
251
 
       (intr->intrinsic == nir_intrinsic_store_shared && (mask & nir_var_mem_shared))) {
252
 
      lower_store_to_scalar(b, intr);
253
 
      return true;
254
 
   }
255
 
 
256
 
   return false;
257
 
}
258
 
 
259
 
void
260
 
nir_lower_io_to_scalar(nir_shader *shader, nir_variable_mode mask)
261
 
{
262
 
   nir_shader_instructions_pass(shader,
263
 
                                nir_lower_io_to_scalar_instr,
264
 
                                nir_metadata_block_index |
265
 
                                nir_metadata_dominance,
266
 
                                &mask);
267
 
}
268
 
 
269
 
static nir_variable **
270
 
get_channel_variables(struct hash_table *ht, nir_variable *var)
271
 
{
272
 
   nir_variable **chan_vars;
273
 
   struct hash_entry *entry = _mesa_hash_table_search(ht, var);
274
 
   if (!entry) {
275
 
      chan_vars = (nir_variable **) calloc(4, sizeof(nir_variable *));
276
 
      _mesa_hash_table_insert(ht, var, chan_vars);
277
 
   } else {
278
 
      chan_vars = (nir_variable **) entry->data;
279
 
   }
280
 
 
281
 
   return chan_vars;
282
 
}
283
 
 
284
 
/*
285
 
 * Note that the src deref that we are cloning is the head of the
286
 
 * chain of deref instructions from the original intrinsic, but
287
 
 * the dst we are cloning to is the tail (because chains of deref
288
 
 * instructions are created back to front)
289
 
 */
290
 
 
291
 
static nir_deref_instr *
292
 
clone_deref_array(nir_builder *b, nir_deref_instr *dst_tail,
293
 
                  const nir_deref_instr *src_head)
294
 
{
295
 
   const nir_deref_instr *parent = nir_deref_instr_parent(src_head);
296
 
 
297
 
   if (!parent)
298
 
      return dst_tail;
299
 
 
300
 
   assert(src_head->deref_type == nir_deref_type_array);
301
 
 
302
 
   dst_tail = clone_deref_array(b, dst_tail, parent);
303
 
 
304
 
   return nir_build_deref_array(b, dst_tail,
305
 
                                nir_ssa_for_src(b, src_head->arr.index, 1));
306
 
}
307
 
 
308
 
static void
309
 
lower_load_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
310
 
                           nir_variable *var, struct hash_table *split_inputs,
311
 
                           struct hash_table *split_outputs)
312
 
{
313
 
   b->cursor = nir_before_instr(&intr->instr);
314
 
 
315
 
   assert(intr->dest.is_ssa);
316
 
 
317
 
   nir_ssa_def *loads[NIR_MAX_VEC_COMPONENTS];
318
 
 
319
 
   nir_variable **chan_vars;
320
 
   if (var->data.mode == nir_var_shader_in) {
321
 
      chan_vars = get_channel_variables(split_inputs, var);
322
 
   } else {
323
 
      chan_vars = get_channel_variables(split_outputs, var);
324
 
   }
325
 
 
326
 
   for (unsigned i = 0; i < intr->num_components; i++) {
327
 
      nir_variable *chan_var = chan_vars[var->data.location_frac + i];
328
 
      if (!chan_vars[var->data.location_frac + i]) {
329
 
         chan_var = nir_variable_clone(var, b->shader);
330
 
         chan_var->data.location_frac =  var->data.location_frac + i;
331
 
         chan_var->type = glsl_channel_type(chan_var->type);
332
 
         if (var->data.explicit_offset) {
333
 
            unsigned comp_size = glsl_get_bit_size(chan_var->type) / 8;
334
 
            chan_var->data.offset = var->data.offset + i * comp_size;
335
 
         }
336
 
 
337
 
         chan_vars[var->data.location_frac + i] = chan_var;
338
 
 
339
 
         nir_shader_add_variable(b->shader, chan_var);
340
 
      }
341
 
 
342
 
      nir_intrinsic_instr *chan_intr =
343
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
344
 
      nir_ssa_dest_init(&chan_intr->instr, &chan_intr->dest,
345
 
                        1, intr->dest.ssa.bit_size, NULL);
346
 
      chan_intr->num_components = 1;
347
 
 
348
 
      nir_deref_instr *deref = nir_build_deref_var(b, chan_var);
349
 
 
350
 
      deref = clone_deref_array(b, deref, nir_src_as_deref(intr->src[0]));
351
 
 
352
 
      chan_intr->src[0] = nir_src_for_ssa(&deref->dest.ssa);
353
 
 
354
 
      if (intr->intrinsic == nir_intrinsic_interp_deref_at_offset ||
355
 
          intr->intrinsic == nir_intrinsic_interp_deref_at_sample ||
356
 
          intr->intrinsic == nir_intrinsic_interp_deref_at_vertex)
357
 
         nir_src_copy(&chan_intr->src[1], &intr->src[1]);
358
 
 
359
 
      nir_builder_instr_insert(b, &chan_intr->instr);
360
 
 
361
 
      loads[i] = &chan_intr->dest.ssa;
362
 
   }
363
 
 
364
 
   nir_ssa_def_rewrite_uses(&intr->dest.ssa,
365
 
                            nir_vec(b, loads, intr->num_components));
366
 
 
367
 
   /* Remove the old load intrinsic */
368
 
   nir_instr_remove(&intr->instr);
369
 
}
370
 
 
371
 
static void
372
 
lower_store_output_to_scalar_early(nir_builder *b, nir_intrinsic_instr *intr,
373
 
                                   nir_variable *var,
374
 
                                   struct hash_table *split_outputs)
375
 
{
376
 
   b->cursor = nir_before_instr(&intr->instr);
377
 
 
378
 
   nir_ssa_def *value = nir_ssa_for_src(b, intr->src[1], intr->num_components);
379
 
 
380
 
   nir_variable **chan_vars = get_channel_variables(split_outputs, var);
381
 
   for (unsigned i = 0; i < intr->num_components; i++) {
382
 
      if (!(nir_intrinsic_write_mask(intr) & (1 << i)))
383
 
         continue;
384
 
 
385
 
      nir_variable *chan_var = chan_vars[var->data.location_frac + i];
386
 
      if (!chan_vars[var->data.location_frac + i]) {
387
 
         chan_var = nir_variable_clone(var, b->shader);
388
 
         chan_var->data.location_frac =  var->data.location_frac + i;
389
 
         chan_var->type = glsl_channel_type(chan_var->type);
390
 
         if (var->data.explicit_offset) {
391
 
            unsigned comp_size = glsl_get_bit_size(chan_var->type) / 8;
392
 
            chan_var->data.offset = var->data.offset + i * comp_size;
393
 
         }
394
 
 
395
 
         chan_vars[var->data.location_frac + i] = chan_var;
396
 
 
397
 
         nir_shader_add_variable(b->shader, chan_var);
398
 
      }
399
 
 
400
 
      nir_intrinsic_instr *chan_intr =
401
 
         nir_intrinsic_instr_create(b->shader, intr->intrinsic);
402
 
      chan_intr->num_components = 1;
403
 
 
404
 
      nir_intrinsic_set_write_mask(chan_intr, 0x1);
405
 
 
406
 
      nir_deref_instr *deref = nir_build_deref_var(b, chan_var);
407
 
 
408
 
      deref = clone_deref_array(b, deref, nir_src_as_deref(intr->src[0]));
409
 
 
410
 
      chan_intr->src[0] = nir_src_for_ssa(&deref->dest.ssa);
411
 
      chan_intr->src[1] = nir_src_for_ssa(nir_channel(b, value, i));
412
 
 
413
 
      nir_builder_instr_insert(b, &chan_intr->instr);
414
 
   }
415
 
 
416
 
   /* Remove the old store intrinsic */
417
 
   nir_instr_remove(&intr->instr);
418
 
}
419
 
 
420
 
struct io_to_scalar_early_state {
421
 
   struct hash_table *split_inputs, *split_outputs;
422
 
   nir_variable_mode mask;
423
 
};
424
 
 
425
 
static bool
426
 
nir_lower_io_to_scalar_early_instr(nir_builder *b, nir_instr *instr, void *data)
427
 
{
428
 
   struct io_to_scalar_early_state *state = data;
429
 
 
430
 
   if (instr->type != nir_instr_type_intrinsic)
431
 
      return false;
432
 
 
433
 
   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
434
 
 
435
 
   if (intr->num_components == 1)
436
 
      return false;
437
 
 
438
 
   if (intr->intrinsic != nir_intrinsic_load_deref &&
439
 
       intr->intrinsic != nir_intrinsic_store_deref &&
440
 
       intr->intrinsic != nir_intrinsic_interp_deref_at_centroid &&
441
 
       intr->intrinsic != nir_intrinsic_interp_deref_at_sample &&
442
 
       intr->intrinsic != nir_intrinsic_interp_deref_at_offset &&
443
 
       intr->intrinsic != nir_intrinsic_interp_deref_at_vertex)
444
 
      return false;
445
 
 
446
 
   nir_deref_instr *deref = nir_src_as_deref(intr->src[0]);
447
 
   if (!nir_deref_mode_is_one_of(deref, state->mask))
448
 
      return false;
449
 
 
450
 
   nir_variable *var = nir_deref_instr_get_variable(deref);
451
 
   nir_variable_mode mode = var->data.mode;
452
 
 
453
 
   /* TODO: add patch support */
454
 
   if (var->data.patch)
455
 
      return false;
456
 
 
457
 
   /* TODO: add doubles support */
458
 
   if (glsl_type_is_64bit(glsl_without_array(var->type)))
459
 
      return false;
460
 
 
461
 
   if (!(b->shader->info.stage == MESA_SHADER_VERTEX &&
462
 
         mode == nir_var_shader_in) &&
463
 
       var->data.location < VARYING_SLOT_VAR0 &&
464
 
       var->data.location >= 0)
465
 
      return false;
466
 
 
467
 
   /* Don't bother splitting if we can't opt away any unused
468
 
    * components.
469
 
    */
470
 
   if (var->data.always_active_io)
471
 
      return false;
472
 
 
473
 
   /* Skip types we cannot split */
474
 
   if (glsl_type_is_matrix(glsl_without_array(var->type)) ||
475
 
       glsl_type_is_struct_or_ifc(glsl_without_array(var->type)))
476
 
      return false;
477
 
 
478
 
   switch (intr->intrinsic) {
479
 
   case nir_intrinsic_interp_deref_at_centroid:
480
 
   case nir_intrinsic_interp_deref_at_sample:
481
 
   case nir_intrinsic_interp_deref_at_offset:
482
 
   case nir_intrinsic_interp_deref_at_vertex:
483
 
   case nir_intrinsic_load_deref:
484
 
      if ((state->mask & nir_var_shader_in && mode == nir_var_shader_in) ||
485
 
          (state->mask & nir_var_shader_out && mode == nir_var_shader_out)) {
486
 
         lower_load_to_scalar_early(b, intr, var, state->split_inputs,
487
 
                                    state->split_outputs);
488
 
         return true;
489
 
      }
490
 
      break;
491
 
   case nir_intrinsic_store_deref:
492
 
      if (state->mask & nir_var_shader_out &&
493
 
          mode == nir_var_shader_out) {
494
 
         lower_store_output_to_scalar_early(b, intr, var, state->split_outputs);
495
 
         return true;
496
 
      }
497
 
      break;
498
 
   default:
499
 
      break;
500
 
   }
501
 
 
502
 
   return false;
503
 
}
504
 
 
505
 
/*
506
 
 * This function is intended to be called earlier than nir_lower_io_to_scalar()
507
 
 * i.e. before nir_lower_io() is called.
508
 
 */
509
 
bool
510
 
nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask)
511
 
{
512
 
   struct io_to_scalar_early_state state = {
513
 
      .split_inputs = _mesa_pointer_hash_table_create(NULL),
514
 
      .split_outputs = _mesa_pointer_hash_table_create(NULL),
515
 
      .mask = mask
516
 
   };
517
 
 
518
 
   bool progress = nir_shader_instructions_pass(shader,
519
 
                                                nir_lower_io_to_scalar_early_instr,
520
 
                                                nir_metadata_block_index |
521
 
                                                nir_metadata_dominance,
522
 
                                                &state);
523
 
 
524
 
   /* Remove old input from the shaders inputs list */
525
 
   hash_table_foreach(state.split_inputs, entry) {
526
 
      nir_variable *var = (nir_variable *) entry->key;
527
 
      exec_node_remove(&var->node);
528
 
 
529
 
      free(entry->data);
530
 
   }
531
 
 
532
 
   /* Remove old output from the shaders outputs list */
533
 
   hash_table_foreach(state.split_outputs, entry) {
534
 
      nir_variable *var = (nir_variable *) entry->key;
535
 
      exec_node_remove(&var->node);
536
 
 
537
 
      free(entry->data);
538
 
   }
539
 
 
540
 
   _mesa_hash_table_destroy(state.split_inputs, NULL);
541
 
   _mesa_hash_table_destroy(state.split_outputs, NULL);
542
 
 
543
 
   nir_remove_dead_derefs(shader);
544
 
 
545
 
   return progress;
546
 
}