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