1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 Broadcom
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci/*
25bf215546Sopenharmony_ci * This lowering pass supports (as configured via nir_lower_tex_options)
26bf215546Sopenharmony_ci * various texture related conversions:
27bf215546Sopenharmony_ci *   + texture projector lowering: converts the coordinate division for
28bf215546Sopenharmony_ci *     texture projection to be done in ALU instructions instead of
29bf215546Sopenharmony_ci *     asking the texture operation to do so.
30bf215546Sopenharmony_ci *   + lowering RECT: converts the un-normalized RECT texture coordinates
31bf215546Sopenharmony_ci *     to normalized coordinates with txs plus ALU instructions
32bf215546Sopenharmony_ci *   + saturate s/t/r coords: to emulate certain texture clamp/wrap modes,
33bf215546Sopenharmony_ci *     inserts instructions to clamp specified coordinates to [0.0, 1.0].
34bf215546Sopenharmony_ci *     Note that this automatically triggers texture projector lowering if
35bf215546Sopenharmony_ci *     needed, since clamping must happen after projector lowering.
36bf215546Sopenharmony_ci *   + YUV-to-RGB conversion: to allow sampling YUV values as RGB values
37bf215546Sopenharmony_ci *     according to a specific YUV color space and range.
38bf215546Sopenharmony_ci */
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci#include "nir.h"
41bf215546Sopenharmony_ci#include "nir_builder.h"
42bf215546Sopenharmony_ci#include "nir_builtin_builder.h"
43bf215546Sopenharmony_ci#include "nir_format_convert.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_citypedef struct nir_const_value_3_4 {
46bf215546Sopenharmony_ci   nir_const_value v[3][4];
47bf215546Sopenharmony_ci} nir_const_value_3_4;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt601_limited_range_csc_coeffs = { {
50bf215546Sopenharmony_ci   { { .f32 = 1.16438356f }, { .f32 =  1.16438356f }, { .f32 = 1.16438356f } },
51bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.39176229f }, { .f32 = 2.01723214f } },
52bf215546Sopenharmony_ci   { { .f32 = 1.59602678f }, { .f32 = -0.81296764f }, { .f32 = 0.0f        } },
53bf215546Sopenharmony_ci} };
54bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt601_full_range_csc_coeffs = { {
55bf215546Sopenharmony_ci   { { .f32 = 1.0f        }, { .f32 =  1.0f        }, { .f32 = 1.0f        } },
56bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.34413629f }, { .f32 = 1.772f      } },
57bf215546Sopenharmony_ci   { { .f32 = 1.402f      }, { .f32 = -0.71413629f }, { .f32 = 0.0f        } },
58bf215546Sopenharmony_ci} };
59bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt709_limited_range_csc_coeffs = { {
60bf215546Sopenharmony_ci   { { .f32 = 1.16438356f }, { .f32 =  1.16438356f }, { .f32 = 1.16438356f } },
61bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.21324861f }, { .f32 = 2.11240179f } },
62bf215546Sopenharmony_ci   { { .f32 = 1.79274107f }, { .f32 = -0.53290933f }, { .f32 = 0.0f        } },
63bf215546Sopenharmony_ci} };
64bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt709_full_range_csc_coeffs = { {
65bf215546Sopenharmony_ci   { { .f32 = 1.0f        }, { .f32 =  1.0f        }, { .f32 = 1.0f        } },
66bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.18732427f }, { .f32 = 1.8556f     } },
67bf215546Sopenharmony_ci   { { .f32 = 1.5748f     }, { .f32 = -0.46812427f }, { .f32 = 0.0f        } },
68bf215546Sopenharmony_ci} };
69bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt2020_limited_range_csc_coeffs = { {
70bf215546Sopenharmony_ci   { { .f32 = 1.16438356f }, { .f32 =  1.16438356f }, { .f32 = 1.16438356f } },
71bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.18732610f }, { .f32 = 2.14177232f } },
72bf215546Sopenharmony_ci   { { .f32 = 1.67878795f }, { .f32 = -0.65046843f }, { .f32 = 0.0f        } },
73bf215546Sopenharmony_ci} };
74bf215546Sopenharmony_cistatic const nir_const_value_3_4 bt2020_full_range_csc_coeffs = { {
75bf215546Sopenharmony_ci   { { .f32 = 1.0f        }, { .f32 =  1.0f        }, { .f32 = 1.0f        } },
76bf215546Sopenharmony_ci   { { .f32 = 0.0f        }, { .f32 = -0.16455313f }, { .f32 = 1.88140000f } },
77bf215546Sopenharmony_ci   { { .f32 = 1.4747f     }, { .f32 = -0.57139187f }, { .f32 = 0.0f        } },
78bf215546Sopenharmony_ci} };
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_cistatic const float bt601_limited_range_csc_offsets[3] = {
81bf215546Sopenharmony_ci   -0.874202218f, 0.531667823f, -1.085630789f
82bf215546Sopenharmony_ci};
83bf215546Sopenharmony_cistatic const float bt601_full_range_csc_offsets[3] = {
84bf215546Sopenharmony_ci   -0.701000000f, 0.529136286f, -0.886000000f
85bf215546Sopenharmony_ci};
86bf215546Sopenharmony_cistatic const float bt709_limited_range_csc_offsets[3] = {
87bf215546Sopenharmony_ci   -0.972945075f, 0.301482665f, -1.133402218f
88bf215546Sopenharmony_ci};
89bf215546Sopenharmony_cistatic const float bt709_full_range_csc_offsets[3] = {
90bf215546Sopenharmony_ci   -0.787400000f, 0.327724273f, -0.927800000f
91bf215546Sopenharmony_ci};
92bf215546Sopenharmony_cistatic const float bt2020_limited_range_csc_offsets[3] = {
93bf215546Sopenharmony_ci   -0.915745075f, 0.347480639f, -1.148145075f
94bf215546Sopenharmony_ci};
95bf215546Sopenharmony_cistatic const float bt2020_full_range_csc_offsets[3] = {
96bf215546Sopenharmony_ci   -0.737350000f, 0.367972500f, -0.940700000f
97bf215546Sopenharmony_ci};
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistatic bool
100bf215546Sopenharmony_ciproject_src(nir_builder *b, nir_tex_instr *tex)
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   /* Find the projector in the srcs list, if present. */
103bf215546Sopenharmony_ci   int proj_index = nir_tex_instr_src_index(tex, nir_tex_src_projector);
104bf215546Sopenharmony_ci   if (proj_index < 0)
105bf215546Sopenharmony_ci      return false;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci   nir_ssa_def *inv_proj =
110bf215546Sopenharmony_ci      nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1));
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   /* Walk through the sources projecting the arguments. */
113bf215546Sopenharmony_ci   for (unsigned i = 0; i < tex->num_srcs; i++) {
114bf215546Sopenharmony_ci      switch (tex->src[i].src_type) {
115bf215546Sopenharmony_ci      case nir_tex_src_coord:
116bf215546Sopenharmony_ci      case nir_tex_src_comparator:
117bf215546Sopenharmony_ci         break;
118bf215546Sopenharmony_ci      default:
119bf215546Sopenharmony_ci         continue;
120bf215546Sopenharmony_ci      }
121bf215546Sopenharmony_ci      nir_ssa_def *unprojected =
122bf215546Sopenharmony_ci         nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
123bf215546Sopenharmony_ci      nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj);
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci      /* Array indices don't get projected, so make an new vector with the
126bf215546Sopenharmony_ci       * coordinate's array index untouched.
127bf215546Sopenharmony_ci       */
128bf215546Sopenharmony_ci      if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) {
129bf215546Sopenharmony_ci         switch (tex->coord_components) {
130bf215546Sopenharmony_ci         case 4:
131bf215546Sopenharmony_ci            projected = nir_vec4(b,
132bf215546Sopenharmony_ci                                 nir_channel(b, projected, 0),
133bf215546Sopenharmony_ci                                 nir_channel(b, projected, 1),
134bf215546Sopenharmony_ci                                 nir_channel(b, projected, 2),
135bf215546Sopenharmony_ci                                 nir_channel(b, unprojected, 3));
136bf215546Sopenharmony_ci            break;
137bf215546Sopenharmony_ci         case 3:
138bf215546Sopenharmony_ci            projected = nir_vec3(b,
139bf215546Sopenharmony_ci                                 nir_channel(b, projected, 0),
140bf215546Sopenharmony_ci                                 nir_channel(b, projected, 1),
141bf215546Sopenharmony_ci                                 nir_channel(b, unprojected, 2));
142bf215546Sopenharmony_ci            break;
143bf215546Sopenharmony_ci         case 2:
144bf215546Sopenharmony_ci            projected = nir_vec2(b,
145bf215546Sopenharmony_ci                                 nir_channel(b, projected, 0),
146bf215546Sopenharmony_ci                                 nir_channel(b, unprojected, 1));
147bf215546Sopenharmony_ci            break;
148bf215546Sopenharmony_ci         default:
149bf215546Sopenharmony_ci            unreachable("bad texture coord count for array");
150bf215546Sopenharmony_ci            break;
151bf215546Sopenharmony_ci         }
152bf215546Sopenharmony_ci      }
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci      nir_instr_rewrite_src(&tex->instr,
155bf215546Sopenharmony_ci                            &tex->src[i].src,
156bf215546Sopenharmony_ci                            nir_src_for_ssa(projected));
157bf215546Sopenharmony_ci   }
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   nir_tex_instr_remove_src(tex, proj_index);
160bf215546Sopenharmony_ci   return true;
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_cistatic bool
164bf215546Sopenharmony_cilower_offset(nir_builder *b, nir_tex_instr *tex)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   int offset_index = nir_tex_instr_src_index(tex, nir_tex_src_offset);
167bf215546Sopenharmony_ci   if (offset_index < 0)
168bf215546Sopenharmony_ci      return false;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
171bf215546Sopenharmony_ci   assert(coord_index >= 0);
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   assert(tex->src[offset_index].src.is_ssa);
174bf215546Sopenharmony_ci   assert(tex->src[coord_index].src.is_ssa);
175bf215546Sopenharmony_ci   nir_ssa_def *offset = tex->src[offset_index].src.ssa;
176bf215546Sopenharmony_ci   nir_ssa_def *coord = tex->src[coord_index].src.ssa;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci   nir_ssa_def *offset_coord;
181bf215546Sopenharmony_ci   if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) {
182bf215546Sopenharmony_ci      if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
183bf215546Sopenharmony_ci         offset_coord = nir_fadd(b, coord, nir_i2f32(b, offset));
184bf215546Sopenharmony_ci      } else {
185bf215546Sopenharmony_ci         nir_ssa_def *txs = nir_i2f32(b, nir_get_texture_size(b, tex));
186bf215546Sopenharmony_ci         nir_ssa_def *scale = nir_frcp(b, txs);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci         offset_coord = nir_fadd(b, coord,
189bf215546Sopenharmony_ci                                 nir_fmul(b,
190bf215546Sopenharmony_ci                                          nir_i2f32(b, offset),
191bf215546Sopenharmony_ci                                          scale));
192bf215546Sopenharmony_ci      }
193bf215546Sopenharmony_ci   } else {
194bf215546Sopenharmony_ci      offset_coord = nir_iadd(b, coord, offset);
195bf215546Sopenharmony_ci   }
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci   if (tex->is_array) {
198bf215546Sopenharmony_ci      /* The offset is not applied to the array index */
199bf215546Sopenharmony_ci      if (tex->coord_components == 2) {
200bf215546Sopenharmony_ci         offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0),
201bf215546Sopenharmony_ci                                    nir_channel(b, coord, 1));
202bf215546Sopenharmony_ci      } else if (tex->coord_components == 3) {
203bf215546Sopenharmony_ci         offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0),
204bf215546Sopenharmony_ci                                    nir_channel(b, offset_coord, 1),
205bf215546Sopenharmony_ci                                    nir_channel(b, coord, 2));
206bf215546Sopenharmony_ci      } else {
207bf215546Sopenharmony_ci         unreachable("Invalid number of components");
208bf215546Sopenharmony_ci      }
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src,
212bf215546Sopenharmony_ci                         nir_src_for_ssa(offset_coord));
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci   nir_tex_instr_remove_src(tex, offset_index);
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   return true;
217bf215546Sopenharmony_ci}
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_cistatic void
220bf215546Sopenharmony_cilower_rect(nir_builder *b, nir_tex_instr *tex)
221bf215546Sopenharmony_ci{
222bf215546Sopenharmony_ci   /* Set the sampler_dim to 2D here so that get_texture_size picks up the
223bf215546Sopenharmony_ci    * right dimensionality.
224bf215546Sopenharmony_ci    */
225bf215546Sopenharmony_ci   tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   nir_ssa_def *txs = nir_i2f32(b, nir_get_texture_size(b, tex));
228bf215546Sopenharmony_ci   nir_ssa_def *scale = nir_frcp(b, txs);
229bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci   if (coord_index != -1) {
232bf215546Sopenharmony_ci      nir_ssa_def *coords =
233bf215546Sopenharmony_ci         nir_ssa_for_src(b, tex->src[coord_index].src, tex->coord_components);
234bf215546Sopenharmony_ci      nir_instr_rewrite_src(&tex->instr,
235bf215546Sopenharmony_ci                            &tex->src[coord_index].src,
236bf215546Sopenharmony_ci                            nir_src_for_ssa(nir_fmul(b, coords, scale)));
237bf215546Sopenharmony_ci   }
238bf215546Sopenharmony_ci}
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_cistatic void
241bf215546Sopenharmony_cilower_rect_tex_scale(nir_builder *b, nir_tex_instr *tex)
242bf215546Sopenharmony_ci{
243bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci   nir_ssa_def *idx = nir_imm_int(b, tex->texture_index);
246bf215546Sopenharmony_ci   nir_ssa_def *scale = nir_build_load_texture_rect_scaling(b, 32, idx);
247bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci   if (coord_index != -1) {
250bf215546Sopenharmony_ci      nir_ssa_def *coords =
251bf215546Sopenharmony_ci         nir_ssa_for_src(b, tex->src[coord_index].src, tex->coord_components);
252bf215546Sopenharmony_ci      nir_instr_rewrite_src(&tex->instr,
253bf215546Sopenharmony_ci                            &tex->src[coord_index].src,
254bf215546Sopenharmony_ci                            nir_src_for_ssa(nir_fmul(b, coords, scale)));
255bf215546Sopenharmony_ci   }
256bf215546Sopenharmony_ci}
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_cistatic void
259bf215546Sopenharmony_cilower_lod(nir_builder *b, nir_tex_instr *tex, nir_ssa_def *lod)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   assert(tex->op == nir_texop_tex || tex->op == nir_texop_txb);
262bf215546Sopenharmony_ci   assert(nir_tex_instr_src_index(tex, nir_tex_src_lod) < 0);
263bf215546Sopenharmony_ci   assert(nir_tex_instr_src_index(tex, nir_tex_src_ddx) < 0);
264bf215546Sopenharmony_ci   assert(nir_tex_instr_src_index(tex, nir_tex_src_ddy) < 0);
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   int bias_idx = nir_tex_instr_src_index(tex, nir_tex_src_bias);
267bf215546Sopenharmony_ci   if (bias_idx >= 0) {
268bf215546Sopenharmony_ci      /* If we have a bias, add it in */
269bf215546Sopenharmony_ci      lod = nir_fadd(b, lod, nir_ssa_for_src(b, tex->src[bias_idx].src, 1));
270bf215546Sopenharmony_ci      nir_tex_instr_remove_src(tex, bias_idx);
271bf215546Sopenharmony_ci   }
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_ci   int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
274bf215546Sopenharmony_ci   if (min_lod_idx >= 0) {
275bf215546Sopenharmony_ci      /* If we have a minimum LOD, clamp LOD accordingly */
276bf215546Sopenharmony_ci      lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
277bf215546Sopenharmony_ci      nir_tex_instr_remove_src(tex, min_lod_idx);
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
281bf215546Sopenharmony_ci   tex->op = nir_texop_txl;
282bf215546Sopenharmony_ci}
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_cistatic void
285bf215546Sopenharmony_cilower_implicit_lod(nir_builder *b, nir_tex_instr *tex)
286bf215546Sopenharmony_ci{
287bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
288bf215546Sopenharmony_ci   lower_lod(b, tex, nir_get_texture_lod(b, tex));
289bf215546Sopenharmony_ci}
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_cistatic void
292bf215546Sopenharmony_cilower_zero_lod(nir_builder *b, nir_tex_instr *tex)
293bf215546Sopenharmony_ci{
294bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   if (tex->op == nir_texop_lod) {
297bf215546Sopenharmony_ci      nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_imm_int(b, 0));
298bf215546Sopenharmony_ci      nir_instr_remove(&tex->instr);
299bf215546Sopenharmony_ci      return;
300bf215546Sopenharmony_ci   }
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci   lower_lod(b, tex, nir_imm_int(b, 0));
303bf215546Sopenharmony_ci}
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_cistatic nir_ssa_def *
306bf215546Sopenharmony_cisample_plane(nir_builder *b, nir_tex_instr *tex, int plane,
307bf215546Sopenharmony_ci             const nir_lower_tex_options *options)
308bf215546Sopenharmony_ci{
309bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
310bf215546Sopenharmony_ci   assert(nir_tex_instr_dest_size(tex) == 4);
311bf215546Sopenharmony_ci   assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
312bf215546Sopenharmony_ci   assert(tex->op == nir_texop_tex);
313bf215546Sopenharmony_ci   assert(tex->coord_components == 2);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   nir_tex_instr *plane_tex =
316bf215546Sopenharmony_ci      nir_tex_instr_create(b->shader, tex->num_srcs + 1);
317bf215546Sopenharmony_ci   for (unsigned i = 0; i < tex->num_srcs; i++) {
318bf215546Sopenharmony_ci      nir_src_copy(&plane_tex->src[i].src, &tex->src[i].src);
319bf215546Sopenharmony_ci      plane_tex->src[i].src_type = tex->src[i].src_type;
320bf215546Sopenharmony_ci   }
321bf215546Sopenharmony_ci   plane_tex->src[tex->num_srcs].src = nir_src_for_ssa(nir_imm_int(b, plane));
322bf215546Sopenharmony_ci   plane_tex->src[tex->num_srcs].src_type = nir_tex_src_plane;
323bf215546Sopenharmony_ci   plane_tex->op = nir_texop_tex;
324bf215546Sopenharmony_ci   plane_tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
325bf215546Sopenharmony_ci   plane_tex->dest_type = nir_type_float | nir_dest_bit_size(tex->dest);
326bf215546Sopenharmony_ci   plane_tex->coord_components = 2;
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci   plane_tex->texture_index = tex->texture_index;
329bf215546Sopenharmony_ci   plane_tex->sampler_index = tex->sampler_index;
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   nir_ssa_dest_init(&plane_tex->instr, &plane_tex->dest, 4,
332bf215546Sopenharmony_ci         nir_dest_bit_size(tex->dest), NULL);
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &plane_tex->instr);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   /* If scaling_factor is set, return a scaled value. */
337bf215546Sopenharmony_ci   if (options->scale_factors[tex->texture_index])
338bf215546Sopenharmony_ci      return nir_fmul_imm(b, &plane_tex->dest.ssa,
339bf215546Sopenharmony_ci                          options->scale_factors[tex->texture_index]);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   return &plane_tex->dest.ssa;
342bf215546Sopenharmony_ci}
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_cistatic void
345bf215546Sopenharmony_ciconvert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex,
346bf215546Sopenharmony_ci                   nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v,
347bf215546Sopenharmony_ci                   nir_ssa_def *a,
348bf215546Sopenharmony_ci                   const nir_lower_tex_options *options,
349bf215546Sopenharmony_ci                   unsigned texture_index)
350bf215546Sopenharmony_ci{
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci   const float *offset_vals;
353bf215546Sopenharmony_ci   const nir_const_value_3_4 *m;
354bf215546Sopenharmony_ci   assert((options->bt709_external & options->bt2020_external) == 0);
355bf215546Sopenharmony_ci   if (options->yuv_full_range_external & (1u << texture_index)) {
356bf215546Sopenharmony_ci      if (options->bt709_external & (1u << texture_index)) {
357bf215546Sopenharmony_ci         m = &bt709_full_range_csc_coeffs;
358bf215546Sopenharmony_ci         offset_vals = bt709_full_range_csc_offsets;
359bf215546Sopenharmony_ci      } else if (options->bt2020_external & (1u << texture_index)) {
360bf215546Sopenharmony_ci         m = &bt2020_full_range_csc_coeffs;
361bf215546Sopenharmony_ci         offset_vals = bt2020_full_range_csc_offsets;
362bf215546Sopenharmony_ci      } else {
363bf215546Sopenharmony_ci         m = &bt601_full_range_csc_coeffs;
364bf215546Sopenharmony_ci         offset_vals = bt601_full_range_csc_offsets;
365bf215546Sopenharmony_ci      }
366bf215546Sopenharmony_ci   } else {
367bf215546Sopenharmony_ci      if (options->bt709_external & (1u << texture_index)) {
368bf215546Sopenharmony_ci         m = &bt709_limited_range_csc_coeffs;
369bf215546Sopenharmony_ci         offset_vals = bt709_limited_range_csc_offsets;
370bf215546Sopenharmony_ci      } else if (options->bt2020_external & (1u << texture_index)) {
371bf215546Sopenharmony_ci         m = &bt2020_limited_range_csc_coeffs;
372bf215546Sopenharmony_ci         offset_vals = bt2020_limited_range_csc_offsets;
373bf215546Sopenharmony_ci      } else {
374bf215546Sopenharmony_ci         m = &bt601_limited_range_csc_coeffs;
375bf215546Sopenharmony_ci         offset_vals = bt601_limited_range_csc_offsets;
376bf215546Sopenharmony_ci      }
377bf215546Sopenharmony_ci   }
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci   unsigned bit_size = nir_dest_bit_size(tex->dest);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   nir_ssa_def *offset =
382bf215546Sopenharmony_ci      nir_vec4(b,
383bf215546Sopenharmony_ci               nir_imm_floatN_t(b, offset_vals[0], a->bit_size),
384bf215546Sopenharmony_ci               nir_imm_floatN_t(b, offset_vals[1], a->bit_size),
385bf215546Sopenharmony_ci               nir_imm_floatN_t(b, offset_vals[2], a->bit_size),
386bf215546Sopenharmony_ci               a);
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci   offset = nir_f2fN(b, offset, bit_size);
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci   nir_ssa_def *m0 = nir_f2fN(b, nir_build_imm(b, 4, 32, m->v[0]), bit_size);
391bf215546Sopenharmony_ci   nir_ssa_def *m1 = nir_f2fN(b, nir_build_imm(b, 4, 32, m->v[1]), bit_size);
392bf215546Sopenharmony_ci   nir_ssa_def *m2 = nir_f2fN(b, nir_build_imm(b, 4, 32, m->v[2]), bit_size);
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci   nir_ssa_def *result =
395bf215546Sopenharmony_ci      nir_ffma(b, y, m0, nir_ffma(b, u, m1, nir_ffma(b, v, m2, offset)));
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses(&tex->dest.ssa, result);
398bf215546Sopenharmony_ci}
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_cistatic void
401bf215546Sopenharmony_cilower_y_uv_external(nir_builder *b, nir_tex_instr *tex,
402bf215546Sopenharmony_ci                    const nir_lower_tex_options *options,
403bf215546Sopenharmony_ci                    unsigned texture_index)
404bf215546Sopenharmony_ci{
405bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   nir_ssa_def *y = sample_plane(b, tex, 0, options);
408bf215546Sopenharmony_ci   nir_ssa_def *uv = sample_plane(b, tex, 1, options);
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   convert_yuv_to_rgb(b, tex,
411bf215546Sopenharmony_ci                      nir_channel(b, y, 0),
412bf215546Sopenharmony_ci                      nir_channel(b, uv, 0),
413bf215546Sopenharmony_ci                      nir_channel(b, uv, 1),
414bf215546Sopenharmony_ci                      nir_imm_float(b, 1.0f),
415bf215546Sopenharmony_ci                      options,
416bf215546Sopenharmony_ci                      texture_index);
417bf215546Sopenharmony_ci}
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_cistatic void
420bf215546Sopenharmony_cilower_y_u_v_external(nir_builder *b, nir_tex_instr *tex,
421bf215546Sopenharmony_ci                     const nir_lower_tex_options *options,
422bf215546Sopenharmony_ci                     unsigned texture_index)
423bf215546Sopenharmony_ci{
424bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci   nir_ssa_def *y = sample_plane(b, tex, 0, options);
427bf215546Sopenharmony_ci   nir_ssa_def *u = sample_plane(b, tex, 1, options);
428bf215546Sopenharmony_ci   nir_ssa_def *v = sample_plane(b, tex, 2, options);
429bf215546Sopenharmony_ci
430bf215546Sopenharmony_ci   convert_yuv_to_rgb(b, tex,
431bf215546Sopenharmony_ci                      nir_channel(b, y, 0),
432bf215546Sopenharmony_ci                      nir_channel(b, u, 0),
433bf215546Sopenharmony_ci                      nir_channel(b, v, 0),
434bf215546Sopenharmony_ci                      nir_imm_float(b, 1.0f),
435bf215546Sopenharmony_ci                      options,
436bf215546Sopenharmony_ci                      texture_index);
437bf215546Sopenharmony_ci}
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_cistatic void
440bf215546Sopenharmony_cilower_yx_xuxv_external(nir_builder *b, nir_tex_instr *tex,
441bf215546Sopenharmony_ci                       const nir_lower_tex_options *options,
442bf215546Sopenharmony_ci                       unsigned texture_index)
443bf215546Sopenharmony_ci{
444bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci   nir_ssa_def *y = sample_plane(b, tex, 0, options);
447bf215546Sopenharmony_ci   nir_ssa_def *xuxv = sample_plane(b, tex, 1, options);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   convert_yuv_to_rgb(b, tex,
450bf215546Sopenharmony_ci                      nir_channel(b, y, 0),
451bf215546Sopenharmony_ci                      nir_channel(b, xuxv, 1),
452bf215546Sopenharmony_ci                      nir_channel(b, xuxv, 3),
453bf215546Sopenharmony_ci                      nir_imm_float(b, 1.0f),
454bf215546Sopenharmony_ci                      options,
455bf215546Sopenharmony_ci                      texture_index);
456bf215546Sopenharmony_ci}
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_cistatic void
459bf215546Sopenharmony_cilower_xy_uxvx_external(nir_builder *b, nir_tex_instr *tex,
460bf215546Sopenharmony_ci                       const nir_lower_tex_options *options,
461bf215546Sopenharmony_ci                       unsigned texture_index)
462bf215546Sopenharmony_ci{
463bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci  nir_ssa_def *y = sample_plane(b, tex, 0, options);
466bf215546Sopenharmony_ci  nir_ssa_def *uxvx = sample_plane(b, tex, 1, options);
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
469bf215546Sopenharmony_ci                     nir_channel(b, y, 1),
470bf215546Sopenharmony_ci                     nir_channel(b, uxvx, 0),
471bf215546Sopenharmony_ci                     nir_channel(b, uxvx, 2),
472bf215546Sopenharmony_ci                     nir_imm_float(b, 1.0f),
473bf215546Sopenharmony_ci                     options,
474bf215546Sopenharmony_ci                     texture_index);
475bf215546Sopenharmony_ci}
476bf215546Sopenharmony_ci
477bf215546Sopenharmony_cistatic void
478bf215546Sopenharmony_cilower_ayuv_external(nir_builder *b, nir_tex_instr *tex,
479bf215546Sopenharmony_ci                    const nir_lower_tex_options *options,
480bf215546Sopenharmony_ci                    unsigned texture_index)
481bf215546Sopenharmony_ci{
482bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci  nir_ssa_def *ayuv = sample_plane(b, tex, 0, options);
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
487bf215546Sopenharmony_ci                     nir_channel(b, ayuv, 2),
488bf215546Sopenharmony_ci                     nir_channel(b, ayuv, 1),
489bf215546Sopenharmony_ci                     nir_channel(b, ayuv, 0),
490bf215546Sopenharmony_ci                     nir_channel(b, ayuv, 3),
491bf215546Sopenharmony_ci                     options,
492bf215546Sopenharmony_ci                     texture_index);
493bf215546Sopenharmony_ci}
494bf215546Sopenharmony_ci
495bf215546Sopenharmony_cistatic void
496bf215546Sopenharmony_cilower_y41x_external(nir_builder *b, nir_tex_instr *tex,
497bf215546Sopenharmony_ci                    const nir_lower_tex_options *options,
498bf215546Sopenharmony_ci                    unsigned texture_index)
499bf215546Sopenharmony_ci{
500bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_ci  nir_ssa_def *y41x = sample_plane(b, tex, 0, options);
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
505bf215546Sopenharmony_ci                     nir_channel(b, y41x, 1),
506bf215546Sopenharmony_ci                     nir_channel(b, y41x, 0),
507bf215546Sopenharmony_ci                     nir_channel(b, y41x, 2),
508bf215546Sopenharmony_ci                     nir_channel(b, y41x, 3),
509bf215546Sopenharmony_ci                     options,
510bf215546Sopenharmony_ci                     texture_index);
511bf215546Sopenharmony_ci}
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_cistatic void
514bf215546Sopenharmony_cilower_xyuv_external(nir_builder *b, nir_tex_instr *tex,
515bf215546Sopenharmony_ci                    const nir_lower_tex_options *options,
516bf215546Sopenharmony_ci                    unsigned texture_index)
517bf215546Sopenharmony_ci{
518bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
519bf215546Sopenharmony_ci
520bf215546Sopenharmony_ci  nir_ssa_def *xyuv = sample_plane(b, tex, 0, options);
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
523bf215546Sopenharmony_ci                     nir_channel(b, xyuv, 2),
524bf215546Sopenharmony_ci                     nir_channel(b, xyuv, 1),
525bf215546Sopenharmony_ci                     nir_channel(b, xyuv, 0),
526bf215546Sopenharmony_ci                     nir_imm_float(b, 1.0f),
527bf215546Sopenharmony_ci                     options,
528bf215546Sopenharmony_ci                     texture_index);
529bf215546Sopenharmony_ci}
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_cistatic void
532bf215546Sopenharmony_cilower_yuv_external(nir_builder *b, nir_tex_instr *tex,
533bf215546Sopenharmony_ci                   const nir_lower_tex_options *options,
534bf215546Sopenharmony_ci                   unsigned texture_index)
535bf215546Sopenharmony_ci{
536bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci  nir_ssa_def *yuv = sample_plane(b, tex, 0, options);
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
541bf215546Sopenharmony_ci                     nir_channel(b, yuv, 0),
542bf215546Sopenharmony_ci                     nir_channel(b, yuv, 1),
543bf215546Sopenharmony_ci                     nir_channel(b, yuv, 2),
544bf215546Sopenharmony_ci                     nir_imm_float(b, 1.0f),
545bf215546Sopenharmony_ci                     options,
546bf215546Sopenharmony_ci                     texture_index);
547bf215546Sopenharmony_ci}
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_cistatic void
550bf215546Sopenharmony_cilower_yu_yv_external(nir_builder *b, nir_tex_instr *tex,
551bf215546Sopenharmony_ci                     const nir_lower_tex_options *options,
552bf215546Sopenharmony_ci                     unsigned texture_index)
553bf215546Sopenharmony_ci{
554bf215546Sopenharmony_ci  b->cursor = nir_after_instr(&tex->instr);
555bf215546Sopenharmony_ci
556bf215546Sopenharmony_ci  nir_ssa_def *yuv = sample_plane(b, tex, 0, options);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci  convert_yuv_to_rgb(b, tex,
559bf215546Sopenharmony_ci                     nir_channel(b, yuv, 1),
560bf215546Sopenharmony_ci                     nir_channel(b, yuv, 2),
561bf215546Sopenharmony_ci                     nir_channel(b, yuv, 0),
562bf215546Sopenharmony_ci                     nir_imm_float(b, 1.0f),
563bf215546Sopenharmony_ci                     options,
564bf215546Sopenharmony_ci                     texture_index);
565bf215546Sopenharmony_ci}
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci/*
568bf215546Sopenharmony_ci * Converts a nir_texop_txd instruction to nir_texop_txl with the given lod
569bf215546Sopenharmony_ci * computed from the gradients.
570bf215546Sopenharmony_ci */
571bf215546Sopenharmony_cistatic void
572bf215546Sopenharmony_cireplace_gradient_with_lod(nir_builder *b, nir_ssa_def *lod, nir_tex_instr *tex)
573bf215546Sopenharmony_ci{
574bf215546Sopenharmony_ci   assert(tex->op == nir_texop_txd);
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddx));
577bf215546Sopenharmony_ci   nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddy));
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci   int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
580bf215546Sopenharmony_ci   if (min_lod_idx >= 0) {
581bf215546Sopenharmony_ci      /* If we have a minimum LOD, clamp LOD accordingly */
582bf215546Sopenharmony_ci      lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
583bf215546Sopenharmony_ci      nir_tex_instr_remove_src(tex, min_lod_idx);
584bf215546Sopenharmony_ci   }
585bf215546Sopenharmony_ci
586bf215546Sopenharmony_ci   nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
587bf215546Sopenharmony_ci   tex->op = nir_texop_txl;
588bf215546Sopenharmony_ci}
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_cistatic void
591bf215546Sopenharmony_cilower_gradient_cube_map(nir_builder *b, nir_tex_instr *tex)
592bf215546Sopenharmony_ci{
593bf215546Sopenharmony_ci   assert(tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE);
594bf215546Sopenharmony_ci   assert(tex->op == nir_texop_txd);
595bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci   /* Use textureSize() to get the width and height of LOD 0 */
598bf215546Sopenharmony_ci   nir_ssa_def *size = nir_i2f32(b, nir_get_texture_size(b, tex));
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   /* Cubemap texture lookups first generate a texture coordinate normalized
601bf215546Sopenharmony_ci    * to [-1, 1] on the appropiate face. The appropiate face is determined
602bf215546Sopenharmony_ci    * by which component has largest magnitude and its sign. The texture
603bf215546Sopenharmony_ci    * coordinate is the quotient of the remaining texture coordinates against
604bf215546Sopenharmony_ci    * that absolute value of the component of largest magnitude. This
605bf215546Sopenharmony_ci    * division requires that the computing of the derivative of the texel
606bf215546Sopenharmony_ci    * coordinate must use the quotient rule. The high level GLSL code is as
607bf215546Sopenharmony_ci    * follows:
608bf215546Sopenharmony_ci    *
609bf215546Sopenharmony_ci    * Step 1: selection
610bf215546Sopenharmony_ci    *
611bf215546Sopenharmony_ci    * vec3 abs_p, Q, dQdx, dQdy;
612bf215546Sopenharmony_ci    * abs_p = abs(ir->coordinate);
613bf215546Sopenharmony_ci    * if (abs_p.x >= max(abs_p.y, abs_p.z)) {
614bf215546Sopenharmony_ci    *    Q = ir->coordinate.yzx;
615bf215546Sopenharmony_ci    *    dQdx = ir->lod_info.grad.dPdx.yzx;
616bf215546Sopenharmony_ci    *    dQdy = ir->lod_info.grad.dPdy.yzx;
617bf215546Sopenharmony_ci    * }
618bf215546Sopenharmony_ci    * if (abs_p.y >= max(abs_p.x, abs_p.z)) {
619bf215546Sopenharmony_ci    *    Q = ir->coordinate.xzy;
620bf215546Sopenharmony_ci    *    dQdx = ir->lod_info.grad.dPdx.xzy;
621bf215546Sopenharmony_ci    *    dQdy = ir->lod_info.grad.dPdy.xzy;
622bf215546Sopenharmony_ci    * }
623bf215546Sopenharmony_ci    * if (abs_p.z >= max(abs_p.x, abs_p.y)) {
624bf215546Sopenharmony_ci    *    Q = ir->coordinate;
625bf215546Sopenharmony_ci    *    dQdx = ir->lod_info.grad.dPdx;
626bf215546Sopenharmony_ci    *    dQdy = ir->lod_info.grad.dPdy;
627bf215546Sopenharmony_ci    * }
628bf215546Sopenharmony_ci    *
629bf215546Sopenharmony_ci    * Step 2: use quotient rule to compute derivative. The normalized to
630bf215546Sopenharmony_ci    * [-1, 1] texel coordinate is given by Q.xy / (sign(Q.z) * Q.z). We are
631bf215546Sopenharmony_ci    * only concerned with the magnitudes of the derivatives whose values are
632bf215546Sopenharmony_ci    * not affected by the sign. We drop the sign from the computation.
633bf215546Sopenharmony_ci    *
634bf215546Sopenharmony_ci    * vec2 dx, dy;
635bf215546Sopenharmony_ci    * float recip;
636bf215546Sopenharmony_ci    *
637bf215546Sopenharmony_ci    * recip = 1.0 / Q.z;
638bf215546Sopenharmony_ci    * dx = recip * ( dQdx.xy - Q.xy * (dQdx.z * recip) );
639bf215546Sopenharmony_ci    * dy = recip * ( dQdy.xy - Q.xy * (dQdy.z * recip) );
640bf215546Sopenharmony_ci    *
641bf215546Sopenharmony_ci    * Step 3: compute LOD. At this point we have the derivatives of the
642bf215546Sopenharmony_ci    * texture coordinates normalized to [-1,1]. We take the LOD to be
643bf215546Sopenharmony_ci    *  result = log2(max(sqrt(dot(dx, dx)), sqrt(dy, dy)) * 0.5 * L)
644bf215546Sopenharmony_ci    *         = -1.0 + log2(max(sqrt(dot(dx, dx)), sqrt(dy, dy)) * L)
645bf215546Sopenharmony_ci    *         = -1.0 + log2(sqrt(max(dot(dx, dx), dot(dy,dy))) * L)
646bf215546Sopenharmony_ci    *         = -1.0 + log2(sqrt(L * L * max(dot(dx, dx), dot(dy,dy))))
647bf215546Sopenharmony_ci    *         = -1.0 + 0.5 * log2(L * L * max(dot(dx, dx), dot(dy,dy)))
648bf215546Sopenharmony_ci    * where L is the dimension of the cubemap. The code is:
649bf215546Sopenharmony_ci    *
650bf215546Sopenharmony_ci    * float M, result;
651bf215546Sopenharmony_ci    * M = max(dot(dx, dx), dot(dy, dy));
652bf215546Sopenharmony_ci    * L = textureSize(sampler, 0).x;
653bf215546Sopenharmony_ci    * result = -1.0 + 0.5 * log2(L * L * M);
654bf215546Sopenharmony_ci    */
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   /* coordinate */
657bf215546Sopenharmony_ci   nir_ssa_def *p =
658bf215546Sopenharmony_ci      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_coord)].src.ssa;
659bf215546Sopenharmony_ci
660bf215546Sopenharmony_ci   /* unmodified dPdx, dPdy values */
661bf215546Sopenharmony_ci   nir_ssa_def *dPdx =
662bf215546Sopenharmony_ci      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddx)].src.ssa;
663bf215546Sopenharmony_ci   nir_ssa_def *dPdy =
664bf215546Sopenharmony_ci      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddy)].src.ssa;
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci   nir_ssa_def *abs_p = nir_fabs(b, p);
667bf215546Sopenharmony_ci   nir_ssa_def *abs_p_x = nir_channel(b, abs_p, 0);
668bf215546Sopenharmony_ci   nir_ssa_def *abs_p_y = nir_channel(b, abs_p, 1);
669bf215546Sopenharmony_ci   nir_ssa_def *abs_p_z = nir_channel(b, abs_p, 2);
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   /* 1. compute selector */
672bf215546Sopenharmony_ci   nir_ssa_def *Q, *dQdx, *dQdy;
673bf215546Sopenharmony_ci
674bf215546Sopenharmony_ci   nir_ssa_def *cond_z = nir_fge(b, abs_p_z, nir_fmax(b, abs_p_x, abs_p_y));
675bf215546Sopenharmony_ci   nir_ssa_def *cond_y = nir_fge(b, abs_p_y, nir_fmax(b, abs_p_x, abs_p_z));
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   unsigned yzx[3] = { 1, 2, 0 };
678bf215546Sopenharmony_ci   unsigned xzy[3] = { 0, 2, 1 };
679bf215546Sopenharmony_ci
680bf215546Sopenharmony_ci   Q = nir_bcsel(b, cond_z,
681bf215546Sopenharmony_ci                 p,
682bf215546Sopenharmony_ci                 nir_bcsel(b, cond_y,
683bf215546Sopenharmony_ci                           nir_swizzle(b, p, xzy, 3),
684bf215546Sopenharmony_ci                           nir_swizzle(b, p, yzx, 3)));
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci   dQdx = nir_bcsel(b, cond_z,
687bf215546Sopenharmony_ci                    dPdx,
688bf215546Sopenharmony_ci                    nir_bcsel(b, cond_y,
689bf215546Sopenharmony_ci                              nir_swizzle(b, dPdx, xzy, 3),
690bf215546Sopenharmony_ci                              nir_swizzle(b, dPdx, yzx, 3)));
691bf215546Sopenharmony_ci
692bf215546Sopenharmony_ci   dQdy = nir_bcsel(b, cond_z,
693bf215546Sopenharmony_ci                    dPdy,
694bf215546Sopenharmony_ci                    nir_bcsel(b, cond_y,
695bf215546Sopenharmony_ci                              nir_swizzle(b, dPdy, xzy, 3),
696bf215546Sopenharmony_ci                              nir_swizzle(b, dPdy, yzx, 3)));
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci   /* 2. quotient rule */
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci   /* tmp = Q.xy * recip;
701bf215546Sopenharmony_ci    * dx = recip * ( dQdx.xy - (tmp * dQdx.z) );
702bf215546Sopenharmony_ci    * dy = recip * ( dQdy.xy - (tmp * dQdy.z) );
703bf215546Sopenharmony_ci    */
704bf215546Sopenharmony_ci   nir_ssa_def *rcp_Q_z = nir_frcp(b, nir_channel(b, Q, 2));
705bf215546Sopenharmony_ci
706bf215546Sopenharmony_ci   nir_ssa_def *Q_xy = nir_channels(b, Q, 0x3);
707bf215546Sopenharmony_ci   nir_ssa_def *tmp = nir_fmul(b, Q_xy, rcp_Q_z);
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   nir_ssa_def *dQdx_xy = nir_channels(b, dQdx, 0x3);
710bf215546Sopenharmony_ci   nir_ssa_def *dQdx_z = nir_channel(b, dQdx, 2);
711bf215546Sopenharmony_ci   nir_ssa_def *dx =
712bf215546Sopenharmony_ci      nir_fmul(b, rcp_Q_z, nir_fsub(b, dQdx_xy, nir_fmul(b, tmp, dQdx_z)));
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci   nir_ssa_def *dQdy_xy = nir_channels(b, dQdy, 0x3);
715bf215546Sopenharmony_ci   nir_ssa_def *dQdy_z = nir_channel(b, dQdy, 2);
716bf215546Sopenharmony_ci   nir_ssa_def *dy =
717bf215546Sopenharmony_ci      nir_fmul(b, rcp_Q_z, nir_fsub(b, dQdy_xy, nir_fmul(b, tmp, dQdy_z)));
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   /* M = max(dot(dx, dx), dot(dy, dy)); */
720bf215546Sopenharmony_ci   nir_ssa_def *M = nir_fmax(b, nir_fdot(b, dx, dx), nir_fdot(b, dy, dy));
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_ci   /* size has textureSize() of LOD 0 */
723bf215546Sopenharmony_ci   nir_ssa_def *L = nir_channel(b, size, 0);
724bf215546Sopenharmony_ci
725bf215546Sopenharmony_ci   /* lod = -1.0 + 0.5 * log2(L * L * M); */
726bf215546Sopenharmony_ci   nir_ssa_def *lod =
727bf215546Sopenharmony_ci      nir_fadd(b,
728bf215546Sopenharmony_ci               nir_imm_float(b, -1.0f),
729bf215546Sopenharmony_ci               nir_fmul(b,
730bf215546Sopenharmony_ci                        nir_imm_float(b, 0.5f),
731bf215546Sopenharmony_ci                        nir_flog2(b, nir_fmul(b, L, nir_fmul(b, L, M)))));
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci   /* 3. Replace the gradient instruction with an equivalent lod instruction */
734bf215546Sopenharmony_ci   replace_gradient_with_lod(b, lod, tex);
735bf215546Sopenharmony_ci}
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_cistatic void
738bf215546Sopenharmony_cilower_gradient(nir_builder *b, nir_tex_instr *tex)
739bf215546Sopenharmony_ci{
740bf215546Sopenharmony_ci   /* Cubes are more complicated and have their own function */
741bf215546Sopenharmony_ci   if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
742bf215546Sopenharmony_ci      lower_gradient_cube_map(b, tex);
743bf215546Sopenharmony_ci      return;
744bf215546Sopenharmony_ci   }
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_ci   assert(tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE);
747bf215546Sopenharmony_ci   assert(tex->op == nir_texop_txd);
748bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci   /* Use textureSize() to get the width and height of LOD 0 */
751bf215546Sopenharmony_ci   unsigned component_mask;
752bf215546Sopenharmony_ci   switch (tex->sampler_dim) {
753bf215546Sopenharmony_ci   case GLSL_SAMPLER_DIM_3D:
754bf215546Sopenharmony_ci      component_mask = 7;
755bf215546Sopenharmony_ci      break;
756bf215546Sopenharmony_ci   case GLSL_SAMPLER_DIM_1D:
757bf215546Sopenharmony_ci      component_mask = 1;
758bf215546Sopenharmony_ci      break;
759bf215546Sopenharmony_ci   default:
760bf215546Sopenharmony_ci      component_mask = 3;
761bf215546Sopenharmony_ci      break;
762bf215546Sopenharmony_ci   }
763bf215546Sopenharmony_ci
764bf215546Sopenharmony_ci   nir_ssa_def *size =
765bf215546Sopenharmony_ci      nir_channels(b, nir_i2f32(b, nir_get_texture_size(b, tex)),
766bf215546Sopenharmony_ci                      component_mask);
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci   /* Scale the gradients by width and height.  Effectively, the incoming
769bf215546Sopenharmony_ci    * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
770bf215546Sopenharmony_ci    * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
771bf215546Sopenharmony_ci    */
772bf215546Sopenharmony_ci   nir_ssa_def *ddx =
773bf215546Sopenharmony_ci      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddx)].src.ssa;
774bf215546Sopenharmony_ci   nir_ssa_def *ddy =
775bf215546Sopenharmony_ci      tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddy)].src.ssa;
776bf215546Sopenharmony_ci
777bf215546Sopenharmony_ci   nir_ssa_def *dPdx = nir_fmul(b, ddx, size);
778bf215546Sopenharmony_ci   nir_ssa_def *dPdy = nir_fmul(b, ddy, size);
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci   nir_ssa_def *rho;
781bf215546Sopenharmony_ci   if (dPdx->num_components == 1) {
782bf215546Sopenharmony_ci      rho = nir_fmax(b, nir_fabs(b, dPdx), nir_fabs(b, dPdy));
783bf215546Sopenharmony_ci   } else {
784bf215546Sopenharmony_ci      rho = nir_fmax(b,
785bf215546Sopenharmony_ci                     nir_fsqrt(b, nir_fdot(b, dPdx, dPdx)),
786bf215546Sopenharmony_ci                     nir_fsqrt(b, nir_fdot(b, dPdy, dPdy)));
787bf215546Sopenharmony_ci   }
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_ci   /* lod = log2(rho).  We're ignoring GL state biases for now. */
790bf215546Sopenharmony_ci   nir_ssa_def *lod = nir_flog2(b, rho);
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_ci   /* Replace the gradient instruction with an equivalent lod instruction */
793bf215546Sopenharmony_ci   replace_gradient_with_lod(b, lod, tex);
794bf215546Sopenharmony_ci}
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci/* tex(s, coord) = txd(s, coord, dfdx(coord), dfdy(coord)) */
797bf215546Sopenharmony_cistatic nir_tex_instr *
798bf215546Sopenharmony_cilower_tex_to_txd(nir_builder *b, nir_tex_instr *tex)
799bf215546Sopenharmony_ci{
800bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
801bf215546Sopenharmony_ci   nir_tex_instr *txd = nir_tex_instr_create(b->shader, tex->num_srcs + 2);
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci   txd->op = nir_texop_txd;
804bf215546Sopenharmony_ci   txd->sampler_dim = tex->sampler_dim;
805bf215546Sopenharmony_ci   txd->dest_type = tex->dest_type;
806bf215546Sopenharmony_ci   txd->coord_components = tex->coord_components;
807bf215546Sopenharmony_ci   txd->texture_index = tex->texture_index;
808bf215546Sopenharmony_ci   txd->sampler_index = tex->sampler_index;
809bf215546Sopenharmony_ci   txd->is_array = tex->is_array;
810bf215546Sopenharmony_ci   txd->is_shadow = tex->is_shadow;
811bf215546Sopenharmony_ci   txd->is_new_style_shadow = tex->is_new_style_shadow;
812bf215546Sopenharmony_ci
813bf215546Sopenharmony_ci   /* reuse existing srcs */
814bf215546Sopenharmony_ci   for (unsigned i = 0; i < tex->num_srcs; i++) {
815bf215546Sopenharmony_ci      nir_src_copy(&txd->src[i].src, &tex->src[i].src);
816bf215546Sopenharmony_ci      txd->src[i].src_type = tex->src[i].src_type;
817bf215546Sopenharmony_ci   }
818bf215546Sopenharmony_ci   int coord = nir_tex_instr_src_index(tex, nir_tex_src_coord);
819bf215546Sopenharmony_ci   assert(coord >= 0);
820bf215546Sopenharmony_ci   nir_ssa_def *dfdx = nir_fddx(b, tex->src[coord].src.ssa);
821bf215546Sopenharmony_ci   nir_ssa_def *dfdy = nir_fddy(b, tex->src[coord].src.ssa);
822bf215546Sopenharmony_ci   txd->src[tex->num_srcs].src = nir_src_for_ssa(dfdx);
823bf215546Sopenharmony_ci   txd->src[tex->num_srcs].src_type = nir_tex_src_ddx;
824bf215546Sopenharmony_ci   txd->src[tex->num_srcs + 1].src = nir_src_for_ssa(dfdy);
825bf215546Sopenharmony_ci   txd->src[tex->num_srcs + 1].src_type = nir_tex_src_ddy;
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ci   nir_ssa_dest_init(&txd->instr, &txd->dest, nir_dest_num_components(tex->dest),
828bf215546Sopenharmony_ci                     nir_dest_bit_size(tex->dest), NULL);
829bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &txd->instr);
830bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses(&tex->dest.ssa, &txd->dest.ssa);
831bf215546Sopenharmony_ci   nir_instr_remove(&tex->instr);
832bf215546Sopenharmony_ci   return txd;
833bf215546Sopenharmony_ci}
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci/* txb(s, coord, bias) = txl(s, coord, lod(s, coord).y + bias) */
836bf215546Sopenharmony_cistatic nir_tex_instr *
837bf215546Sopenharmony_cilower_txb_to_txl(nir_builder *b, nir_tex_instr *tex)
838bf215546Sopenharmony_ci{
839bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
840bf215546Sopenharmony_ci   nir_tex_instr *txl = nir_tex_instr_create(b->shader, tex->num_srcs);
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci   txl->op = nir_texop_txl;
843bf215546Sopenharmony_ci   txl->sampler_dim = tex->sampler_dim;
844bf215546Sopenharmony_ci   txl->dest_type = tex->dest_type;
845bf215546Sopenharmony_ci   txl->coord_components = tex->coord_components;
846bf215546Sopenharmony_ci   txl->texture_index = tex->texture_index;
847bf215546Sopenharmony_ci   txl->sampler_index = tex->sampler_index;
848bf215546Sopenharmony_ci   txl->is_array = tex->is_array;
849bf215546Sopenharmony_ci   txl->is_shadow = tex->is_shadow;
850bf215546Sopenharmony_ci   txl->is_new_style_shadow = tex->is_new_style_shadow;
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ci   /* reuse all but bias src */
853bf215546Sopenharmony_ci   for (int i = 0; i < 2; i++) {
854bf215546Sopenharmony_ci      if (tex->src[i].src_type != nir_tex_src_bias) {
855bf215546Sopenharmony_ci         nir_src_copy(&txl->src[i].src, &tex->src[i].src);
856bf215546Sopenharmony_ci         txl->src[i].src_type = tex->src[i].src_type;
857bf215546Sopenharmony_ci      }
858bf215546Sopenharmony_ci   }
859bf215546Sopenharmony_ci   nir_ssa_def *lod = nir_get_texture_lod(b, txl);
860bf215546Sopenharmony_ci
861bf215546Sopenharmony_ci   int bias_idx = nir_tex_instr_src_index(tex, nir_tex_src_bias);
862bf215546Sopenharmony_ci   assert(bias_idx >= 0);
863bf215546Sopenharmony_ci   lod = nir_fadd(b, nir_channel(b, lod, 1), nir_ssa_for_src(b, tex->src[bias_idx].src, 1));
864bf215546Sopenharmony_ci   txl->src[tex->num_srcs - 1].src = nir_src_for_ssa(lod);
865bf215546Sopenharmony_ci   txl->src[tex->num_srcs - 1].src_type = nir_tex_src_lod;
866bf215546Sopenharmony_ci
867bf215546Sopenharmony_ci   nir_ssa_dest_init(&txl->instr, &txl->dest, nir_dest_num_components(tex->dest),
868bf215546Sopenharmony_ci                     nir_dest_bit_size(tex->dest), NULL);
869bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &txl->instr);
870bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses(&tex->dest.ssa, &txl->dest.ssa);
871bf215546Sopenharmony_ci   nir_instr_remove(&tex->instr);
872bf215546Sopenharmony_ci   return txl;
873bf215546Sopenharmony_ci}
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_cistatic nir_tex_instr *
876bf215546Sopenharmony_cisaturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
877bf215546Sopenharmony_ci{
878bf215546Sopenharmony_ci   if (tex->op == nir_texop_tex)
879bf215546Sopenharmony_ci      tex = lower_tex_to_txd(b, tex);
880bf215546Sopenharmony_ci   else if (tex->op == nir_texop_txb)
881bf215546Sopenharmony_ci      tex = lower_txb_to_txl(b, tex);
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
884bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
885bf215546Sopenharmony_ci
886bf215546Sopenharmony_ci   if (coord_index != -1) {
887bf215546Sopenharmony_ci      nir_ssa_def *src =
888bf215546Sopenharmony_ci         nir_ssa_for_src(b, tex->src[coord_index].src, tex->coord_components);
889bf215546Sopenharmony_ci
890bf215546Sopenharmony_ci      /* split src into components: */
891bf215546Sopenharmony_ci      nir_ssa_def *comp[4];
892bf215546Sopenharmony_ci
893bf215546Sopenharmony_ci      assume(tex->coord_components >= 1);
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci      for (unsigned j = 0; j < tex->coord_components; j++)
896bf215546Sopenharmony_ci         comp[j] = nir_channel(b, src, j);
897bf215546Sopenharmony_ci
898bf215546Sopenharmony_ci      /* clamp requested components, array index does not get clamped: */
899bf215546Sopenharmony_ci      unsigned ncomp = tex->coord_components;
900bf215546Sopenharmony_ci      if (tex->is_array)
901bf215546Sopenharmony_ci         ncomp--;
902bf215546Sopenharmony_ci
903bf215546Sopenharmony_ci      for (unsigned j = 0; j < ncomp; j++) {
904bf215546Sopenharmony_ci         if ((1 << j) & sat_mask) {
905bf215546Sopenharmony_ci            if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
906bf215546Sopenharmony_ci               /* non-normalized texture coords, so clamp to texture
907bf215546Sopenharmony_ci                * size rather than [0.0, 1.0]
908bf215546Sopenharmony_ci                */
909bf215546Sopenharmony_ci               nir_ssa_def *txs = nir_i2f32(b, nir_get_texture_size(b, tex));
910bf215546Sopenharmony_ci               comp[j] = nir_fmax(b, comp[j], nir_imm_float(b, 0.0));
911bf215546Sopenharmony_ci               comp[j] = nir_fmin(b, comp[j], nir_channel(b, txs, j));
912bf215546Sopenharmony_ci            } else {
913bf215546Sopenharmony_ci               comp[j] = nir_fsat(b, comp[j]);
914bf215546Sopenharmony_ci            }
915bf215546Sopenharmony_ci         }
916bf215546Sopenharmony_ci      }
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci      /* and move the result back into a single vecN: */
919bf215546Sopenharmony_ci      src = nir_vec(b, comp, tex->coord_components);
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci      nir_instr_rewrite_src(&tex->instr,
922bf215546Sopenharmony_ci                            &tex->src[coord_index].src,
923bf215546Sopenharmony_ci                            nir_src_for_ssa(src));
924bf215546Sopenharmony_ci   }
925bf215546Sopenharmony_ci   return tex;
926bf215546Sopenharmony_ci}
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_cistatic nir_ssa_def *
929bf215546Sopenharmony_ciget_zero_or_one(nir_builder *b, nir_alu_type type, uint8_t swizzle_val)
930bf215546Sopenharmony_ci{
931bf215546Sopenharmony_ci   nir_const_value v[4];
932bf215546Sopenharmony_ci
933bf215546Sopenharmony_ci   memset(&v, 0, sizeof(v));
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci   if (swizzle_val == 4) {
936bf215546Sopenharmony_ci      v[0].u32 = v[1].u32 = v[2].u32 = v[3].u32 = 0;
937bf215546Sopenharmony_ci   } else {
938bf215546Sopenharmony_ci      assert(swizzle_val == 5);
939bf215546Sopenharmony_ci      if (type == nir_type_float32)
940bf215546Sopenharmony_ci         v[0].f32 = v[1].f32 = v[2].f32 = v[3].f32 = 1.0;
941bf215546Sopenharmony_ci      else
942bf215546Sopenharmony_ci         v[0].u32 = v[1].u32 = v[2].u32 = v[3].u32 = 1;
943bf215546Sopenharmony_ci   }
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_ci   return nir_build_imm(b, 4, 32, v);
946bf215546Sopenharmony_ci}
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_cistatic void
949bf215546Sopenharmony_ciswizzle_tg4_broadcom(nir_builder *b, nir_tex_instr *tex)
950bf215546Sopenharmony_ci{
951bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
954bf215546Sopenharmony_ci
955bf215546Sopenharmony_ci   assert(nir_tex_instr_dest_size(tex) == 4);
956bf215546Sopenharmony_ci   unsigned swiz[4] = { 2, 3, 1, 0 };
957bf215546Sopenharmony_ci   nir_ssa_def *swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4);
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, swizzled,
960bf215546Sopenharmony_ci                                  swizzled->parent_instr);
961bf215546Sopenharmony_ci}
962bf215546Sopenharmony_ci
963bf215546Sopenharmony_cistatic void
964bf215546Sopenharmony_ciswizzle_result(nir_builder *b, nir_tex_instr *tex, const uint8_t swizzle[4])
965bf215546Sopenharmony_ci{
966bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
967bf215546Sopenharmony_ci
968bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
969bf215546Sopenharmony_ci
970bf215546Sopenharmony_ci   nir_ssa_def *swizzled;
971bf215546Sopenharmony_ci   if (tex->op == nir_texop_tg4) {
972bf215546Sopenharmony_ci      if (swizzle[tex->component] < 4) {
973bf215546Sopenharmony_ci         /* This one's easy */
974bf215546Sopenharmony_ci         tex->component = swizzle[tex->component];
975bf215546Sopenharmony_ci         return;
976bf215546Sopenharmony_ci      } else {
977bf215546Sopenharmony_ci         swizzled = get_zero_or_one(b, tex->dest_type, swizzle[tex->component]);
978bf215546Sopenharmony_ci      }
979bf215546Sopenharmony_ci   } else {
980bf215546Sopenharmony_ci      assert(nir_tex_instr_dest_size(tex) == 4);
981bf215546Sopenharmony_ci      if (swizzle[0] < 4 && swizzle[1] < 4 &&
982bf215546Sopenharmony_ci          swizzle[2] < 4 && swizzle[3] < 4) {
983bf215546Sopenharmony_ci         unsigned swiz[4] = { swizzle[0], swizzle[1], swizzle[2], swizzle[3] };
984bf215546Sopenharmony_ci         /* We have no 0s or 1s, just emit a swizzling MOV */
985bf215546Sopenharmony_ci         swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4);
986bf215546Sopenharmony_ci      } else {
987bf215546Sopenharmony_ci         nir_ssa_scalar srcs[4];
988bf215546Sopenharmony_ci         for (unsigned i = 0; i < 4; i++) {
989bf215546Sopenharmony_ci            if (swizzle[i] < 4) {
990bf215546Sopenharmony_ci               srcs[i] = nir_get_ssa_scalar(&tex->dest.ssa, swizzle[i]);
991bf215546Sopenharmony_ci            } else {
992bf215546Sopenharmony_ci               srcs[i] = nir_get_ssa_scalar(get_zero_or_one(b, tex->dest_type, swizzle[i]), 0);
993bf215546Sopenharmony_ci            }
994bf215546Sopenharmony_ci         }
995bf215546Sopenharmony_ci         swizzled = nir_vec_scalars(b, srcs, 4);
996bf215546Sopenharmony_ci      }
997bf215546Sopenharmony_ci   }
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, swizzled,
1000bf215546Sopenharmony_ci                                  swizzled->parent_instr);
1001bf215546Sopenharmony_ci}
1002bf215546Sopenharmony_ci
1003bf215546Sopenharmony_cistatic void
1004bf215546Sopenharmony_cilinearize_srgb_result(nir_builder *b, nir_tex_instr *tex)
1005bf215546Sopenharmony_ci{
1006bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
1007bf215546Sopenharmony_ci   assert(nir_tex_instr_dest_size(tex) == 4);
1008bf215546Sopenharmony_ci   assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
1009bf215546Sopenharmony_ci
1010bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1011bf215546Sopenharmony_ci
1012bf215546Sopenharmony_ci   nir_ssa_def *rgb =
1013bf215546Sopenharmony_ci      nir_format_srgb_to_linear(b, nir_channels(b, &tex->dest.ssa, 0x7));
1014bf215546Sopenharmony_ci
1015bf215546Sopenharmony_ci   /* alpha is untouched: */
1016bf215546Sopenharmony_ci   nir_ssa_def *result = nir_vec4(b,
1017bf215546Sopenharmony_ci                                  nir_channel(b, rgb, 0),
1018bf215546Sopenharmony_ci                                  nir_channel(b, rgb, 1),
1019bf215546Sopenharmony_ci                                  nir_channel(b, rgb, 2),
1020bf215546Sopenharmony_ci                                  nir_channel(b, &tex->dest.ssa, 3));
1021bf215546Sopenharmony_ci
1022bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, result,
1023bf215546Sopenharmony_ci                                  result->parent_instr);
1024bf215546Sopenharmony_ci}
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_ci/**
1027bf215546Sopenharmony_ci * Lowers texture instructions from giving a vec4 result to a vec2 of f16,
1028bf215546Sopenharmony_ci * i16, or u16, or a single unorm4x8 value.
1029bf215546Sopenharmony_ci *
1030bf215546Sopenharmony_ci * Note that we don't change the destination num_components, because
1031bf215546Sopenharmony_ci * nir_tex_instr_dest_size() will still return 4.  The driver is just expected
1032bf215546Sopenharmony_ci * to not store the other channels, given that nothing at the NIR level will
1033bf215546Sopenharmony_ci * read them.
1034bf215546Sopenharmony_ci */
1035bf215546Sopenharmony_cistatic void
1036bf215546Sopenharmony_cilower_tex_packing(nir_builder *b, nir_tex_instr *tex,
1037bf215546Sopenharmony_ci                  const nir_lower_tex_options *options)
1038bf215546Sopenharmony_ci{
1039bf215546Sopenharmony_ci   nir_ssa_def *color = &tex->dest.ssa;
1040bf215546Sopenharmony_ci
1041bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_ci   switch (options->lower_tex_packing[tex->sampler_index]) {
1044bf215546Sopenharmony_ci   case nir_lower_tex_packing_none:
1045bf215546Sopenharmony_ci      return;
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_ci   case nir_lower_tex_packing_16: {
1048bf215546Sopenharmony_ci      static const unsigned bits[4] = {16, 16, 16, 16};
1049bf215546Sopenharmony_ci
1050bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(tex->dest_type)) {
1051bf215546Sopenharmony_ci      case nir_type_float:
1052bf215546Sopenharmony_ci         switch (nir_tex_instr_dest_size(tex)) {
1053bf215546Sopenharmony_ci         case 1:
1054bf215546Sopenharmony_ci            assert(tex->is_shadow && tex->is_new_style_shadow);
1055bf215546Sopenharmony_ci            color = nir_unpack_half_2x16_split_x(b, nir_channel(b, color, 0));
1056bf215546Sopenharmony_ci            break;
1057bf215546Sopenharmony_ci         case 2: {
1058bf215546Sopenharmony_ci            nir_ssa_def *rg = nir_channel(b, color, 0);
1059bf215546Sopenharmony_ci            color = nir_vec2(b,
1060bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_x(b, rg),
1061bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_y(b, rg));
1062bf215546Sopenharmony_ci            break;
1063bf215546Sopenharmony_ci         }
1064bf215546Sopenharmony_ci         case 4: {
1065bf215546Sopenharmony_ci            nir_ssa_def *rg = nir_channel(b, color, 0);
1066bf215546Sopenharmony_ci            nir_ssa_def *ba = nir_channel(b, color, 1);
1067bf215546Sopenharmony_ci            color = nir_vec4(b,
1068bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_x(b, rg),
1069bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_y(b, rg),
1070bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_x(b, ba),
1071bf215546Sopenharmony_ci                             nir_unpack_half_2x16_split_y(b, ba));
1072bf215546Sopenharmony_ci            break;
1073bf215546Sopenharmony_ci         }
1074bf215546Sopenharmony_ci         default:
1075bf215546Sopenharmony_ci            unreachable("wrong dest_size");
1076bf215546Sopenharmony_ci         }
1077bf215546Sopenharmony_ci         break;
1078bf215546Sopenharmony_ci
1079bf215546Sopenharmony_ci      case nir_type_int:
1080bf215546Sopenharmony_ci         color = nir_format_unpack_sint(b, color, bits, 4);
1081bf215546Sopenharmony_ci         break;
1082bf215546Sopenharmony_ci
1083bf215546Sopenharmony_ci      case nir_type_uint:
1084bf215546Sopenharmony_ci         color = nir_format_unpack_uint(b, color, bits, 4);
1085bf215546Sopenharmony_ci         break;
1086bf215546Sopenharmony_ci
1087bf215546Sopenharmony_ci      default:
1088bf215546Sopenharmony_ci         unreachable("unknown base type");
1089bf215546Sopenharmony_ci      }
1090bf215546Sopenharmony_ci      break;
1091bf215546Sopenharmony_ci   }
1092bf215546Sopenharmony_ci
1093bf215546Sopenharmony_ci   case nir_lower_tex_packing_8:
1094bf215546Sopenharmony_ci      assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
1095bf215546Sopenharmony_ci      color = nir_unpack_unorm_4x8(b, nir_channel(b, color, 0));
1096bf215546Sopenharmony_ci      break;
1097bf215546Sopenharmony_ci   }
1098bf215546Sopenharmony_ci
1099bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, color,
1100bf215546Sopenharmony_ci                                  color->parent_instr);
1101bf215546Sopenharmony_ci}
1102bf215546Sopenharmony_ci
1103bf215546Sopenharmony_cistatic bool
1104bf215546Sopenharmony_cilower_array_layer_round_even(nir_builder *b, nir_tex_instr *tex)
1105bf215546Sopenharmony_ci{
1106bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
1107bf215546Sopenharmony_ci   if (coord_index < 0 || nir_tex_instr_src_type(tex, coord_index) != nir_type_float)
1108bf215546Sopenharmony_ci      return false;
1109bf215546Sopenharmony_ci
1110bf215546Sopenharmony_ci   assert(tex->src[coord_index].src.is_ssa);
1111bf215546Sopenharmony_ci   nir_ssa_def *coord = tex->src[coord_index].src.ssa;
1112bf215546Sopenharmony_ci
1113bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
1114bf215546Sopenharmony_ci
1115bf215546Sopenharmony_ci   unsigned layer = tex->coord_components - 1;
1116bf215546Sopenharmony_ci   nir_ssa_def *rounded_layer = nir_fround_even(b, nir_channel(b, coord, layer));
1117bf215546Sopenharmony_ci   nir_ssa_def *new_coord = nir_vector_insert_imm(b, coord, rounded_layer, layer);
1118bf215546Sopenharmony_ci
1119bf215546Sopenharmony_ci   nir_instr_rewrite_src_ssa(&tex->instr, &tex->src[coord_index].src, new_coord);
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci   return true;
1122bf215546Sopenharmony_ci}
1123bf215546Sopenharmony_ci
1124bf215546Sopenharmony_cistatic bool
1125bf215546Sopenharmony_cisampler_index_lt(nir_tex_instr *tex, unsigned max)
1126bf215546Sopenharmony_ci{
1127bf215546Sopenharmony_ci   assert(nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref) == -1);
1128bf215546Sopenharmony_ci
1129bf215546Sopenharmony_ci   unsigned sampler_index = tex->sampler_index;
1130bf215546Sopenharmony_ci
1131bf215546Sopenharmony_ci   int sampler_offset_idx =
1132bf215546Sopenharmony_ci      nir_tex_instr_src_index(tex, nir_tex_src_sampler_offset);
1133bf215546Sopenharmony_ci   if (sampler_offset_idx >= 0) {
1134bf215546Sopenharmony_ci      if (!nir_src_is_const(tex->src[sampler_offset_idx].src))
1135bf215546Sopenharmony_ci         return false;
1136bf215546Sopenharmony_ci
1137bf215546Sopenharmony_ci      sampler_index += nir_src_as_uint(tex->src[sampler_offset_idx].src);
1138bf215546Sopenharmony_ci   }
1139bf215546Sopenharmony_ci
1140bf215546Sopenharmony_ci   return sampler_index < max;
1141bf215546Sopenharmony_ci}
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_cistatic bool
1144bf215546Sopenharmony_cilower_tg4_offsets(nir_builder *b, nir_tex_instr *tex)
1145bf215546Sopenharmony_ci{
1146bf215546Sopenharmony_ci   assert(tex->op == nir_texop_tg4);
1147bf215546Sopenharmony_ci   assert(nir_tex_instr_has_explicit_tg4_offsets(tex));
1148bf215546Sopenharmony_ci   assert(nir_tex_instr_src_index(tex, nir_tex_src_offset) == -1);
1149bf215546Sopenharmony_ci
1150bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1151bf215546Sopenharmony_ci
1152bf215546Sopenharmony_ci   nir_ssa_scalar dest[5] = { 0 };
1153bf215546Sopenharmony_ci   nir_ssa_def *residency = NULL;
1154bf215546Sopenharmony_ci   for (unsigned i = 0; i < 4; ++i) {
1155bf215546Sopenharmony_ci      nir_tex_instr *tex_copy = nir_tex_instr_create(b->shader, tex->num_srcs + 1);
1156bf215546Sopenharmony_ci      tex_copy->op = tex->op;
1157bf215546Sopenharmony_ci      tex_copy->coord_components = tex->coord_components;
1158bf215546Sopenharmony_ci      tex_copy->sampler_dim = tex->sampler_dim;
1159bf215546Sopenharmony_ci      tex_copy->is_array = tex->is_array;
1160bf215546Sopenharmony_ci      tex_copy->is_shadow = tex->is_shadow;
1161bf215546Sopenharmony_ci      tex_copy->is_new_style_shadow = tex->is_new_style_shadow;
1162bf215546Sopenharmony_ci      tex_copy->is_sparse = tex->is_sparse;
1163bf215546Sopenharmony_ci      tex_copy->component = tex->component;
1164bf215546Sopenharmony_ci      tex_copy->dest_type = tex->dest_type;
1165bf215546Sopenharmony_ci
1166bf215546Sopenharmony_ci      for (unsigned j = 0; j < tex->num_srcs; ++j) {
1167bf215546Sopenharmony_ci         nir_src_copy(&tex_copy->src[j].src, &tex->src[j].src);
1168bf215546Sopenharmony_ci         tex_copy->src[j].src_type = tex->src[j].src_type;
1169bf215546Sopenharmony_ci      }
1170bf215546Sopenharmony_ci
1171bf215546Sopenharmony_ci      nir_tex_src src;
1172bf215546Sopenharmony_ci      src.src = nir_src_for_ssa(nir_imm_ivec2(b, tex->tg4_offsets[i][0],
1173bf215546Sopenharmony_ci                                                 tex->tg4_offsets[i][1]));
1174bf215546Sopenharmony_ci      src.src_type = nir_tex_src_offset;
1175bf215546Sopenharmony_ci      tex_copy->src[tex_copy->num_srcs - 1] = src;
1176bf215546Sopenharmony_ci
1177bf215546Sopenharmony_ci      nir_ssa_dest_init(&tex_copy->instr, &tex_copy->dest,
1178bf215546Sopenharmony_ci                        nir_tex_instr_dest_size(tex), 32, NULL);
1179bf215546Sopenharmony_ci
1180bf215546Sopenharmony_ci      nir_builder_instr_insert(b, &tex_copy->instr);
1181bf215546Sopenharmony_ci
1182bf215546Sopenharmony_ci      dest[i] = nir_get_ssa_scalar(&tex_copy->dest.ssa, 3);
1183bf215546Sopenharmony_ci      if (tex->is_sparse) {
1184bf215546Sopenharmony_ci         nir_ssa_def *code = nir_channel(b, &tex_copy->dest.ssa, 4);
1185bf215546Sopenharmony_ci         if (residency)
1186bf215546Sopenharmony_ci            residency = nir_sparse_residency_code_and(b, residency, code);
1187bf215546Sopenharmony_ci         else
1188bf215546Sopenharmony_ci            residency = code;
1189bf215546Sopenharmony_ci      }
1190bf215546Sopenharmony_ci   }
1191bf215546Sopenharmony_ci   dest[4] = nir_get_ssa_scalar(residency, 0);
1192bf215546Sopenharmony_ci
1193bf215546Sopenharmony_ci   nir_ssa_def *res = nir_vec_scalars(b, dest, tex->dest.ssa.num_components);
1194bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses(&tex->dest.ssa, res);
1195bf215546Sopenharmony_ci   nir_instr_remove(&tex->instr);
1196bf215546Sopenharmony_ci
1197bf215546Sopenharmony_ci   return true;
1198bf215546Sopenharmony_ci}
1199bf215546Sopenharmony_ci
1200bf215546Sopenharmony_cistatic bool
1201bf215546Sopenharmony_cinir_lower_txs_lod(nir_builder *b, nir_tex_instr *tex)
1202bf215546Sopenharmony_ci{
1203bf215546Sopenharmony_ci   int lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_lod);
1204bf215546Sopenharmony_ci   if (lod_idx < 0 ||
1205bf215546Sopenharmony_ci       (nir_src_is_const(tex->src[lod_idx].src) &&
1206bf215546Sopenharmony_ci        nir_src_as_int(tex->src[lod_idx].src) == 0))
1207bf215546Sopenharmony_ci      return false;
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_ci   unsigned dest_size = nir_tex_instr_dest_size(tex);
1210bf215546Sopenharmony_ci
1211bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
1212bf215546Sopenharmony_ci   nir_ssa_def *lod = nir_ssa_for_src(b, tex->src[lod_idx].src, 1);
1213bf215546Sopenharmony_ci
1214bf215546Sopenharmony_ci   /* Replace the non-0-LOD in the initial TXS operation by a 0-LOD. */
1215bf215546Sopenharmony_ci   nir_instr_rewrite_src(&tex->instr, &tex->src[lod_idx].src,
1216bf215546Sopenharmony_ci                         nir_src_for_ssa(nir_imm_int(b, 0)));
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ci   /* TXS(LOD) = max(TXS(0) >> LOD, 1)
1219bf215546Sopenharmony_ci    * But we do min(TXS(0), TXS(LOD)) to catch the case of a null surface,
1220bf215546Sopenharmony_ci    * which should return 0, not 1.
1221bf215546Sopenharmony_ci    */
1222bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1223bf215546Sopenharmony_ci   nir_ssa_def *minified = nir_imin(b, &tex->dest.ssa,
1224bf215546Sopenharmony_ci                                    nir_imax(b, nir_ushr(b, &tex->dest.ssa, lod),
1225bf215546Sopenharmony_ci                                             nir_imm_int(b, 1)));
1226bf215546Sopenharmony_ci
1227bf215546Sopenharmony_ci   /* Make sure the component encoding the array size (if any) is not
1228bf215546Sopenharmony_ci    * minified.
1229bf215546Sopenharmony_ci    */
1230bf215546Sopenharmony_ci   if (tex->is_array) {
1231bf215546Sopenharmony_ci      nir_ssa_def *comp[3];
1232bf215546Sopenharmony_ci
1233bf215546Sopenharmony_ci      assert(dest_size <= ARRAY_SIZE(comp));
1234bf215546Sopenharmony_ci      for (unsigned i = 0; i < dest_size - 1; i++)
1235bf215546Sopenharmony_ci         comp[i] = nir_channel(b, minified, i);
1236bf215546Sopenharmony_ci
1237bf215546Sopenharmony_ci      comp[dest_size - 1] = nir_channel(b, &tex->dest.ssa, dest_size - 1);
1238bf215546Sopenharmony_ci      minified = nir_vec(b, comp, dest_size);
1239bf215546Sopenharmony_ci   }
1240bf215546Sopenharmony_ci
1241bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, minified,
1242bf215546Sopenharmony_ci                                  minified->parent_instr);
1243bf215546Sopenharmony_ci   return true;
1244bf215546Sopenharmony_ci}
1245bf215546Sopenharmony_ci
1246bf215546Sopenharmony_cistatic void
1247bf215546Sopenharmony_cinir_lower_txs_cube_array(nir_builder *b, nir_tex_instr *tex)
1248bf215546Sopenharmony_ci{
1249bf215546Sopenharmony_ci   assert(tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE && tex->is_array);
1250bf215546Sopenharmony_ci   tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
1251bf215546Sopenharmony_ci
1252bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1253bf215546Sopenharmony_ci
1254bf215546Sopenharmony_ci   assert(tex->dest.is_ssa);
1255bf215546Sopenharmony_ci   assert(tex->dest.ssa.num_components == 3);
1256bf215546Sopenharmony_ci   nir_ssa_def *size = &tex->dest.ssa;
1257bf215546Sopenharmony_ci   size = nir_vec3(b, nir_channel(b, size, 0),
1258bf215546Sopenharmony_ci                      nir_channel(b, size, 1),
1259bf215546Sopenharmony_ci                      nir_idiv(b, nir_channel(b, size, 2),
1260bf215546Sopenharmony_ci                                  nir_imm_int(b, 6)));
1261bf215546Sopenharmony_ci
1262bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, size, size->parent_instr);
1263bf215546Sopenharmony_ci}
1264bf215546Sopenharmony_ci
1265bf215546Sopenharmony_cistatic void
1266bf215546Sopenharmony_cinir_lower_ms_txf_to_fragment_fetch(nir_builder *b, nir_tex_instr *tex)
1267bf215546Sopenharmony_ci{
1268bf215546Sopenharmony_ci   lower_offset(b, tex);
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   b->cursor = nir_before_instr(&tex->instr);
1271bf215546Sopenharmony_ci
1272bf215546Sopenharmony_ci   /* Create FMASK fetch. */
1273bf215546Sopenharmony_ci   assert(tex->texture_index == 0);
1274bf215546Sopenharmony_ci   nir_tex_instr *fmask_fetch = nir_tex_instr_create(b->shader, tex->num_srcs - 1);
1275bf215546Sopenharmony_ci   fmask_fetch->op = nir_texop_fragment_mask_fetch_amd;
1276bf215546Sopenharmony_ci   fmask_fetch->coord_components = tex->coord_components;
1277bf215546Sopenharmony_ci   fmask_fetch->sampler_dim = tex->sampler_dim;
1278bf215546Sopenharmony_ci   fmask_fetch->is_array = tex->is_array;
1279bf215546Sopenharmony_ci   fmask_fetch->texture_non_uniform = tex->texture_non_uniform;
1280bf215546Sopenharmony_ci   fmask_fetch->dest_type = nir_type_uint32;
1281bf215546Sopenharmony_ci   nir_ssa_dest_init(&fmask_fetch->instr, &fmask_fetch->dest, 1, 32, NULL);
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_ci   fmask_fetch->num_srcs = 0;
1284bf215546Sopenharmony_ci   for (unsigned i = 0; i < tex->num_srcs; i++) {
1285bf215546Sopenharmony_ci      if (tex->src[i].src_type == nir_tex_src_ms_index)
1286bf215546Sopenharmony_ci         continue;
1287bf215546Sopenharmony_ci      nir_tex_src *src = &fmask_fetch->src[fmask_fetch->num_srcs++];
1288bf215546Sopenharmony_ci      src->src = nir_src_for_ssa(tex->src[i].src.ssa);
1289bf215546Sopenharmony_ci      src->src_type = tex->src[i].src_type;
1290bf215546Sopenharmony_ci   }
1291bf215546Sopenharmony_ci
1292bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &fmask_fetch->instr);
1293bf215546Sopenharmony_ci
1294bf215546Sopenharmony_ci   /* Obtain new sample index. */
1295bf215546Sopenharmony_ci   int ms_index = nir_tex_instr_src_index(tex, nir_tex_src_ms_index);
1296bf215546Sopenharmony_ci   assert(ms_index >= 0);
1297bf215546Sopenharmony_ci   nir_src sample = tex->src[ms_index].src;
1298bf215546Sopenharmony_ci   nir_ssa_def *new_sample = NULL;
1299bf215546Sopenharmony_ci   if (nir_src_is_const(sample) && (nir_src_as_uint(sample) == 0 || nir_src_as_uint(sample) == 7)) {
1300bf215546Sopenharmony_ci      if (nir_src_as_uint(sample) == 7)
1301bf215546Sopenharmony_ci         new_sample = nir_ushr(b, &fmask_fetch->dest.ssa, nir_imm_int(b, 28));
1302bf215546Sopenharmony_ci      else
1303bf215546Sopenharmony_ci         new_sample = nir_iand_imm(b, &fmask_fetch->dest.ssa, 0xf);
1304bf215546Sopenharmony_ci   } else {
1305bf215546Sopenharmony_ci      new_sample = nir_ubitfield_extract(b, &fmask_fetch->dest.ssa,
1306bf215546Sopenharmony_ci                                         nir_imul_imm(b, sample.ssa, 4), nir_imm_int(b, 4));
1307bf215546Sopenharmony_ci   }
1308bf215546Sopenharmony_ci
1309bf215546Sopenharmony_ci   /* Update instruction. */
1310bf215546Sopenharmony_ci   tex->op = nir_texop_fragment_fetch_amd;
1311bf215546Sopenharmony_ci   nir_instr_rewrite_src_ssa(&tex->instr, &tex->src[ms_index].src, new_sample);
1312bf215546Sopenharmony_ci}
1313bf215546Sopenharmony_ci
1314bf215546Sopenharmony_cistatic void
1315bf215546Sopenharmony_cinir_lower_samples_identical_to_fragment_fetch(nir_builder *b, nir_tex_instr *tex)
1316bf215546Sopenharmony_ci{
1317bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1318bf215546Sopenharmony_ci
1319bf215546Sopenharmony_ci   nir_tex_instr *fmask_fetch = nir_instr_as_tex(nir_instr_clone(b->shader, &tex->instr));
1320bf215546Sopenharmony_ci   fmask_fetch->op = nir_texop_fragment_mask_fetch_amd;
1321bf215546Sopenharmony_ci   fmask_fetch->dest_type = nir_type_uint32;
1322bf215546Sopenharmony_ci   nir_ssa_dest_init(&fmask_fetch->instr, &fmask_fetch->dest, 1, 32, NULL);
1323bf215546Sopenharmony_ci   nir_builder_instr_insert(b, &fmask_fetch->instr);
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_ieq_imm(b, &fmask_fetch->dest.ssa, 0));
1326bf215546Sopenharmony_ci   nir_instr_remove_v(&tex->instr);
1327bf215546Sopenharmony_ci}
1328bf215546Sopenharmony_ci
1329bf215546Sopenharmony_cistatic void
1330bf215546Sopenharmony_cinir_lower_lod_zero_width(nir_builder *b, nir_tex_instr *tex)
1331bf215546Sopenharmony_ci{
1332bf215546Sopenharmony_ci   int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
1333bf215546Sopenharmony_ci   assert(coord_index >= 0);
1334bf215546Sopenharmony_ci
1335bf215546Sopenharmony_ci   b->cursor = nir_after_instr(&tex->instr);
1336bf215546Sopenharmony_ci
1337bf215546Sopenharmony_ci   nir_ssa_def *is_zero = nir_imm_bool(b, true);
1338bf215546Sopenharmony_ci   for (unsigned i = 0; i < tex->coord_components; i++) {
1339bf215546Sopenharmony_ci      nir_ssa_def *coord = nir_channel(b, tex->src[coord_index].src.ssa, i);
1340bf215546Sopenharmony_ci
1341bf215546Sopenharmony_ci      /* Compute the sum of the absolute values of derivatives. */
1342bf215546Sopenharmony_ci      nir_ssa_def *dfdx = nir_fddx(b, coord);
1343bf215546Sopenharmony_ci      nir_ssa_def *dfdy = nir_fddy(b, coord);
1344bf215546Sopenharmony_ci      nir_ssa_def *fwidth = nir_fadd(b, nir_fabs(b, dfdx), nir_fabs(b, dfdy));
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci      /* Check if the sum is 0. */
1347bf215546Sopenharmony_ci      is_zero = nir_iand(b, is_zero, nir_feq(b, fwidth, nir_imm_float(b, 0.0)));
1348bf215546Sopenharmony_ci   }
1349bf215546Sopenharmony_ci
1350bf215546Sopenharmony_ci   /* Replace the raw LOD by -FLT_MAX if the sum is 0 for all coordinates. */
1351bf215546Sopenharmony_ci   nir_ssa_def *adjusted_lod =
1352bf215546Sopenharmony_ci      nir_bcsel(b, is_zero, nir_imm_float(b, -FLT_MAX),
1353bf215546Sopenharmony_ci                   nir_channel(b, &tex->dest.ssa, 1));
1354bf215546Sopenharmony_ci
1355bf215546Sopenharmony_ci   nir_ssa_def *def =
1356bf215546Sopenharmony_ci      nir_vec2(b, nir_channel(b, &tex->dest.ssa, 0), adjusted_lod);
1357bf215546Sopenharmony_ci
1358bf215546Sopenharmony_ci   nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, def, def->parent_instr);
1359bf215546Sopenharmony_ci}
1360bf215546Sopenharmony_ci
1361bf215546Sopenharmony_cistatic bool
1362bf215546Sopenharmony_cinir_lower_tex_block(nir_block *block, nir_builder *b,
1363bf215546Sopenharmony_ci                    const nir_lower_tex_options *options,
1364bf215546Sopenharmony_ci                    const struct nir_shader_compiler_options *compiler_options)
1365bf215546Sopenharmony_ci{
1366bf215546Sopenharmony_ci   bool progress = false;
1367bf215546Sopenharmony_ci
1368bf215546Sopenharmony_ci   nir_foreach_instr_safe(instr, block) {
1369bf215546Sopenharmony_ci      if (instr->type != nir_instr_type_tex)
1370bf215546Sopenharmony_ci         continue;
1371bf215546Sopenharmony_ci
1372bf215546Sopenharmony_ci      nir_tex_instr *tex = nir_instr_as_tex(instr);
1373bf215546Sopenharmony_ci      bool lower_txp = !!(options->lower_txp & (1 << tex->sampler_dim));
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci      /* mask of src coords to saturate (clamp): */
1376bf215546Sopenharmony_ci      unsigned sat_mask = 0;
1377bf215546Sopenharmony_ci
1378bf215546Sopenharmony_ci      if ((1 << tex->sampler_index) & options->saturate_r)
1379bf215546Sopenharmony_ci         sat_mask |= (1 << 2);    /* .z */
1380bf215546Sopenharmony_ci      if ((1 << tex->sampler_index) & options->saturate_t)
1381bf215546Sopenharmony_ci         sat_mask |= (1 << 1);    /* .y */
1382bf215546Sopenharmony_ci      if ((1 << tex->sampler_index) & options->saturate_s)
1383bf215546Sopenharmony_ci         sat_mask |= (1 << 0);    /* .x */
1384bf215546Sopenharmony_ci
1385bf215546Sopenharmony_ci      /* If we are clamping any coords, we must lower projector first
1386bf215546Sopenharmony_ci       * as clamping happens *after* projection:
1387bf215546Sopenharmony_ci       */
1388bf215546Sopenharmony_ci      if (lower_txp || sat_mask ||
1389bf215546Sopenharmony_ci          (options->lower_txp_array && tex->is_array)) {
1390bf215546Sopenharmony_ci         progress |= project_src(b, tex);
1391bf215546Sopenharmony_ci      }
1392bf215546Sopenharmony_ci
1393bf215546Sopenharmony_ci      if ((tex->op == nir_texop_txf && options->lower_txf_offset) ||
1394bf215546Sopenharmony_ci          (sat_mask && nir_tex_instr_src_index(tex, nir_tex_src_coord) >= 0) ||
1395bf215546Sopenharmony_ci          (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT &&
1396bf215546Sopenharmony_ci           options->lower_rect_offset) ||
1397bf215546Sopenharmony_ci          (options->lower_offset_filter &&
1398bf215546Sopenharmony_ci           options->lower_offset_filter(instr, options->callback_data))) {
1399bf215546Sopenharmony_ci         progress = lower_offset(b, tex) || progress;
1400bf215546Sopenharmony_ci      }
1401bf215546Sopenharmony_ci
1402bf215546Sopenharmony_ci      if ((tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) && options->lower_rect &&
1403bf215546Sopenharmony_ci          tex->op != nir_texop_txf) {
1404bf215546Sopenharmony_ci         if (nir_tex_instr_is_query(tex))
1405bf215546Sopenharmony_ci            tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
1406bf215546Sopenharmony_ci         else if (compiler_options->has_txs)
1407bf215546Sopenharmony_ci            lower_rect(b, tex);
1408bf215546Sopenharmony_ci         else
1409bf215546Sopenharmony_ci            lower_rect_tex_scale(b, tex);
1410bf215546Sopenharmony_ci
1411bf215546Sopenharmony_ci         progress = true;
1412bf215546Sopenharmony_ci      }
1413bf215546Sopenharmony_ci
1414bf215546Sopenharmony_ci      unsigned texture_index = tex->texture_index;
1415bf215546Sopenharmony_ci      uint32_t texture_mask = 1u << texture_index;
1416bf215546Sopenharmony_ci      int tex_index = nir_tex_instr_src_index(tex, nir_tex_src_texture_deref);
1417bf215546Sopenharmony_ci      if (tex_index >= 0) {
1418bf215546Sopenharmony_ci         nir_deref_instr *deref = nir_src_as_deref(tex->src[tex_index].src);
1419bf215546Sopenharmony_ci         nir_variable *var = nir_deref_instr_get_variable(deref);
1420bf215546Sopenharmony_ci         texture_index = var ? var->data.binding : 0;
1421bf215546Sopenharmony_ci         texture_mask = var && texture_index < 32 ? (1u << texture_index) : 0u;
1422bf215546Sopenharmony_ci      }
1423bf215546Sopenharmony_ci
1424bf215546Sopenharmony_ci      if (texture_mask & options->lower_y_uv_external) {
1425bf215546Sopenharmony_ci         lower_y_uv_external(b, tex, options, texture_index);
1426bf215546Sopenharmony_ci         progress = true;
1427bf215546Sopenharmony_ci      }
1428bf215546Sopenharmony_ci
1429bf215546Sopenharmony_ci      if (texture_mask & options->lower_y_u_v_external) {
1430bf215546Sopenharmony_ci         lower_y_u_v_external(b, tex, options, texture_index);
1431bf215546Sopenharmony_ci         progress = true;
1432bf215546Sopenharmony_ci      }
1433bf215546Sopenharmony_ci
1434bf215546Sopenharmony_ci      if (texture_mask & options->lower_yx_xuxv_external) {
1435bf215546Sopenharmony_ci         lower_yx_xuxv_external(b, tex, options, texture_index);
1436bf215546Sopenharmony_ci         progress = true;
1437bf215546Sopenharmony_ci      }
1438bf215546Sopenharmony_ci
1439bf215546Sopenharmony_ci      if (texture_mask & options->lower_xy_uxvx_external) {
1440bf215546Sopenharmony_ci         lower_xy_uxvx_external(b, tex, options, texture_index);
1441bf215546Sopenharmony_ci         progress = true;
1442bf215546Sopenharmony_ci      }
1443bf215546Sopenharmony_ci
1444bf215546Sopenharmony_ci      if (texture_mask & options->lower_ayuv_external) {
1445bf215546Sopenharmony_ci         lower_ayuv_external(b, tex, options, texture_index);
1446bf215546Sopenharmony_ci         progress = true;
1447bf215546Sopenharmony_ci      }
1448bf215546Sopenharmony_ci
1449bf215546Sopenharmony_ci      if (texture_mask & options->lower_xyuv_external) {
1450bf215546Sopenharmony_ci         lower_xyuv_external(b, tex, options, texture_index);
1451bf215546Sopenharmony_ci         progress = true;
1452bf215546Sopenharmony_ci      }
1453bf215546Sopenharmony_ci
1454bf215546Sopenharmony_ci      if (texture_mask & options->lower_yuv_external) {
1455bf215546Sopenharmony_ci         lower_yuv_external(b, tex, options, texture_index);
1456bf215546Sopenharmony_ci         progress = true;
1457bf215546Sopenharmony_ci      }
1458bf215546Sopenharmony_ci
1459bf215546Sopenharmony_ci      if ((1 << tex->texture_index) & options->lower_yu_yv_external) {
1460bf215546Sopenharmony_ci         lower_yu_yv_external(b, tex, options, texture_index);
1461bf215546Sopenharmony_ci         progress = true;
1462bf215546Sopenharmony_ci      }
1463bf215546Sopenharmony_ci
1464bf215546Sopenharmony_ci      if ((1 << tex->texture_index) & options->lower_y41x_external) {
1465bf215546Sopenharmony_ci         lower_y41x_external(b, tex, options, texture_index);
1466bf215546Sopenharmony_ci         progress = true;
1467bf215546Sopenharmony_ci      }
1468bf215546Sopenharmony_ci
1469bf215546Sopenharmony_ci      if (sat_mask) {
1470bf215546Sopenharmony_ci         tex = saturate_src(b, tex, sat_mask);
1471bf215546Sopenharmony_ci         progress = true;
1472bf215546Sopenharmony_ci      }
1473bf215546Sopenharmony_ci
1474bf215546Sopenharmony_ci      if (tex->op == nir_texop_tg4 && options->lower_tg4_broadcom_swizzle) {
1475bf215546Sopenharmony_ci         swizzle_tg4_broadcom(b, tex);
1476bf215546Sopenharmony_ci         progress = true;
1477bf215546Sopenharmony_ci      }
1478bf215546Sopenharmony_ci
1479bf215546Sopenharmony_ci      if ((texture_mask & options->swizzle_result) &&
1480bf215546Sopenharmony_ci          !nir_tex_instr_is_query(tex) &&
1481bf215546Sopenharmony_ci          !(tex->is_shadow && tex->is_new_style_shadow)) {
1482bf215546Sopenharmony_ci         swizzle_result(b, tex, options->swizzles[tex->texture_index]);
1483bf215546Sopenharmony_ci         progress = true;
1484bf215546Sopenharmony_ci      }
1485bf215546Sopenharmony_ci
1486bf215546Sopenharmony_ci      /* should be after swizzle so we know which channels are rgb: */
1487bf215546Sopenharmony_ci      if ((texture_mask & options->lower_srgb) &&
1488bf215546Sopenharmony_ci          !nir_tex_instr_is_query(tex) && !tex->is_shadow) {
1489bf215546Sopenharmony_ci         linearize_srgb_result(b, tex);
1490bf215546Sopenharmony_ci         progress = true;
1491bf215546Sopenharmony_ci      }
1492bf215546Sopenharmony_ci
1493bf215546Sopenharmony_ci      const bool has_min_lod =
1494bf215546Sopenharmony_ci         nir_tex_instr_src_index(tex, nir_tex_src_min_lod) >= 0;
1495bf215546Sopenharmony_ci      const bool has_offset =
1496bf215546Sopenharmony_ci         nir_tex_instr_src_index(tex, nir_tex_src_offset) >= 0;
1497bf215546Sopenharmony_ci
1498bf215546Sopenharmony_ci      if (tex->op == nir_texop_txb && tex->is_shadow && has_min_lod &&
1499bf215546Sopenharmony_ci          options->lower_txb_shadow_clamp) {
1500bf215546Sopenharmony_ci         lower_implicit_lod(b, tex);
1501bf215546Sopenharmony_ci         progress = true;
1502bf215546Sopenharmony_ci      }
1503bf215546Sopenharmony_ci
1504bf215546Sopenharmony_ci      if (options->lower_tex_packing[tex->sampler_index] !=
1505bf215546Sopenharmony_ci          nir_lower_tex_packing_none &&
1506bf215546Sopenharmony_ci          tex->op != nir_texop_txs &&
1507bf215546Sopenharmony_ci          tex->op != nir_texop_query_levels &&
1508bf215546Sopenharmony_ci          tex->op != nir_texop_texture_samples) {
1509bf215546Sopenharmony_ci         lower_tex_packing(b, tex, options);
1510bf215546Sopenharmony_ci         progress = true;
1511bf215546Sopenharmony_ci      }
1512bf215546Sopenharmony_ci
1513bf215546Sopenharmony_ci      if (options->lower_array_layer_round_even && tex->is_array &&
1514bf215546Sopenharmony_ci          tex->op != nir_texop_lod) {
1515bf215546Sopenharmony_ci         progress |= lower_array_layer_round_even(b, tex);
1516bf215546Sopenharmony_ci      }
1517bf215546Sopenharmony_ci
1518bf215546Sopenharmony_ci      if (tex->op == nir_texop_txd &&
1519bf215546Sopenharmony_ci          (options->lower_txd ||
1520bf215546Sopenharmony_ci           (options->lower_txd_shadow && tex->is_shadow) ||
1521bf215546Sopenharmony_ci           (options->lower_txd_shadow_clamp && tex->is_shadow && has_min_lod) ||
1522bf215546Sopenharmony_ci           (options->lower_txd_offset_clamp && has_offset && has_min_lod) ||
1523bf215546Sopenharmony_ci           (options->lower_txd_clamp_bindless_sampler && has_min_lod &&
1524bf215546Sopenharmony_ci            nir_tex_instr_src_index(tex, nir_tex_src_sampler_handle) != -1) ||
1525bf215546Sopenharmony_ci           (options->lower_txd_clamp_if_sampler_index_not_lt_16 &&
1526bf215546Sopenharmony_ci            has_min_lod && !sampler_index_lt(tex, 16)) ||
1527bf215546Sopenharmony_ci           (options->lower_txd_cube_map &&
1528bf215546Sopenharmony_ci            tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE) ||
1529bf215546Sopenharmony_ci           (options->lower_txd_3d &&
1530bf215546Sopenharmony_ci            tex->sampler_dim == GLSL_SAMPLER_DIM_3D) ||
1531bf215546Sopenharmony_ci           (options->lower_txd_array && tex->is_array))) {
1532bf215546Sopenharmony_ci         lower_gradient(b, tex);
1533bf215546Sopenharmony_ci         progress = true;
1534bf215546Sopenharmony_ci         continue;
1535bf215546Sopenharmony_ci      }
1536bf215546Sopenharmony_ci
1537bf215546Sopenharmony_ci      /* TXF, TXS and TXL require a LOD but not everything we implement using those
1538bf215546Sopenharmony_ci       * three opcodes provides one.  Provide a default LOD of 0.
1539bf215546Sopenharmony_ci       */
1540bf215546Sopenharmony_ci      if ((nir_tex_instr_src_index(tex, nir_tex_src_lod) == -1) &&
1541bf215546Sopenharmony_ci          (tex->op == nir_texop_txf || tex->op == nir_texop_txs ||
1542bf215546Sopenharmony_ci           tex->op == nir_texop_txl || tex->op == nir_texop_query_levels)) {
1543bf215546Sopenharmony_ci         b->cursor = nir_before_instr(&tex->instr);
1544bf215546Sopenharmony_ci         nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(nir_imm_int(b, 0)));
1545bf215546Sopenharmony_ci         progress = true;
1546bf215546Sopenharmony_ci         continue;
1547bf215546Sopenharmony_ci      }
1548bf215546Sopenharmony_ci
1549bf215546Sopenharmony_ci      /* Only fragment and compute (in some cases) support implicit
1550bf215546Sopenharmony_ci       * derivatives.  Lower those opcodes which use implicit derivatives to
1551bf215546Sopenharmony_ci       * use an explicit LOD of 0.
1552bf215546Sopenharmony_ci       * But don't touch RECT samplers because they don't have mips.
1553bf215546Sopenharmony_ci       */
1554bf215546Sopenharmony_ci      if (options->lower_invalid_implicit_lod &&
1555bf215546Sopenharmony_ci          nir_tex_instr_has_implicit_derivative(tex) &&
1556bf215546Sopenharmony_ci          tex->sampler_dim != GLSL_SAMPLER_DIM_RECT &&
1557bf215546Sopenharmony_ci          !nir_shader_supports_implicit_lod(b->shader)) {
1558bf215546Sopenharmony_ci         lower_zero_lod(b, tex);
1559bf215546Sopenharmony_ci         progress = true;
1560bf215546Sopenharmony_ci      }
1561bf215546Sopenharmony_ci
1562bf215546Sopenharmony_ci      if (options->lower_txs_lod && tex->op == nir_texop_txs) {
1563bf215546Sopenharmony_ci         progress |= nir_lower_txs_lod(b, tex);
1564bf215546Sopenharmony_ci         continue;
1565bf215546Sopenharmony_ci      }
1566bf215546Sopenharmony_ci
1567bf215546Sopenharmony_ci      if (options->lower_txs_cube_array && tex->op == nir_texop_txs &&
1568bf215546Sopenharmony_ci          tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE && tex->is_array) {
1569bf215546Sopenharmony_ci         nir_lower_txs_cube_array(b, tex);
1570bf215546Sopenharmony_ci         progress = true;
1571bf215546Sopenharmony_ci         continue;
1572bf215546Sopenharmony_ci      }
1573bf215546Sopenharmony_ci
1574bf215546Sopenharmony_ci      /* has to happen after all the other lowerings as the original tg4 gets
1575bf215546Sopenharmony_ci       * replaced by 4 tg4 instructions.
1576bf215546Sopenharmony_ci       */
1577bf215546Sopenharmony_ci      if (tex->op == nir_texop_tg4 &&
1578bf215546Sopenharmony_ci          nir_tex_instr_has_explicit_tg4_offsets(tex) &&
1579bf215546Sopenharmony_ci          options->lower_tg4_offsets) {
1580bf215546Sopenharmony_ci         progress |= lower_tg4_offsets(b, tex);
1581bf215546Sopenharmony_ci         continue;
1582bf215546Sopenharmony_ci      }
1583bf215546Sopenharmony_ci
1584bf215546Sopenharmony_ci      if (options->lower_to_fragment_fetch_amd && tex->op == nir_texop_txf_ms) {
1585bf215546Sopenharmony_ci         nir_lower_ms_txf_to_fragment_fetch(b, tex);
1586bf215546Sopenharmony_ci         progress = true;
1587bf215546Sopenharmony_ci         continue;
1588bf215546Sopenharmony_ci      }
1589bf215546Sopenharmony_ci
1590bf215546Sopenharmony_ci      if (options->lower_to_fragment_fetch_amd && tex->op == nir_texop_samples_identical) {
1591bf215546Sopenharmony_ci         nir_lower_samples_identical_to_fragment_fetch(b, tex);
1592bf215546Sopenharmony_ci         progress = true;
1593bf215546Sopenharmony_ci         continue;
1594bf215546Sopenharmony_ci      }
1595bf215546Sopenharmony_ci
1596bf215546Sopenharmony_ci      if (options->lower_lod_zero_width && tex->op == nir_texop_lod) {
1597bf215546Sopenharmony_ci         nir_lower_lod_zero_width(b, tex);
1598bf215546Sopenharmony_ci         progress = true;
1599bf215546Sopenharmony_ci         continue;
1600bf215546Sopenharmony_ci      }
1601bf215546Sopenharmony_ci   }
1602bf215546Sopenharmony_ci
1603bf215546Sopenharmony_ci   return progress;
1604bf215546Sopenharmony_ci}
1605bf215546Sopenharmony_ci
1606bf215546Sopenharmony_cistatic bool
1607bf215546Sopenharmony_cinir_lower_tex_impl(nir_function_impl *impl,
1608bf215546Sopenharmony_ci                   const nir_lower_tex_options *options,
1609bf215546Sopenharmony_ci                   const struct nir_shader_compiler_options *compiler_options)
1610bf215546Sopenharmony_ci{
1611bf215546Sopenharmony_ci   bool progress = false;
1612bf215546Sopenharmony_ci   nir_builder builder;
1613bf215546Sopenharmony_ci   nir_builder_init(&builder, impl);
1614bf215546Sopenharmony_ci
1615bf215546Sopenharmony_ci   nir_foreach_block(block, impl) {
1616bf215546Sopenharmony_ci      progress |= nir_lower_tex_block(block, &builder, options, compiler_options);
1617bf215546Sopenharmony_ci   }
1618bf215546Sopenharmony_ci
1619bf215546Sopenharmony_ci   nir_metadata_preserve(impl, nir_metadata_block_index |
1620bf215546Sopenharmony_ci                               nir_metadata_dominance);
1621bf215546Sopenharmony_ci   return progress;
1622bf215546Sopenharmony_ci}
1623bf215546Sopenharmony_ci
1624bf215546Sopenharmony_cibool
1625bf215546Sopenharmony_cinir_lower_tex(nir_shader *shader, const nir_lower_tex_options *options)
1626bf215546Sopenharmony_ci{
1627bf215546Sopenharmony_ci   bool progress = false;
1628bf215546Sopenharmony_ci
1629bf215546Sopenharmony_ci   nir_foreach_function(function, shader) {
1630bf215546Sopenharmony_ci      if (function->impl)
1631bf215546Sopenharmony_ci         progress |= nir_lower_tex_impl(function->impl, options, shader->options);
1632bf215546Sopenharmony_ci   }
1633bf215546Sopenharmony_ci
1634bf215546Sopenharmony_ci   return progress;
1635bf215546Sopenharmony_ci}
1636