gallivm: Factor out the SI->FP texture size conversion for SoA path too
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_sample_soa.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Texture sampling -- SoA.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 * @author Brian Paul <brianp@vmware.com>
34 */
35
36 #include "pipe/p_defines.h"
37 #include "pipe/p_state.h"
38 #include "util/u_debug.h"
39 #include "util/u_dump.h"
40 #include "util/u_memory.h"
41 #include "util/u_math.h"
42 #include "util/u_format.h"
43 #include "lp_bld_debug.h"
44 #include "lp_bld_type.h"
45 #include "lp_bld_const.h"
46 #include "lp_bld_conv.h"
47 #include "lp_bld_arit.h"
48 #include "lp_bld_bitarit.h"
49 #include "lp_bld_logic.h"
50 #include "lp_bld_printf.h"
51 #include "lp_bld_swizzle.h"
52 #include "lp_bld_flow.h"
53 #include "lp_bld_gather.h"
54 #include "lp_bld_format.h"
55 #include "lp_bld_sample.h"
56 #include "lp_bld_sample_aos.h"
57 #include "lp_bld_struct.h"
58 #include "lp_bld_quad.h"
59
60
61 /**
62 * Generate code to fetch a texel from a texture at int coords (x, y, z).
63 * The computation depends on whether the texture is 1D, 2D or 3D.
64 * The result, texel, will be float vectors:
65 * texel[0] = red values
66 * texel[1] = green values
67 * texel[2] = blue values
68 * texel[3] = alpha values
69 */
70 static void
71 lp_build_sample_texel_soa(struct lp_build_sample_context *bld,
72 unsigned unit,
73 LLVMValueRef width,
74 LLVMValueRef height,
75 LLVMValueRef depth,
76 LLVMValueRef x,
77 LLVMValueRef y,
78 LLVMValueRef z,
79 LLVMValueRef y_stride,
80 LLVMValueRef z_stride,
81 LLVMValueRef data_ptr,
82 LLVMValueRef texel_out[4])
83 {
84 const struct lp_sampler_static_state *static_state = bld->static_state;
85 const unsigned dims = bld->dims;
86 struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
87 LLVMValueRef offset;
88 LLVMValueRef i, j;
89 LLVMValueRef use_border = NULL;
90
91 /* use_border = x < 0 || x >= width || y < 0 || y >= height */
92 if (lp_sampler_wrap_mode_uses_border_color(static_state->wrap_s,
93 static_state->min_img_filter,
94 static_state->mag_img_filter)) {
95 LLVMValueRef b1, b2;
96 b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, x, int_coord_bld->zero);
97 b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, x, width);
98 use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
99 }
100
101 if (dims >= 2 &&
102 lp_sampler_wrap_mode_uses_border_color(static_state->wrap_t,
103 static_state->min_img_filter,
104 static_state->mag_img_filter)) {
105 LLVMValueRef b1, b2;
106 b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, y, int_coord_bld->zero);
107 b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, y, height);
108 if (use_border) {
109 use_border = LLVMBuildOr(bld->builder, use_border, b1, "ub_or_b1");
110 use_border = LLVMBuildOr(bld->builder, use_border, b2, "ub_or_b2");
111 }
112 else {
113 use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
114 }
115 }
116
117 if (dims == 3 &&
118 lp_sampler_wrap_mode_uses_border_color(static_state->wrap_r,
119 static_state->min_img_filter,
120 static_state->mag_img_filter)) {
121 LLVMValueRef b1, b2;
122 b1 = lp_build_cmp(int_coord_bld, PIPE_FUNC_LESS, z, int_coord_bld->zero);
123 b2 = lp_build_cmp(int_coord_bld, PIPE_FUNC_GEQUAL, z, depth);
124 if (use_border) {
125 use_border = LLVMBuildOr(bld->builder, use_border, b1, "ub_or_b1");
126 use_border = LLVMBuildOr(bld->builder, use_border, b2, "ub_or_b2");
127 }
128 else {
129 use_border = LLVMBuildOr(bld->builder, b1, b2, "b1_or_b2");
130 }
131 }
132
133 /* convert x,y,z coords to linear offset from start of texture, in bytes */
134 lp_build_sample_offset(&bld->uint_coord_bld,
135 bld->format_desc,
136 x, y, z, y_stride, z_stride,
137 &offset, &i, &j);
138
139 if (use_border) {
140 /* If we can sample the border color, it means that texcoords may
141 * lie outside the bounds of the texture image. We need to do
142 * something to prevent reading out of bounds and causing a segfault.
143 *
144 * Simply AND the texture coords with !use_border. This will cause
145 * coords which are out of bounds to become zero. Zero's guaranteed
146 * to be inside the texture image.
147 */
148 offset = lp_build_andnot(&bld->uint_coord_bld, offset, use_border);
149 }
150
151 lp_build_fetch_rgba_soa(bld->builder,
152 bld->format_desc,
153 bld->texel_type,
154 data_ptr, offset,
155 i, j,
156 texel_out);
157
158 /*
159 * Note: if we find an app which frequently samples the texture border
160 * we might want to implement a true conditional here to avoid sampling
161 * the texture whenever possible (since that's quite a bit of code).
162 * Ex:
163 * if (use_border) {
164 * texel = border_color;
165 * }
166 * else {
167 * texel = sample_texture(coord);
168 * }
169 * As it is now, we always sample the texture, then selectively replace
170 * the texel color results with the border color.
171 */
172
173 if (use_border) {
174 /* select texel color or border color depending on use_border */
175 LLVMValueRef border_color_ptr =
176 bld->dynamic_state->border_color(bld->dynamic_state,
177 bld->builder, unit);
178 int chan;
179 for (chan = 0; chan < 4; chan++) {
180 LLVMValueRef border_chan =
181 lp_build_array_get(bld->builder, border_color_ptr,
182 lp_build_const_int32(chan));
183 LLVMValueRef border_chan_vec =
184 lp_build_broadcast_scalar(&bld->float_vec_bld, border_chan);
185 texel_out[chan] = lp_build_select(&bld->texel_bld, use_border,
186 border_chan_vec, texel_out[chan]);
187 }
188 }
189
190 apply_sampler_swizzle(bld, texel_out);
191 }
192
193
194 /**
195 * Helper to compute the mirror function for the PIPE_WRAP_MIRROR modes.
196 */
197 static LLVMValueRef
198 lp_build_coord_mirror(struct lp_build_sample_context *bld,
199 LLVMValueRef coord)
200 {
201 struct lp_build_context *coord_bld = &bld->coord_bld;
202 struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
203 LLVMValueRef fract, flr, isOdd;
204
205 lp_build_ifloor_fract(coord_bld, coord, &flr, &fract);
206
207 /* isOdd = flr & 1 */
208 isOdd = LLVMBuildAnd(bld->builder, flr, int_coord_bld->one, "");
209
210 /* make coord positive or negative depending on isOdd */
211 coord = lp_build_set_sign(coord_bld, fract, isOdd);
212
213 /* convert isOdd to float */
214 isOdd = lp_build_int_to_float(coord_bld, isOdd);
215
216 /* add isOdd to coord */
217 coord = lp_build_add(coord_bld, coord, isOdd);
218
219 return coord;
220 }
221
222
223 /**
224 * Build LLVM code for texture wrap mode for linear filtering.
225 * \param x0_out returns first integer texcoord
226 * \param x1_out returns second integer texcoord
227 * \param weight_out returns linear interpolation weight
228 */
229 static void
230 lp_build_sample_wrap_linear(struct lp_build_sample_context *bld,
231 LLVMValueRef coord,
232 LLVMValueRef length,
233 LLVMValueRef length_f,
234 boolean is_pot,
235 unsigned wrap_mode,
236 LLVMValueRef *x0_out,
237 LLVMValueRef *x1_out,
238 LLVMValueRef *weight_out)
239 {
240 struct lp_build_context *coord_bld = &bld->coord_bld;
241 struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
242 struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
243 LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5);
244 LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
245 LLVMValueRef coord0, coord1, weight;
246
247 switch(wrap_mode) {
248 case PIPE_TEX_WRAP_REPEAT:
249 /* mul by size and subtract 0.5 */
250 coord = lp_build_mul(coord_bld, coord, length_f);
251 coord = lp_build_sub(coord_bld, coord, half);
252 /* convert to int, compute lerp weight */
253 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
254 /* repeat wrap */
255 if (is_pot) {
256 coord1 = lp_build_add(uint_coord_bld, coord0, uint_coord_bld->one);
257 coord0 = LLVMBuildAnd(bld->builder, coord0, length_minus_one, "");
258 coord1 = LLVMBuildAnd(bld->builder, coord1, length_minus_one, "");
259 }
260 else {
261 /* Add a bias to the texcoord to handle negative coords */
262 LLVMValueRef bias = lp_build_mul_imm(uint_coord_bld, length, 1024);
263 LLVMValueRef mask;
264 coord0 = LLVMBuildAdd(bld->builder, coord0, bias, "");
265 coord0 = LLVMBuildURem(bld->builder, coord0, length, "");
266 mask = lp_build_compare(bld->builder, int_coord_bld->type,
267 PIPE_FUNC_NOTEQUAL, coord0, length_minus_one);
268 coord1 = LLVMBuildAnd(bld->builder,
269 lp_build_add(uint_coord_bld, coord0, uint_coord_bld->one),
270 mask, "");
271 }
272 break;
273
274 case PIPE_TEX_WRAP_CLAMP:
275 if (bld->static_state->normalized_coords) {
276 /* scale coord to length */
277 coord = lp_build_mul(coord_bld, coord, length_f);
278 }
279
280 /* clamp to [0, length] */
281 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f);
282
283 coord = lp_build_sub(coord_bld, coord, half);
284
285 /* convert to int, compute lerp weight */
286 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
287 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
288 break;
289
290 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
291 {
292 struct lp_build_context abs_coord_bld = bld->coord_bld;
293 abs_coord_bld.type.sign = FALSE;
294
295 if (bld->static_state->normalized_coords) {
296 /* mul by tex size */
297 coord = lp_build_mul(coord_bld, coord, length_f);
298 /* clamp to length max */
299 coord = lp_build_min(coord_bld, coord, length_f);
300 /* subtract 0.5 */
301 coord = lp_build_sub(coord_bld, coord, half);
302 /* clamp to [0, length - 0.5] */
303 coord = lp_build_max(coord_bld, coord, coord_bld->zero);
304 }
305 /* XXX this is odd normalized ranges from 0 to length-0.5 after denorm
306 but non-normalized ranges from to 0.5 to length-0.5 after clamp.
307 Is this missing the sub 0.5? */
308 else {
309 LLVMValueRef min, max;
310 /* clamp to [0.5, length - 0.5] */
311 min = half;
312 max = lp_build_sub(coord_bld, length_f, min);
313 coord = lp_build_clamp(coord_bld, coord, min, max);
314 }
315 /* convert to int, compute lerp weight */
316 lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
317 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
318 /* coord1 = min(coord1, length-1) */
319 coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
320 break;
321 }
322
323 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
324 {
325 LLVMValueRef min;
326 if (bld->static_state->normalized_coords) {
327 /* scale coord to length */
328 coord = lp_build_mul(coord_bld, coord, length_f);
329 }
330 /* was: clamp to [-0.5, length + 0.5], then sub 0.5 */
331 coord = lp_build_sub(coord_bld, coord, half);
332 min = lp_build_const_vec(coord_bld->type, -1.0F);
333 coord = lp_build_clamp(coord_bld, coord, min, length_f);
334 /* convert to int, compute lerp weight */
335 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
336 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
337 }
338 break;
339
340 case PIPE_TEX_WRAP_MIRROR_REPEAT:
341 /* compute mirror function */
342 coord = lp_build_coord_mirror(bld, coord);
343
344 /* scale coord to length */
345 coord = lp_build_mul(coord_bld, coord, length_f);
346 coord = lp_build_sub(coord_bld, coord, half);
347
348 /* convert to int, compute lerp weight */
349 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
350 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
351
352 /* coord0 = max(coord0, 0) */
353 coord0 = lp_build_max(int_coord_bld, coord0, int_coord_bld->zero);
354 /* coord1 = min(coord1, length-1) */
355 coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one);
356 break;
357
358 case PIPE_TEX_WRAP_MIRROR_CLAMP:
359 coord = lp_build_abs(coord_bld, coord);
360
361 if (bld->static_state->normalized_coords) {
362 /* scale coord to length */
363 coord = lp_build_mul(coord_bld, coord, length_f);
364 }
365
366 /* clamp to [0, length] */
367 coord = lp_build_min(coord_bld, coord, length_f);
368
369 coord = lp_build_sub(coord_bld, coord, half);
370
371 /* convert to int, compute lerp weight */
372 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
373 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
374 break;
375
376 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
377 {
378 LLVMValueRef min, max;
379 struct lp_build_context abs_coord_bld = bld->coord_bld;
380 abs_coord_bld.type.sign = FALSE;
381 coord = lp_build_abs(coord_bld, coord);
382
383 if (bld->static_state->normalized_coords) {
384 /* scale coord to length */
385 coord = lp_build_mul(coord_bld, coord, length_f);
386 }
387
388 /* clamp to [0.5, length - 0.5] */
389 min = half;
390 max = lp_build_sub(coord_bld, length_f, min);
391 coord = lp_build_clamp(coord_bld, coord, min, max);
392
393 coord = lp_build_sub(coord_bld, coord, half);
394
395 /* convert to int, compute lerp weight */
396 lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight);
397 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
398 }
399 break;
400
401 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
402 {
403 coord = lp_build_abs(coord_bld, coord);
404
405 if (bld->static_state->normalized_coords) {
406 /* scale coord to length */
407 coord = lp_build_mul(coord_bld, coord, length_f);
408 }
409
410 /* was: clamp to [-0.5, length + 0.5] then sub 0.5 */
411 /* skip -0.5 clamp (always positive), do sub first */
412 coord = lp_build_sub(coord_bld, coord, half);
413 coord = lp_build_min(coord_bld, coord, length_f);
414
415 /* convert to int, compute lerp weight */
416 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight);
417 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one);
418 }
419 break;
420
421 default:
422 assert(0);
423 coord0 = NULL;
424 coord1 = NULL;
425 weight = NULL;
426 }
427
428 *x0_out = coord0;
429 *x1_out = coord1;
430 *weight_out = weight;
431 }
432
433
434 /**
435 * Build LLVM code for texture wrap mode for nearest filtering.
436 * \param coord the incoming texcoord (nominally in [0,1])
437 * \param length the texture size along one dimension, as int vector
438 * \param is_pot if TRUE, length is a power of two
439 * \param wrap_mode one of PIPE_TEX_WRAP_x
440 */
441 static LLVMValueRef
442 lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld,
443 LLVMValueRef coord,
444 LLVMValueRef length,
445 LLVMValueRef length_f,
446 boolean is_pot,
447 unsigned wrap_mode)
448 {
449 struct lp_build_context *coord_bld = &bld->coord_bld;
450 struct lp_build_context *int_coord_bld = &bld->int_coord_bld;
451 struct lp_build_context *uint_coord_bld = &bld->uint_coord_bld;
452 LLVMValueRef length_minus_one = lp_build_sub(uint_coord_bld, length, uint_coord_bld->one);
453 LLVMValueRef icoord;
454
455 switch(wrap_mode) {
456 case PIPE_TEX_WRAP_REPEAT:
457 coord = lp_build_mul(coord_bld, coord, length_f);
458 icoord = lp_build_ifloor(coord_bld, coord);
459 if (is_pot)
460 icoord = LLVMBuildAnd(bld->builder, icoord, length_minus_one, "");
461 else {
462 /* Add a bias to the texcoord to handle negative coords */
463 LLVMValueRef bias = lp_build_mul_imm(uint_coord_bld, length, 1024);
464 icoord = LLVMBuildAdd(bld->builder, icoord, bias, "");
465 icoord = LLVMBuildURem(bld->builder, icoord, length, "");
466 }
467 break;
468
469 case PIPE_TEX_WRAP_CLAMP:
470 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
471 if (bld->static_state->normalized_coords) {
472 /* scale coord to length */
473 coord = lp_build_mul(coord_bld, coord, length_f);
474 }
475
476 /* floor */
477 /* use itrunc instead since we clamp to 0 anyway */
478 icoord = lp_build_itrunc(coord_bld, coord);
479
480 /* clamp to [0, length - 1]. */
481 icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero,
482 length_minus_one);
483 break;
484
485 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
486 /* Note: this is the same as CLAMP_TO_EDGE, except min = -min */
487 {
488 LLVMValueRef min, max;
489
490 if (bld->static_state->normalized_coords) {
491 /* scale coord to length */
492 coord = lp_build_mul(coord_bld, coord, length_f);
493 }
494
495 icoord = lp_build_ifloor(coord_bld, coord);
496
497 /* clamp to [-1, length] */
498 min = lp_build_negate(int_coord_bld, int_coord_bld->one);
499 max = length;
500 icoord = lp_build_clamp(int_coord_bld, icoord, min, max);
501 }
502 break;
503
504 case PIPE_TEX_WRAP_MIRROR_REPEAT:
505 /* compute mirror function */
506 coord = lp_build_coord_mirror(bld, coord);
507
508 /* scale coord to length */
509 assert(bld->static_state->normalized_coords);
510 coord = lp_build_mul(coord_bld, coord, length_f);
511
512 /* itrunc == ifloor here */
513 icoord = lp_build_itrunc(coord_bld, coord);
514
515 /* clamp to [0, length - 1] */
516 icoord = lp_build_min(int_coord_bld, icoord, length_minus_one);
517 break;
518
519 case PIPE_TEX_WRAP_MIRROR_CLAMP:
520 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
521 coord = lp_build_abs(coord_bld, coord);
522
523 if (bld->static_state->normalized_coords) {
524 /* scale coord to length */
525 coord = lp_build_mul(coord_bld, coord, length_f);
526 }
527
528 /* itrunc == ifloor here */
529 icoord = lp_build_itrunc(coord_bld, coord);
530
531 /* clamp to [0, length - 1] */
532 icoord = lp_build_min(int_coord_bld, icoord, length_minus_one);
533 break;
534
535 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
536 coord = lp_build_abs(coord_bld, coord);
537
538 if (bld->static_state->normalized_coords) {
539 /* scale coord to length */
540 coord = lp_build_mul(coord_bld, coord, length_f);
541 }
542
543 /* itrunc == ifloor here */
544 icoord = lp_build_itrunc(coord_bld, coord);
545
546 /* clamp to [0, length] */
547 icoord = lp_build_min(int_coord_bld, icoord, length);
548 break;
549
550 default:
551 assert(0);
552 icoord = NULL;
553 }
554
555 return icoord;
556 }
557
558
559 /**
560 * Generate code to sample a mipmap level with nearest filtering.
561 * If sampling a cube texture, r = cube face in [0,5].
562 */
563 static void
564 lp_build_sample_image_nearest(struct lp_build_sample_context *bld,
565 unsigned unit,
566 LLVMValueRef size,
567 LLVMValueRef row_stride_vec,
568 LLVMValueRef img_stride_vec,
569 LLVMValueRef data_ptr,
570 LLVMValueRef s,
571 LLVMValueRef t,
572 LLVMValueRef r,
573 LLVMValueRef colors_out[4])
574 {
575 const unsigned dims = bld->dims;
576 LLVMValueRef width_vec;
577 LLVMValueRef height_vec;
578 LLVMValueRef depth_vec;
579 LLVMValueRef flt_size;
580 LLVMValueRef flt_width_vec;
581 LLVMValueRef flt_height_vec;
582 LLVMValueRef flt_depth_vec;
583 LLVMValueRef x, y, z;
584
585 lp_build_extract_image_sizes(bld,
586 bld->int_size_type,
587 bld->int_coord_type,
588 size,
589 &width_vec, &height_vec, &depth_vec);
590
591 flt_size = lp_build_int_to_float(&bld->float_size_bld, size);
592
593 lp_build_extract_image_sizes(bld,
594 bld->float_size_type,
595 bld->coord_type,
596 flt_size,
597 &flt_width_vec, &flt_height_vec, &flt_depth_vec);
598
599 /*
600 * Compute integer texcoords.
601 */
602 x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec,
603 bld->static_state->pot_width,
604 bld->static_state->wrap_s);
605 lp_build_name(x, "tex.x.wrapped");
606
607 if (dims >= 2) {
608 y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec,
609 bld->static_state->pot_height,
610 bld->static_state->wrap_t);
611 lp_build_name(y, "tex.y.wrapped");
612
613 if (dims == 3) {
614 z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec,
615 bld->static_state->pot_depth,
616 bld->static_state->wrap_r);
617 lp_build_name(z, "tex.z.wrapped");
618 }
619 else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
620 z = r;
621 }
622 else {
623 z = NULL;
624 }
625 }
626 else {
627 y = z = NULL;
628 }
629
630 /*
631 * Get texture colors.
632 */
633 lp_build_sample_texel_soa(bld, unit,
634 width_vec, height_vec, depth_vec,
635 x, y, z,
636 row_stride_vec, img_stride_vec,
637 data_ptr, colors_out);
638 }
639
640
641 /**
642 * Generate code to sample a mipmap level with linear filtering.
643 * If sampling a cube texture, r = cube face in [0,5].
644 */
645 static void
646 lp_build_sample_image_linear(struct lp_build_sample_context *bld,
647 unsigned unit,
648 LLVMValueRef size,
649 LLVMValueRef row_stride_vec,
650 LLVMValueRef img_stride_vec,
651 LLVMValueRef data_ptr,
652 LLVMValueRef s,
653 LLVMValueRef t,
654 LLVMValueRef r,
655 LLVMValueRef colors_out[4])
656 {
657 const unsigned dims = bld->dims;
658 LLVMValueRef width_vec;
659 LLVMValueRef height_vec;
660 LLVMValueRef depth_vec;
661 LLVMValueRef flt_size;
662 LLVMValueRef flt_width_vec;
663 LLVMValueRef flt_height_vec;
664 LLVMValueRef flt_depth_vec;
665 LLVMValueRef x0, y0, z0, x1, y1, z1;
666 LLVMValueRef s_fpart, t_fpart, r_fpart;
667 LLVMValueRef neighbors[2][2][4];
668 int chan;
669
670 lp_build_extract_image_sizes(bld,
671 bld->int_size_type,
672 bld->int_coord_type,
673 size,
674 &width_vec, &height_vec, &depth_vec);
675
676 flt_size = lp_build_int_to_float(&bld->float_size_bld, size);
677
678 lp_build_extract_image_sizes(bld,
679 bld->float_size_type,
680 bld->coord_type,
681 flt_size,
682 &flt_width_vec, &flt_height_vec, &flt_depth_vec);
683
684 /*
685 * Compute integer texcoords.
686 */
687 lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec,
688 bld->static_state->pot_width,
689 bld->static_state->wrap_s,
690 &x0, &x1, &s_fpart);
691 lp_build_name(x0, "tex.x0.wrapped");
692 lp_build_name(x1, "tex.x1.wrapped");
693
694 if (dims >= 2) {
695 lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec,
696 bld->static_state->pot_height,
697 bld->static_state->wrap_t,
698 &y0, &y1, &t_fpart);
699 lp_build_name(y0, "tex.y0.wrapped");
700 lp_build_name(y1, "tex.y1.wrapped");
701
702 if (dims == 3) {
703 lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec,
704 bld->static_state->pot_depth,
705 bld->static_state->wrap_r,
706 &z0, &z1, &r_fpart);
707 lp_build_name(z0, "tex.z0.wrapped");
708 lp_build_name(z1, "tex.z1.wrapped");
709 }
710 else if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
711 z0 = z1 = r; /* cube face */
712 r_fpart = NULL;
713 }
714 else {
715 z0 = z1 = NULL;
716 r_fpart = NULL;
717 }
718 }
719 else {
720 y0 = y1 = t_fpart = NULL;
721 z0 = z1 = r_fpart = NULL;
722 }
723
724 /*
725 * Get texture colors.
726 */
727 /* get x0/x1 texels */
728 lp_build_sample_texel_soa(bld, unit,
729 width_vec, height_vec, depth_vec,
730 x0, y0, z0,
731 row_stride_vec, img_stride_vec,
732 data_ptr, neighbors[0][0]);
733 lp_build_sample_texel_soa(bld, unit,
734 width_vec, height_vec, depth_vec,
735 x1, y0, z0,
736 row_stride_vec, img_stride_vec,
737 data_ptr, neighbors[0][1]);
738
739 if (dims == 1) {
740 /* Interpolate two samples from 1D image to produce one color */
741 for (chan = 0; chan < 4; chan++) {
742 colors_out[chan] = lp_build_lerp(&bld->texel_bld, s_fpart,
743 neighbors[0][0][chan],
744 neighbors[0][1][chan]);
745 }
746 }
747 else {
748 /* 2D/3D texture */
749 LLVMValueRef colors0[4];
750
751 /* get x0/x1 texels at y1 */
752 lp_build_sample_texel_soa(bld, unit,
753 width_vec, height_vec, depth_vec,
754 x0, y1, z0,
755 row_stride_vec, img_stride_vec,
756 data_ptr, neighbors[1][0]);
757 lp_build_sample_texel_soa(bld, unit,
758 width_vec, height_vec, depth_vec,
759 x1, y1, z0,
760 row_stride_vec, img_stride_vec,
761 data_ptr, neighbors[1][1]);
762
763 /* Bilinear interpolate the four samples from the 2D image / 3D slice */
764 for (chan = 0; chan < 4; chan++) {
765 colors0[chan] = lp_build_lerp_2d(&bld->texel_bld,
766 s_fpart, t_fpart,
767 neighbors[0][0][chan],
768 neighbors[0][1][chan],
769 neighbors[1][0][chan],
770 neighbors[1][1][chan]);
771 }
772
773 if (dims == 3) {
774 LLVMValueRef neighbors1[2][2][4];
775 LLVMValueRef colors1[4];
776
777 /* get x0/x1/y0/y1 texels at z1 */
778 lp_build_sample_texel_soa(bld, unit,
779 width_vec, height_vec, depth_vec,
780 x0, y0, z1,
781 row_stride_vec, img_stride_vec,
782 data_ptr, neighbors1[0][0]);
783 lp_build_sample_texel_soa(bld, unit,
784 width_vec, height_vec, depth_vec,
785 x1, y0, z1,
786 row_stride_vec, img_stride_vec,
787 data_ptr, neighbors1[0][1]);
788 lp_build_sample_texel_soa(bld, unit,
789 width_vec, height_vec, depth_vec,
790 x0, y1, z1,
791 row_stride_vec, img_stride_vec,
792 data_ptr, neighbors1[1][0]);
793 lp_build_sample_texel_soa(bld, unit,
794 width_vec, height_vec, depth_vec,
795 x1, y1, z1,
796 row_stride_vec, img_stride_vec,
797 data_ptr, neighbors1[1][1]);
798
799 /* Bilinear interpolate the four samples from the second Z slice */
800 for (chan = 0; chan < 4; chan++) {
801 colors1[chan] = lp_build_lerp_2d(&bld->texel_bld,
802 s_fpart, t_fpart,
803 neighbors1[0][0][chan],
804 neighbors1[0][1][chan],
805 neighbors1[1][0][chan],
806 neighbors1[1][1][chan]);
807 }
808
809 /* Linearly interpolate the two samples from the two 3D slices */
810 for (chan = 0; chan < 4; chan++) {
811 colors_out[chan] = lp_build_lerp(&bld->texel_bld,
812 r_fpart,
813 colors0[chan], colors1[chan]);
814 }
815 }
816 else {
817 /* 2D tex */
818 for (chan = 0; chan < 4; chan++) {
819 colors_out[chan] = colors0[chan];
820 }
821 }
822 }
823 }
824
825
826 /**
827 * Sample the texture/mipmap using given image filter and mip filter.
828 * data0_ptr and data1_ptr point to the two mipmap levels to sample
829 * from. width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes.
830 * If we're using nearest miplevel sampling the '1' values will be null/unused.
831 */
832 static void
833 lp_build_sample_mipmap(struct lp_build_sample_context *bld,
834 unsigned unit,
835 unsigned img_filter,
836 unsigned mip_filter,
837 LLVMValueRef s,
838 LLVMValueRef t,
839 LLVMValueRef r,
840 LLVMValueRef ilevel0,
841 LLVMValueRef ilevel1,
842 LLVMValueRef lod_fpart,
843 LLVMValueRef *colors_out)
844 {
845 LLVMBuilderRef builder = bld->builder;
846 LLVMValueRef size0;
847 LLVMValueRef size1;
848 LLVMValueRef row_stride0_vec;
849 LLVMValueRef row_stride1_vec;
850 LLVMValueRef img_stride0_vec;
851 LLVMValueRef img_stride1_vec;
852 LLVMValueRef data_ptr0;
853 LLVMValueRef data_ptr1;
854 LLVMValueRef colors0[4], colors1[4];
855 unsigned chan;
856
857 /* sample the first mipmap level */
858 lp_build_mipmap_level_sizes(bld, ilevel0,
859 &size0,
860 &row_stride0_vec, &img_stride0_vec);
861 data_ptr0 = lp_build_get_mipmap_level(bld, ilevel0);
862 if (img_filter == PIPE_TEX_FILTER_NEAREST) {
863 lp_build_sample_image_nearest(bld, unit,
864 size0,
865 row_stride0_vec, img_stride0_vec,
866 data_ptr0, s, t, r,
867 colors0);
868 }
869 else {
870 assert(img_filter == PIPE_TEX_FILTER_LINEAR);
871 lp_build_sample_image_linear(bld, unit,
872 size0,
873 row_stride0_vec, img_stride0_vec,
874 data_ptr0, s, t, r,
875 colors0);
876 }
877
878 /* Store the first level's colors in the output variables */
879 for (chan = 0; chan < 4; chan++) {
880 LLVMBuildStore(builder, colors0[chan], colors_out[chan]);
881 }
882
883 if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) {
884 struct lp_build_flow_context *flow_ctx;
885 struct lp_build_if_state if_ctx;
886 LLVMValueRef need_lerp;
887
888 flow_ctx = lp_build_flow_create(builder);
889
890 /* need_lerp = lod_fpart > 0 */
891 need_lerp = LLVMBuildFCmp(builder, LLVMRealUGT,
892 lod_fpart,
893 bld->float_bld.zero,
894 "need_lerp");
895
896 lp_build_if(&if_ctx, flow_ctx, builder, need_lerp);
897 {
898 /* sample the second mipmap level */
899 lp_build_mipmap_level_sizes(bld, ilevel1,
900 &size1,
901 &row_stride1_vec, &img_stride1_vec);
902 data_ptr1 = lp_build_get_mipmap_level(bld, ilevel1);
903 if (img_filter == PIPE_TEX_FILTER_NEAREST) {
904 lp_build_sample_image_nearest(bld, unit,
905 size1,
906 row_stride1_vec, img_stride1_vec,
907 data_ptr1, s, t, r,
908 colors1);
909 }
910 else {
911 lp_build_sample_image_linear(bld, unit,
912 size1,
913 row_stride1_vec, img_stride1_vec,
914 data_ptr1, s, t, r,
915 colors1);
916 }
917
918 /* interpolate samples from the two mipmap levels */
919
920 lod_fpart = lp_build_broadcast_scalar(&bld->texel_bld, lod_fpart);
921
922 for (chan = 0; chan < 4; chan++) {
923 colors0[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart,
924 colors0[chan], colors1[chan]);
925 LLVMBuildStore(builder, colors0[chan], colors_out[chan]);
926 }
927 }
928 lp_build_endif(&if_ctx);
929
930 lp_build_flow_destroy(flow_ctx);
931 }
932 }
933
934
935
936 /**
937 * General texture sampling codegen.
938 * This function handles texture sampling for all texture targets (1D,
939 * 2D, 3D, cube) and all filtering modes.
940 */
941 static void
942 lp_build_sample_general(struct lp_build_sample_context *bld,
943 unsigned unit,
944 LLVMValueRef s,
945 LLVMValueRef t,
946 LLVMValueRef r,
947 const LLVMValueRef *ddx,
948 const LLVMValueRef *ddy,
949 LLVMValueRef lod_bias, /* optional */
950 LLVMValueRef explicit_lod, /* optional */
951 LLVMValueRef *colors_out)
952 {
953 struct lp_build_context *int_bld = &bld->int_bld;
954 LLVMBuilderRef builder = bld->builder;
955 const unsigned mip_filter = bld->static_state->min_mip_filter;
956 const unsigned min_filter = bld->static_state->min_img_filter;
957 const unsigned mag_filter = bld->static_state->mag_img_filter;
958 LLVMValueRef lod_ipart = NULL, lod_fpart = NULL;
959 LLVMValueRef ilevel0, ilevel1 = NULL;
960 LLVMValueRef face_ddx[4], face_ddy[4];
961 LLVMValueRef texels[4];
962 LLVMTypeRef i32t = LLVMInt32Type();
963 LLVMValueRef i32t_zero = LLVMConstInt(i32t, 0, 0);
964 unsigned chan;
965
966 /*
967 printf("%s mip %d min %d mag %d\n", __FUNCTION__,
968 mip_filter, min_filter, mag_filter);
969 */
970
971 /*
972 * Choose cube face, recompute texcoords and derivatives for the chosen face.
973 */
974 if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
975 LLVMValueRef face, face_s, face_t;
976 lp_build_cube_lookup(bld, s, t, r, &face, &face_s, &face_t);
977 s = face_s; /* vec */
978 t = face_t; /* vec */
979 /* use 'r' to indicate cube face */
980 r = lp_build_broadcast_scalar(&bld->int_coord_bld, face); /* vec */
981
982 /* recompute ddx, ddy using the new (s,t) face texcoords */
983 face_ddx[0] = lp_build_ddx(&bld->coord_bld, s);
984 face_ddx[1] = lp_build_ddx(&bld->coord_bld, t);
985 face_ddx[2] = NULL;
986 face_ddx[3] = NULL;
987 face_ddy[0] = lp_build_ddy(&bld->coord_bld, s);
988 face_ddy[1] = lp_build_ddy(&bld->coord_bld, t);
989 face_ddy[2] = NULL;
990 face_ddy[3] = NULL;
991 ddx = face_ddx;
992 ddy = face_ddy;
993 }
994
995 /*
996 * Compute the level of detail (float).
997 */
998 if (min_filter != mag_filter ||
999 mip_filter != PIPE_TEX_MIPFILTER_NONE) {
1000 /* Need to compute lod either to choose mipmap levels or to
1001 * distinguish between minification/magnification with one mipmap level.
1002 */
1003 lp_build_lod_selector(bld, unit, ddx, ddy,
1004 lod_bias, explicit_lod,
1005 mip_filter,
1006 &lod_ipart, &lod_fpart);
1007 } else {
1008 lod_ipart = i32t_zero;
1009 }
1010
1011 /*
1012 * Compute integer mipmap level(s) to fetch texels from: ilevel0, ilevel1
1013 */
1014 switch (mip_filter) {
1015 default:
1016 assert(0 && "bad mip_filter value in lp_build_sample_soa()");
1017 /* fall-through */
1018 case PIPE_TEX_MIPFILTER_NONE:
1019 /* always use mip level 0 */
1020 if (bld->static_state->target == PIPE_TEXTURE_CUBE) {
1021 /* XXX this is a work-around for an apparent bug in LLVM 2.7.
1022 * We should be able to set ilevel0 = const(0) but that causes
1023 * bad x86 code to be emitted.
1024 */
1025 assert(lod_ipart);
1026 lp_build_nearest_mip_level(bld, unit, lod_ipart, &ilevel0);
1027 }
1028 else {
1029 ilevel0 = i32t_zero;
1030 }
1031 break;
1032 case PIPE_TEX_MIPFILTER_NEAREST:
1033 assert(lod_ipart);
1034 lp_build_nearest_mip_level(bld, unit, lod_ipart, &ilevel0);
1035 break;
1036 case PIPE_TEX_MIPFILTER_LINEAR:
1037 assert(lod_ipart);
1038 assert(lod_fpart);
1039 lp_build_linear_mip_levels(bld, unit,
1040 lod_ipart, &lod_fpart,
1041 &ilevel0, &ilevel1);
1042 break;
1043 }
1044
1045 /*
1046 * Get/interpolate texture colors.
1047 */
1048
1049 for (chan = 0; chan < 4; ++chan) {
1050 texels[chan] = lp_build_alloca(builder, bld->texel_bld.vec_type, "");
1051 lp_build_name(texels[chan], "sampler%u_texel_%c_var", unit, "xyzw"[chan]);
1052 }
1053
1054 if (min_filter == mag_filter) {
1055 /* no need to distinquish between minification and magnification */
1056 lp_build_sample_mipmap(bld, unit,
1057 min_filter, mip_filter,
1058 s, t, r,
1059 ilevel0, ilevel1, lod_fpart,
1060 texels);
1061 }
1062 else {
1063 /* Emit conditional to choose min image filter or mag image filter
1064 * depending on the lod being > 0 or <= 0, respectively.
1065 */
1066 struct lp_build_flow_context *flow_ctx;
1067 struct lp_build_if_state if_ctx;
1068 LLVMValueRef minify;
1069
1070 flow_ctx = lp_build_flow_create(builder);
1071
1072 /* minify = lod >= 0.0 */
1073 minify = LLVMBuildICmp(builder, LLVMIntSGE,
1074 lod_ipart, int_bld->zero, "");
1075
1076 lp_build_if(&if_ctx, flow_ctx, builder, minify);
1077 {
1078 /* Use the minification filter */
1079 lp_build_sample_mipmap(bld, unit,
1080 min_filter, mip_filter,
1081 s, t, r,
1082 ilevel0, ilevel1, lod_fpart,
1083 texels);
1084 }
1085 lp_build_else(&if_ctx);
1086 {
1087 /* Use the magnification filter */
1088 lp_build_sample_mipmap(bld, unit,
1089 mag_filter, PIPE_TEX_MIPFILTER_NONE,
1090 s, t, r,
1091 i32t_zero, NULL, NULL,
1092 texels);
1093 }
1094 lp_build_endif(&if_ctx);
1095
1096 lp_build_flow_destroy(flow_ctx);
1097 }
1098
1099 for (chan = 0; chan < 4; ++chan) {
1100 colors_out[chan] = LLVMBuildLoad(builder, texels[chan], "");
1101 lp_build_name(colors_out[chan], "sampler%u_texel_%c", unit, "xyzw"[chan]);
1102 }
1103 }
1104
1105
1106 /**
1107 * Do shadow test/comparison.
1108 * \param p the texcoord Z (aka R, aka P) component
1109 * \param texel the texel to compare against (use the X channel)
1110 */
1111 static void
1112 lp_build_sample_compare(struct lp_build_sample_context *bld,
1113 LLVMValueRef p,
1114 LLVMValueRef texel[4])
1115 {
1116 struct lp_build_context *texel_bld = &bld->texel_bld;
1117 LLVMValueRef res;
1118 const unsigned chan = 0;
1119
1120 if (bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE)
1121 return;
1122
1123 /* debug code */
1124 if (0) {
1125 LLVMValueRef indx = lp_build_const_int32(0);
1126 LLVMValueRef coord = LLVMBuildExtractElement(bld->builder, p, indx, "");
1127 LLVMValueRef tex = LLVMBuildExtractElement(bld->builder,
1128 texel[chan], indx, "");
1129 lp_build_printf(bld->builder, "shadow compare coord %f to texture %f\n",
1130 coord, tex);
1131 }
1132
1133 /* result = (p FUNC texel) ? 1 : 0 */
1134 res = lp_build_cmp(texel_bld, bld->static_state->compare_func,
1135 p, texel[chan]);
1136 res = lp_build_select(texel_bld, res, texel_bld->one, texel_bld->zero);
1137
1138 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
1139 texel[0] =
1140 texel[1] =
1141 texel[2] = res;
1142 texel[3] = texel_bld->one;
1143 }
1144
1145
1146 /**
1147 * Just set texels to white instead of actually sampling the texture.
1148 * For debugging.
1149 */
1150 void
1151 lp_build_sample_nop(struct lp_type type,
1152 LLVMValueRef texel_out[4])
1153 {
1154 LLVMValueRef one = lp_build_one(type);
1155 unsigned chan;
1156
1157 for (chan = 0; chan < 4; chan++) {
1158 texel_out[chan] = one;
1159 }
1160 }
1161
1162
1163 /**
1164 * Build texture sampling code.
1165 * 'texel' will return a vector of four LLVMValueRefs corresponding to
1166 * R, G, B, A.
1167 * \param type vector float type to use for coords, etc.
1168 * \param ddx partial derivatives of (s,t,r,q) with respect to x
1169 * \param ddy partial derivatives of (s,t,r,q) with respect to y
1170 */
1171 void
1172 lp_build_sample_soa(LLVMBuilderRef builder,
1173 const struct lp_sampler_static_state *static_state,
1174 struct lp_sampler_dynamic_state *dynamic_state,
1175 struct lp_type type,
1176 unsigned unit,
1177 unsigned num_coords,
1178 const LLVMValueRef *coords,
1179 const LLVMValueRef ddx[4],
1180 const LLVMValueRef ddy[4],
1181 LLVMValueRef lod_bias, /* optional */
1182 LLVMValueRef explicit_lod, /* optional */
1183 LLVMValueRef texel_out[4])
1184 {
1185 unsigned dims = texture_dims(static_state->target);
1186 struct lp_build_sample_context bld;
1187 LLVMTypeRef i32t = LLVMInt32Type();
1188
1189 LLVMValueRef s;
1190 LLVMValueRef t;
1191 LLVMValueRef r;
1192 struct lp_type float_vec_type;
1193
1194 if (0) {
1195 enum pipe_format fmt = static_state->format;
1196 debug_printf("Sample from %s\n", util_format_name(fmt));
1197 }
1198
1199 assert(type.floating);
1200
1201 /* Setup our build context */
1202 memset(&bld, 0, sizeof bld);
1203 bld.builder = builder;
1204 bld.static_state = static_state;
1205 bld.dynamic_state = dynamic_state;
1206 bld.format_desc = util_format_description(static_state->format);
1207 bld.dims = dims;
1208
1209 bld.float_type = lp_type_float(32);
1210 bld.int_type = lp_type_int(32);
1211 bld.coord_type = type;
1212 bld.uint_coord_type = lp_uint_type(type);
1213 bld.int_coord_type = lp_int_type(type);
1214 bld.float_size_type = lp_type_float(32);
1215 bld.float_size_type.length = dims > 1 ? 4 : 1;
1216 bld.int_size_type = lp_int_type(bld.float_size_type);
1217 bld.texel_type = type;
1218
1219 float_vec_type = lp_type_float_vec(32);
1220
1221 lp_build_context_init(&bld.float_bld, builder, bld.float_type);
1222 lp_build_context_init(&bld.float_vec_bld, builder, float_vec_type);
1223 lp_build_context_init(&bld.int_bld, builder, bld.int_type);
1224 lp_build_context_init(&bld.coord_bld, builder, bld.coord_type);
1225 lp_build_context_init(&bld.uint_coord_bld, builder, bld.uint_coord_type);
1226 lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type);
1227 lp_build_context_init(&bld.int_size_bld, builder, bld.int_size_type);
1228 lp_build_context_init(&bld.float_size_bld, builder, bld.float_size_type);
1229 lp_build_context_init(&bld.texel_bld, builder, bld.texel_type);
1230
1231 /* Get the dynamic state */
1232 bld.width = dynamic_state->width(dynamic_state, builder, unit);
1233 bld.height = dynamic_state->height(dynamic_state, builder, unit);
1234 bld.depth = dynamic_state->depth(dynamic_state, builder, unit);
1235 bld.row_stride_array = dynamic_state->row_stride(dynamic_state, builder, unit);
1236 bld.img_stride_array = dynamic_state->img_stride(dynamic_state, builder, unit);
1237 bld.data_array = dynamic_state->data_ptr(dynamic_state, builder, unit);
1238 /* Note that data_array is an array[level] of pointers to texture images */
1239
1240 s = coords[0];
1241 t = coords[1];
1242 r = coords[2];
1243
1244 /* width, height, depth as single int vector */
1245 if (dims <= 1) {
1246 bld.int_size = bld.width;
1247 }
1248 else {
1249 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size_bld.undef,
1250 bld.width, LLVMConstInt(i32t, 0, 0), "");
1251 if (dims >= 2) {
1252 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size,
1253 bld.height, LLVMConstInt(i32t, 1, 0), "");
1254 if (dims >= 3) {
1255 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size,
1256 bld.depth, LLVMConstInt(i32t, 2, 0), "");
1257 }
1258 }
1259 }
1260
1261 if (0) {
1262 /* For debug: no-op texture sampling */
1263 lp_build_sample_nop(bld.texel_type, texel_out);
1264 }
1265 else if (util_format_fits_8unorm(bld.format_desc) &&
1266 lp_is_simple_wrap_mode(static_state->wrap_s) &&
1267 lp_is_simple_wrap_mode(static_state->wrap_t)) {
1268 /* do sampling/filtering with fixed pt arithmetic */
1269 lp_build_sample_aos(&bld, unit, s, t, r, ddx, ddy,
1270 lod_bias, explicit_lod,
1271 texel_out);
1272 }
1273
1274 else {
1275 if ((gallivm_debug & GALLIVM_DEBUG_PERF) &&
1276 util_format_fits_8unorm(bld.format_desc)) {
1277 debug_printf("%s: using floating point linear filtering for %s\n",
1278 __FUNCTION__, bld.format_desc->short_name);
1279 debug_printf(" min_img %d mag_img %d mip %d wraps %d wrapt %d\n",
1280 static_state->min_img_filter,
1281 static_state->mag_img_filter,
1282 static_state->min_mip_filter,
1283 static_state->wrap_s,
1284 static_state->wrap_t);
1285 }
1286
1287 lp_build_sample_general(&bld, unit, s, t, r, ddx, ddy,
1288 lod_bias, explicit_lod,
1289 texel_out);
1290 }
1291
1292 lp_build_sample_compare(&bld, r, texel_out);
1293 }