1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2015 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #include "util/u_half.h" 29 30 #include "ilo_debug.h" 31 #include "ilo_state_surface.h" 32 #include "ilo_state_sampler.h" 33 34 static bool 35 sampler_validate_gen6_non_normalized(const struct ilo_dev *dev, 36 const struct ilo_state_sampler_info *info) 37 { 38 const enum gen_texcoord_mode addr_ctrls[3] = { 39 info->tcx_ctrl, info->tcy_ctrl, info->tcz_ctrl, 40 }; 41 int i; 42 43 ILO_DEV_ASSERT(dev, 6, 8); 44 45 /* 46 * From the Ivy Bridge PRM, volume 4 part 1, page 98: 47 * 48 * "The following state must be set as indicated if this field 49 * (Non-normalized Coordinate Enable) is enabled: 50 * 51 * - TCX/Y/Z Address Control Mode must be TEXCOORDMODE_CLAMP, 52 * TEXCOORDMODE_HALF_BORDER, or TEXCOORDMODE_CLAMP_BORDER. 53 * - Surface Type must be SURFTYPE_2D or SURFTYPE_3D. 54 * - Mag Mode Filter must be MAPFILTER_NEAREST or 55 * MAPFILTER_LINEAR. 56 * - Min Mode Filter must be MAPFILTER_NEAREST or 57 * MAPFILTER_LINEAR. 58 * - Mip Mode Filter must be MIPFILTER_NONE. 59 * - Min LOD must be 0. 60 * - Max LOD must be 0. 61 * - MIP Count must be 0. 62 * - Surface Min LOD must be 0. 63 * - Texture LOD Bias must be 0." 64 */ 65 for (i = 0; i < 3; i++) { 66 switch (addr_ctrls[i]) { 67 case GEN6_TEXCOORDMODE_CLAMP: 68 case GEN6_TEXCOORDMODE_CLAMP_BORDER: 69 case GEN8_TEXCOORDMODE_HALF_BORDER: 70 break; 71 default: 72 assert(!"bad non-normalized coordinate wrap mode"); 73 break; 74 } 75 } 76 77 assert(info->mip_filter == GEN6_MIPFILTER_NONE); 78 79 assert((info->min_filter == GEN6_MAPFILTER_NEAREST || 80 info->min_filter == GEN6_MAPFILTER_LINEAR) && 81 (info->mag_filter == GEN6_MAPFILTER_NEAREST || 82 info->mag_filter == GEN6_MAPFILTER_LINEAR)); 83 84 assert(info->min_lod == 0.0f && 85 info->max_lod == 0.0f && 86 info->lod_bias == 0.0f); 87 88 return true; 89 } 90 91 static bool 92 sampler_validate_gen6_sampler(const struct ilo_dev *dev, 93 const struct ilo_state_sampler_info *info) 94 { 95 ILO_DEV_ASSERT(dev, 6, 8); 96 97 if (info->non_normalized && 98 !sampler_validate_gen6_non_normalized(dev, info)) 99 return false; 100 101 if (ilo_dev_gen(dev) < ILO_GEN(8)) { 102 assert(info->tcx_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER && 103 info->tcy_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER && 104 info->tcz_ctrl != GEN8_TEXCOORDMODE_HALF_BORDER); 105 } 106 107 return true; 108 } 109 110 static uint32_t 111 sampler_get_gen6_integer_filters(const struct ilo_dev *dev, 112 const struct ilo_state_sampler_info *info) 113 { 114 /* 115 * From the Sandy Bridge PRM, volume 4 part 1, page 103: 116 * 117 * "MIPFILTER_LINEAR is not supported for surface formats that do not 118 * support "Sampling Engine Filtering" as indicated in the Surface 119 * Formats table unless using the sample_c message type." 120 * 121 * "Only MAPFILTER_NEAREST is supported for surface formats that do not 122 * support "Sampling Engine Filtering" as indicated in the Surface 123 * Formats table unless using the sample_c message type. 124 */ 125 const enum gen_mip_filter mip_filter = 126 (info->mip_filter == GEN6_MIPFILTER_LINEAR) ? 127 GEN6_MIPFILTER_NEAREST : info->mip_filter; 128 const enum gen_map_filter min_filter = GEN6_MAPFILTER_NEAREST; 129 const enum gen_map_filter mag_filter = GEN6_MAPFILTER_NEAREST; 130 131 ILO_DEV_ASSERT(dev, 6, 8); 132 133 return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT | 134 mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT | 135 min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT; 136 } 137 138 static uint32_t 139 sampler_get_gen6_3d_filters(const struct ilo_dev *dev, 140 const struct ilo_state_sampler_info *info) 141 { 142 const enum gen_mip_filter mip_filter = info->mip_filter; 143 /* 144 * From the Sandy Bridge PRM, volume 4 part 1, page 103: 145 * 146 * "Only MAPFILTER_NEAREST and MAPFILTER_LINEAR are supported for 147 * surfaces of type SURFTYPE_3D." 148 */ 149 const enum gen_map_filter min_filter = 150 (info->min_filter == GEN6_MAPFILTER_NEAREST || 151 info->min_filter == GEN6_MAPFILTER_LINEAR) ? 152 info->min_filter : GEN6_MAPFILTER_LINEAR; 153 const enum gen_map_filter mag_filter = 154 (info->mag_filter == GEN6_MAPFILTER_NEAREST || 155 info->mag_filter == GEN6_MAPFILTER_LINEAR) ? 156 info->mag_filter : GEN6_MAPFILTER_LINEAR; 157 158 ILO_DEV_ASSERT(dev, 6, 8); 159 160 return mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT | 161 mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT | 162 min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT; 163 } 164 165 static uint32_t 166 get_gen6_addr_controls(const struct ilo_dev *dev, 167 enum gen_texcoord_mode tcx_ctrl, 168 enum gen_texcoord_mode tcy_ctrl, 169 enum gen_texcoord_mode tcz_ctrl) 170 { 171 ILO_DEV_ASSERT(dev, 6, 8); 172 173 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 174 return tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT | 175 tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT | 176 tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT; 177 } else { 178 return tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT | 179 tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT | 180 tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT; 181 } 182 } 183 184 static uint32_t 185 sampler_get_gen6_1d_addr_controls(const struct ilo_dev *dev, 186 const struct ilo_state_sampler_info *info) 187 { 188 const enum gen_texcoord_mode tcx_ctrl = 189 (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ? 190 GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl; 191 /* 192 * From the Ivy Bridge PRM, volume 4 part 1, page 100: 193 * 194 * "If this field (TCY Address Control Mode) is set to 195 * TEXCOORDMODE_CLAMP_BORDER or TEXCOORDMODE_HALF_BORDER and a 1D 196 * surface is sampled, incorrect blending with the border color in the 197 * vertical direction may occur." 198 */ 199 const enum gen_texcoord_mode tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP; 200 const enum gen_texcoord_mode tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP; 201 202 ILO_DEV_ASSERT(dev, 6, 8); 203 204 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl); 205 } 206 207 static uint32_t 208 sampler_get_gen6_2d_3d_addr_controls(const struct ilo_dev *dev, 209 const struct ilo_state_sampler_info *info) 210 { 211 const enum gen_texcoord_mode tcx_ctrl = 212 (info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE) ? 213 GEN6_TEXCOORDMODE_CLAMP : info->tcx_ctrl; 214 const enum gen_texcoord_mode tcy_ctrl = 215 (info->tcy_ctrl == GEN6_TEXCOORDMODE_CUBE) ? 216 GEN6_TEXCOORDMODE_CLAMP : info->tcy_ctrl; 217 /* 218 * From the Sandy Bridge PRM, volume 4 part 1, page 108: 219 * 220 * "[DevSNB]: if this field (TCZ Address Control Mode) is set to 221 * TEXCOORDMODE_CLAMP_BORDER samples outside the map will clamp to 0 222 * instead of boarder color" 223 * 224 * From the Ivy Bridge PRM, volume 4 part 1, page 100: 225 * 226 * "If this field is set to TEXCOORDMODE_CLAMP_BORDER for 3D maps on 227 * formats without an alpha channel, samples straddling the map in the 228 * Z direction may have their alpha channels off by 1." 229 * 230 * Do we want to do something here? 231 */ 232 const enum gen_texcoord_mode tcz_ctrl = 233 (info->tcz_ctrl == GEN6_TEXCOORDMODE_CUBE) ? 234 GEN6_TEXCOORDMODE_CLAMP : info->tcz_ctrl; 235 236 ILO_DEV_ASSERT(dev, 6, 8); 237 238 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl); 239 } 240 241 static uint32_t 242 sampler_get_gen6_cube_addr_controls(const struct ilo_dev *dev, 243 const struct ilo_state_sampler_info *info) 244 { 245 /* 246 * From the Ivy Bridge PRM, volume 4 part 1, page 99: 247 * 248 * "When using cube map texture coordinates, only TEXCOORDMODE_CLAMP 249 * and TEXCOORDMODE_CUBE settings are valid, and each TC component 250 * must have the same Address Control mode. 251 * 252 * When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's 253 * Cube Face Enable field must be programmed to 111111b (all faces 254 * enabled)." 255 * 256 * From the Haswell PRM, volume 2d, page 278: 257 * 258 * "When using cube map texture coordinates, each TC component must 259 * have the same Address Control Mode. 260 * 261 * When TEXCOORDMODE_CUBE is not used accessing a cube map, the map's 262 * Cube Face Enable field must be programmed to 111111b (all faces 263 * enabled)." 264 * 265 * We always enable all cube faces and only need to make sure all address 266 * control modes are the same. 267 */ 268 const enum gen_texcoord_mode tcx_ctrl = 269 (ilo_dev_gen(dev) >= ILO_GEN(7.5) || 270 info->tcx_ctrl == GEN6_TEXCOORDMODE_CUBE || 271 info->tcx_ctrl == GEN6_TEXCOORDMODE_CLAMP) ? 272 info->tcx_ctrl : GEN6_TEXCOORDMODE_CLAMP; 273 const enum gen_texcoord_mode tcy_ctrl = tcx_ctrl; 274 const enum gen_texcoord_mode tcz_ctrl = tcx_ctrl; 275 276 ILO_DEV_ASSERT(dev, 6, 8); 277 278 return get_gen6_addr_controls(dev, tcx_ctrl, tcy_ctrl, tcz_ctrl); 279 } 280 281 static uint16_t 282 get_gen6_lod_bias(const struct ilo_dev *dev, float bias) 283 { 284 /* [-16.0, 16.0) in S4.6 or S4.8 */ 285 const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6; 286 const float max = 16.0f; 287 const float scale = (float) (1 << fbits); 288 const int mask = (1 << (1 + 4 + fbits)) - 1; 289 const int scaled_max = (16 << fbits) - 1; 290 int scaled; 291 292 ILO_DEV_ASSERT(dev, 6, 8); 293 294 if (bias > max) 295 bias = max; 296 else if (bias < -max) 297 bias = -max; 298 299 scaled = (int) (bias * scale); 300 if (scaled > scaled_max) 301 scaled = scaled_max; 302 303 return (scaled & mask); 304 } 305 306 static uint16_t 307 get_gen6_lod_clamp(const struct ilo_dev *dev, float clamp) 308 { 309 /* [0.0, 13.0] in U4.6 or [0.0, 14.0] in U4.8 */ 310 const int fbits = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 8 : 6; 311 const float max = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 14.0f : 13.0f; 312 const float scale = (float) (1 << fbits); 313 314 ILO_DEV_ASSERT(dev, 6, 8); 315 316 if (clamp > max) 317 clamp = max; 318 else if (clamp < 0.0f) 319 clamp = 0.0f; 320 321 return (int) (clamp * scale); 322 } 323 324 static bool 325 sampler_set_gen6_SAMPLER_STATE(struct ilo_state_sampler *sampler, 326 const struct ilo_dev *dev, 327 const struct ilo_state_sampler_info *info) 328 { 329 uint16_t lod_bias, max_lod, min_lod; 330 uint32_t dw0, dw1, dw3; 331 332 ILO_DEV_ASSERT(dev, 6, 8); 333 334 if (!sampler_validate_gen6_sampler(dev, info)) 335 return false; 336 337 /* 338 * From the Ivy Bridge PRM, volume 4 part 1, page 15: 339 * 340 * "The per-pixel LOD is computed in an implementation-dependent manner 341 * and approximates the log2 of the texel/pixel ratio at the given 342 * pixel. The computation is typically based on the differential 343 * texel-space distances associated with a one-pixel differential 344 * distance along the screen x- and y-axes. These texel-space 345 * distances are computed by evaluating neighboring pixel texture 346 * coordinates, these coordinates being in units of texels on the base 347 * MIP level (multiplied by the corresponding surface size in 348 * texels)." 349 * 350 * Judging from the LOD computation pseudocode on page 16-18, the "base MIP 351 * level" should be given by SurfMinLod. To summarize, for the "sample" 352 * message, 353 * 354 * 1) LOD is set to log2(texel/pixel ratio). The number of texels is 355 * measured against level SurfMinLod. 356 * 2) Bias is added to LOD. 357 * 3) if pre-clamp is enabled, LOD is clamped to [MinLod, MaxLod] first 358 * 4) LOD is compared with Base to determine whether magnification or 359 * minification is needed. 360 * 5) If magnification is needed, or no mipmapping is requested, LOD is 361 * set to floor(MinLod). 362 * 6) LOD is clamped to [0, MIPCnt], and SurfMinLod is added to LOD. 363 * 364 * As an example, we could set SurfMinLod to GL_TEXTURE_BASE_LEVEL and Base 365 * to 0 to match GL. But GL expects LOD to be set to 0, instead of 366 * floor(MinLod), in 5). Since this is only an issue when MinLod is 367 * greater than or equal to one, and, with Base being 0, a non-zero MinLod 368 * implies minification, we only need to deal with the case when mipmapping 369 * is disabled. We can thus do: 370 * 371 * if (MipFilter == MIPFILTER_NONE && MinLod) { 372 * MinLod = 0; 373 * MagFilter = MinFilter; 374 * } 375 */ 376 377 lod_bias = get_gen6_lod_bias(dev, info->lod_bias); 378 min_lod = get_gen6_lod_clamp(dev, info->min_lod); 379 max_lod = get_gen6_lod_clamp(dev, info->max_lod); 380 381 dw0 = GEN6_SAMPLER_DW0_LOD_PRECLAMP_ENABLE | 382 0 << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT | 383 info->mip_filter << GEN6_SAMPLER_DW0_MIP_FILTER__SHIFT | 384 info->mag_filter << GEN6_SAMPLER_DW0_MAG_FILTER__SHIFT | 385 info->min_filter << GEN6_SAMPLER_DW0_MIN_FILTER__SHIFT; 386 387 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 388 dw0 |= GEN7_SAMPLER_DW0_BORDER_COLOR_MODE_DX10_OGL | 389 lod_bias << GEN7_SAMPLER_DW0_LOD_BIAS__SHIFT; 390 391 if (info->min_filter == GEN6_MAPFILTER_ANISOTROPIC || 392 info->mag_filter == GEN6_MAPFILTER_ANISOTROPIC) 393 dw0 |= GEN7_SAMPLER_DW0_ANISO_ALGO_EWA; 394 } else { 395 dw0 |= lod_bias << GEN6_SAMPLER_DW0_LOD_BIAS__SHIFT | 396 info->shadow_func << GEN6_SAMPLER_DW0_SHADOW_FUNC__SHIFT; 397 398 /* 399 * From the Sandy Bridge PRM, volume 4 part 1, page 102: 400 * 401 * "(Min and Mag State Not Equal) Must be set to 1 if any of the 402 * following are true: 403 * 404 * - Mag Mode Filter and Min Mode Filter are not the same 405 * - Address Rounding Enable: U address mag filter and U address 406 * min filter are not the same 407 * - Address Rounding Enable: V address mag filter and V address 408 * min filter are not the same 409 * - Address Rounding Enable: R address mag filter and R address 410 * min filter are not the same" 411 * 412 * We set address rounding for U, V, and R uniformly. Only need to 413 * check the filters. 414 */ 415 if (info->min_filter != info->mag_filter) 416 dw0 |= GEN6_SAMPLER_DW0_MIN_MAG_NOT_EQUAL; 417 } 418 419 dw1 = 0; 420 421 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 422 /* 423 * From the Ivy Bridge PRM, volume 4 part 1, page 96: 424 * 425 * "This field (Cube Surface Control Mode) must be set to 426 * CUBECTRLMODE_PROGRAMMED" 427 */ 428 dw1 |= min_lod << GEN7_SAMPLER_DW1_MIN_LOD__SHIFT | 429 max_lod << GEN7_SAMPLER_DW1_MAX_LOD__SHIFT | 430 info->shadow_func << GEN7_SAMPLER_DW1_SHADOW_FUNC__SHIFT | 431 GEN7_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED; 432 } else { 433 dw1 |= min_lod << GEN6_SAMPLER_DW1_MIN_LOD__SHIFT | 434 max_lod << GEN6_SAMPLER_DW1_MAX_LOD__SHIFT | 435 GEN6_SAMPLER_DW1_CUBECTRLMODE_PROGRAMMED | 436 info->tcx_ctrl << GEN6_SAMPLER_DW1_U_WRAP__SHIFT | 437 info->tcy_ctrl << GEN6_SAMPLER_DW1_V_WRAP__SHIFT | 438 info->tcz_ctrl << GEN6_SAMPLER_DW1_R_WRAP__SHIFT; 439 } 440 441 dw3 = info->max_anisotropy << GEN6_SAMPLER_DW3_MAX_ANISO__SHIFT; 442 443 /* round the coordinates for linear filtering */ 444 if (info->min_filter != GEN6_MAPFILTER_NEAREST) { 445 dw3 |= GEN6_SAMPLER_DW3_U_MIN_ROUND | 446 GEN6_SAMPLER_DW3_V_MIN_ROUND | 447 GEN6_SAMPLER_DW3_R_MIN_ROUND; 448 } 449 if (info->mag_filter != GEN6_MAPFILTER_NEAREST) { 450 dw3 |= GEN6_SAMPLER_DW3_U_MAG_ROUND | 451 GEN6_SAMPLER_DW3_V_MAG_ROUND | 452 GEN6_SAMPLER_DW3_R_MAG_ROUND; 453 } 454 455 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 456 dw3 |= GEN7_SAMPLER_DW3_TRIQUAL_FULL | 457 info->tcx_ctrl << GEN7_SAMPLER_DW3_U_WRAP__SHIFT | 458 info->tcy_ctrl << GEN7_SAMPLER_DW3_V_WRAP__SHIFT | 459 info->tcz_ctrl << GEN7_SAMPLER_DW3_R_WRAP__SHIFT; 460 461 if (info->non_normalized) 462 dw3 |= GEN7_SAMPLER_DW3_NON_NORMALIZED_COORD; 463 } else { 464 if (info->non_normalized) 465 dw3 |= GEN6_SAMPLER_DW3_NON_NORMALIZED_COORD; 466 } 467 468 STATIC_ASSERT(ARRAY_SIZE(sampler->sampler) >= 3); 469 sampler->sampler[0] = dw0; 470 sampler->sampler[1] = dw1; 471 sampler->sampler[2] = dw3; 472 473 sampler->filter_integer = sampler_get_gen6_integer_filters(dev, info); 474 sampler->filter_3d = sampler_get_gen6_3d_filters(dev, info); 475 sampler->addr_ctrl_1d = sampler_get_gen6_1d_addr_controls(dev, info); 476 sampler->addr_ctrl_2d_3d = sampler_get_gen6_2d_3d_addr_controls(dev, info); 477 sampler->addr_ctrl_cube = sampler_get_gen6_cube_addr_controls(dev, info); 478 479 sampler->non_normalized = info->non_normalized; 480 481 /* 482 * From the Sandy Bridge PRM, volume 4 part 1, page 21: 483 * 484 * "[DevSNB] Errata: Incorrect behavior is observed in cases where the 485 * min and mag mode filters are different and SurfMinLOD is nonzero. 486 * The determination of MagMode uses the following equation instead of 487 * the one in the above pseudocode: 488 * 489 * MagMode = (LOD + SurfMinLOD - Base <= 0)" 490 * 491 * As a way to work around that, request Base to be set to SurfMinLod. 492 */ 493 if (ilo_dev_gen(dev) == ILO_GEN(6) && 494 info->min_filter != info->mag_filter) 495 sampler->base_to_surf_min_lod = true; 496 497 return true; 498 } 499 500 static bool 501 sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border, 502 const struct ilo_dev *dev, 503 const struct ilo_state_sampler_border_info *info) 504 { 505 uint32_t dw[12]; 506 float rgba[4]; 507 508 /* 509 * From the Ivy Bridge PRM, volume 4 part 1, page 117: 510 * 511 * "For ([DevSNB]), if border color is used, all formats must be 512 * provided. Hardware will choose the appropriate format based on 513 * Surface Format and Texture Border Color Mode. The values 514 * represented by each format should be the same (other than being 515 * subject to range-based clamping and precision) to avoid unexpected 516 * behavior." 517 * 518 * XXX We do not honor info->is_integer yet. 519 */ 520 521 ILO_DEV_ASSERT(dev, 6, 6); 522 523 /* make a copy so that we can clamp for SNORM and UNORM */ 524 memcpy(rgba, info->rgba.f, sizeof(rgba)); 525 526 /* IEEE_FP */ 527 dw[1] = fui(rgba[0]); 528 dw[2] = fui(rgba[1]); 529 dw[3] = fui(rgba[2]); 530 dw[4] = fui(rgba[3]); 531 532 /* FLOAT_16 */ 533 dw[5] = util_float_to_half(rgba[0]) | 534 util_float_to_half(rgba[1]) << 16; 535 dw[6] = util_float_to_half(rgba[2]) | 536 util_float_to_half(rgba[3]) << 16; 537 538 /* clamp to [-1.0f, 1.0f] */ 539 rgba[0] = CLAMP(rgba[0], -1.0f, 1.0f); 540 rgba[1] = CLAMP(rgba[1], -1.0f, 1.0f); 541 rgba[2] = CLAMP(rgba[2], -1.0f, 1.0f); 542 rgba[3] = CLAMP(rgba[3], -1.0f, 1.0f); 543 544 /* SNORM16 */ 545 dw[9] = (int16_t) util_iround(rgba[0] * 32767.0f) | 546 (int16_t) util_iround(rgba[1] * 32767.0f) << 16; 547 dw[10] = (int16_t) util_iround(rgba[2] * 32767.0f) | 548 (int16_t) util_iround(rgba[3] * 32767.0f) << 16; 549 550 /* SNORM8 */ 551 dw[11] = (int8_t) util_iround(rgba[0] * 127.0f) | 552 (int8_t) util_iround(rgba[1] * 127.0f) << 8 | 553 (int8_t) util_iround(rgba[2] * 127.0f) << 16 | 554 (int8_t) util_iround(rgba[3] * 127.0f) << 24; 555 556 /* clamp to [0.0f, 1.0f] */ 557 rgba[0] = CLAMP(rgba[0], 0.0f, 1.0f); 558 rgba[1] = CLAMP(rgba[1], 0.0f, 1.0f); 559 rgba[2] = CLAMP(rgba[2], 0.0f, 1.0f); 560 rgba[3] = CLAMP(rgba[3], 0.0f, 1.0f); 561 562 /* UNORM8 */ 563 dw[0] = (uint8_t) util_iround(rgba[0] * 255.0f) | 564 (uint8_t) util_iround(rgba[1] * 255.0f) << 8 | 565 (uint8_t) util_iround(rgba[2] * 255.0f) << 16 | 566 (uint8_t) util_iround(rgba[3] * 255.0f) << 24; 567 568 /* UNORM16 */ 569 dw[7] = (uint16_t) util_iround(rgba[0] * 65535.0f) | 570 (uint16_t) util_iround(rgba[1] * 65535.0f) << 16; 571 dw[8] = (uint16_t) util_iround(rgba[2] * 65535.0f) | 572 (uint16_t) util_iround(rgba[3] * 65535.0f) << 16; 573 574 STATIC_ASSERT(ARRAY_SIZE(border->color) >= 12); 575 memcpy(border->color, dw, sizeof(dw)); 576 577 return true; 578 } 579 580 static bool 581 sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(struct ilo_state_sampler_border *border, 582 const struct ilo_dev *dev, 583 const struct ilo_state_sampler_border_info *info) 584 { 585 ILO_DEV_ASSERT(dev, 7, 8); 586 587 /* 588 * From the Ivy Bridge PRM, volume 4 part 1, page 116: 589 * 590 * "In DX10/OGL mode, the format of the border color is 591 * R32G32B32A32_FLOAT, regardless of the surface format chosen." 592 * 593 * From the Haswell PRM, volume 2d, page 240: 594 * 595 * "So, SW will have to program the table in SAMPLER_BORDER_COLOR_STATE 596 * at offsets DWORD16 to 19, as per the integer surface format type." 597 * 598 * From the Broadwell PRM, volume 2d, page 297: 599 * 600 * "DX10/OGL mode: the format of the border color depends on the format 601 * of the surface being sampled. If the map format is UINT, then the 602 * border color format is R32G32B32A32_UINT. If the map format is 603 * SINT, then the border color format is R32G32B32A32_SINT. Otherwise, 604 * the border color format is R32G32B32A32_FLOAT." 605 * 606 * XXX every Gen is different 607 */ 608 609 STATIC_ASSERT(ARRAY_SIZE(border->color) >= 4); 610 memcpy(border->color, info->rgba.f, sizeof(info->rgba.f)); 611 612 return true; 613 } 614 615 bool 616 ilo_state_sampler_init(struct ilo_state_sampler *sampler, 617 const struct ilo_dev *dev, 618 const struct ilo_state_sampler_info *info) 619 { 620 bool ret = true; 621 622 assert(ilo_is_zeroed(sampler, sizeof(*sampler))); 623 624 ret &= sampler_set_gen6_SAMPLER_STATE(sampler, dev, info); 625 626 assert(ret); 627 628 return ret; 629 } 630 631 bool 632 ilo_state_sampler_init_disabled(struct ilo_state_sampler *sampler, 633 const struct ilo_dev *dev) 634 { 635 ILO_DEV_ASSERT(dev, 6, 8); 636 637 assert(ilo_is_zeroed(sampler, sizeof(*sampler))); 638 639 sampler->sampler[0] = GEN6_SAMPLER_DW0_DISABLE; 640 sampler->sampler[1] = 0; 641 sampler->sampler[2] = 0; 642 643 return true; 644 } 645 646 /** 647 * Modify \p sampler to work with \p surf. There will be loss of information. 648 * Callers should make a copy of the orignal sampler first. 649 */ 650 bool 651 ilo_state_sampler_set_surface(struct ilo_state_sampler *sampler, 652 const struct ilo_dev *dev, 653 const struct ilo_state_surface *surf) 654 { 655 uint32_t addr_ctrl; 656 657 ILO_DEV_ASSERT(dev, 6, 8); 658 659 if (sampler->non_normalized) { 660 /* see sampler_validate_gen6_non_normalized() */ 661 assert(surf->type == GEN6_SURFTYPE_2D || 662 surf->type == GEN6_SURFTYPE_3D); 663 assert(!surf->min_lod && !surf->mip_count); 664 } 665 666 if (sampler->base_to_surf_min_lod) { 667 const uint8_t base = surf->min_lod << GEN6_SAMPLER_DW0_BASE_LOD__RADIX; 668 669 sampler->sampler[0] = 670 (sampler->sampler[0] & ~GEN6_SAMPLER_DW0_BASE_LOD__MASK) | 671 base << GEN6_SAMPLER_DW0_BASE_LOD__SHIFT; 672 } 673 674 if (surf->is_integer || surf->type == GEN6_SURFTYPE_3D) { 675 const uint32_t mask = (GEN6_SAMPLER_DW0_MIP_FILTER__MASK | 676 GEN6_SAMPLER_DW0_MIN_FILTER__MASK | 677 GEN6_SAMPLER_DW0_MAG_FILTER__MASK); 678 const uint32_t filter = (surf->is_integer) ? 679 sampler->filter_integer : sampler->filter_3d; 680 681 assert((filter & mask) == filter); 682 sampler->sampler[0] = (sampler->sampler[0] & ~mask) | 683 filter; 684 } 685 686 switch (surf->type) { 687 case GEN6_SURFTYPE_1D: 688 addr_ctrl = sampler->addr_ctrl_1d; 689 break; 690 case GEN6_SURFTYPE_2D: 691 case GEN6_SURFTYPE_3D: 692 addr_ctrl = sampler->addr_ctrl_2d_3d; 693 break; 694 case GEN6_SURFTYPE_CUBE: 695 addr_ctrl = sampler->addr_ctrl_cube; 696 break; 697 default: 698 assert(!"unexpected surface type"); 699 addr_ctrl = 0; 700 break; 701 } 702 703 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 704 const uint32_t mask = (GEN7_SAMPLER_DW3_U_WRAP__MASK | 705 GEN7_SAMPLER_DW3_V_WRAP__MASK | 706 GEN7_SAMPLER_DW3_R_WRAP__MASK); 707 708 assert((addr_ctrl & mask) == addr_ctrl); 709 sampler->sampler[2] = (sampler->sampler[2] & ~mask) | 710 addr_ctrl; 711 } else { 712 const uint32_t mask = (GEN6_SAMPLER_DW1_U_WRAP__MASK | 713 GEN6_SAMPLER_DW1_V_WRAP__MASK | 714 GEN6_SAMPLER_DW1_R_WRAP__MASK); 715 716 assert((addr_ctrl & mask) == addr_ctrl); 717 sampler->sampler[1] = (sampler->sampler[1] & ~mask) | 718 addr_ctrl; 719 } 720 721 return true; 722 } 723 724 bool 725 ilo_state_sampler_border_init(struct ilo_state_sampler_border *border, 726 const struct ilo_dev *dev, 727 const struct ilo_state_sampler_border_info *info) 728 { 729 bool ret = true; 730 731 if (ilo_dev_gen(dev) >= ILO_GEN(7)) { 732 ret &= sampler_border_set_gen7_SAMPLER_BORDER_COLOR_STATE(border, 733 dev, info); 734 } else { 735 ret &= sampler_border_set_gen6_SAMPLER_BORDER_COLOR_STATE(border, 736 dev, info); 737 } 738 739 assert(ret); 740 741 return ret; 742 } 743