xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/r600/sfn/sfn_nir_legalize_image_load_store.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /* -*- mesa-c++  -*-
2  * Copyright 2021 Collabora LTD
3  * Author: Gert Wollny <[email protected]>
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "nir.h"
8 #include "nir_builder.h"
9 #include "nir_intrinsics.h"
10 #include "nir_intrinsics_indices.h"
11 #include "sfn_nir.h"
12 
13 static nir_def *
r600_legalize_image_load_store_impl(nir_builder * b,nir_instr * instr,UNUSED void * _options)14 r600_legalize_image_load_store_impl(nir_builder *b,
15                                     nir_instr *instr,
16                                     UNUSED void *_options)
17 {
18    b->cursor = nir_before_instr(instr);
19    auto ir = nir_instr_as_intrinsic(instr);
20 
21    nir_def *default_value = nir_imm_vec4(b, 0.0, 0.0, 0.0, 0.0);
22 
23    nir_def *result = NIR_LOWER_INSTR_PROGRESS_REPLACE;
24 
25    bool load_value = ir->intrinsic != nir_intrinsic_image_store;
26 
27    if (load_value)
28       default_value =
29          nir_imm_zero(b, ir->def.num_components, ir->def.bit_size);
30 
31    auto image_exists =
32       nir_ult_imm(b, ir->src[0].ssa, b->shader->info.num_images);
33 
34    nir_if *if_exists = nir_push_if(b, image_exists);
35 
36    nir_if *load_if = nullptr;
37 
38    if (ir->intrinsic != nir_intrinsic_image_size) {
39 
40       /*  Image exists start */
41       auto new_index =
42          nir_umin(b,
43                   ir->src[0].ssa,
44                   nir_imm_int(b, b->shader->info.num_images - 1));
45       nir_src_rewrite(&ir->src[0], new_index);
46 
47       enum glsl_sampler_dim dim = nir_intrinsic_image_dim(ir);
48 
49       unsigned num_components = 2;
50       switch (dim) {
51       case GLSL_SAMPLER_DIM_BUF:
52       case GLSL_SAMPLER_DIM_1D:
53          num_components = 1;
54          break;
55       case GLSL_SAMPLER_DIM_2D:
56       case GLSL_SAMPLER_DIM_MS:
57       case GLSL_SAMPLER_DIM_RECT:
58       case GLSL_SAMPLER_DIM_CUBE:
59          num_components = 2;
60          break;
61       case GLSL_SAMPLER_DIM_3D:
62          num_components = 3;
63          break;
64       default:
65          unreachable("Unexpected image size");
66       }
67 
68       if (num_components < 3 && nir_intrinsic_image_array(ir))
69          num_components++;
70 
71       auto img_size = nir_image_size(b,
72                                      num_components,
73                                      32,
74                                      ir->src[0].ssa,
75                                      nir_imm_int(b, 0),
76                                      dim,
77                                      nir_intrinsic_image_array(ir),
78                                      nir_intrinsic_format(ir),
79                                      nir_intrinsic_access(ir),
80                                      nir_intrinsic_range_base(ir));
81 
82       unsigned mask = (1 << num_components) - 1;
83       unsigned num_src1_comp = MIN2(ir->src[1].ssa->num_components, num_components);
84       unsigned src1_mask = (1 << num_src1_comp) - 1;
85 
86       auto in_range = nir_ult(b,
87                               nir_channels(b, ir->src[1].ssa, src1_mask),
88                               nir_channels(b, img_size, mask));
89 
90       switch (num_components) {
91       case 2:
92          in_range = nir_iand(b, nir_channel(b, in_range, 0), nir_channel(b, in_range, 1));
93          break;
94       case 3: {
95          auto tmp = nir_iand(b, nir_channel(b, in_range, 0), nir_channel(b, in_range, 1));
96          in_range = nir_iand(b, tmp, nir_channel(b, in_range, 2));
97          break;
98       }
99       }
100 
101       /*  Access is in range start */
102       load_if = nir_push_if(b, in_range);
103    }
104 
105    auto new_load = nir_instr_clone(b->shader, instr);
106    auto new_load_ir = nir_instr_as_intrinsic(new_load);
107 
108    nir_builder_instr_insert(b, new_load);
109 
110    if (load_value)
111       result = &new_load_ir->def;
112 
113    if (ir->intrinsic != nir_intrinsic_image_size) {
114       /*  Access is out of range start */
115       nir_if *load_else = nir_push_else(b, load_if);
116 
117       nir_pop_if(b, load_else);
118       /* End range check */
119 
120       if (load_value)
121          result = nir_if_phi(b, result, default_value);
122    }
123 
124    /* Start image doesn't exists */
125    nir_if *else_exists = nir_push_else(b, if_exists);
126 
127    /* Nothing to do, default is already set */
128    nir_pop_if(b, else_exists);
129 
130    if (load_value)
131       result = nir_if_phi(b, result, default_value);
132 
133    if (load_value)
134       b->cursor = nir_after_instr(result->parent_instr);
135    else
136       b->cursor = nir_after_cf_node(&else_exists->cf_node);
137 
138    return result;
139 }
140 
141 static bool
r600_legalize_image_load_store_filter(const nir_instr * instr,UNUSED const void * _options)142 r600_legalize_image_load_store_filter(const nir_instr *instr, UNUSED const void *_options)
143 {
144    if (instr->type != nir_instr_type_intrinsic)
145       return false;
146 
147    auto ir = nir_instr_as_intrinsic(instr);
148    switch (ir->intrinsic) {
149    case nir_intrinsic_image_store:
150    case nir_intrinsic_image_load:
151    case nir_intrinsic_image_atomic:
152    case nir_intrinsic_image_atomic_swap:
153    case nir_intrinsic_image_size:
154       return true;
155    default:
156       return false;
157    }
158 }
159 
160 /* This pass makes sure only existing images are accessd and
161  * the access is within range, if not zero is returned by all
162  * image ops that return a value.
163  */
164 bool
r600_legalize_image_load_store(nir_shader * shader)165 r600_legalize_image_load_store(nir_shader *shader)
166 {
167    bool progress = nir_shader_lower_instructions(shader,
168                                         r600_legalize_image_load_store_filter,
169                                         r600_legalize_image_load_store_impl,
170                                         nullptr);
171    return progress;
172 };
173