nir/builder: Remove the use_fmov parameter from nir_swizzle
[mesa.git] / src / compiler / nir / nir_lower_tex.c
1 /*
2 * Copyright © 2015 Broadcom
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 /*
25 * This lowering pass supports (as configured via nir_lower_tex_options)
26 * various texture related conversions:
27 * + texture projector lowering: converts the coordinate division for
28 * texture projection to be done in ALU instructions instead of
29 * asking the texture operation to do so.
30 * + lowering RECT: converts the un-normalized RECT texture coordinates
31 * to normalized coordinates with txs plus ALU instructions
32 * + saturate s/t/r coords: to emulate certain texture clamp/wrap modes,
33 * inserts instructions to clamp specified coordinates to [0.0, 1.0].
34 * Note that this automatically triggers texture projector lowering if
35 * needed, since clamping must happen after projector lowering.
36 */
37
38 #include "nir.h"
39 #include "nir_builder.h"
40 #include "nir_format_convert.h"
41
42 static void
43 project_src(nir_builder *b, nir_tex_instr *tex)
44 {
45 /* Find the projector in the srcs list, if present. */
46 int proj_index = nir_tex_instr_src_index(tex, nir_tex_src_projector);
47 if (proj_index < 0)
48 return;
49
50 b->cursor = nir_before_instr(&tex->instr);
51
52 nir_ssa_def *inv_proj =
53 nir_frcp(b, nir_ssa_for_src(b, tex->src[proj_index].src, 1));
54
55 /* Walk through the sources projecting the arguments. */
56 for (unsigned i = 0; i < tex->num_srcs; i++) {
57 switch (tex->src[i].src_type) {
58 case nir_tex_src_coord:
59 case nir_tex_src_comparator:
60 break;
61 default:
62 continue;
63 }
64 nir_ssa_def *unprojected =
65 nir_ssa_for_src(b, tex->src[i].src, nir_tex_instr_src_size(tex, i));
66 nir_ssa_def *projected = nir_fmul(b, unprojected, inv_proj);
67
68 /* Array indices don't get projected, so make an new vector with the
69 * coordinate's array index untouched.
70 */
71 if (tex->is_array && tex->src[i].src_type == nir_tex_src_coord) {
72 switch (tex->coord_components) {
73 case 4:
74 projected = nir_vec4(b,
75 nir_channel(b, projected, 0),
76 nir_channel(b, projected, 1),
77 nir_channel(b, projected, 2),
78 nir_channel(b, unprojected, 3));
79 break;
80 case 3:
81 projected = nir_vec3(b,
82 nir_channel(b, projected, 0),
83 nir_channel(b, projected, 1),
84 nir_channel(b, unprojected, 2));
85 break;
86 case 2:
87 projected = nir_vec2(b,
88 nir_channel(b, projected, 0),
89 nir_channel(b, unprojected, 1));
90 break;
91 default:
92 unreachable("bad texture coord count for array");
93 break;
94 }
95 }
96
97 nir_instr_rewrite_src(&tex->instr,
98 &tex->src[i].src,
99 nir_src_for_ssa(projected));
100 }
101
102 nir_tex_instr_remove_src(tex, proj_index);
103 }
104
105 static nir_ssa_def *
106 get_texture_size(nir_builder *b, nir_tex_instr *tex)
107 {
108 b->cursor = nir_before_instr(&tex->instr);
109
110 nir_tex_instr *txs;
111
112 unsigned num_srcs = 1; /* One for the LOD */
113 for (unsigned i = 0; i < tex->num_srcs; i++) {
114 if (tex->src[i].src_type == nir_tex_src_texture_deref ||
115 tex->src[i].src_type == nir_tex_src_sampler_deref ||
116 tex->src[i].src_type == nir_tex_src_texture_offset ||
117 tex->src[i].src_type == nir_tex_src_sampler_offset ||
118 tex->src[i].src_type == nir_tex_src_texture_handle ||
119 tex->src[i].src_type == nir_tex_src_sampler_handle)
120 num_srcs++;
121 }
122
123 txs = nir_tex_instr_create(b->shader, num_srcs);
124 txs->op = nir_texop_txs;
125 txs->sampler_dim = tex->sampler_dim;
126 txs->is_array = tex->is_array;
127 txs->is_shadow = tex->is_shadow;
128 txs->is_new_style_shadow = tex->is_new_style_shadow;
129 txs->texture_index = tex->texture_index;
130 txs->sampler_index = tex->sampler_index;
131 txs->dest_type = nir_type_int;
132
133 unsigned idx = 0;
134 for (unsigned i = 0; i < tex->num_srcs; i++) {
135 if (tex->src[i].src_type == nir_tex_src_texture_deref ||
136 tex->src[i].src_type == nir_tex_src_sampler_deref ||
137 tex->src[i].src_type == nir_tex_src_texture_offset ||
138 tex->src[i].src_type == nir_tex_src_sampler_offset ||
139 tex->src[i].src_type == nir_tex_src_texture_handle ||
140 tex->src[i].src_type == nir_tex_src_sampler_handle) {
141 nir_src_copy(&txs->src[idx].src, &tex->src[i].src, txs);
142 txs->src[idx].src_type = tex->src[i].src_type;
143 idx++;
144 }
145 }
146 /* Add in an LOD because some back-ends require it */
147 txs->src[idx].src = nir_src_for_ssa(nir_imm_int(b, 0));
148 txs->src[idx].src_type = nir_tex_src_lod;
149
150 nir_ssa_dest_init(&txs->instr, &txs->dest,
151 nir_tex_instr_dest_size(txs), 32, NULL);
152 nir_builder_instr_insert(b, &txs->instr);
153
154 return nir_i2f32(b, &txs->dest.ssa);
155 }
156
157 static nir_ssa_def *
158 get_texture_lod(nir_builder *b, nir_tex_instr *tex)
159 {
160 b->cursor = nir_before_instr(&tex->instr);
161
162 nir_tex_instr *tql;
163
164 unsigned num_srcs = 0;
165 for (unsigned i = 0; i < tex->num_srcs; i++) {
166 if (tex->src[i].src_type == nir_tex_src_coord ||
167 tex->src[i].src_type == nir_tex_src_texture_deref ||
168 tex->src[i].src_type == nir_tex_src_sampler_deref ||
169 tex->src[i].src_type == nir_tex_src_texture_offset ||
170 tex->src[i].src_type == nir_tex_src_sampler_offset ||
171 tex->src[i].src_type == nir_tex_src_texture_handle ||
172 tex->src[i].src_type == nir_tex_src_sampler_handle)
173 num_srcs++;
174 }
175
176 tql = nir_tex_instr_create(b->shader, num_srcs);
177 tql->op = nir_texop_lod;
178 tql->coord_components = tex->coord_components;
179 tql->sampler_dim = tex->sampler_dim;
180 tql->is_array = tex->is_array;
181 tql->is_shadow = tex->is_shadow;
182 tql->is_new_style_shadow = tex->is_new_style_shadow;
183 tql->texture_index = tex->texture_index;
184 tql->sampler_index = tex->sampler_index;
185 tql->dest_type = nir_type_float;
186
187 unsigned idx = 0;
188 for (unsigned i = 0; i < tex->num_srcs; i++) {
189 if (tex->src[i].src_type == nir_tex_src_coord ||
190 tex->src[i].src_type == nir_tex_src_texture_deref ||
191 tex->src[i].src_type == nir_tex_src_sampler_deref ||
192 tex->src[i].src_type == nir_tex_src_texture_offset ||
193 tex->src[i].src_type == nir_tex_src_sampler_offset ||
194 tex->src[i].src_type == nir_tex_src_texture_handle ||
195 tex->src[i].src_type == nir_tex_src_sampler_handle) {
196 nir_src_copy(&tql->src[idx].src, &tex->src[i].src, tql);
197 tql->src[idx].src_type = tex->src[i].src_type;
198 idx++;
199 }
200 }
201
202 nir_ssa_dest_init(&tql->instr, &tql->dest, 2, 32, NULL);
203 nir_builder_instr_insert(b, &tql->instr);
204
205 /* The LOD is the y component of the result */
206 return nir_channel(b, &tql->dest.ssa, 1);
207 }
208
209 static bool
210 lower_offset(nir_builder *b, nir_tex_instr *tex)
211 {
212 int offset_index = nir_tex_instr_src_index(tex, nir_tex_src_offset);
213 if (offset_index < 0)
214 return false;
215
216 int coord_index = nir_tex_instr_src_index(tex, nir_tex_src_coord);
217 assert(coord_index >= 0);
218
219 assert(tex->src[offset_index].src.is_ssa);
220 assert(tex->src[coord_index].src.is_ssa);
221 nir_ssa_def *offset = tex->src[offset_index].src.ssa;
222 nir_ssa_def *coord = tex->src[coord_index].src.ssa;
223
224 b->cursor = nir_before_instr(&tex->instr);
225
226 nir_ssa_def *offset_coord;
227 if (nir_tex_instr_src_type(tex, coord_index) == nir_type_float) {
228 if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
229 offset_coord = nir_fadd(b, coord, nir_i2f32(b, offset));
230 } else {
231 nir_ssa_def *txs = get_texture_size(b, tex);
232 nir_ssa_def *scale = nir_frcp(b, txs);
233
234 offset_coord = nir_fadd(b, coord,
235 nir_fmul(b,
236 nir_i2f32(b, offset),
237 scale));
238 }
239 } else {
240 offset_coord = nir_iadd(b, coord, offset);
241 }
242
243 if (tex->is_array) {
244 /* The offset is not applied to the array index */
245 if (tex->coord_components == 2) {
246 offset_coord = nir_vec2(b, nir_channel(b, offset_coord, 0),
247 nir_channel(b, coord, 1));
248 } else if (tex->coord_components == 3) {
249 offset_coord = nir_vec3(b, nir_channel(b, offset_coord, 0),
250 nir_channel(b, offset_coord, 1),
251 nir_channel(b, coord, 2));
252 } else {
253 unreachable("Invalid number of components");
254 }
255 }
256
257 nir_instr_rewrite_src(&tex->instr, &tex->src[coord_index].src,
258 nir_src_for_ssa(offset_coord));
259
260 nir_tex_instr_remove_src(tex, offset_index);
261
262 return true;
263 }
264
265 static void
266 lower_rect(nir_builder *b, nir_tex_instr *tex)
267 {
268 nir_ssa_def *txs = get_texture_size(b, tex);
269 nir_ssa_def *scale = nir_frcp(b, txs);
270
271 /* Walk through the sources normalizing the requested arguments. */
272 for (unsigned i = 0; i < tex->num_srcs; i++) {
273 if (tex->src[i].src_type != nir_tex_src_coord)
274 continue;
275
276 nir_ssa_def *coords =
277 nir_ssa_for_src(b, tex->src[i].src, tex->coord_components);
278 nir_instr_rewrite_src(&tex->instr,
279 &tex->src[i].src,
280 nir_src_for_ssa(nir_fmul(b, coords, scale)));
281 }
282
283 tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
284 }
285
286 static void
287 lower_implicit_lod(nir_builder *b, nir_tex_instr *tex)
288 {
289 assert(tex->op == nir_texop_tex || tex->op == nir_texop_txb);
290 assert(nir_tex_instr_src_index(tex, nir_tex_src_lod) < 0);
291 assert(nir_tex_instr_src_index(tex, nir_tex_src_ddx) < 0);
292 assert(nir_tex_instr_src_index(tex, nir_tex_src_ddy) < 0);
293
294 b->cursor = nir_before_instr(&tex->instr);
295
296 nir_ssa_def *lod = get_texture_lod(b, tex);
297
298 int bias_idx = nir_tex_instr_src_index(tex, nir_tex_src_bias);
299 if (bias_idx >= 0) {
300 /* If we have a bias, add it in */
301 lod = nir_fadd(b, lod, nir_ssa_for_src(b, tex->src[bias_idx].src, 1));
302 nir_tex_instr_remove_src(tex, bias_idx);
303 }
304
305 int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
306 if (min_lod_idx >= 0) {
307 /* If we have a minimum LOD, clamp LOD accordingly */
308 lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
309 nir_tex_instr_remove_src(tex, min_lod_idx);
310 }
311
312 nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
313 tex->op = nir_texop_txl;
314 }
315
316 static nir_ssa_def *
317 sample_plane(nir_builder *b, nir_tex_instr *tex, int plane,
318 const nir_lower_tex_options *options)
319 {
320 assert(tex->dest.is_ssa);
321 assert(nir_tex_instr_dest_size(tex) == 4);
322 assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
323 assert(tex->op == nir_texop_tex);
324 assert(tex->coord_components == 2);
325
326 nir_tex_instr *plane_tex =
327 nir_tex_instr_create(b->shader, tex->num_srcs + 1);
328 for (unsigned i = 0; i < tex->num_srcs; i++) {
329 nir_src_copy(&plane_tex->src[i].src, &tex->src[i].src, plane_tex);
330 plane_tex->src[i].src_type = tex->src[i].src_type;
331 }
332 plane_tex->src[tex->num_srcs].src = nir_src_for_ssa(nir_imm_int(b, plane));
333 plane_tex->src[tex->num_srcs].src_type = nir_tex_src_plane;
334 plane_tex->op = nir_texop_tex;
335 plane_tex->sampler_dim = GLSL_SAMPLER_DIM_2D;
336 plane_tex->dest_type = nir_type_float;
337 plane_tex->coord_components = 2;
338
339 plane_tex->texture_index = tex->texture_index;
340 plane_tex->sampler_index = tex->sampler_index;
341
342 nir_ssa_dest_init(&plane_tex->instr, &plane_tex->dest, 4, 32, NULL);
343
344 nir_builder_instr_insert(b, &plane_tex->instr);
345
346 /* If scaling_factor is set, return a scaled value. */
347 if (options->scale_factors[tex->texture_index])
348 return nir_fmul_imm(b, &plane_tex->dest.ssa,
349 options->scale_factors[tex->texture_index]);
350
351 return &plane_tex->dest.ssa;
352 }
353
354 static void
355 convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex,
356 nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v,
357 nir_ssa_def *a)
358 {
359 nir_const_value m[3][4] = {
360 { { .f32 = 1.16438356f }, { .f32 = 1.16438356f }, { .f32 = 1.16438356f }, { .f32 = 0.0f } },
361 { { .f32 = 0.0f }, { .f32 = -0.39176229f }, { .f32 = 2.01723214f }, { .f32 = 0.0f } },
362 { { .f32 = 1.59602678f }, { .f32 = -0.81296764f }, { .f32 = 0.0f }, { .f32 = 0.0f } },
363 };
364
365 nir_ssa_def *offset =
366 nir_vec4(b,
367 nir_imm_float(b, -0.874202214f),
368 nir_imm_float(b, 0.531667820f),
369 nir_imm_float(b, -1.085630787f),
370 a);
371
372 nir_ssa_def *result =
373 nir_ffma(b, y, nir_build_imm(b, 4, 32, m[0]),
374 nir_ffma(b, u, nir_build_imm(b, 4, 32, m[1]),
375 nir_ffma(b, v, nir_build_imm(b, 4, 32, m[2]),
376 offset)));
377
378 nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_src_for_ssa(result));
379 }
380
381 static void
382 lower_y_uv_external(nir_builder *b, nir_tex_instr *tex,
383 const nir_lower_tex_options *options)
384 {
385 b->cursor = nir_after_instr(&tex->instr);
386
387 nir_ssa_def *y = sample_plane(b, tex, 0, options);
388 nir_ssa_def *uv = sample_plane(b, tex, 1, options);
389
390 convert_yuv_to_rgb(b, tex,
391 nir_channel(b, y, 0),
392 nir_channel(b, uv, 0),
393 nir_channel(b, uv, 1),
394 nir_imm_float(b, 1.0f));
395 }
396
397 static void
398 lower_y_u_v_external(nir_builder *b, nir_tex_instr *tex,
399 const nir_lower_tex_options *options)
400 {
401 b->cursor = nir_after_instr(&tex->instr);
402
403 nir_ssa_def *y = sample_plane(b, tex, 0, options);
404 nir_ssa_def *u = sample_plane(b, tex, 1, options);
405 nir_ssa_def *v = sample_plane(b, tex, 2, options);
406
407 convert_yuv_to_rgb(b, tex,
408 nir_channel(b, y, 0),
409 nir_channel(b, u, 0),
410 nir_channel(b, v, 0),
411 nir_imm_float(b, 1.0f));
412 }
413
414 static void
415 lower_yx_xuxv_external(nir_builder *b, nir_tex_instr *tex,
416 const nir_lower_tex_options *options)
417 {
418 b->cursor = nir_after_instr(&tex->instr);
419
420 nir_ssa_def *y = sample_plane(b, tex, 0, options);
421 nir_ssa_def *xuxv = sample_plane(b, tex, 1, options);
422
423 convert_yuv_to_rgb(b, tex,
424 nir_channel(b, y, 0),
425 nir_channel(b, xuxv, 1),
426 nir_channel(b, xuxv, 3),
427 nir_imm_float(b, 1.0f));
428 }
429
430 static void
431 lower_xy_uxvx_external(nir_builder *b, nir_tex_instr *tex,
432 const nir_lower_tex_options *options)
433 {
434 b->cursor = nir_after_instr(&tex->instr);
435
436 nir_ssa_def *y = sample_plane(b, tex, 0, options);
437 nir_ssa_def *uxvx = sample_plane(b, tex, 1, options);
438
439 convert_yuv_to_rgb(b, tex,
440 nir_channel(b, y, 1),
441 nir_channel(b, uxvx, 0),
442 nir_channel(b, uxvx, 2),
443 nir_imm_float(b, 1.0f));
444 }
445
446 static void
447 lower_ayuv_external(nir_builder *b, nir_tex_instr *tex,
448 const nir_lower_tex_options *options)
449 {
450 b->cursor = nir_after_instr(&tex->instr);
451
452 nir_ssa_def *ayuv = sample_plane(b, tex, 0, options);
453
454 convert_yuv_to_rgb(b, tex,
455 nir_channel(b, ayuv, 2),
456 nir_channel(b, ayuv, 1),
457 nir_channel(b, ayuv, 0),
458 nir_channel(b, ayuv, 3));
459 }
460
461 static void
462 lower_xyuv_external(nir_builder *b, nir_tex_instr *tex,
463 const nir_lower_tex_options *options)
464 {
465 b->cursor = nir_after_instr(&tex->instr);
466
467 nir_ssa_def *xyuv = sample_plane(b, tex, 0, options);
468
469 convert_yuv_to_rgb(b, tex,
470 nir_channel(b, xyuv, 2),
471 nir_channel(b, xyuv, 1),
472 nir_channel(b, xyuv, 0),
473 nir_imm_float(b, 1.0f));
474 }
475
476 /*
477 * Converts a nir_texop_txd instruction to nir_texop_txl with the given lod
478 * computed from the gradients.
479 */
480 static void
481 replace_gradient_with_lod(nir_builder *b, nir_ssa_def *lod, nir_tex_instr *tex)
482 {
483 assert(tex->op == nir_texop_txd);
484
485 nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddx));
486 nir_tex_instr_remove_src(tex, nir_tex_instr_src_index(tex, nir_tex_src_ddy));
487
488 int min_lod_idx = nir_tex_instr_src_index(tex, nir_tex_src_min_lod);
489 if (min_lod_idx >= 0) {
490 /* If we have a minimum LOD, clamp LOD accordingly */
491 lod = nir_fmax(b, lod, nir_ssa_for_src(b, tex->src[min_lod_idx].src, 1));
492 nir_tex_instr_remove_src(tex, min_lod_idx);
493 }
494
495 nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(lod));
496 tex->op = nir_texop_txl;
497 }
498
499 static void
500 lower_gradient_cube_map(nir_builder *b, nir_tex_instr *tex)
501 {
502 assert(tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE);
503 assert(tex->op == nir_texop_txd);
504 assert(tex->dest.is_ssa);
505
506 /* Use textureSize() to get the width and height of LOD 0 */
507 nir_ssa_def *size = get_texture_size(b, tex);
508
509 /* Cubemap texture lookups first generate a texture coordinate normalized
510 * to [-1, 1] on the appropiate face. The appropiate face is determined
511 * by which component has largest magnitude and its sign. The texture
512 * coordinate is the quotient of the remaining texture coordinates against
513 * that absolute value of the component of largest magnitude. This
514 * division requires that the computing of the derivative of the texel
515 * coordinate must use the quotient rule. The high level GLSL code is as
516 * follows:
517 *
518 * Step 1: selection
519 *
520 * vec3 abs_p, Q, dQdx, dQdy;
521 * abs_p = abs(ir->coordinate);
522 * if (abs_p.x >= max(abs_p.y, abs_p.z)) {
523 * Q = ir->coordinate.yzx;
524 * dQdx = ir->lod_info.grad.dPdx.yzx;
525 * dQdy = ir->lod_info.grad.dPdy.yzx;
526 * }
527 * if (abs_p.y >= max(abs_p.x, abs_p.z)) {
528 * Q = ir->coordinate.xzy;
529 * dQdx = ir->lod_info.grad.dPdx.xzy;
530 * dQdy = ir->lod_info.grad.dPdy.xzy;
531 * }
532 * if (abs_p.z >= max(abs_p.x, abs_p.y)) {
533 * Q = ir->coordinate;
534 * dQdx = ir->lod_info.grad.dPdx;
535 * dQdy = ir->lod_info.grad.dPdy;
536 * }
537 *
538 * Step 2: use quotient rule to compute derivative. The normalized to
539 * [-1, 1] texel coordinate is given by Q.xy / (sign(Q.z) * Q.z). We are
540 * only concerned with the magnitudes of the derivatives whose values are
541 * not affected by the sign. We drop the sign from the computation.
542 *
543 * vec2 dx, dy;
544 * float recip;
545 *
546 * recip = 1.0 / Q.z;
547 * dx = recip * ( dQdx.xy - Q.xy * (dQdx.z * recip) );
548 * dy = recip * ( dQdy.xy - Q.xy * (dQdy.z * recip) );
549 *
550 * Step 3: compute LOD. At this point we have the derivatives of the
551 * texture coordinates normalized to [-1,1]. We take the LOD to be
552 * result = log2(max(sqrt(dot(dx, dx)), sqrt(dy, dy)) * 0.5 * L)
553 * = -1.0 + log2(max(sqrt(dot(dx, dx)), sqrt(dy, dy)) * L)
554 * = -1.0 + log2(sqrt(max(dot(dx, dx), dot(dy,dy))) * L)
555 * = -1.0 + log2(sqrt(L * L * max(dot(dx, dx), dot(dy,dy))))
556 * = -1.0 + 0.5 * log2(L * L * max(dot(dx, dx), dot(dy,dy)))
557 * where L is the dimension of the cubemap. The code is:
558 *
559 * float M, result;
560 * M = max(dot(dx, dx), dot(dy, dy));
561 * L = textureSize(sampler, 0).x;
562 * result = -1.0 + 0.5 * log2(L * L * M);
563 */
564
565 /* coordinate */
566 nir_ssa_def *p =
567 tex->src[nir_tex_instr_src_index(tex, nir_tex_src_coord)].src.ssa;
568
569 /* unmodified dPdx, dPdy values */
570 nir_ssa_def *dPdx =
571 tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddx)].src.ssa;
572 nir_ssa_def *dPdy =
573 tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddy)].src.ssa;
574
575 nir_ssa_def *abs_p = nir_fabs(b, p);
576 nir_ssa_def *abs_p_x = nir_channel(b, abs_p, 0);
577 nir_ssa_def *abs_p_y = nir_channel(b, abs_p, 1);
578 nir_ssa_def *abs_p_z = nir_channel(b, abs_p, 2);
579
580 /* 1. compute selector */
581 nir_ssa_def *Q, *dQdx, *dQdy;
582
583 nir_ssa_def *cond_z = nir_fge(b, abs_p_z, nir_fmax(b, abs_p_x, abs_p_y));
584 nir_ssa_def *cond_y = nir_fge(b, abs_p_y, nir_fmax(b, abs_p_x, abs_p_z));
585
586 unsigned yzx[3] = { 1, 2, 0 };
587 unsigned xzy[3] = { 0, 2, 1 };
588
589 Q = nir_bcsel(b, cond_z,
590 p,
591 nir_bcsel(b, cond_y,
592 nir_swizzle(b, p, xzy, 3),
593 nir_swizzle(b, p, yzx, 3)));
594
595 dQdx = nir_bcsel(b, cond_z,
596 dPdx,
597 nir_bcsel(b, cond_y,
598 nir_swizzle(b, dPdx, xzy, 3),
599 nir_swizzle(b, dPdx, yzx, 3)));
600
601 dQdy = nir_bcsel(b, cond_z,
602 dPdy,
603 nir_bcsel(b, cond_y,
604 nir_swizzle(b, dPdy, xzy, 3),
605 nir_swizzle(b, dPdy, yzx, 3)));
606
607 /* 2. quotient rule */
608
609 /* tmp = Q.xy * recip;
610 * dx = recip * ( dQdx.xy - (tmp * dQdx.z) );
611 * dy = recip * ( dQdy.xy - (tmp * dQdy.z) );
612 */
613 nir_ssa_def *rcp_Q_z = nir_frcp(b, nir_channel(b, Q, 2));
614
615 nir_ssa_def *Q_xy = nir_channels(b, Q, 0x3);
616 nir_ssa_def *tmp = nir_fmul(b, Q_xy, rcp_Q_z);
617
618 nir_ssa_def *dQdx_xy = nir_channels(b, dQdx, 0x3);
619 nir_ssa_def *dQdx_z = nir_channel(b, dQdx, 2);
620 nir_ssa_def *dx =
621 nir_fmul(b, rcp_Q_z, nir_fsub(b, dQdx_xy, nir_fmul(b, tmp, dQdx_z)));
622
623 nir_ssa_def *dQdy_xy = nir_channels(b, dQdy, 0x3);
624 nir_ssa_def *dQdy_z = nir_channel(b, dQdy, 2);
625 nir_ssa_def *dy =
626 nir_fmul(b, rcp_Q_z, nir_fsub(b, dQdy_xy, nir_fmul(b, tmp, dQdy_z)));
627
628 /* M = max(dot(dx, dx), dot(dy, dy)); */
629 nir_ssa_def *M = nir_fmax(b, nir_fdot(b, dx, dx), nir_fdot(b, dy, dy));
630
631 /* size has textureSize() of LOD 0 */
632 nir_ssa_def *L = nir_channel(b, size, 0);
633
634 /* lod = -1.0 + 0.5 * log2(L * L * M); */
635 nir_ssa_def *lod =
636 nir_fadd(b,
637 nir_imm_float(b, -1.0f),
638 nir_fmul(b,
639 nir_imm_float(b, 0.5f),
640 nir_flog2(b, nir_fmul(b, L, nir_fmul(b, L, M)))));
641
642 /* 3. Replace the gradient instruction with an equivalent lod instruction */
643 replace_gradient_with_lod(b, lod, tex);
644 }
645
646 static void
647 lower_gradient(nir_builder *b, nir_tex_instr *tex)
648 {
649 /* Cubes are more complicated and have their own function */
650 if (tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE) {
651 lower_gradient_cube_map(b, tex);
652 return;
653 }
654
655 assert(tex->sampler_dim != GLSL_SAMPLER_DIM_CUBE);
656 assert(tex->op == nir_texop_txd);
657 assert(tex->dest.is_ssa);
658
659 /* Use textureSize() to get the width and height of LOD 0 */
660 unsigned component_mask;
661 switch (tex->sampler_dim) {
662 case GLSL_SAMPLER_DIM_3D:
663 component_mask = 7;
664 break;
665 case GLSL_SAMPLER_DIM_1D:
666 component_mask = 1;
667 break;
668 default:
669 component_mask = 3;
670 break;
671 }
672
673 nir_ssa_def *size =
674 nir_channels(b, get_texture_size(b, tex), component_mask);
675
676 /* Scale the gradients by width and height. Effectively, the incoming
677 * gradients are s'(x,y), t'(x,y), and r'(x,y) from equation 3.19 in the
678 * GL 3.0 spec; we want u'(x,y), which is w_t * s'(x,y).
679 */
680 nir_ssa_def *ddx =
681 tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddx)].src.ssa;
682 nir_ssa_def *ddy =
683 tex->src[nir_tex_instr_src_index(tex, nir_tex_src_ddy)].src.ssa;
684
685 nir_ssa_def *dPdx = nir_fmul(b, ddx, size);
686 nir_ssa_def *dPdy = nir_fmul(b, ddy, size);
687
688 nir_ssa_def *rho;
689 if (dPdx->num_components == 1) {
690 rho = nir_fmax(b, nir_fabs(b, dPdx), nir_fabs(b, dPdy));
691 } else {
692 rho = nir_fmax(b,
693 nir_fsqrt(b, nir_fdot(b, dPdx, dPdx)),
694 nir_fsqrt(b, nir_fdot(b, dPdy, dPdy)));
695 }
696
697 /* lod = log2(rho). We're ignoring GL state biases for now. */
698 nir_ssa_def *lod = nir_flog2(b, rho);
699
700 /* Replace the gradient instruction with an equivalent lod instruction */
701 replace_gradient_with_lod(b, lod, tex);
702 }
703
704 static void
705 saturate_src(nir_builder *b, nir_tex_instr *tex, unsigned sat_mask)
706 {
707 b->cursor = nir_before_instr(&tex->instr);
708
709 /* Walk through the sources saturating the requested arguments. */
710 for (unsigned i = 0; i < tex->num_srcs; i++) {
711 if (tex->src[i].src_type != nir_tex_src_coord)
712 continue;
713
714 nir_ssa_def *src =
715 nir_ssa_for_src(b, tex->src[i].src, tex->coord_components);
716
717 /* split src into components: */
718 nir_ssa_def *comp[4];
719
720 assume(tex->coord_components >= 1);
721
722 for (unsigned j = 0; j < tex->coord_components; j++)
723 comp[j] = nir_channel(b, src, j);
724
725 /* clamp requested components, array index does not get clamped: */
726 unsigned ncomp = tex->coord_components;
727 if (tex->is_array)
728 ncomp--;
729
730 for (unsigned j = 0; j < ncomp; j++) {
731 if ((1 << j) & sat_mask) {
732 if (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
733 /* non-normalized texture coords, so clamp to texture
734 * size rather than [0.0, 1.0]
735 */
736 nir_ssa_def *txs = get_texture_size(b, tex);
737 comp[j] = nir_fmax(b, comp[j], nir_imm_float(b, 0.0));
738 comp[j] = nir_fmin(b, comp[j], nir_channel(b, txs, j));
739 } else {
740 comp[j] = nir_fsat(b, comp[j]);
741 }
742 }
743 }
744
745 /* and move the result back into a single vecN: */
746 src = nir_vec(b, comp, tex->coord_components);
747
748 nir_instr_rewrite_src(&tex->instr,
749 &tex->src[i].src,
750 nir_src_for_ssa(src));
751 }
752 }
753
754 static nir_ssa_def *
755 get_zero_or_one(nir_builder *b, nir_alu_type type, uint8_t swizzle_val)
756 {
757 nir_const_value v[4];
758
759 memset(&v, 0, sizeof(v));
760
761 if (swizzle_val == 4) {
762 v[0].u32 = v[1].u32 = v[2].u32 = v[3].u32 = 0;
763 } else {
764 assert(swizzle_val == 5);
765 if (type == nir_type_float)
766 v[0].f32 = v[1].f32 = v[2].f32 = v[3].f32 = 1.0;
767 else
768 v[0].u32 = v[1].u32 = v[2].u32 = v[3].u32 = 1;
769 }
770
771 return nir_build_imm(b, 4, 32, v);
772 }
773
774 static void
775 swizzle_tg4_broadcom(nir_builder *b, nir_tex_instr *tex)
776 {
777 assert(tex->dest.is_ssa);
778
779 b->cursor = nir_after_instr(&tex->instr);
780
781 assert(nir_tex_instr_dest_size(tex) == 4);
782 unsigned swiz[4] = { 2, 3, 1, 0 };
783 nir_ssa_def *swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4);
784
785 nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(swizzled),
786 swizzled->parent_instr);
787 }
788
789 static void
790 swizzle_result(nir_builder *b, nir_tex_instr *tex, const uint8_t swizzle[4])
791 {
792 assert(tex->dest.is_ssa);
793
794 b->cursor = nir_after_instr(&tex->instr);
795
796 nir_ssa_def *swizzled;
797 if (tex->op == nir_texop_tg4) {
798 if (swizzle[tex->component] < 4) {
799 /* This one's easy */
800 tex->component = swizzle[tex->component];
801 return;
802 } else {
803 swizzled = get_zero_or_one(b, tex->dest_type, swizzle[tex->component]);
804 }
805 } else {
806 assert(nir_tex_instr_dest_size(tex) == 4);
807 if (swizzle[0] < 4 && swizzle[1] < 4 &&
808 swizzle[2] < 4 && swizzle[3] < 4) {
809 unsigned swiz[4] = { swizzle[0], swizzle[1], swizzle[2], swizzle[3] };
810 /* We have no 0s or 1s, just emit a swizzling MOV */
811 swizzled = nir_swizzle(b, &tex->dest.ssa, swiz, 4);
812 } else {
813 nir_ssa_def *srcs[4];
814 for (unsigned i = 0; i < 4; i++) {
815 if (swizzle[i] < 4) {
816 srcs[i] = nir_channel(b, &tex->dest.ssa, swizzle[i]);
817 } else {
818 srcs[i] = get_zero_or_one(b, tex->dest_type, swizzle[i]);
819 }
820 }
821 swizzled = nir_vec(b, srcs, 4);
822 }
823 }
824
825 nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(swizzled),
826 swizzled->parent_instr);
827 }
828
829 static void
830 linearize_srgb_result(nir_builder *b, nir_tex_instr *tex)
831 {
832 assert(tex->dest.is_ssa);
833 assert(nir_tex_instr_dest_size(tex) == 4);
834 assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
835
836 b->cursor = nir_after_instr(&tex->instr);
837
838 nir_ssa_def *rgb =
839 nir_format_srgb_to_linear(b, nir_channels(b, &tex->dest.ssa, 0x7));
840
841 /* alpha is untouched: */
842 nir_ssa_def *result = nir_vec4(b,
843 nir_channel(b, rgb, 0),
844 nir_channel(b, rgb, 1),
845 nir_channel(b, rgb, 2),
846 nir_channel(b, &tex->dest.ssa, 3));
847
848 nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(result),
849 result->parent_instr);
850 }
851
852 /**
853 * Lowers texture instructions from giving a vec4 result to a vec2 of f16,
854 * i16, or u16, or a single unorm4x8 value.
855 *
856 * Note that we don't change the destination num_components, because
857 * nir_tex_instr_dest_size() will still return 4. The driver is just expected
858 * to not store the other channels, given that nothing at the NIR level will
859 * read them.
860 */
861 static void
862 lower_tex_packing(nir_builder *b, nir_tex_instr *tex,
863 const nir_lower_tex_options *options)
864 {
865 nir_ssa_def *color = &tex->dest.ssa;
866
867 b->cursor = nir_after_instr(&tex->instr);
868
869 switch (options->lower_tex_packing[tex->sampler_index]) {
870 case nir_lower_tex_packing_none:
871 return;
872
873 case nir_lower_tex_packing_16: {
874 static const unsigned bits[4] = {16, 16, 16, 16};
875
876 switch (nir_alu_type_get_base_type(tex->dest_type)) {
877 case nir_type_float:
878 if (tex->is_shadow && tex->is_new_style_shadow) {
879 color = nir_unpack_half_2x16_split_x(b, nir_channel(b, color, 0));
880 } else {
881 nir_ssa_def *rg = nir_channel(b, color, 0);
882 nir_ssa_def *ba = nir_channel(b, color, 1);
883 color = nir_vec4(b,
884 nir_unpack_half_2x16_split_x(b, rg),
885 nir_unpack_half_2x16_split_y(b, rg),
886 nir_unpack_half_2x16_split_x(b, ba),
887 nir_unpack_half_2x16_split_y(b, ba));
888 }
889 break;
890
891 case nir_type_int:
892 color = nir_format_unpack_sint(b, color, bits, 4);
893 break;
894
895 case nir_type_uint:
896 color = nir_format_unpack_uint(b, color, bits, 4);
897 break;
898
899 default:
900 unreachable("unknown base type");
901 }
902 break;
903 }
904
905 case nir_lower_tex_packing_8:
906 assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
907 color = nir_unpack_unorm_4x8(b, nir_channel(b, color, 0));
908 break;
909 }
910
911 nir_ssa_def_rewrite_uses_after(&tex->dest.ssa, nir_src_for_ssa(color),
912 color->parent_instr);
913 }
914
915 static bool
916 sampler_index_lt(nir_tex_instr *tex, unsigned max)
917 {
918 assert(nir_tex_instr_src_index(tex, nir_tex_src_sampler_deref) == -1);
919
920 unsigned sampler_index = tex->sampler_index;
921
922 int sampler_offset_idx =
923 nir_tex_instr_src_index(tex, nir_tex_src_sampler_offset);
924 if (sampler_offset_idx >= 0) {
925 if (!nir_src_is_const(tex->src[sampler_offset_idx].src))
926 return false;
927
928 sampler_index += nir_src_as_uint(tex->src[sampler_offset_idx].src);
929 }
930
931 return sampler_index < max;
932 }
933
934 static bool
935 lower_tg4_offsets(nir_builder *b, nir_tex_instr *tex)
936 {
937 assert(tex->op == nir_texop_tg4);
938 assert(nir_tex_instr_has_explicit_tg4_offsets(tex));
939 assert(nir_tex_instr_src_index(tex, nir_tex_src_offset) == -1);
940
941 b->cursor = nir_after_instr(&tex->instr);
942
943 nir_ssa_def *dest[4];
944 for (unsigned i = 0; i < 4; ++i) {
945 nir_tex_instr *tex_copy = nir_tex_instr_create(b->shader, tex->num_srcs + 1);
946 tex_copy->op = tex->op;
947 tex_copy->coord_components = tex->coord_components;
948 tex_copy->sampler_dim = tex->sampler_dim;
949 tex_copy->is_array = tex->is_array;
950 tex_copy->is_shadow = tex->is_shadow;
951 tex_copy->is_new_style_shadow = tex->is_new_style_shadow;
952 tex_copy->component = tex->component;
953 tex_copy->dest_type = tex->dest_type;
954
955 for (unsigned j = 0; j < tex->num_srcs; ++j) {
956 nir_src_copy(&tex_copy->src[j].src, &tex->src[j].src, tex_copy);
957 tex_copy->src[j].src_type = tex->src[j].src_type;
958 }
959
960 nir_tex_src src;
961 src.src = nir_src_for_ssa(nir_imm_ivec2(b, tex->tg4_offsets[i][0],
962 tex->tg4_offsets[i][1]));
963 src.src_type = nir_tex_src_offset;
964 tex_copy->src[tex_copy->num_srcs - 1] = src;
965
966 nir_ssa_dest_init(&tex_copy->instr, &tex_copy->dest,
967 nir_tex_instr_dest_size(tex), 32, NULL);
968
969 nir_builder_instr_insert(b, &tex_copy->instr);
970
971 dest[i] = nir_channel(b, &tex_copy->dest.ssa, 3);
972 }
973
974 nir_ssa_def *res = nir_vec4(b, dest[0], dest[1], dest[2], dest[3]);
975 nir_ssa_def_rewrite_uses(&tex->dest.ssa, nir_src_for_ssa(res));
976 nir_instr_remove(&tex->instr);
977
978 return true;
979 }
980
981 static bool
982 nir_lower_tex_block(nir_block *block, nir_builder *b,
983 const nir_lower_tex_options *options)
984 {
985 bool progress = false;
986
987 nir_foreach_instr_safe(instr, block) {
988 if (instr->type != nir_instr_type_tex)
989 continue;
990
991 nir_tex_instr *tex = nir_instr_as_tex(instr);
992 bool lower_txp = !!(options->lower_txp & (1 << tex->sampler_dim));
993
994 /* mask of src coords to saturate (clamp): */
995 unsigned sat_mask = 0;
996
997 if ((1 << tex->sampler_index) & options->saturate_r)
998 sat_mask |= (1 << 2); /* .z */
999 if ((1 << tex->sampler_index) & options->saturate_t)
1000 sat_mask |= (1 << 1); /* .y */
1001 if ((1 << tex->sampler_index) & options->saturate_s)
1002 sat_mask |= (1 << 0); /* .x */
1003
1004 /* If we are clamping any coords, we must lower projector first
1005 * as clamping happens *after* projection:
1006 */
1007 if (lower_txp || sat_mask) {
1008 project_src(b, tex);
1009 progress = true;
1010 }
1011
1012 if ((tex->op == nir_texop_txf && options->lower_txf_offset) ||
1013 (sat_mask && nir_tex_instr_src_index(tex, nir_tex_src_coord) >= 0) ||
1014 (tex->sampler_dim == GLSL_SAMPLER_DIM_RECT &&
1015 options->lower_rect_offset)) {
1016 progress = lower_offset(b, tex) || progress;
1017 }
1018
1019 if ((tex->sampler_dim == GLSL_SAMPLER_DIM_RECT) && options->lower_rect) {
1020 lower_rect(b, tex);
1021 progress = true;
1022 }
1023
1024 if ((1 << tex->texture_index) & options->lower_y_uv_external) {
1025 lower_y_uv_external(b, tex, options);
1026 progress = true;
1027 }
1028
1029 if ((1 << tex->texture_index) & options->lower_y_u_v_external) {
1030 lower_y_u_v_external(b, tex, options);
1031 progress = true;
1032 }
1033
1034 if ((1 << tex->texture_index) & options->lower_yx_xuxv_external) {
1035 lower_yx_xuxv_external(b, tex, options);
1036 progress = true;
1037 }
1038
1039 if ((1 << tex->texture_index) & options->lower_xy_uxvx_external) {
1040 lower_xy_uxvx_external(b, tex, options);
1041 progress = true;
1042 }
1043
1044 if ((1 << tex->texture_index) & options->lower_ayuv_external) {
1045 lower_ayuv_external(b, tex, options);
1046 progress = true;
1047 }
1048
1049 if ((1 << tex->texture_index) & options->lower_xyuv_external) {
1050 lower_xyuv_external(b, tex, options);
1051 progress = true;
1052 }
1053
1054 if (sat_mask) {
1055 saturate_src(b, tex, sat_mask);
1056 progress = true;
1057 }
1058
1059 if (tex->op == nir_texop_tg4 && options->lower_tg4_broadcom_swizzle) {
1060 swizzle_tg4_broadcom(b, tex);
1061 progress = true;
1062 }
1063
1064 if (((1 << tex->texture_index) & options->swizzle_result) &&
1065 !nir_tex_instr_is_query(tex) &&
1066 !(tex->is_shadow && tex->is_new_style_shadow)) {
1067 swizzle_result(b, tex, options->swizzles[tex->texture_index]);
1068 progress = true;
1069 }
1070
1071 /* should be after swizzle so we know which channels are rgb: */
1072 if (((1 << tex->texture_index) & options->lower_srgb) &&
1073 !nir_tex_instr_is_query(tex) && !tex->is_shadow) {
1074 linearize_srgb_result(b, tex);
1075 progress = true;
1076 }
1077
1078 const bool has_min_lod =
1079 nir_tex_instr_src_index(tex, nir_tex_src_min_lod) >= 0;
1080 const bool has_offset =
1081 nir_tex_instr_src_index(tex, nir_tex_src_offset) >= 0;
1082
1083 if (tex->op == nir_texop_txb && tex->is_shadow && has_min_lod &&
1084 options->lower_txb_shadow_clamp) {
1085 lower_implicit_lod(b, tex);
1086 progress = true;
1087 }
1088
1089 if (options->lower_tex_packing[tex->sampler_index] !=
1090 nir_lower_tex_packing_none &&
1091 tex->op != nir_texop_txs &&
1092 tex->op != nir_texop_query_levels) {
1093 lower_tex_packing(b, tex, options);
1094 progress = true;
1095 }
1096
1097 if (tex->op == nir_texop_txd &&
1098 (options->lower_txd ||
1099 (options->lower_txd_shadow && tex->is_shadow) ||
1100 (options->lower_txd_shadow_clamp && tex->is_shadow && has_min_lod) ||
1101 (options->lower_txd_offset_clamp && has_offset && has_min_lod) ||
1102 (options->lower_txd_clamp_bindless_sampler && has_min_lod &&
1103 nir_tex_instr_src_index(tex, nir_tex_src_sampler_handle) != -1) ||
1104 (options->lower_txd_clamp_if_sampler_index_not_lt_16 &&
1105 has_min_lod && !sampler_index_lt(tex, 16)) ||
1106 (options->lower_txd_cube_map &&
1107 tex->sampler_dim == GLSL_SAMPLER_DIM_CUBE) ||
1108 (options->lower_txd_3d &&
1109 tex->sampler_dim == GLSL_SAMPLER_DIM_3D))) {
1110 lower_gradient(b, tex);
1111 progress = true;
1112 continue;
1113 }
1114
1115 bool shader_supports_implicit_lod =
1116 b->shader->info.stage == MESA_SHADER_FRAGMENT ||
1117 (b->shader->info.stage == MESA_SHADER_COMPUTE &&
1118 b->shader->info.cs.derivative_group != DERIVATIVE_GROUP_NONE);
1119
1120 /* TXF, TXS and TXL require a LOD but not everything we implement using those
1121 * three opcodes provides one. Provide a default LOD of 0.
1122 */
1123 if ((nir_tex_instr_src_index(tex, nir_tex_src_lod) == -1) &&
1124 (tex->op == nir_texop_txf || tex->op == nir_texop_txs ||
1125 tex->op == nir_texop_txl || tex->op == nir_texop_query_levels ||
1126 (tex->op == nir_texop_tex && !shader_supports_implicit_lod))) {
1127 b->cursor = nir_before_instr(&tex->instr);
1128 nir_tex_instr_add_src(tex, nir_tex_src_lod, nir_src_for_ssa(nir_imm_int(b, 0)));
1129 if (tex->op == nir_texop_tex && options->lower_tex_without_implicit_lod)
1130 tex->op = nir_texop_txl;
1131 progress = true;
1132 continue;
1133 }
1134
1135 /* has to happen after all the other lowerings as the original tg4 gets
1136 * replaced by 4 tg4 instructions.
1137 */
1138 if (tex->op == nir_texop_tg4 &&
1139 nir_tex_instr_has_explicit_tg4_offsets(tex) &&
1140 options->lower_tg4_offsets) {
1141 progress |= lower_tg4_offsets(b, tex);
1142 continue;
1143 }
1144 }
1145
1146 return progress;
1147 }
1148
1149 static bool
1150 nir_lower_tex_impl(nir_function_impl *impl,
1151 const nir_lower_tex_options *options)
1152 {
1153 bool progress = false;
1154 nir_builder builder;
1155 nir_builder_init(&builder, impl);
1156
1157 nir_foreach_block(block, impl) {
1158 progress |= nir_lower_tex_block(block, &builder, options);
1159 }
1160
1161 nir_metadata_preserve(impl, nir_metadata_block_index |
1162 nir_metadata_dominance);
1163 return progress;
1164 }
1165
1166 bool
1167 nir_lower_tex(nir_shader *shader, const nir_lower_tex_options *options)
1168 {
1169 bool progress = false;
1170
1171 nir_foreach_function(function, shader) {
1172 if (function->impl)
1173 progress |= nir_lower_tex_impl(function->impl, options);
1174 }
1175
1176 return progress;
1177 }