lp_bld_sample_soa.c revision e1003336f0dcd9248c0127fbdc173522e35c5bdb
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 */ 70static void 71lp_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->int_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->int_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 */ 197static LLVMValueRef 198lp_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 */ 229static void 230lp_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 LLVMValueRef half = lp_build_const_vec(coord_bld->type, 0.5); 243 LLVMValueRef length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one); 244 LLVMValueRef coord0, coord1, weight; 245 246 switch(wrap_mode) { 247 case PIPE_TEX_WRAP_REPEAT: 248 /* mul by size and subtract 0.5 */ 249 coord = lp_build_mul(coord_bld, coord, length_f); 250 coord = lp_build_sub(coord_bld, coord, half); 251 /* convert to int, compute lerp weight */ 252 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 253 /* repeat wrap */ 254 if (is_pot) { 255 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 256 coord0 = LLVMBuildAnd(bld->builder, coord0, length_minus_one, ""); 257 coord1 = LLVMBuildAnd(bld->builder, coord1, length_minus_one, ""); 258 } 259 else { 260 /* Add a bias to the texcoord to handle negative coords */ 261 LLVMValueRef bias = lp_build_mul_imm(int_coord_bld, length, 1024); 262 LLVMValueRef mask; 263 coord0 = LLVMBuildAdd(bld->builder, coord0, bias, ""); 264 coord0 = LLVMBuildURem(bld->builder, coord0, length, ""); 265 mask = lp_build_compare(bld->builder, int_coord_bld->type, 266 PIPE_FUNC_NOTEQUAL, coord0, length_minus_one); 267 coord1 = LLVMBuildAnd(bld->builder, 268 lp_build_add(int_coord_bld, coord0, int_coord_bld->one), 269 mask, ""); 270 } 271 break; 272 273 case PIPE_TEX_WRAP_CLAMP: 274 if (bld->static_state->normalized_coords) { 275 /* scale coord to length */ 276 coord = lp_build_mul(coord_bld, coord, length_f); 277 } 278 279 /* clamp to [0, length] */ 280 coord = lp_build_clamp(coord_bld, coord, coord_bld->zero, length_f); 281 282 coord = lp_build_sub(coord_bld, coord, half); 283 284 /* convert to int, compute lerp weight */ 285 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 286 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 287 break; 288 289 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 290 { 291 struct lp_build_context abs_coord_bld = bld->coord_bld; 292 abs_coord_bld.type.sign = FALSE; 293 294 if (bld->static_state->normalized_coords) { 295 /* mul by tex size */ 296 coord = lp_build_mul(coord_bld, coord, length_f); 297 /* clamp to length max */ 298 coord = lp_build_min(coord_bld, coord, length_f); 299 /* subtract 0.5 */ 300 coord = lp_build_sub(coord_bld, coord, half); 301 /* clamp to [0, length - 0.5] */ 302 coord = lp_build_max(coord_bld, coord, coord_bld->zero); 303 } 304 /* XXX this is odd normalized ranges from 0 to length-0.5 after denorm 305 but non-normalized ranges from to 0.5 to length-0.5 after clamp. 306 Is this missing the sub 0.5? */ 307 else { 308 LLVMValueRef min, max; 309 /* clamp to [0.5, length - 0.5] */ 310 min = half; 311 max = lp_build_sub(coord_bld, length_f, min); 312 coord = lp_build_clamp(coord_bld, coord, min, max); 313 } 314 /* convert to int, compute lerp weight */ 315 lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight); 316 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 317 /* coord1 = min(coord1, length-1) */ 318 coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one); 319 break; 320 } 321 322 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 323 { 324 LLVMValueRef min; 325 if (bld->static_state->normalized_coords) { 326 /* scale coord to length */ 327 coord = lp_build_mul(coord_bld, coord, length_f); 328 } 329 /* was: clamp to [-0.5, length + 0.5], then sub 0.5 */ 330 coord = lp_build_sub(coord_bld, coord, half); 331 min = lp_build_const_vec(coord_bld->type, -1.0F); 332 coord = lp_build_clamp(coord_bld, coord, min, length_f); 333 /* convert to int, compute lerp weight */ 334 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 335 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 336 } 337 break; 338 339 case PIPE_TEX_WRAP_MIRROR_REPEAT: 340 /* compute mirror function */ 341 coord = lp_build_coord_mirror(bld, coord); 342 343 /* scale coord to length */ 344 coord = lp_build_mul(coord_bld, coord, length_f); 345 coord = lp_build_sub(coord_bld, coord, half); 346 347 /* convert to int, compute lerp weight */ 348 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 349 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 350 351 /* coord0 = max(coord0, 0) */ 352 coord0 = lp_build_max(int_coord_bld, coord0, int_coord_bld->zero); 353 /* coord1 = min(coord1, length-1) */ 354 coord1 = lp_build_min(int_coord_bld, coord1, length_minus_one); 355 break; 356 357 case PIPE_TEX_WRAP_MIRROR_CLAMP: 358 coord = lp_build_abs(coord_bld, coord); 359 360 if (bld->static_state->normalized_coords) { 361 /* scale coord to length */ 362 coord = lp_build_mul(coord_bld, coord, length_f); 363 } 364 365 /* clamp to [0, length] */ 366 coord = lp_build_min(coord_bld, coord, length_f); 367 368 coord = lp_build_sub(coord_bld, coord, half); 369 370 /* convert to int, compute lerp weight */ 371 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 372 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 373 break; 374 375 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 376 { 377 LLVMValueRef min, max; 378 struct lp_build_context abs_coord_bld = bld->coord_bld; 379 abs_coord_bld.type.sign = FALSE; 380 coord = lp_build_abs(coord_bld, coord); 381 382 if (bld->static_state->normalized_coords) { 383 /* scale coord to length */ 384 coord = lp_build_mul(coord_bld, coord, length_f); 385 } 386 387 /* clamp to [0.5, length - 0.5] */ 388 min = half; 389 max = lp_build_sub(coord_bld, length_f, min); 390 coord = lp_build_clamp(coord_bld, coord, min, max); 391 392 coord = lp_build_sub(coord_bld, coord, half); 393 394 /* convert to int, compute lerp weight */ 395 lp_build_ifloor_fract(&abs_coord_bld, coord, &coord0, &weight); 396 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 397 } 398 break; 399 400 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 401 { 402 coord = lp_build_abs(coord_bld, coord); 403 404 if (bld->static_state->normalized_coords) { 405 /* scale coord to length */ 406 coord = lp_build_mul(coord_bld, coord, length_f); 407 } 408 409 /* was: clamp to [-0.5, length + 0.5] then sub 0.5 */ 410 /* skip -0.5 clamp (always positive), do sub first */ 411 coord = lp_build_sub(coord_bld, coord, half); 412 coord = lp_build_min(coord_bld, coord, length_f); 413 414 /* convert to int, compute lerp weight */ 415 lp_build_ifloor_fract(coord_bld, coord, &coord0, &weight); 416 coord1 = lp_build_add(int_coord_bld, coord0, int_coord_bld->one); 417 } 418 break; 419 420 default: 421 assert(0); 422 coord0 = NULL; 423 coord1 = NULL; 424 weight = NULL; 425 } 426 427 *x0_out = coord0; 428 *x1_out = coord1; 429 *weight_out = weight; 430} 431 432 433/** 434 * Build LLVM code for texture wrap mode for nearest filtering. 435 * \param coord the incoming texcoord (nominally in [0,1]) 436 * \param length the texture size along one dimension, as int vector 437 * \param is_pot if TRUE, length is a power of two 438 * \param wrap_mode one of PIPE_TEX_WRAP_x 439 */ 440static LLVMValueRef 441lp_build_sample_wrap_nearest(struct lp_build_sample_context *bld, 442 LLVMValueRef coord, 443 LLVMValueRef length, 444 LLVMValueRef length_f, 445 boolean is_pot, 446 unsigned wrap_mode) 447{ 448 struct lp_build_context *coord_bld = &bld->coord_bld; 449 struct lp_build_context *int_coord_bld = &bld->int_coord_bld; 450 LLVMValueRef length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one); 451 LLVMValueRef icoord; 452 453 switch(wrap_mode) { 454 case PIPE_TEX_WRAP_REPEAT: 455 coord = lp_build_mul(coord_bld, coord, length_f); 456 icoord = lp_build_ifloor(coord_bld, coord); 457 if (is_pot) 458 icoord = LLVMBuildAnd(bld->builder, icoord, length_minus_one, ""); 459 else { 460 /* Add a bias to the texcoord to handle negative coords */ 461 LLVMValueRef bias = lp_build_mul_imm(int_coord_bld, length, 1024); 462 icoord = LLVMBuildAdd(bld->builder, icoord, bias, ""); 463 icoord = LLVMBuildURem(bld->builder, icoord, length, ""); 464 } 465 break; 466 467 case PIPE_TEX_WRAP_CLAMP: 468 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 469 if (bld->static_state->normalized_coords) { 470 /* scale coord to length */ 471 coord = lp_build_mul(coord_bld, coord, length_f); 472 } 473 474 /* floor */ 475 /* use itrunc instead since we clamp to 0 anyway */ 476 icoord = lp_build_itrunc(coord_bld, coord); 477 478 /* clamp to [0, length - 1]. */ 479 icoord = lp_build_clamp(int_coord_bld, icoord, int_coord_bld->zero, 480 length_minus_one); 481 break; 482 483 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 484 /* Note: this is the same as CLAMP_TO_EDGE, except min = -min */ 485 { 486 LLVMValueRef min, max; 487 488 if (bld->static_state->normalized_coords) { 489 /* scale coord to length */ 490 coord = lp_build_mul(coord_bld, coord, length_f); 491 } 492 493 icoord = lp_build_ifloor(coord_bld, coord); 494 495 /* clamp to [-1, length] */ 496 min = lp_build_negate(int_coord_bld, int_coord_bld->one); 497 max = length; 498 icoord = lp_build_clamp(int_coord_bld, icoord, min, max); 499 } 500 break; 501 502 case PIPE_TEX_WRAP_MIRROR_REPEAT: 503 /* compute mirror function */ 504 coord = lp_build_coord_mirror(bld, coord); 505 506 /* scale coord to length */ 507 assert(bld->static_state->normalized_coords); 508 coord = lp_build_mul(coord_bld, coord, length_f); 509 510 /* itrunc == ifloor here */ 511 icoord = lp_build_itrunc(coord_bld, coord); 512 513 /* clamp to [0, length - 1] */ 514 icoord = lp_build_min(int_coord_bld, icoord, length_minus_one); 515 break; 516 517 case PIPE_TEX_WRAP_MIRROR_CLAMP: 518 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 519 coord = lp_build_abs(coord_bld, coord); 520 521 if (bld->static_state->normalized_coords) { 522 /* scale coord to length */ 523 coord = lp_build_mul(coord_bld, coord, length_f); 524 } 525 526 /* itrunc == ifloor here */ 527 icoord = lp_build_itrunc(coord_bld, coord); 528 529 /* clamp to [0, length - 1] */ 530 icoord = lp_build_min(int_coord_bld, icoord, length_minus_one); 531 break; 532 533 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 534 coord = lp_build_abs(coord_bld, coord); 535 536 if (bld->static_state->normalized_coords) { 537 /* scale coord to length */ 538 coord = lp_build_mul(coord_bld, coord, length_f); 539 } 540 541 /* itrunc == ifloor here */ 542 icoord = lp_build_itrunc(coord_bld, coord); 543 544 /* clamp to [0, length] */ 545 icoord = lp_build_min(int_coord_bld, icoord, length); 546 break; 547 548 default: 549 assert(0); 550 icoord = NULL; 551 } 552 553 return icoord; 554} 555 556 557/** 558 * Generate code to sample a mipmap level with nearest filtering. 559 * If sampling a cube texture, r = cube face in [0,5]. 560 */ 561static void 562lp_build_sample_image_nearest(struct lp_build_sample_context *bld, 563 unsigned unit, 564 LLVMValueRef size, 565 LLVMValueRef row_stride_vec, 566 LLVMValueRef img_stride_vec, 567 LLVMValueRef data_ptr, 568 LLVMValueRef s, 569 LLVMValueRef t, 570 LLVMValueRef r, 571 LLVMValueRef colors_out[4]) 572{ 573 const unsigned dims = bld->dims; 574 LLVMValueRef width_vec; 575 LLVMValueRef height_vec; 576 LLVMValueRef depth_vec; 577 LLVMValueRef flt_size; 578 LLVMValueRef flt_width_vec; 579 LLVMValueRef flt_height_vec; 580 LLVMValueRef flt_depth_vec; 581 LLVMValueRef x, y, z; 582 583 lp_build_extract_image_sizes(bld, 584 bld->int_size_type, 585 bld->int_coord_type, 586 size, 587 &width_vec, &height_vec, &depth_vec); 588 589 flt_size = lp_build_int_to_float(&bld->float_size_bld, size); 590 591 lp_build_extract_image_sizes(bld, 592 bld->float_size_type, 593 bld->coord_type, 594 flt_size, 595 &flt_width_vec, &flt_height_vec, &flt_depth_vec); 596 597 /* 598 * Compute integer texcoords. 599 */ 600 x = lp_build_sample_wrap_nearest(bld, s, width_vec, flt_width_vec, 601 bld->static_state->pot_width, 602 bld->static_state->wrap_s); 603 lp_build_name(x, "tex.x.wrapped"); 604 605 if (dims >= 2) { 606 y = lp_build_sample_wrap_nearest(bld, t, height_vec, flt_height_vec, 607 bld->static_state->pot_height, 608 bld->static_state->wrap_t); 609 lp_build_name(y, "tex.y.wrapped"); 610 611 if (dims == 3) { 612 z = lp_build_sample_wrap_nearest(bld, r, depth_vec, flt_depth_vec, 613 bld->static_state->pot_depth, 614 bld->static_state->wrap_r); 615 lp_build_name(z, "tex.z.wrapped"); 616 } 617 else if (bld->static_state->target == PIPE_TEXTURE_CUBE) { 618 z = r; 619 } 620 else { 621 z = NULL; 622 } 623 } 624 else { 625 y = z = NULL; 626 } 627 628 /* 629 * Get texture colors. 630 */ 631 lp_build_sample_texel_soa(bld, unit, 632 width_vec, height_vec, depth_vec, 633 x, y, z, 634 row_stride_vec, img_stride_vec, 635 data_ptr, colors_out); 636} 637 638 639/** 640 * Generate code to sample a mipmap level with linear filtering. 641 * If sampling a cube texture, r = cube face in [0,5]. 642 */ 643static void 644lp_build_sample_image_linear(struct lp_build_sample_context *bld, 645 unsigned unit, 646 LLVMValueRef size, 647 LLVMValueRef row_stride_vec, 648 LLVMValueRef img_stride_vec, 649 LLVMValueRef data_ptr, 650 LLVMValueRef s, 651 LLVMValueRef t, 652 LLVMValueRef r, 653 LLVMValueRef colors_out[4]) 654{ 655 const unsigned dims = bld->dims; 656 LLVMValueRef width_vec; 657 LLVMValueRef height_vec; 658 LLVMValueRef depth_vec; 659 LLVMValueRef flt_size; 660 LLVMValueRef flt_width_vec; 661 LLVMValueRef flt_height_vec; 662 LLVMValueRef flt_depth_vec; 663 LLVMValueRef x0, y0, z0, x1, y1, z1; 664 LLVMValueRef s_fpart, t_fpart, r_fpart; 665 LLVMValueRef neighbors[2][2][4]; 666 int chan; 667 668 lp_build_extract_image_sizes(bld, 669 bld->int_size_type, 670 bld->int_coord_type, 671 size, 672 &width_vec, &height_vec, &depth_vec); 673 674 flt_size = lp_build_int_to_float(&bld->float_size_bld, size); 675 676 lp_build_extract_image_sizes(bld, 677 bld->float_size_type, 678 bld->coord_type, 679 flt_size, 680 &flt_width_vec, &flt_height_vec, &flt_depth_vec); 681 682 /* 683 * Compute integer texcoords. 684 */ 685 lp_build_sample_wrap_linear(bld, s, width_vec, flt_width_vec, 686 bld->static_state->pot_width, 687 bld->static_state->wrap_s, 688 &x0, &x1, &s_fpart); 689 lp_build_name(x0, "tex.x0.wrapped"); 690 lp_build_name(x1, "tex.x1.wrapped"); 691 692 if (dims >= 2) { 693 lp_build_sample_wrap_linear(bld, t, height_vec, flt_height_vec, 694 bld->static_state->pot_height, 695 bld->static_state->wrap_t, 696 &y0, &y1, &t_fpart); 697 lp_build_name(y0, "tex.y0.wrapped"); 698 lp_build_name(y1, "tex.y1.wrapped"); 699 700 if (dims == 3) { 701 lp_build_sample_wrap_linear(bld, r, depth_vec, flt_depth_vec, 702 bld->static_state->pot_depth, 703 bld->static_state->wrap_r, 704 &z0, &z1, &r_fpart); 705 lp_build_name(z0, "tex.z0.wrapped"); 706 lp_build_name(z1, "tex.z1.wrapped"); 707 } 708 else if (bld->static_state->target == PIPE_TEXTURE_CUBE) { 709 z0 = z1 = r; /* cube face */ 710 r_fpart = NULL; 711 } 712 else { 713 z0 = z1 = NULL; 714 r_fpart = NULL; 715 } 716 } 717 else { 718 y0 = y1 = t_fpart = NULL; 719 z0 = z1 = r_fpart = NULL; 720 } 721 722 /* 723 * Get texture colors. 724 */ 725 /* get x0/x1 texels */ 726 lp_build_sample_texel_soa(bld, unit, 727 width_vec, height_vec, depth_vec, 728 x0, y0, z0, 729 row_stride_vec, img_stride_vec, 730 data_ptr, neighbors[0][0]); 731 lp_build_sample_texel_soa(bld, unit, 732 width_vec, height_vec, depth_vec, 733 x1, y0, z0, 734 row_stride_vec, img_stride_vec, 735 data_ptr, neighbors[0][1]); 736 737 if (dims == 1) { 738 /* Interpolate two samples from 1D image to produce one color */ 739 for (chan = 0; chan < 4; chan++) { 740 colors_out[chan] = lp_build_lerp(&bld->texel_bld, s_fpart, 741 neighbors[0][0][chan], 742 neighbors[0][1][chan]); 743 } 744 } 745 else { 746 /* 2D/3D texture */ 747 LLVMValueRef colors0[4]; 748 749 /* get x0/x1 texels at y1 */ 750 lp_build_sample_texel_soa(bld, unit, 751 width_vec, height_vec, depth_vec, 752 x0, y1, z0, 753 row_stride_vec, img_stride_vec, 754 data_ptr, neighbors[1][0]); 755 lp_build_sample_texel_soa(bld, unit, 756 width_vec, height_vec, depth_vec, 757 x1, y1, z0, 758 row_stride_vec, img_stride_vec, 759 data_ptr, neighbors[1][1]); 760 761 /* Bilinear interpolate the four samples from the 2D image / 3D slice */ 762 for (chan = 0; chan < 4; chan++) { 763 colors0[chan] = lp_build_lerp_2d(&bld->texel_bld, 764 s_fpart, t_fpart, 765 neighbors[0][0][chan], 766 neighbors[0][1][chan], 767 neighbors[1][0][chan], 768 neighbors[1][1][chan]); 769 } 770 771 if (dims == 3) { 772 LLVMValueRef neighbors1[2][2][4]; 773 LLVMValueRef colors1[4]; 774 775 /* get x0/x1/y0/y1 texels at z1 */ 776 lp_build_sample_texel_soa(bld, unit, 777 width_vec, height_vec, depth_vec, 778 x0, y0, z1, 779 row_stride_vec, img_stride_vec, 780 data_ptr, neighbors1[0][0]); 781 lp_build_sample_texel_soa(bld, unit, 782 width_vec, height_vec, depth_vec, 783 x1, y0, z1, 784 row_stride_vec, img_stride_vec, 785 data_ptr, neighbors1[0][1]); 786 lp_build_sample_texel_soa(bld, unit, 787 width_vec, height_vec, depth_vec, 788 x0, y1, z1, 789 row_stride_vec, img_stride_vec, 790 data_ptr, neighbors1[1][0]); 791 lp_build_sample_texel_soa(bld, unit, 792 width_vec, height_vec, depth_vec, 793 x1, y1, z1, 794 row_stride_vec, img_stride_vec, 795 data_ptr, neighbors1[1][1]); 796 797 /* Bilinear interpolate the four samples from the second Z slice */ 798 for (chan = 0; chan < 4; chan++) { 799 colors1[chan] = lp_build_lerp_2d(&bld->texel_bld, 800 s_fpart, t_fpart, 801 neighbors1[0][0][chan], 802 neighbors1[0][1][chan], 803 neighbors1[1][0][chan], 804 neighbors1[1][1][chan]); 805 } 806 807 /* Linearly interpolate the two samples from the two 3D slices */ 808 for (chan = 0; chan < 4; chan++) { 809 colors_out[chan] = lp_build_lerp(&bld->texel_bld, 810 r_fpart, 811 colors0[chan], colors1[chan]); 812 } 813 } 814 else { 815 /* 2D tex */ 816 for (chan = 0; chan < 4; chan++) { 817 colors_out[chan] = colors0[chan]; 818 } 819 } 820 } 821} 822 823 824/** 825 * Sample the texture/mipmap using given image filter and mip filter. 826 * data0_ptr and data1_ptr point to the two mipmap levels to sample 827 * from. width0/1_vec, height0/1_vec, depth0/1_vec indicate their sizes. 828 * If we're using nearest miplevel sampling the '1' values will be null/unused. 829 */ 830static void 831lp_build_sample_mipmap(struct lp_build_sample_context *bld, 832 unsigned unit, 833 unsigned img_filter, 834 unsigned mip_filter, 835 LLVMValueRef s, 836 LLVMValueRef t, 837 LLVMValueRef r, 838 LLVMValueRef ilevel0, 839 LLVMValueRef ilevel1, 840 LLVMValueRef lod_fpart, 841 LLVMValueRef *colors_out) 842{ 843 LLVMBuilderRef builder = bld->builder; 844 LLVMValueRef size0; 845 LLVMValueRef size1; 846 LLVMValueRef row_stride0_vec; 847 LLVMValueRef row_stride1_vec; 848 LLVMValueRef img_stride0_vec; 849 LLVMValueRef img_stride1_vec; 850 LLVMValueRef data_ptr0; 851 LLVMValueRef data_ptr1; 852 LLVMValueRef colors0[4], colors1[4]; 853 unsigned chan; 854 855 /* sample the first mipmap level */ 856 lp_build_mipmap_level_sizes(bld, ilevel0, 857 &size0, 858 &row_stride0_vec, &img_stride0_vec); 859 data_ptr0 = lp_build_get_mipmap_level(bld, ilevel0); 860 if (img_filter == PIPE_TEX_FILTER_NEAREST) { 861 lp_build_sample_image_nearest(bld, unit, 862 size0, 863 row_stride0_vec, img_stride0_vec, 864 data_ptr0, s, t, r, 865 colors0); 866 } 867 else { 868 assert(img_filter == PIPE_TEX_FILTER_LINEAR); 869 lp_build_sample_image_linear(bld, unit, 870 size0, 871 row_stride0_vec, img_stride0_vec, 872 data_ptr0, s, t, r, 873 colors0); 874 } 875 876 /* Store the first level's colors in the output variables */ 877 for (chan = 0; chan < 4; chan++) { 878 LLVMBuildStore(builder, colors0[chan], colors_out[chan]); 879 } 880 881 if (mip_filter == PIPE_TEX_MIPFILTER_LINEAR) { 882 struct lp_build_if_state if_ctx; 883 LLVMValueRef need_lerp; 884 885 /* need_lerp = lod_fpart > 0 */ 886 need_lerp = LLVMBuildFCmp(builder, LLVMRealUGT, 887 lod_fpart, 888 bld->float_bld.zero, 889 "need_lerp"); 890 891 lp_build_if(&if_ctx, builder, need_lerp); 892 { 893 /* sample the second mipmap level */ 894 lp_build_mipmap_level_sizes(bld, ilevel1, 895 &size1, 896 &row_stride1_vec, &img_stride1_vec); 897 data_ptr1 = lp_build_get_mipmap_level(bld, ilevel1); 898 if (img_filter == PIPE_TEX_FILTER_NEAREST) { 899 lp_build_sample_image_nearest(bld, unit, 900 size1, 901 row_stride1_vec, img_stride1_vec, 902 data_ptr1, s, t, r, 903 colors1); 904 } 905 else { 906 lp_build_sample_image_linear(bld, unit, 907 size1, 908 row_stride1_vec, img_stride1_vec, 909 data_ptr1, s, t, r, 910 colors1); 911 } 912 913 /* interpolate samples from the two mipmap levels */ 914 915 lod_fpart = lp_build_broadcast_scalar(&bld->texel_bld, lod_fpart); 916 917 for (chan = 0; chan < 4; chan++) { 918 colors0[chan] = lp_build_lerp(&bld->texel_bld, lod_fpart, 919 colors0[chan], colors1[chan]); 920 LLVMBuildStore(builder, colors0[chan], colors_out[chan]); 921 } 922 } 923 lp_build_endif(&if_ctx); 924 } 925} 926 927 928 929/** 930 * General texture sampling codegen. 931 * This function handles texture sampling for all texture targets (1D, 932 * 2D, 3D, cube) and all filtering modes. 933 */ 934static void 935lp_build_sample_general(struct lp_build_sample_context *bld, 936 unsigned unit, 937 LLVMValueRef s, 938 LLVMValueRef t, 939 LLVMValueRef r, 940 const LLVMValueRef *ddx, 941 const LLVMValueRef *ddy, 942 LLVMValueRef lod_bias, /* optional */ 943 LLVMValueRef explicit_lod, /* optional */ 944 LLVMValueRef *colors_out) 945{ 946 struct lp_build_context *int_bld = &bld->int_bld; 947 LLVMBuilderRef builder = bld->builder; 948 const unsigned mip_filter = bld->static_state->min_mip_filter; 949 const unsigned min_filter = bld->static_state->min_img_filter; 950 const unsigned mag_filter = bld->static_state->mag_img_filter; 951 LLVMValueRef lod_ipart = NULL, lod_fpart = NULL; 952 LLVMValueRef ilevel0, ilevel1 = NULL; 953 LLVMValueRef face_ddx[4], face_ddy[4]; 954 LLVMValueRef texels[4]; 955 LLVMTypeRef i32t = LLVMInt32Type(); 956 LLVMValueRef i32t_zero = LLVMConstInt(i32t, 0, 0); 957 unsigned chan; 958 959 /* 960 printf("%s mip %d min %d mag %d\n", __FUNCTION__, 961 mip_filter, min_filter, mag_filter); 962 */ 963 964 /* 965 * Choose cube face, recompute texcoords and derivatives for the chosen face. 966 */ 967 if (bld->static_state->target == PIPE_TEXTURE_CUBE) { 968 LLVMValueRef face, face_s, face_t; 969 lp_build_cube_lookup(bld, s, t, r, &face, &face_s, &face_t); 970 s = face_s; /* vec */ 971 t = face_t; /* vec */ 972 /* use 'r' to indicate cube face */ 973 r = lp_build_broadcast_scalar(&bld->int_coord_bld, face); /* vec */ 974 975 /* recompute ddx, ddy using the new (s,t) face texcoords */ 976 face_ddx[0] = lp_build_ddx(&bld->coord_bld, s); 977 face_ddx[1] = lp_build_ddx(&bld->coord_bld, t); 978 face_ddx[2] = NULL; 979 face_ddx[3] = NULL; 980 face_ddy[0] = lp_build_ddy(&bld->coord_bld, s); 981 face_ddy[1] = lp_build_ddy(&bld->coord_bld, t); 982 face_ddy[2] = NULL; 983 face_ddy[3] = NULL; 984 ddx = face_ddx; 985 ddy = face_ddy; 986 } 987 988 /* 989 * Compute the level of detail (float). 990 */ 991 if (min_filter != mag_filter || 992 mip_filter != PIPE_TEX_MIPFILTER_NONE) { 993 /* Need to compute lod either to choose mipmap levels or to 994 * distinguish between minification/magnification with one mipmap level. 995 */ 996 lp_build_lod_selector(bld, unit, ddx, ddy, 997 lod_bias, explicit_lod, 998 mip_filter, 999 &lod_ipart, &lod_fpart); 1000 } else { 1001 lod_ipart = i32t_zero; 1002 } 1003 1004 /* 1005 * Compute integer mipmap level(s) to fetch texels from: ilevel0, ilevel1 1006 */ 1007 switch (mip_filter) { 1008 default: 1009 assert(0 && "bad mip_filter value in lp_build_sample_soa()"); 1010 /* fall-through */ 1011 case PIPE_TEX_MIPFILTER_NONE: 1012 /* always use mip level 0 */ 1013 if (bld->static_state->target == PIPE_TEXTURE_CUBE) { 1014 /* XXX this is a work-around for an apparent bug in LLVM 2.7. 1015 * We should be able to set ilevel0 = const(0) but that causes 1016 * bad x86 code to be emitted. 1017 */ 1018 assert(lod_ipart); 1019 lp_build_nearest_mip_level(bld, unit, lod_ipart, &ilevel0); 1020 } 1021 else { 1022 ilevel0 = i32t_zero; 1023 } 1024 break; 1025 case PIPE_TEX_MIPFILTER_NEAREST: 1026 assert(lod_ipart); 1027 lp_build_nearest_mip_level(bld, unit, lod_ipart, &ilevel0); 1028 break; 1029 case PIPE_TEX_MIPFILTER_LINEAR: 1030 assert(lod_ipart); 1031 assert(lod_fpart); 1032 lp_build_linear_mip_levels(bld, unit, 1033 lod_ipart, &lod_fpart, 1034 &ilevel0, &ilevel1); 1035 break; 1036 } 1037 1038 /* 1039 * Get/interpolate texture colors. 1040 */ 1041 1042 for (chan = 0; chan < 4; ++chan) { 1043 texels[chan] = lp_build_alloca(builder, bld->texel_bld.vec_type, ""); 1044 lp_build_name(texels[chan], "sampler%u_texel_%c_var", unit, "xyzw"[chan]); 1045 } 1046 1047 if (min_filter == mag_filter) { 1048 /* no need to distinquish between minification and magnification */ 1049 lp_build_sample_mipmap(bld, unit, 1050 min_filter, mip_filter, 1051 s, t, r, 1052 ilevel0, ilevel1, lod_fpart, 1053 texels); 1054 } 1055 else { 1056 /* Emit conditional to choose min image filter or mag image filter 1057 * depending on the lod being > 0 or <= 0, respectively. 1058 */ 1059 struct lp_build_if_state if_ctx; 1060 LLVMValueRef minify; 1061 1062 /* minify = lod >= 0.0 */ 1063 minify = LLVMBuildICmp(builder, LLVMIntSGE, 1064 lod_ipart, int_bld->zero, ""); 1065 1066 lp_build_if(&if_ctx, builder, minify); 1067 { 1068 /* Use the minification filter */ 1069 lp_build_sample_mipmap(bld, unit, 1070 min_filter, mip_filter, 1071 s, t, r, 1072 ilevel0, ilevel1, lod_fpart, 1073 texels); 1074 } 1075 lp_build_else(&if_ctx); 1076 { 1077 /* Use the magnification filter */ 1078 lp_build_sample_mipmap(bld, unit, 1079 mag_filter, PIPE_TEX_MIPFILTER_NONE, 1080 s, t, r, 1081 i32t_zero, NULL, NULL, 1082 texels); 1083 } 1084 lp_build_endif(&if_ctx); 1085 } 1086 1087 for (chan = 0; chan < 4; ++chan) { 1088 colors_out[chan] = LLVMBuildLoad(builder, texels[chan], ""); 1089 lp_build_name(colors_out[chan], "sampler%u_texel_%c", unit, "xyzw"[chan]); 1090 } 1091} 1092 1093 1094/** 1095 * Do shadow test/comparison. 1096 * \param p the texcoord Z (aka R, aka P) component 1097 * \param texel the texel to compare against (use the X channel) 1098 */ 1099static void 1100lp_build_sample_compare(struct lp_build_sample_context *bld, 1101 LLVMValueRef p, 1102 LLVMValueRef texel[4]) 1103{ 1104 struct lp_build_context *texel_bld = &bld->texel_bld; 1105 LLVMValueRef res; 1106 const unsigned chan = 0; 1107 1108 if (bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE) 1109 return; 1110 1111 /* debug code */ 1112 if (0) { 1113 LLVMValueRef indx = lp_build_const_int32(0); 1114 LLVMValueRef coord = LLVMBuildExtractElement(bld->builder, p, indx, ""); 1115 LLVMValueRef tex = LLVMBuildExtractElement(bld->builder, 1116 texel[chan], indx, ""); 1117 lp_build_printf(bld->builder, "shadow compare coord %f to texture %f\n", 1118 coord, tex); 1119 } 1120 1121 /* result = (p FUNC texel) ? 1 : 0 */ 1122 res = lp_build_cmp(texel_bld, bld->static_state->compare_func, 1123 p, texel[chan]); 1124 res = lp_build_select(texel_bld, res, texel_bld->one, texel_bld->zero); 1125 1126 /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ 1127 texel[0] = 1128 texel[1] = 1129 texel[2] = res; 1130 texel[3] = texel_bld->one; 1131} 1132 1133 1134/** 1135 * Just set texels to white instead of actually sampling the texture. 1136 * For debugging. 1137 */ 1138void 1139lp_build_sample_nop(struct lp_type type, 1140 LLVMValueRef texel_out[4]) 1141{ 1142 LLVMValueRef one = lp_build_one(type); 1143 unsigned chan; 1144 1145 for (chan = 0; chan < 4; chan++) { 1146 texel_out[chan] = one; 1147 } 1148} 1149 1150 1151/** 1152 * Build texture sampling code. 1153 * 'texel' will return a vector of four LLVMValueRefs corresponding to 1154 * R, G, B, A. 1155 * \param type vector float type to use for coords, etc. 1156 * \param ddx partial derivatives of (s,t,r,q) with respect to x 1157 * \param ddy partial derivatives of (s,t,r,q) with respect to y 1158 */ 1159void 1160lp_build_sample_soa(LLVMBuilderRef builder, 1161 const struct lp_sampler_static_state *static_state, 1162 struct lp_sampler_dynamic_state *dynamic_state, 1163 struct lp_type type, 1164 unsigned unit, 1165 unsigned num_coords, 1166 const LLVMValueRef *coords, 1167 const LLVMValueRef ddx[4], 1168 const LLVMValueRef ddy[4], 1169 LLVMValueRef lod_bias, /* optional */ 1170 LLVMValueRef explicit_lod, /* optional */ 1171 LLVMValueRef texel_out[4]) 1172{ 1173 unsigned dims = texture_dims(static_state->target); 1174 struct lp_build_sample_context bld; 1175 LLVMTypeRef i32t = LLVMInt32Type(); 1176 1177 LLVMValueRef s; 1178 LLVMValueRef t; 1179 LLVMValueRef r; 1180 struct lp_type float_vec_type; 1181 1182 if (0) { 1183 enum pipe_format fmt = static_state->format; 1184 debug_printf("Sample from %s\n", util_format_name(fmt)); 1185 } 1186 1187 assert(type.floating); 1188 1189 /* Setup our build context */ 1190 memset(&bld, 0, sizeof bld); 1191 bld.builder = builder; 1192 bld.static_state = static_state; 1193 bld.dynamic_state = dynamic_state; 1194 bld.format_desc = util_format_description(static_state->format); 1195 bld.dims = dims; 1196 1197 bld.float_type = lp_type_float(32); 1198 bld.int_type = lp_type_int(32); 1199 bld.coord_type = type; 1200 bld.int_coord_type = lp_int_type(type); 1201 bld.float_size_type = lp_type_float(32); 1202 bld.float_size_type.length = dims > 1 ? 4 : 1; 1203 bld.int_size_type = lp_int_type(bld.float_size_type); 1204 bld.texel_type = type; 1205 1206 float_vec_type = lp_type_float_vec(32); 1207 1208 lp_build_context_init(&bld.float_bld, builder, bld.float_type); 1209 lp_build_context_init(&bld.float_vec_bld, builder, float_vec_type); 1210 lp_build_context_init(&bld.int_bld, builder, bld.int_type); 1211 lp_build_context_init(&bld.coord_bld, builder, bld.coord_type); 1212 lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type); 1213 lp_build_context_init(&bld.int_size_bld, builder, bld.int_size_type); 1214 lp_build_context_init(&bld.float_size_bld, builder, bld.float_size_type); 1215 lp_build_context_init(&bld.texel_bld, builder, bld.texel_type); 1216 1217 /* Get the dynamic state */ 1218 bld.width = dynamic_state->width(dynamic_state, builder, unit); 1219 bld.height = dynamic_state->height(dynamic_state, builder, unit); 1220 bld.depth = dynamic_state->depth(dynamic_state, builder, unit); 1221 bld.row_stride_array = dynamic_state->row_stride(dynamic_state, builder, unit); 1222 bld.img_stride_array = dynamic_state->img_stride(dynamic_state, builder, unit); 1223 bld.data_array = dynamic_state->data_ptr(dynamic_state, builder, unit); 1224 /* Note that data_array is an array[level] of pointers to texture images */ 1225 1226 s = coords[0]; 1227 t = coords[1]; 1228 r = coords[2]; 1229 1230 /* width, height, depth as single int vector */ 1231 if (dims <= 1) { 1232 bld.int_size = bld.width; 1233 } 1234 else { 1235 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size_bld.undef, 1236 bld.width, LLVMConstInt(i32t, 0, 0), ""); 1237 if (dims >= 2) { 1238 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size, 1239 bld.height, LLVMConstInt(i32t, 1, 0), ""); 1240 if (dims >= 3) { 1241 bld.int_size = LLVMBuildInsertElement(builder, bld.int_size, 1242 bld.depth, LLVMConstInt(i32t, 2, 0), ""); 1243 } 1244 } 1245 } 1246 1247 if (0) { 1248 /* For debug: no-op texture sampling */ 1249 lp_build_sample_nop(bld.texel_type, texel_out); 1250 } 1251 else if (util_format_fits_8unorm(bld.format_desc) && 1252 lp_is_simple_wrap_mode(static_state->wrap_s) && 1253 lp_is_simple_wrap_mode(static_state->wrap_t)) { 1254 /* do sampling/filtering with fixed pt arithmetic */ 1255 lp_build_sample_aos(&bld, unit, s, t, r, ddx, ddy, 1256 lod_bias, explicit_lod, 1257 texel_out); 1258 } 1259 1260 else { 1261 if ((gallivm_debug & GALLIVM_DEBUG_PERF) && 1262 util_format_fits_8unorm(bld.format_desc)) { 1263 debug_printf("%s: using floating point linear filtering for %s\n", 1264 __FUNCTION__, bld.format_desc->short_name); 1265 debug_printf(" min_img %d mag_img %d mip %d wraps %d wrapt %d\n", 1266 static_state->min_img_filter, 1267 static_state->mag_img_filter, 1268 static_state->min_mip_filter, 1269 static_state->wrap_s, 1270 static_state->wrap_t); 1271 } 1272 1273 lp_build_sample_general(&bld, unit, s, t, r, ddx, ddy, 1274 lod_bias, explicit_lod, 1275 texel_out); 1276 } 1277 1278 lp_build_sample_compare(&bld, r, texel_out); 1279} 1280