1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "SamplerCore.hpp" 16 17 #include "Constants.hpp" 18 #include "Debug.hpp" 19 20 namespace 21 { applySwizzle(sw::SwizzleType swizzle,sw::Short4 & s,const sw::Vector4s & c)22 void applySwizzle(sw::SwizzleType swizzle, sw::Short4& s, const sw::Vector4s& c) 23 { 24 switch(swizzle) 25 { 26 case sw::SWIZZLE_RED: s = c.x; break; 27 case sw::SWIZZLE_GREEN: s = c.y; break; 28 case sw::SWIZZLE_BLUE: s = c.z; break; 29 case sw::SWIZZLE_ALPHA: s = c.w; break; 30 case sw::SWIZZLE_ZERO: s = sw::Short4(0x0000, 0x0000, 0x0000, 0x0000); break; 31 case sw::SWIZZLE_ONE: s = sw::Short4(0x1000, 0x1000, 0x1000, 0x1000); break; 32 default: ASSERT(false); 33 } 34 } 35 applySwizzle(sw::SwizzleType swizzle,sw::Float4 & f,const sw::Vector4f & c)36 void applySwizzle(sw::SwizzleType swizzle, sw::Float4& f, const sw::Vector4f& c) 37 { 38 switch(swizzle) 39 { 40 case sw::SWIZZLE_RED: f = c.x; break; 41 case sw::SWIZZLE_GREEN: f = c.y; break; 42 case sw::SWIZZLE_BLUE: f = c.z; break; 43 case sw::SWIZZLE_ALPHA: f = c.w; break; 44 case sw::SWIZZLE_ZERO: f = sw::Float4(0.0f, 0.0f, 0.0f, 0.0f); break; 45 case sw::SWIZZLE_ONE: f = sw::Float4(1.0f, 1.0f, 1.0f, 1.0f); break; 46 default: ASSERT(false); 47 } 48 } 49 } 50 51 namespace sw 52 { SamplerCore(Pointer<Byte> & constants,const Sampler::State & state)53 SamplerCore::SamplerCore(Pointer<Byte> &constants, const Sampler::State &state) : constants(constants), state(state) 54 { 55 } 56 sampleTexture(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float4 & q,Vector4f & dsx,Vector4f & dsy,SamplerMethod method)57 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method) 58 { 59 sampleTexture(texture, c, u, v, w, q, dsx, dsy, method, true); 60 } 61 sampleTexture(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float4 & q,Vector4f & dsx,Vector4f & dsy,SamplerMethod method,bool fixed12)62 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method, bool fixed12) 63 { 64 #if PERF_PROFILE 65 AddAtomic(Pointer<Long>(&profiler.texOperations), 4); 66 67 if(state.compressedFormat) 68 { 69 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4); 70 } 71 #endif 72 73 Float4 uuuu = u; 74 Float4 vvvv = v; 75 Float4 wwww = w; 76 77 if(state.textureType == TEXTURE_NULL) 78 { 79 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000); 80 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000); 81 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000); 82 83 if(fixed12) // FIXME: Convert to fixed12 at higher level, when required 84 { 85 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); 86 } 87 else 88 { 89 c.w = Short4((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); // FIXME 90 } 91 } 92 else 93 { 94 Int face[4]; 95 Float4 lodX; 96 Float4 lodY; 97 Float4 lodZ; 98 99 if(state.textureType == TEXTURE_CUBE) 100 { 101 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w); 102 } 103 104 Float lod; 105 Float anisotropy; 106 Float4 uDelta; 107 Float4 vDelta; 108 109 if(state.textureType != TEXTURE_3D) 110 { 111 if(state.textureType != TEXTURE_CUBE) 112 { 113 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method); 114 } 115 else 116 { 117 computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method); 118 } 119 } 120 else 121 { 122 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method); 123 } 124 125 if(!hasFloatTexture()) 126 { 127 sampleFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method); 128 } 129 else 130 { 131 Vector4f cf; 132 133 sampleFloatFilter(texture, cf, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method); 134 135 convertFixed12(c, cf); 136 } 137 138 if(fixed12 && !hasFloatTexture()) 139 { 140 if(has16bitTextureFormat()) 141 { 142 switch(state.textureFormat) 143 { 144 case FORMAT_R5G6B5: 145 if(state.sRGB) 146 { 147 sRGBtoLinear16_5_12(c.x); 148 sRGBtoLinear16_6_12(c.y); 149 sRGBtoLinear16_5_12(c.z); 150 } 151 else 152 { 153 c.x = MulHigh(As<UShort4>(c.x), UShort4(0x10000000 / 0xF800)); 154 c.y = MulHigh(As<UShort4>(c.y), UShort4(0x10000000 / 0xFC00)); 155 c.z = MulHigh(As<UShort4>(c.z), UShort4(0x10000000 / 0xF800)); 156 } 157 break; 158 default: 159 ASSERT(false); 160 } 161 } 162 else 163 { 164 for(int component = 0; component < textureComponentCount(); component++) 165 { 166 if(state.sRGB && isRGBComponent(component)) 167 { 168 sRGBtoLinear16_8_12(c[component]); // FIXME: Perform linearization at surface level for read-only textures 169 } 170 else 171 { 172 if(hasUnsignedTextureComponent(component)) 173 { 174 c[component] = As<UShort4>(c[component]) >> 4; 175 } 176 else 177 { 178 c[component] = c[component] >> 3; 179 } 180 } 181 } 182 } 183 } 184 185 if(fixed12 && state.textureFilter != FILTER_GATHER) 186 { 187 int componentCount = textureComponentCount(); 188 189 switch(state.textureFormat) 190 { 191 case FORMAT_R8I_SNORM: 192 case FORMAT_G8R8I_SNORM: 193 case FORMAT_X8B8G8R8I_SNORM: 194 case FORMAT_A8B8G8R8I_SNORM: 195 case FORMAT_R8: 196 case FORMAT_R5G6B5: 197 case FORMAT_G8R8: 198 case FORMAT_R8I: 199 case FORMAT_R8UI: 200 case FORMAT_G8R8I: 201 case FORMAT_G8R8UI: 202 case FORMAT_X8B8G8R8I: 203 case FORMAT_X8B8G8R8UI: 204 case FORMAT_A8B8G8R8I: 205 case FORMAT_A8B8G8R8UI: 206 case FORMAT_R16I: 207 case FORMAT_R16UI: 208 case FORMAT_G16R16: 209 case FORMAT_G16R16I: 210 case FORMAT_G16R16UI: 211 case FORMAT_X16B16G16R16I: 212 case FORMAT_X16B16G16R16UI: 213 case FORMAT_A16B16G16R16: 214 case FORMAT_A16B16G16R16I: 215 case FORMAT_A16B16G16R16UI: 216 case FORMAT_R32I: 217 case FORMAT_R32UI: 218 case FORMAT_G32R32I: 219 case FORMAT_G32R32UI: 220 case FORMAT_X32B32G32R32I: 221 case FORMAT_X32B32G32R32UI: 222 case FORMAT_A32B32G32R32I: 223 case FORMAT_A32B32G32R32UI: 224 case FORMAT_X8R8G8B8: 225 case FORMAT_X8B8G8R8: 226 case FORMAT_A8R8G8B8: 227 case FORMAT_A8B8G8R8: 228 case FORMAT_SRGB8_X8: 229 case FORMAT_SRGB8_A8: 230 case FORMAT_V8U8: 231 case FORMAT_Q8W8V8U8: 232 case FORMAT_X8L8V8U8: 233 case FORMAT_V16U16: 234 case FORMAT_A16W16V16U16: 235 case FORMAT_Q16W16V16U16: 236 case FORMAT_YV12_BT601: 237 case FORMAT_YV12_BT709: 238 case FORMAT_YV12_JFIF: 239 if(componentCount < 2) c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000); 240 if(componentCount < 3) c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000); 241 if(componentCount < 4) c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); 242 break; 243 case FORMAT_A8: 244 c.w = c.x; 245 c.x = Short4(0x0000, 0x0000, 0x0000, 0x0000); 246 c.y = Short4(0x0000, 0x0000, 0x0000, 0x0000); 247 c.z = Short4(0x0000, 0x0000, 0x0000, 0x0000); 248 break; 249 case FORMAT_L8: 250 case FORMAT_L16: 251 c.y = c.x; 252 c.z = c.x; 253 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); 254 break; 255 case FORMAT_A8L8: 256 c.w = c.y; 257 c.y = c.x; 258 c.z = c.x; 259 break; 260 case FORMAT_R32F: 261 c.y = Short4(0x1000, 0x1000, 0x1000, 0x1000); 262 case FORMAT_G32R32F: 263 c.z = Short4(0x1000, 0x1000, 0x1000, 0x1000); 264 case FORMAT_X32B32G32R32F: 265 c.w = Short4(0x1000, 0x1000, 0x1000, 0x1000); 266 case FORMAT_A32B32G32R32F: 267 break; 268 case FORMAT_D32F: 269 case FORMAT_D32F_LOCKABLE: 270 case FORMAT_D32FS8_TEXTURE: 271 case FORMAT_D32FS8_SHADOW: 272 c.y = c.x; 273 c.z = c.x; 274 c.w = c.x; 275 break; 276 default: 277 ASSERT(false); 278 } 279 } 280 } 281 282 if(fixed12 && 283 ((state.swizzleR != SWIZZLE_RED) || 284 (state.swizzleG != SWIZZLE_GREEN) || 285 (state.swizzleB != SWIZZLE_BLUE) || 286 (state.swizzleA != SWIZZLE_ALPHA))) 287 { 288 const Vector4s col(c); 289 applySwizzle(state.swizzleR, c.x, col); 290 applySwizzle(state.swizzleG, c.y, col); 291 applySwizzle(state.swizzleB, c.z, col); 292 applySwizzle(state.swizzleA, c.w, col); 293 } 294 } 295 sampleTexture(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float4 & q,Vector4f & dsx,Vector4f & dsy,SamplerMethod method)296 void SamplerCore::sampleTexture(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float4 &q, Vector4f &dsx, Vector4f &dsy, SamplerMethod method) 297 { 298 #if PERF_PROFILE 299 AddAtomic(Pointer<Long>(&profiler.texOperations), 4); 300 301 if(state.compressedFormat) 302 { 303 AddAtomic(Pointer<Long>(&profiler.compressedTex), 4); 304 } 305 #endif 306 307 if(state.textureType == TEXTURE_NULL) 308 { 309 c.x = Float4(0.0f); 310 c.y = Float4(0.0f); 311 c.z = Float4(0.0f); 312 c.w = Float4(1.0f); 313 } 314 else 315 { 316 if(hasFloatTexture()) // FIXME: Mostly identical to integer sampling 317 { 318 Float4 uuuu = u; 319 Float4 vvvv = v; 320 Float4 wwww = w; 321 322 Int face[4]; 323 Float4 lodX; 324 Float4 lodY; 325 Float4 lodZ; 326 327 if(state.textureType == TEXTURE_CUBE) 328 { 329 cubeFace(face, uuuu, vvvv, lodX, lodY, lodZ, u, v, w); 330 } 331 332 Float lod; 333 Float anisotropy; 334 Float4 uDelta; 335 Float4 vDelta; 336 337 if(state.textureType != TEXTURE_3D) 338 { 339 if(state.textureType != TEXTURE_CUBE) 340 { 341 computeLod(texture, lod, anisotropy, uDelta, vDelta, uuuu, vvvv, q.x, dsx, dsy, method); 342 } 343 else 344 { 345 computeLodCube(texture, lod, lodX, lodY, lodZ, q.x, dsx, dsy, method); 346 } 347 } 348 else 349 { 350 computeLod3D(texture, lod, uuuu, vvvv, wwww, q.x, dsx, dsy, method); 351 } 352 353 sampleFloatFilter(texture, c, uuuu, vvvv, wwww, lod, anisotropy, uDelta, vDelta, face, method); 354 } 355 else 356 { 357 Vector4s cs; 358 359 sampleTexture(texture, cs, u, v, w, q, dsx, dsy, method, false); 360 361 for(int component = 0; component < textureComponentCount(); component++) 362 { 363 if(has16bitTextureFormat()) 364 { 365 switch(state.textureFormat) 366 { 367 case FORMAT_R5G6B5: 368 if(state.sRGB) 369 { 370 sRGBtoLinear16_5_12(cs.x); 371 sRGBtoLinear16_6_12(cs.y); 372 sRGBtoLinear16_5_12(cs.z); 373 374 convertSigned12(c.x, cs.x); 375 convertSigned12(c.y, cs.y); 376 convertSigned12(c.z, cs.z); 377 } 378 else 379 { 380 c.x = Float4(As<UShort4>(cs.x)) * Float4(1.0f / 0xF800); 381 c.y = Float4(As<UShort4>(cs.y)) * Float4(1.0f / 0xFC00); 382 c.z = Float4(As<UShort4>(cs.z)) * Float4(1.0f / 0xF800); 383 } 384 break; 385 default: 386 ASSERT(false); 387 } 388 } 389 else 390 { 391 switch(state.textureFormat) 392 { 393 case FORMAT_R8I: 394 case FORMAT_G8R8I: 395 case FORMAT_X8B8G8R8I: 396 case FORMAT_A8B8G8R8I: 397 c[component] = As<Float4>(Int4(cs[component]) >> 8); 398 break; 399 case FORMAT_R8UI: 400 case FORMAT_G8R8UI: 401 case FORMAT_X8B8G8R8UI: 402 case FORMAT_A8B8G8R8UI: 403 c[component] = As<Float4>(Int4(As<UShort4>(cs[component]) >> 8)); 404 break; 405 case FORMAT_R16I: 406 case FORMAT_G16R16I: 407 case FORMAT_X16B16G16R16I: 408 case FORMAT_A16B16G16R16I: 409 c[component] = As<Float4>(Int4(cs[component])); 410 break; 411 case FORMAT_R16UI: 412 case FORMAT_G16R16UI: 413 case FORMAT_X16B16G16R16UI: 414 case FORMAT_A16B16G16R16UI: 415 c[component] = As<Float4>(Int4(As<UShort4>(cs[component]))); 416 break; 417 default: 418 // Normalized integer formats 419 if(state.sRGB && isRGBComponent(component)) 420 { 421 sRGBtoLinear16_8_12(cs[component]); // FIXME: Perform linearization at surface level for read-only textures 422 convertSigned12(c[component], cs[component]); 423 } 424 else 425 { 426 if(hasUnsignedTextureComponent(component)) 427 { 428 convertUnsigned16(c[component], cs[component]); 429 } 430 else 431 { 432 convertSigned15(c[component], cs[component]); 433 } 434 } 435 break; 436 } 437 } 438 } 439 } 440 441 int componentCount = textureComponentCount(); 442 443 if(state.textureFilter != FILTER_GATHER) 444 { 445 switch(state.textureFormat) 446 { 447 case FORMAT_R8I: 448 case FORMAT_R8UI: 449 case FORMAT_R16I: 450 case FORMAT_R16UI: 451 case FORMAT_R32I: 452 case FORMAT_R32UI: 453 c.y = As<Float4>(UInt4(0)); 454 case FORMAT_G8R8I: 455 case FORMAT_G8R8UI: 456 case FORMAT_G16R16I: 457 case FORMAT_G16R16UI: 458 case FORMAT_G32R32I: 459 case FORMAT_G32R32UI: 460 c.z = As<Float4>(UInt4(0)); 461 case FORMAT_X8B8G8R8I: 462 case FORMAT_X8B8G8R8UI: 463 case FORMAT_X16B16G16R16I: 464 case FORMAT_X16B16G16R16UI: 465 case FORMAT_X32B32G32R32I: 466 case FORMAT_X32B32G32R32UI: 467 c.w = As<Float4>(UInt4(1)); 468 case FORMAT_A8B8G8R8I: 469 case FORMAT_A8B8G8R8UI: 470 case FORMAT_A16B16G16R16I: 471 case FORMAT_A16B16G16R16UI: 472 case FORMAT_A32B32G32R32I: 473 case FORMAT_A32B32G32R32UI: 474 break; 475 case FORMAT_R8I_SNORM: 476 case FORMAT_G8R8I_SNORM: 477 case FORMAT_X8B8G8R8I_SNORM: 478 case FORMAT_A8B8G8R8I_SNORM: 479 case FORMAT_R8: 480 case FORMAT_R5G6B5: 481 case FORMAT_G8R8: 482 case FORMAT_G16R16: 483 case FORMAT_A16B16G16R16: 484 case FORMAT_X8R8G8B8: 485 case FORMAT_X8B8G8R8: 486 case FORMAT_A8R8G8B8: 487 case FORMAT_A8B8G8R8: 488 case FORMAT_SRGB8_X8: 489 case FORMAT_SRGB8_A8: 490 case FORMAT_V8U8: 491 case FORMAT_Q8W8V8U8: 492 case FORMAT_X8L8V8U8: 493 case FORMAT_V16U16: 494 case FORMAT_A16W16V16U16: 495 case FORMAT_Q16W16V16U16: 496 if(componentCount < 2) c.y = Float4(1.0f); 497 if(componentCount < 3) c.z = Float4(1.0f); 498 if(componentCount < 4) c.w = Float4(1.0f); 499 break; 500 case FORMAT_A8: 501 c.w = c.x; 502 c.x = Float4(0.0f); 503 c.y = Float4(0.0f); 504 c.z = Float4(0.0f); 505 break; 506 case FORMAT_L8: 507 case FORMAT_L16: 508 c.y = c.x; 509 c.z = c.x; 510 c.w = Float4(1.0f); 511 break; 512 case FORMAT_A8L8: 513 c.w = c.y; 514 c.y = c.x; 515 c.z = c.x; 516 break; 517 case FORMAT_R32F: 518 c.y = Float4(1.0f); 519 case FORMAT_G32R32F: 520 c.z = Float4(1.0f); 521 case FORMAT_X32B32G32R32F: 522 c.w = Float4(1.0f); 523 case FORMAT_A32B32G32R32F: 524 break; 525 case FORMAT_D32F: 526 case FORMAT_D32F_LOCKABLE: 527 case FORMAT_D32FS8_TEXTURE: 528 case FORMAT_D32FS8_SHADOW: 529 c.y = c.x; 530 c.z = c.x; 531 c.w = c.x; 532 break; 533 default: 534 ASSERT(false); 535 } 536 } 537 } 538 539 if((state.swizzleR != SWIZZLE_RED) || 540 (state.swizzleG != SWIZZLE_GREEN) || 541 (state.swizzleB != SWIZZLE_BLUE) || 542 (state.swizzleA != SWIZZLE_ALPHA)) 543 { 544 const Vector4f col(c); 545 applySwizzle(state.swizzleR, c.x, col); 546 applySwizzle(state.swizzleG, c.y, col); 547 applySwizzle(state.swizzleB, c.z, col); 548 applySwizzle(state.swizzleA, c.w, col); 549 } 550 } 551 border(Short4 & mask,Float4 & coordinates)552 void SamplerCore::border(Short4 &mask, Float4 &coordinates) 553 { 554 Int4 border = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f))); 555 mask = As<Short4>(Int2(As<Int4>(Pack(border, border)))); 556 } 557 border(Int4 & mask,Float4 & coordinates)558 void SamplerCore::border(Int4 &mask, Float4 &coordinates) 559 { 560 mask = As<Int4>(CmpLT(Abs(coordinates - Float4(0.5f)), Float4(0.5f))); 561 } 562 offsetSample(Short4 & uvw,Pointer<Byte> & mipmap,int halfOffset,bool wrap,int count,Float & lod)563 Short4 SamplerCore::offsetSample(Short4 &uvw, Pointer<Byte> &mipmap, int halfOffset, bool wrap, int count, Float &lod) 564 { 565 Short4 offset = *Pointer<Short4>(mipmap + halfOffset); 566 567 if(state.textureFilter == FILTER_MIN_LINEAR_MAG_POINT) 568 { 569 offset &= Short4(CmpNLE(Float4(lod), Float4(0.0f))); 570 } 571 else if(state.textureFilter == FILTER_MIN_POINT_MAG_LINEAR) 572 { 573 offset &= Short4(CmpLE(Float4(lod), Float4(0.0f))); 574 } 575 576 if(wrap) 577 { 578 switch(count) 579 { 580 case -1: return uvw - offset; 581 case 0: return uvw; 582 case +1: return uvw + offset; 583 case 2: return uvw + offset + offset; 584 } 585 } 586 else // Clamp or mirror 587 { 588 switch(count) 589 { 590 case -1: return SubSat(As<UShort4>(uvw), As<UShort4>(offset)); 591 case 0: return uvw; 592 case +1: return AddSat(As<UShort4>(uvw), As<UShort4>(offset)); 593 case 2: return AddSat(AddSat(As<UShort4>(uvw), As<UShort4>(offset)), As<UShort4>(offset)); 594 } 595 } 596 597 return uvw; 598 } 599 sampleFilter(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Float & anisotropy,Float4 & uDelta,Float4 & vDelta,Int face[4],SamplerMethod method)600 void SamplerCore::sampleFilter(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method) 601 { 602 sampleAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method); 603 604 if(state.mipmapFilter > MIPMAP_POINT) 605 { 606 Vector4s cc; 607 608 sampleAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method); 609 610 lod *= Float(1 << 16); 611 612 UShort4 utri = UShort4(Float4(lod)); // FIXME: Optimize 613 Short4 stri = utri >> 1; // FIXME: Optimize 614 615 if(hasUnsignedTextureComponent(0)) cc.x = MulHigh(As<UShort4>(cc.x), utri); else cc.x = MulHigh(cc.x, stri); 616 if(hasUnsignedTextureComponent(1)) cc.y = MulHigh(As<UShort4>(cc.y), utri); else cc.y = MulHigh(cc.y, stri); 617 if(hasUnsignedTextureComponent(2)) cc.z = MulHigh(As<UShort4>(cc.z), utri); else cc.z = MulHigh(cc.z, stri); 618 if(hasUnsignedTextureComponent(3)) cc.w = MulHigh(As<UShort4>(cc.w), utri); else cc.w = MulHigh(cc.w, stri); 619 620 utri = ~utri; 621 stri = Short4(0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF) - stri; 622 623 if(hasUnsignedTextureComponent(0)) c.x = MulHigh(As<UShort4>(c.x), utri); else c.x = MulHigh(c.x, stri); 624 if(hasUnsignedTextureComponent(1)) c.y = MulHigh(As<UShort4>(c.y), utri); else c.y = MulHigh(c.y, stri); 625 if(hasUnsignedTextureComponent(2)) c.z = MulHigh(As<UShort4>(c.z), utri); else c.z = MulHigh(c.z, stri); 626 if(hasUnsignedTextureComponent(3)) c.w = MulHigh(As<UShort4>(c.w), utri); else c.w = MulHigh(c.w, stri); 627 628 c.x += cc.x; 629 c.y += cc.y; 630 c.z += cc.z; 631 c.w += cc.w; 632 633 if(!hasUnsignedTextureComponent(0)) c.x += c.x; 634 if(!hasUnsignedTextureComponent(1)) c.y += c.y; 635 if(!hasUnsignedTextureComponent(2)) c.z += c.z; 636 if(!hasUnsignedTextureComponent(3)) c.w += c.w; 637 } 638 639 Short4 borderMask; 640 641 if(state.addressingModeU == ADDRESSING_BORDER) 642 { 643 Short4 u0; 644 645 border(u0, u); 646 647 borderMask = u0; 648 } 649 650 if(state.addressingModeV == ADDRESSING_BORDER) 651 { 652 Short4 v0; 653 654 border(v0, v); 655 656 if(state.addressingModeU == ADDRESSING_BORDER) 657 { 658 borderMask &= v0; 659 } 660 else 661 { 662 borderMask = v0; 663 } 664 } 665 666 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D) 667 { 668 Short4 s0; 669 670 border(s0, w); 671 672 if(state.addressingModeU == ADDRESSING_BORDER || 673 state.addressingModeV == ADDRESSING_BORDER) 674 { 675 borderMask &= s0; 676 } 677 else 678 { 679 borderMask = s0; 680 } 681 } 682 683 if(state.addressingModeU == ADDRESSING_BORDER || 684 state.addressingModeV == ADDRESSING_BORDER || 685 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)) 686 { 687 Short4 b; 688 689 c.x = borderMask & c.x | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[0])) >> (hasUnsignedTextureComponent(0) ? 0 : 1)); 690 c.y = borderMask & c.y | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[1])) >> (hasUnsignedTextureComponent(1) ? 0 : 1)); 691 c.z = borderMask & c.z | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[2])) >> (hasUnsignedTextureComponent(2) ? 0 : 1)); 692 c.w = borderMask & c.w | ~borderMask & (*Pointer<Short4>(texture + OFFSET(Texture,borderColor4[3])) >> (hasUnsignedTextureComponent(3) ? 0 : 1)); 693 } 694 } 695 sampleAniso(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Float & anisotropy,Float4 & uDelta,Float4 & vDelta,Int face[4],bool secondLOD,SamplerMethod method)696 void SamplerCore::sampleAniso(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method) 697 { 698 if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod) 699 { 700 sampleQuad(texture, c, u, v, w, lod, face, secondLOD); 701 } 702 else 703 { 704 Int a = RoundInt(anisotropy); 705 706 Vector4s cSum; 707 708 cSum.x = Short4(0, 0, 0, 0); 709 cSum.y = Short4(0, 0, 0, 0); 710 cSum.z = Short4(0, 0, 0, 0); 711 cSum.w = Short4(0, 0, 0, 0); 712 713 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a); 714 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a); 715 UShort4 cw = *Pointer<UShort4>(constants + OFFSET(Constants,cWeight) + 8 * a); 716 Short4 sw = Short4(cw >> 1); 717 718 Float4 du = uDelta; 719 Float4 dv = vDelta; 720 721 Float4 u0 = u + B * du; 722 Float4 v0 = v + B * dv; 723 724 du *= A; 725 dv *= A; 726 727 Int i = 0; 728 729 Do 730 { 731 sampleQuad(texture, c, u0, v0, w, lod, face, secondLOD); 732 733 u0 += du; 734 v0 += dv; 735 736 if(hasUnsignedTextureComponent(0)) cSum.x += As<Short4>(MulHigh(As<UShort4>(c.x), cw)); else cSum.x += MulHigh(c.x, sw); 737 if(hasUnsignedTextureComponent(1)) cSum.y += As<Short4>(MulHigh(As<UShort4>(c.y), cw)); else cSum.y += MulHigh(c.y, sw); 738 if(hasUnsignedTextureComponent(2)) cSum.z += As<Short4>(MulHigh(As<UShort4>(c.z), cw)); else cSum.z += MulHigh(c.z, sw); 739 if(hasUnsignedTextureComponent(3)) cSum.w += As<Short4>(MulHigh(As<UShort4>(c.w), cw)); else cSum.w += MulHigh(c.w, sw); 740 741 i++; 742 } 743 Until(i >= a) 744 745 if(hasUnsignedTextureComponent(0)) c.x = cSum.x; else c.x = AddSat(cSum.x, cSum.x); 746 if(hasUnsignedTextureComponent(1)) c.y = cSum.y; else c.y = AddSat(cSum.y, cSum.y); 747 if(hasUnsignedTextureComponent(2)) c.z = cSum.z; else c.z = AddSat(cSum.z, cSum.z); 748 if(hasUnsignedTextureComponent(3)) c.w = cSum.w; else c.w = AddSat(cSum.w, cSum.w); 749 } 750 } 751 sampleQuad(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Int face[4],bool secondLOD)752 void SamplerCore::sampleQuad(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) 753 { 754 if(state.textureType != TEXTURE_3D) 755 { 756 sampleQuad2D(texture, c, u, v, w, lod, face, secondLOD); 757 } 758 else 759 { 760 sample3D(texture, c, u, v, w, lod, secondLOD); 761 } 762 } 763 sampleQuad2D(Pointer<Byte> & texture,Vector4s & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Int face[4],bool secondLOD)764 void SamplerCore::sampleQuad2D(Pointer<Byte> &texture, Vector4s &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) 765 { 766 int componentCount = textureComponentCount(); 767 bool gather = state.textureFilter == FILTER_GATHER; 768 769 Pointer<Byte> mipmap; 770 Pointer<Byte> buffer[4]; 771 772 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD); 773 774 Short4 uuuu = address(u, state.addressingModeU, mipmap); 775 Short4 vvvv = address(v, state.addressingModeV, mipmap); 776 Short4 wwww = address(w, state.addressingModeW, mipmap); 777 778 if(state.textureFilter == FILTER_POINT) 779 { 780 sampleTexel(c, uuuu, vvvv, wwww, mipmap, buffer); 781 } 782 else 783 { 784 Vector4s c0; 785 Vector4s c1; 786 Vector4s c2; 787 Vector4s c3; 788 789 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod); 790 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod); 791 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod); 792 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod); 793 794 sampleTexel(c0, uuuu0, vvvv0, wwww, mipmap, buffer); 795 sampleTexel(c1, uuuu1, vvvv0, wwww, mipmap, buffer); 796 sampleTexel(c2, uuuu0, vvvv1, wwww, mipmap, buffer); 797 sampleTexel(c3, uuuu1, vvvv1, wwww, mipmap, buffer); 798 799 if(!gather) // Blend 800 { 801 // Fractions 802 UShort4 f0u = uuuu0; 803 UShort4 f0v = vvvv0; 804 805 if(!state.hasNPOTTexture) 806 { 807 f0u = f0u << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)); // .u 808 f0v = f0v << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt)); // .v 809 } 810 else 811 { 812 f0u = f0u * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width)); 813 f0v = f0v * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height)); 814 } 815 816 UShort4 f1u = ~f0u; 817 UShort4 f1v = ~f0v; 818 819 UShort4 f0u0v = MulHigh(f0u, f0v); 820 UShort4 f1u0v = MulHigh(f1u, f0v); 821 UShort4 f0u1v = MulHigh(f0u, f1v); 822 UShort4 f1u1v = MulHigh(f1u, f1v); 823 824 // Signed fractions 825 Short4 f1u1vs; 826 Short4 f0u1vs; 827 Short4 f1u0vs; 828 Short4 f0u0vs; 829 830 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3)) 831 { 832 f1u1vs = f1u1v >> 1; 833 f0u1vs = f0u1v >> 1; 834 f1u0vs = f1u0v >> 1; 835 f0u0vs = f0u0v >> 1; 836 } 837 838 // Bilinear interpolation 839 if(componentCount >= 1) 840 { 841 if(has16bitTextureComponents() && hasUnsignedTextureComponent(0)) 842 { 843 c0.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0u) + MulHigh(As<UShort4>(c1.x), f0u); 844 c2.x = As<UShort4>(c2.x) - MulHigh(As<UShort4>(c2.x), f0u) + MulHigh(As<UShort4>(c3.x), f0u); 845 c.x = As<UShort4>(c0.x) - MulHigh(As<UShort4>(c0.x), f0v) + MulHigh(As<UShort4>(c2.x), f0v); 846 } 847 else 848 { 849 if(hasUnsignedTextureComponent(0)) 850 { 851 c0.x = MulHigh(As<UShort4>(c0.x), f1u1v); 852 c1.x = MulHigh(As<UShort4>(c1.x), f0u1v); 853 c2.x = MulHigh(As<UShort4>(c2.x), f1u0v); 854 c3.x = MulHigh(As<UShort4>(c3.x), f0u0v); 855 } 856 else 857 { 858 c0.x = MulHigh(c0.x, f1u1vs); 859 c1.x = MulHigh(c1.x, f0u1vs); 860 c2.x = MulHigh(c2.x, f1u0vs); 861 c3.x = MulHigh(c3.x, f0u0vs); 862 } 863 864 c.x = (c0.x + c1.x) + (c2.x + c3.x); 865 if(!hasUnsignedTextureComponent(0)) c.x = AddSat(c.x, c.x); // Correct for signed fractions 866 } 867 } 868 869 if(componentCount >= 2) 870 { 871 if(has16bitTextureComponents() && hasUnsignedTextureComponent(1)) 872 { 873 c0.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0u) + MulHigh(As<UShort4>(c1.y), f0u); 874 c2.y = As<UShort4>(c2.y) - MulHigh(As<UShort4>(c2.y), f0u) + MulHigh(As<UShort4>(c3.y), f0u); 875 c.y = As<UShort4>(c0.y) - MulHigh(As<UShort4>(c0.y), f0v) + MulHigh(As<UShort4>(c2.y), f0v); 876 } 877 else 878 { 879 if(hasUnsignedTextureComponent(1)) 880 { 881 c0.y = MulHigh(As<UShort4>(c0.y), f1u1v); 882 c1.y = MulHigh(As<UShort4>(c1.y), f0u1v); 883 c2.y = MulHigh(As<UShort4>(c2.y), f1u0v); 884 c3.y = MulHigh(As<UShort4>(c3.y), f0u0v); 885 } 886 else 887 { 888 c0.y = MulHigh(c0.y, f1u1vs); 889 c1.y = MulHigh(c1.y, f0u1vs); 890 c2.y = MulHigh(c2.y, f1u0vs); 891 c3.y = MulHigh(c3.y, f0u0vs); 892 } 893 894 c.y = (c0.y + c1.y) + (c2.y + c3.y); 895 if(!hasUnsignedTextureComponent(1)) c.y = AddSat(c.y, c.y); // Correct for signed fractions 896 } 897 } 898 899 if(componentCount >= 3) 900 { 901 if(has16bitTextureComponents() && hasUnsignedTextureComponent(2)) 902 { 903 c0.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0u) + MulHigh(As<UShort4>(c1.z), f0u); 904 c2.z = As<UShort4>(c2.z) - MulHigh(As<UShort4>(c2.z), f0u) + MulHigh(As<UShort4>(c3.z), f0u); 905 c.z = As<UShort4>(c0.z) - MulHigh(As<UShort4>(c0.z), f0v) + MulHigh(As<UShort4>(c2.z), f0v); 906 } 907 else 908 { 909 if(hasUnsignedTextureComponent(2)) 910 { 911 c0.z = MulHigh(As<UShort4>(c0.z), f1u1v); 912 c1.z = MulHigh(As<UShort4>(c1.z), f0u1v); 913 c2.z = MulHigh(As<UShort4>(c2.z), f1u0v); 914 c3.z = MulHigh(As<UShort4>(c3.z), f0u0v); 915 } 916 else 917 { 918 c0.z = MulHigh(c0.z, f1u1vs); 919 c1.z = MulHigh(c1.z, f0u1vs); 920 c2.z = MulHigh(c2.z, f1u0vs); 921 c3.z = MulHigh(c3.z, f0u0vs); 922 } 923 924 c.z = (c0.z + c1.z) + (c2.z + c3.z); 925 if(!hasUnsignedTextureComponent(2)) c.z = AddSat(c.z, c.z); // Correct for signed fractions 926 } 927 } 928 929 if(componentCount >= 4) 930 { 931 if(has16bitTextureComponents() && hasUnsignedTextureComponent(3)) 932 { 933 c0.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0u) + MulHigh(As<UShort4>(c1.w), f0u); 934 c2.w = As<UShort4>(c2.w) - MulHigh(As<UShort4>(c2.w), f0u) + MulHigh(As<UShort4>(c3.w), f0u); 935 c.w = As<UShort4>(c0.w) - MulHigh(As<UShort4>(c0.w), f0v) + MulHigh(As<UShort4>(c2.w), f0v); 936 } 937 else 938 { 939 if(hasUnsignedTextureComponent(3)) 940 { 941 c0.w = MulHigh(As<UShort4>(c0.w), f1u1v); 942 c1.w = MulHigh(As<UShort4>(c1.w), f0u1v); 943 c2.w = MulHigh(As<UShort4>(c2.w), f1u0v); 944 c3.w = MulHigh(As<UShort4>(c3.w), f0u0v); 945 } 946 else 947 { 948 c0.w = MulHigh(c0.w, f1u1vs); 949 c1.w = MulHigh(c1.w, f0u1vs); 950 c2.w = MulHigh(c2.w, f1u0vs); 951 c3.w = MulHigh(c3.w, f0u0vs); 952 } 953 954 c.w = (c0.w + c1.w) + (c2.w + c3.w); 955 if(!hasUnsignedTextureComponent(3)) c.w = AddSat(c.w, c.w); // Correct for signed fractions 956 } 957 } 958 } 959 else 960 { 961 c.x = c1.x; 962 c.y = c2.x; 963 c.z = c3.x; 964 c.w = c0.x; 965 } 966 } 967 } 968 sample3D(Pointer<Byte> & texture,Vector4s & c_,Float4 & u_,Float4 & v_,Float4 & w_,Float & lod,bool secondLOD)969 void SamplerCore::sample3D(Pointer<Byte> &texture, Vector4s &c_, Float4 &u_, Float4 &v_, Float4 &w_, Float &lod, bool secondLOD) 970 { 971 int componentCount = textureComponentCount(); 972 973 Pointer<Byte> mipmap; 974 Pointer<Byte> buffer[4]; 975 Int face[4]; 976 977 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD); 978 979 Short4 uuuu = address(u_, state.addressingModeU, mipmap); 980 Short4 vvvv = address(v_, state.addressingModeV, mipmap); 981 Short4 wwww = address(w_, state.addressingModeW, mipmap); 982 983 if(state.textureFilter == FILTER_POINT) 984 { 985 sampleTexel(c_, uuuu, vvvv, wwww, mipmap, buffer); 986 } 987 else 988 { 989 Vector4s c[2][2][2]; 990 991 Short4 u[2][2][2]; 992 Short4 v[2][2][2]; 993 Short4 s[2][2][2]; 994 995 for(int i = 0; i < 2; i++) 996 { 997 for(int j = 0; j < 2; j++) 998 { 999 for(int k = 0; k < 2; k++) 1000 { 1001 u[i][j][k] = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, i * 2 - 1, lod); 1002 v[i][j][k] = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, j * 2 - 1, lod); 1003 s[i][j][k] = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, k * 2 - 1, lod); 1004 } 1005 } 1006 } 1007 1008 // Fractions 1009 UShort4 f[2][2][2]; 1010 Short4 fs[2][2][2]; 1011 UShort4 f0u; 1012 UShort4 f0v; 1013 UShort4 f0s; 1014 1015 if(!state.hasNPOTTexture) 1016 { 1017 f0u = As<UShort4>(u[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,uInt)); 1018 f0v = As<UShort4>(v[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,vInt)); 1019 f0s = As<UShort4>(s[0][0][0]) << *Pointer<Long1>(mipmap + OFFSET(Mipmap,wInt)); 1020 } 1021 else 1022 { 1023 f0u = As<UShort4>(u[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width)); 1024 f0v = As<UShort4>(v[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height)); 1025 f0s = As<UShort4>(s[0][0][0]) * *Pointer<UShort4>(mipmap + OFFSET(Mipmap,depth)); 1026 } 1027 1028 UShort4 f1u = ~f0u; 1029 UShort4 f1v = ~f0v; 1030 UShort4 f1s = ~f0s; 1031 1032 f[1][1][1] = MulHigh(f1u, f1v); 1033 f[0][1][1] = MulHigh(f0u, f1v); 1034 f[1][0][1] = MulHigh(f1u, f0v); 1035 f[0][0][1] = MulHigh(f0u, f0v); 1036 f[1][1][0] = MulHigh(f1u, f1v); 1037 f[0][1][0] = MulHigh(f0u, f1v); 1038 f[1][0][0] = MulHigh(f1u, f0v); 1039 f[0][0][0] = MulHigh(f0u, f0v); 1040 1041 f[1][1][1] = MulHigh(f[1][1][1], f1s); 1042 f[0][1][1] = MulHigh(f[0][1][1], f1s); 1043 f[1][0][1] = MulHigh(f[1][0][1], f1s); 1044 f[0][0][1] = MulHigh(f[0][0][1], f1s); 1045 f[1][1][0] = MulHigh(f[1][1][0], f0s); 1046 f[0][1][0] = MulHigh(f[0][1][0], f0s); 1047 f[1][0][0] = MulHigh(f[1][0][0], f0s); 1048 f[0][0][0] = MulHigh(f[0][0][0], f0s); 1049 1050 // Signed fractions 1051 if(!hasUnsignedTextureComponent(0) || !hasUnsignedTextureComponent(1) || !hasUnsignedTextureComponent(2) || !hasUnsignedTextureComponent(3)) 1052 { 1053 fs[0][0][0] = f[0][0][0] >> 1; 1054 fs[0][0][1] = f[0][0][1] >> 1; 1055 fs[0][1][0] = f[0][1][0] >> 1; 1056 fs[0][1][1] = f[0][1][1] >> 1; 1057 fs[1][0][0] = f[1][0][0] >> 1; 1058 fs[1][0][1] = f[1][0][1] >> 1; 1059 fs[1][1][0] = f[1][1][0] >> 1; 1060 fs[1][1][1] = f[1][1][1] >> 1; 1061 } 1062 1063 for(int i = 0; i < 2; i++) 1064 { 1065 for(int j = 0; j < 2; j++) 1066 { 1067 for(int k = 0; k < 2; k++) 1068 { 1069 sampleTexel(c[i][j][k], u[i][j][k], v[i][j][k], s[i][j][k], mipmap, buffer); 1070 1071 if(componentCount >= 1) { if(hasUnsignedTextureComponent(0)) c[i][j][k].x = MulHigh(As<UShort4>(c[i][j][k].x), f[1 - i][1 - j][1 - k]); else c[i][j][k].x = MulHigh(c[i][j][k].x, fs[1 - i][1 - j][1 - k]); } 1072 if(componentCount >= 2) { if(hasUnsignedTextureComponent(1)) c[i][j][k].y = MulHigh(As<UShort4>(c[i][j][k].y), f[1 - i][1 - j][1 - k]); else c[i][j][k].y = MulHigh(c[i][j][k].y, fs[1 - i][1 - j][1 - k]); } 1073 if(componentCount >= 3) { if(hasUnsignedTextureComponent(2)) c[i][j][k].z = MulHigh(As<UShort4>(c[i][j][k].z), f[1 - i][1 - j][1 - k]); else c[i][j][k].z = MulHigh(c[i][j][k].z, fs[1 - i][1 - j][1 - k]); } 1074 if(componentCount >= 4) { if(hasUnsignedTextureComponent(3)) c[i][j][k].w = MulHigh(As<UShort4>(c[i][j][k].w), f[1 - i][1 - j][1 - k]); else c[i][j][k].w = MulHigh(c[i][j][k].w, fs[1 - i][1 - j][1 - k]); } 1075 1076 if(i != 0 || j != 0 || k != 0) 1077 { 1078 if(componentCount >= 1) c[0][0][0].x += c[i][j][k].x; 1079 if(componentCount >= 2) c[0][0][0].y += c[i][j][k].y; 1080 if(componentCount >= 3) c[0][0][0].z += c[i][j][k].z; 1081 if(componentCount >= 4) c[0][0][0].w += c[i][j][k].w; 1082 } 1083 } 1084 } 1085 } 1086 1087 if(componentCount >= 1) c_.x = c[0][0][0].x; 1088 if(componentCount >= 2) c_.y = c[0][0][0].y; 1089 if(componentCount >= 3) c_.z = c[0][0][0].z; 1090 if(componentCount >= 4) c_.w = c[0][0][0].w; 1091 1092 // Correct for signed fractions 1093 if(componentCount >= 1) if(!hasUnsignedTextureComponent(0)) c_.x = AddSat(c_.x, c_.x); 1094 if(componentCount >= 2) if(!hasUnsignedTextureComponent(1)) c_.y = AddSat(c_.y, c_.y); 1095 if(componentCount >= 3) if(!hasUnsignedTextureComponent(2)) c_.z = AddSat(c_.z, c_.z); 1096 if(componentCount >= 4) if(!hasUnsignedTextureComponent(3)) c_.w = AddSat(c_.w, c_.w); 1097 } 1098 } 1099 sampleFloatFilter(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Float & anisotropy,Float4 & uDelta,Float4 & vDelta,Int face[4],SamplerMethod method)1100 void SamplerCore::sampleFloatFilter(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], SamplerMethod method) 1101 { 1102 sampleFloatAniso(texture, c, u, v, w, lod, anisotropy, uDelta, vDelta, face, false, method); 1103 1104 if(state.mipmapFilter > MIPMAP_POINT) 1105 { 1106 Vector4f cc; 1107 1108 sampleFloatAniso(texture, cc, u, v, w, lod, anisotropy, uDelta, vDelta, face, true, method); 1109 1110 Float4 lod4 = Float4(Frac(lod)); 1111 1112 c.x = (cc.x - c.x) * lod4 + c.x; 1113 c.y = (cc.y - c.y) * lod4 + c.y; 1114 c.z = (cc.z - c.z) * lod4 + c.z; 1115 c.w = (cc.w - c.w) * lod4 + c.w; 1116 } 1117 1118 Int4 borderMask; 1119 1120 if(state.addressingModeU == ADDRESSING_BORDER) 1121 { 1122 Int4 u0; 1123 1124 border(u0, u); 1125 1126 borderMask = u0; 1127 } 1128 1129 if(state.addressingModeV == ADDRESSING_BORDER) 1130 { 1131 Int4 v0; 1132 1133 border(v0, v); 1134 1135 if(state.addressingModeU == ADDRESSING_BORDER) 1136 { 1137 borderMask &= v0; 1138 } 1139 else 1140 { 1141 borderMask = v0; 1142 } 1143 } 1144 1145 if(state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D) 1146 { 1147 Int4 s0; 1148 1149 border(s0, w); 1150 1151 if(state.addressingModeU == ADDRESSING_BORDER || 1152 state.addressingModeV == ADDRESSING_BORDER) 1153 { 1154 borderMask &= s0; 1155 } 1156 else 1157 { 1158 borderMask = s0; 1159 } 1160 } 1161 1162 if(state.addressingModeU == ADDRESSING_BORDER || 1163 state.addressingModeV == ADDRESSING_BORDER || 1164 (state.addressingModeW == ADDRESSING_BORDER && state.textureType == TEXTURE_3D)) 1165 { 1166 Int4 b; 1167 1168 c.x = As<Float4>(borderMask & As<Int4>(c.x) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[0]))); 1169 c.y = As<Float4>(borderMask & As<Int4>(c.y) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[1]))); 1170 c.z = As<Float4>(borderMask & As<Int4>(c.z) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[2]))); 1171 c.w = As<Float4>(borderMask & As<Int4>(c.w) | ~borderMask & *Pointer<Int4>(texture + OFFSET(Texture,borderColorF[3]))); 1172 } 1173 } 1174 sampleFloatAniso(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Float & anisotropy,Float4 & uDelta,Float4 & vDelta,Int face[4],bool secondLOD,SamplerMethod method)1175 void SamplerCore::sampleFloatAniso(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Int face[4], bool secondLOD, SamplerMethod method) 1176 { 1177 if(state.textureFilter != FILTER_ANISOTROPIC || method == Lod) 1178 { 1179 sampleFloat(texture, c, u, v, w, lod, face, secondLOD); 1180 } 1181 else 1182 { 1183 Int a = RoundInt(anisotropy); 1184 1185 Vector4f cSum; 1186 1187 cSum.x = Float4(0.0f); 1188 cSum.y = Float4(0.0f); 1189 cSum.z = Float4(0.0f); 1190 cSum.w = Float4(0.0f); 1191 1192 Float4 A = *Pointer<Float4>(constants + OFFSET(Constants,uvWeight) + 16 * a); 1193 Float4 B = *Pointer<Float4>(constants + OFFSET(Constants,uvStart) + 16 * a); 1194 1195 Float4 du = uDelta; 1196 Float4 dv = vDelta; 1197 1198 Float4 u0 = u + B * du; 1199 Float4 v0 = v + B * dv; 1200 1201 du *= A; 1202 dv *= A; 1203 1204 Int i = 0; 1205 1206 Do 1207 { 1208 sampleFloat(texture, c, u0, v0, w, lod, face, secondLOD); 1209 1210 u0 += du; 1211 v0 += dv; 1212 1213 cSum.x += c.x * A; 1214 cSum.y += c.y * A; 1215 cSum.z += c.z * A; 1216 cSum.w += c.w * A; 1217 1218 i++; 1219 } 1220 Until(i >= a) 1221 1222 c.x = cSum.x; 1223 c.y = cSum.y; 1224 c.z = cSum.z; 1225 c.w = cSum.w; 1226 } 1227 } 1228 sampleFloat(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Int face[4],bool secondLOD)1229 void SamplerCore::sampleFloat(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) 1230 { 1231 if(state.textureType != TEXTURE_3D) 1232 { 1233 sampleFloat2D(texture, c, u, v, w, lod, face, secondLOD); 1234 } 1235 else 1236 { 1237 sampleFloat3D(texture, c, u, v, w, lod, secondLOD); 1238 } 1239 } 1240 sampleFloat2D(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,Int face[4],bool secondLOD)1241 void SamplerCore::sampleFloat2D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, Int face[4], bool secondLOD) 1242 { 1243 int componentCount = textureComponentCount(); 1244 bool gather = state.textureFilter == FILTER_GATHER; 1245 1246 Pointer<Byte> mipmap; 1247 Pointer<Byte> buffer[4]; 1248 1249 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD); 1250 1251 Short4 uuuu = address(u, state.addressingModeU, mipmap); 1252 Short4 vvvv = address(v, state.addressingModeV, mipmap); 1253 Short4 wwww = address(w, state.addressingModeW, mipmap); 1254 1255 if(state.textureFilter == FILTER_POINT) 1256 { 1257 sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer); 1258 } 1259 else 1260 { 1261 Vector4f c0; 1262 Vector4f c1; 1263 Vector4f c2; 1264 Vector4f c3; 1265 1266 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 0 : -1, lod); 1267 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 0 : -1, lod); 1268 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, gather ? 2 : +1, lod); 1269 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, gather ? 2 : +1, lod); 1270 1271 sampleTexel(c0, uuuu0, vvvv0, wwww, w, mipmap, buffer); 1272 sampleTexel(c1, uuuu1, vvvv0, wwww, w, mipmap, buffer); 1273 sampleTexel(c2, uuuu0, vvvv1, wwww, w, mipmap, buffer); 1274 sampleTexel(c3, uuuu1, vvvv1, wwww, w, mipmap, buffer); 1275 1276 if(!gather) // Blend 1277 { 1278 // Fractions 1279 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth))); 1280 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight))); 1281 1282 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x); 1283 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y); 1284 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z); 1285 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w); 1286 1287 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x); 1288 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y); 1289 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z); 1290 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w); 1291 1292 if(componentCount >= 1) c.x = c0.x + fv * (c2.x - c0.x); 1293 if(componentCount >= 2) c.y = c0.y + fv * (c2.y - c0.y); 1294 if(componentCount >= 3) c.z = c0.z + fv * (c2.z - c0.z); 1295 if(componentCount >= 4) c.w = c0.w + fv * (c2.w - c0.w); 1296 } 1297 else 1298 { 1299 c.x = c1.x; 1300 c.y = c2.x; 1301 c.z = c3.x; 1302 c.w = c0.x; 1303 } 1304 } 1305 } 1306 sampleFloat3D(Pointer<Byte> & texture,Vector4f & c,Float4 & u,Float4 & v,Float4 & w,Float & lod,bool secondLOD)1307 void SamplerCore::sampleFloat3D(Pointer<Byte> &texture, Vector4f &c, Float4 &u, Float4 &v, Float4 &w, Float &lod, bool secondLOD) 1308 { 1309 int componentCount = textureComponentCount(); 1310 1311 Pointer<Byte> mipmap; 1312 Pointer<Byte> buffer[4]; 1313 Int face[4]; 1314 1315 selectMipmap(texture, buffer, mipmap, lod, face, secondLOD); 1316 1317 Short4 uuuu = address(u, state.addressingModeU, mipmap); 1318 Short4 vvvv = address(v, state.addressingModeV, mipmap); 1319 Short4 wwww = address(w, state.addressingModeW, mipmap); 1320 1321 if(state.textureFilter == FILTER_POINT) 1322 { 1323 sampleTexel(c, uuuu, vvvv, wwww, w, mipmap, buffer); 1324 } 1325 else 1326 { 1327 Vector4f &c0 = c; 1328 Vector4f c1; 1329 Vector4f c2; 1330 Vector4f c3; 1331 Vector4f c4; 1332 Vector4f c5; 1333 Vector4f c6; 1334 Vector4f c7; 1335 1336 Short4 uuuu0 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, -1, lod); 1337 Short4 vvvv0 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, -1, lod); 1338 Short4 wwww0 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, -1, lod); 1339 Short4 uuuu1 = offsetSample(uuuu, mipmap, OFFSET(Mipmap,uHalf), state.addressingModeU == ADDRESSING_WRAP, +1, lod); 1340 Short4 vvvv1 = offsetSample(vvvv, mipmap, OFFSET(Mipmap,vHalf), state.addressingModeV == ADDRESSING_WRAP, +1, lod); 1341 Short4 wwww1 = offsetSample(wwww, mipmap, OFFSET(Mipmap,wHalf), state.addressingModeW == ADDRESSING_WRAP, +1, lod); 1342 1343 sampleTexel(c0, uuuu0, vvvv0, wwww0, w, mipmap, buffer); 1344 sampleTexel(c1, uuuu1, vvvv0, wwww0, w, mipmap, buffer); 1345 sampleTexel(c2, uuuu0, vvvv1, wwww0, w, mipmap, buffer); 1346 sampleTexel(c3, uuuu1, vvvv1, wwww0, w, mipmap, buffer); 1347 sampleTexel(c4, uuuu0, vvvv0, wwww1, w, mipmap, buffer); 1348 sampleTexel(c5, uuuu1, vvvv0, wwww1, w, mipmap, buffer); 1349 sampleTexel(c6, uuuu0, vvvv1, wwww1, w, mipmap, buffer); 1350 sampleTexel(c7, uuuu1, vvvv1, wwww1, w, mipmap, buffer); 1351 1352 // Fractions 1353 Float4 fu = Frac(Float4(As<UShort4>(uuuu0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fWidth))); 1354 Float4 fv = Frac(Float4(As<UShort4>(vvvv0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fHeight))); 1355 Float4 fw = Frac(Float4(As<UShort4>(wwww0)) * *Pointer<Float4>(mipmap + OFFSET(Mipmap,fDepth))); 1356 1357 // Blend first slice 1358 if(componentCount >= 1) c0.x = c0.x + fu * (c1.x - c0.x); 1359 if(componentCount >= 2) c0.y = c0.y + fu * (c1.y - c0.y); 1360 if(componentCount >= 3) c0.z = c0.z + fu * (c1.z - c0.z); 1361 if(componentCount >= 4) c0.w = c0.w + fu * (c1.w - c0.w); 1362 1363 if(componentCount >= 1) c2.x = c2.x + fu * (c3.x - c2.x); 1364 if(componentCount >= 2) c2.y = c2.y + fu * (c3.y - c2.y); 1365 if(componentCount >= 3) c2.z = c2.z + fu * (c3.z - c2.z); 1366 if(componentCount >= 4) c2.w = c2.w + fu * (c3.w - c2.w); 1367 1368 if(componentCount >= 1) c0.x = c0.x + fv * (c2.x - c0.x); 1369 if(componentCount >= 2) c0.y = c0.y + fv * (c2.y - c0.y); 1370 if(componentCount >= 3) c0.z = c0.z + fv * (c2.z - c0.z); 1371 if(componentCount >= 4) c0.w = c0.w + fv * (c2.w - c0.w); 1372 1373 // Blend second slice 1374 if(componentCount >= 1) c4.x = c4.x + fu * (c5.x - c4.x); 1375 if(componentCount >= 2) c4.y = c4.y + fu * (c5.y - c4.y); 1376 if(componentCount >= 3) c4.z = c4.z + fu * (c5.z - c4.z); 1377 if(componentCount >= 4) c4.w = c4.w + fu * (c5.w - c4.w); 1378 1379 if(componentCount >= 1) c6.x = c6.x + fu * (c7.x - c6.x); 1380 if(componentCount >= 2) c6.y = c6.y + fu * (c7.y - c6.y); 1381 if(componentCount >= 3) c6.z = c6.z + fu * (c7.z - c6.z); 1382 if(componentCount >= 4) c6.w = c6.w + fu * (c7.w - c6.w); 1383 1384 if(componentCount >= 1) c4.x = c4.x + fv * (c6.x - c4.x); 1385 if(componentCount >= 2) c4.y = c4.y + fv * (c6.y - c4.y); 1386 if(componentCount >= 3) c4.z = c4.z + fv * (c6.z - c4.z); 1387 if(componentCount >= 4) c4.w = c4.w + fv * (c6.w - c4.w); 1388 1389 // Blend slices 1390 if(componentCount >= 1) c0.x = c0.x + fw * (c4.x - c0.x); 1391 if(componentCount >= 2) c0.y = c0.y + fw * (c4.y - c0.y); 1392 if(componentCount >= 3) c0.z = c0.z + fw * (c4.z - c0.z); 1393 if(componentCount >= 4) c0.w = c0.w + fw * (c4.w - c0.w); 1394 } 1395 } 1396 computeLod(Pointer<Byte> & texture,Float & lod,Float & anisotropy,Float4 & uDelta,Float4 & vDelta,Float4 & uuuu,Float4 & vvvv,const Float & lodBias,Vector4f & dsx,Vector4f & dsy,SamplerMethod method)1397 void SamplerCore::computeLod(Pointer<Byte> &texture, Float &lod, Float &anisotropy, Float4 &uDelta, Float4 &vDelta, Float4 &uuuu, Float4 &vvvv, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method) 1398 { 1399 if(method != Lod) 1400 { 1401 Float4 duvdxy; 1402 1403 if(method != Grad) 1404 { 1405 duvdxy = Float4(uuuu.yz, vvvv.yz) - Float4(uuuu.xx, vvvv.xx); 1406 } 1407 else 1408 { 1409 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx); 1410 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx); 1411 1412 duvdxy = Float4(dudxy.xz, dvdxy.xz); 1413 } 1414 1415 // Scale by texture dimensions and LOD 1416 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthHeightLOD)); 1417 1418 Float4 dUV2dxy = dUVdxy * dUVdxy; 1419 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw; 1420 1421 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis 1422 1423 if(state.textureFilter == FILTER_ANISOTROPIC) 1424 { 1425 Float det = Abs(Float(dUVdxy.x) * Float(dUVdxy.w) - Float(dUVdxy.y) * Float(dUVdxy.z)); 1426 1427 Float4 dudx = duvdxy.xxxx; 1428 Float4 dudy = duvdxy.yyyy; 1429 Float4 dvdx = duvdxy.zzzz; 1430 Float4 dvdy = duvdxy.wwww; 1431 1432 Int4 mask = As<Int4>(CmpNLT(dUV2.x, dUV2.y)); 1433 uDelta = As<Float4>(As<Int4>(dudx) & mask | As<Int4>(dudy) & ~mask); 1434 vDelta = As<Float4>(As<Int4>(dvdx) & mask | As<Int4>(dvdy) & ~mask); 1435 1436 anisotropy = lod * Rcp_pp(det); 1437 anisotropy = Min(anisotropy, *Pointer<Float>(texture + OFFSET(Texture,maxAnisotropy))); 1438 1439 lod *= Rcp_pp(anisotropy * anisotropy); 1440 } 1441 1442 // log2(sqrt(lod)) 1443 lod = Float(As<Int>(lod)); 1444 lod -= Float(0x3F800000); 1445 lod *= As<Float>(Int(0x33800000)); 1446 1447 if(method == Bias) 1448 { 1449 lod += lodBias; 1450 } 1451 } 1452 else 1453 { 1454 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD)); 1455 } 1456 1457 lod = Max(lod, 0.0f); 1458 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1 1459 } 1460 computeLodCube(Pointer<Byte> & texture,Float & lod,Float4 & u,Float4 & v,Float4 & s,const Float & lodBias,Vector4f & dsx,Vector4f & dsy,SamplerMethod method)1461 void SamplerCore::computeLodCube(Pointer<Byte> &texture, Float &lod, Float4 &u, Float4 &v, Float4 &s, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method) 1462 { 1463 if(method != Lod) 1464 { 1465 if(method != Grad) 1466 { 1467 Float4 dudxy = u.ywyw - u; 1468 Float4 dvdxy = v.ywyw - v; 1469 Float4 dsdxy = s.ywyw - s; 1470 1471 // Scale by texture dimensions and LOD 1472 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD)); 1473 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD)); 1474 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD)); 1475 1476 dudxy *= dudxy; 1477 dvdxy *= dvdxy; 1478 dsdxy *= dsdxy; 1479 1480 dudxy += dvdxy; 1481 dudxy += dsdxy; 1482 1483 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y); 1484 } 1485 else 1486 { 1487 Float4 dudxy = Float4(dsx.x.xx, dsy.x.xx); 1488 Float4 dvdxy = Float4(dsx.y.xx, dsy.y.xx); 1489 1490 Float4 duvdxy = Float4(dudxy.xz, dvdxy.xz); 1491 1492 // Scale by texture dimensions and LOD 1493 Float4 dUVdxy = duvdxy * *Pointer<Float4>(texture + OFFSET(Texture,widthLOD)); 1494 1495 Float4 dUV2dxy = dUVdxy * dUVdxy; 1496 Float4 dUV2 = dUV2dxy.xy + dUV2dxy.zw; 1497 1498 lod = Max(Float(dUV2.x), Float(dUV2.y)); // Square length of major axis 1499 } 1500 1501 // log2(sqrt(lod)) 1502 lod = Float(As<Int>(lod)); 1503 lod -= Float(0x3F800000); 1504 lod *= As<Float>(Int(0x33800000)); 1505 1506 if(method == Bias) 1507 { 1508 lod += lodBias; 1509 } 1510 } 1511 else 1512 { 1513 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD)); 1514 } 1515 1516 lod = Max(lod, 0.0f); 1517 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1 1518 } 1519 computeLod3D(Pointer<Byte> & texture,Float & lod,Float4 & uuuu,Float4 & vvvv,Float4 & wwww,const Float & lodBias,Vector4f & dsx,Vector4f & dsy,SamplerMethod method)1520 void SamplerCore::computeLod3D(Pointer<Byte> &texture, Float &lod, Float4 &uuuu, Float4 &vvvv, Float4 &wwww, const Float &lodBias, Vector4f &dsx, Vector4f &dsy, SamplerMethod method) 1521 { 1522 if(state.mipmapFilter == MIPMAP_NONE) 1523 { 1524 } 1525 else // Point and linear filter 1526 { 1527 if(method != Lod) 1528 { 1529 Float4 dudxy; 1530 Float4 dvdxy; 1531 Float4 dsdxy; 1532 1533 if(method != Grad) 1534 { 1535 dudxy = uuuu.ywyw - uuuu; 1536 dvdxy = vvvv.ywyw - vvvv; 1537 dsdxy = wwww.ywyw - wwww; 1538 } 1539 else 1540 { 1541 dudxy = dsx.x; 1542 dvdxy = dsx.y; 1543 dsdxy = dsx.z; 1544 1545 dudxy = Float4(dudxy.xx, dsy.x.xx); 1546 dvdxy = Float4(dvdxy.xx, dsy.y.xx); 1547 dsdxy = Float4(dsdxy.xx, dsy.z.xx); 1548 1549 dudxy = Float4(dudxy.xz, dudxy.xz); 1550 dvdxy = Float4(dvdxy.xz, dvdxy.xz); 1551 dsdxy = Float4(dsdxy.xz, dsdxy.xz); 1552 } 1553 1554 // Scale by texture dimensions and LOD 1555 dudxy *= *Pointer<Float4>(texture + OFFSET(Texture,widthLOD)); 1556 dvdxy *= *Pointer<Float4>(texture + OFFSET(Texture,heightLOD)); 1557 dsdxy *= *Pointer<Float4>(texture + OFFSET(Texture,depthLOD)); 1558 1559 dudxy *= dudxy; 1560 dvdxy *= dvdxy; 1561 dsdxy *= dsdxy; 1562 1563 dudxy += dvdxy; 1564 dudxy += dsdxy; 1565 1566 lod = Max(Float(dudxy.x), Float(dudxy.y)); // FIXME: Max(dudxy.x, dudxy.y); 1567 1568 // log2(sqrt(lod)) 1569 lod = Float(As<Int>(lod)); 1570 lod -= Float(0x3F800000); 1571 lod *= As<Float>(Int(0x33800000)); 1572 1573 if(method == Bias) 1574 { 1575 lod += lodBias; 1576 } 1577 } 1578 else 1579 { 1580 lod = lodBias + *Pointer<Float>(texture + OFFSET(Texture,LOD)); 1581 } 1582 1583 lod = Max(lod, Float(0.0f)); // FIXME 1584 lod = Min(lod, Float(MIPMAP_LEVELS - 2)); // Trilinear accesses lod+1 1585 } 1586 } 1587 cubeFace(Int face[4],Float4 & U,Float4 & V,Float4 & lodX,Float4 & lodY,Float4 & lodZ,Float4 & x,Float4 & y,Float4 & z)1588 void SamplerCore::cubeFace(Int face[4], Float4 &U, Float4 &V, Float4 &lodX, Float4 &lodY, Float4 &lodZ, Float4 &x, Float4 &y, Float4 &z) 1589 { 1590 Int4 xn = CmpLT(x, Float4(0.0f)); // x < 0 1591 Int4 yn = CmpLT(y, Float4(0.0f)); // y < 0 1592 Int4 zn = CmpLT(z, Float4(0.0f)); // z < 0 1593 1594 Float4 absX = Abs(x); 1595 Float4 absY = Abs(y); 1596 Float4 absZ = Abs(z); 1597 1598 Int4 xy = CmpNLE(absX, absY); // abs(x) > abs(y) 1599 Int4 yz = CmpNLE(absY, absZ); // abs(y) > abs(z) 1600 Int4 zx = CmpNLE(absZ, absX); // abs(z) > abs(x) 1601 Int4 xMajor = xy & ~zx; // abs(x) > abs(y) && abs(x) > abs(z) 1602 Int4 yMajor = yz & ~xy; // abs(y) > abs(z) && abs(y) > abs(x) 1603 Int4 zMajor = zx & ~yz; // abs(z) > abs(x) && abs(z) > abs(y) 1604 1605 // FACE_POSITIVE_X = 000b 1606 // FACE_NEGATIVE_X = 001b 1607 // FACE_POSITIVE_Y = 010b 1608 // FACE_NEGATIVE_Y = 011b 1609 // FACE_POSITIVE_Z = 100b 1610 // FACE_NEGATIVE_Z = 101b 1611 1612 Int yAxis = SignMask(yMajor); 1613 Int zAxis = SignMask(zMajor); 1614 1615 Int4 n = ((xn & xMajor) | (yn & yMajor) | (zn & zMajor)) & Int4(0x80000000); 1616 Int negative = SignMask(n); 1617 1618 face[0] = *Pointer<Int>(constants + OFFSET(Constants,transposeBit0) + negative * 4); 1619 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit1) + yAxis * 4); 1620 face[0] |= *Pointer<Int>(constants + OFFSET(Constants,transposeBit2) + zAxis * 4); 1621 face[1] = (face[0] >> 4) & 0x7; 1622 face[2] = (face[0] >> 8) & 0x7; 1623 face[3] = (face[0] >> 12) & 0x7; 1624 face[0] &= 0x7; 1625 1626 Float4 M = Max(Max(absX, absY), absZ); 1627 1628 // U = xMajor ? (neg ^ -z) : (zMajor & neg) ^ x) 1629 U = As<Float4>((xMajor & (n ^ As<Int4>(-z))) | (~xMajor & ((zMajor & n) ^ As<Int4>(x)))); 1630 1631 // V = !yMajor ? -y : (n ^ z) 1632 V = As<Float4>((~yMajor & As<Int4>(-y)) | (yMajor & (n ^ As<Int4>(z)))); 1633 1634 M = reciprocal(M) * Float4(0.5f); 1635 U = U * M + Float4(0.5f); 1636 V = V * M + Float4(0.5f); 1637 1638 lodX = x * M; 1639 lodY = y * M; 1640 lodZ = z * M; 1641 } 1642 computeIndices(Int index[4],Short4 uuuu,Short4 vvvv,Short4 wwww,const Pointer<Byte> & mipmap)1643 void SamplerCore::computeIndices(Int index[4], Short4 uuuu, Short4 vvvv, Short4 wwww, const Pointer<Byte> &mipmap) 1644 { 1645 Short4 uuu2; 1646 1647 if(!state.hasNPOTTexture && !hasFloatTexture()) 1648 { 1649 vvvv = As<UShort4>(vvvv) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,vFrac)); 1650 uuu2 = uuuu; 1651 uuuu = As<Short4>(UnpackLow(uuuu, vvvv)); 1652 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv)); 1653 uuuu = As<Short4>(As<UInt2>(uuuu) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac))); 1654 uuu2 = As<Short4>(As<UInt2>(uuu2) >> *Pointer<Long1>(mipmap + OFFSET(Mipmap,uFrac))); 1655 } 1656 else 1657 { 1658 uuuu = MulHigh(As<UShort4>(uuuu), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,width))); 1659 vvvv = MulHigh(As<UShort4>(vvvv), *Pointer<UShort4>(mipmap + OFFSET(Mipmap,height))); 1660 uuu2 = uuuu; 1661 uuuu = As<Short4>(UnpackLow(uuuu, vvvv)); 1662 uuu2 = As<Short4>(UnpackHigh(uuu2, vvvv)); 1663 uuuu = As<Short4>(MulAdd(uuuu, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP)))); 1664 uuu2 = As<Short4>(MulAdd(uuu2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,onePitchP)))); 1665 } 1666 1667 if((state.textureType == TEXTURE_3D) || (state.textureType == TEXTURE_2D_ARRAY)) 1668 { 1669 if(state.textureType != TEXTURE_2D_ARRAY) 1670 { 1671 wwww = MulHigh(As<UShort4>(wwww), *Pointer<UShort4>(mipmap + OFFSET(Mipmap, depth))); 1672 } 1673 Short4 www2 = wwww; 1674 wwww = As<Short4>(UnpackLow(wwww, Short4(0x0000, 0x0000, 0x0000, 0x0000))); 1675 www2 = As<Short4>(UnpackHigh(www2, Short4(0x0000, 0x0000, 0x0000, 0x0000))); 1676 wwww = As<Short4>(MulAdd(wwww, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP)))); 1677 www2 = As<Short4>(MulAdd(www2, *Pointer<Short4>(mipmap + OFFSET(Mipmap,sliceP)))); 1678 uuuu = As<Short4>(As<Int2>(uuuu) + As<Int2>(wwww)); 1679 uuu2 = As<Short4>(As<Int2>(uuu2) + As<Int2>(www2)); 1680 } 1681 1682 index[0] = Extract(As<Int2>(uuuu), 0); 1683 index[1] = Extract(As<Int2>(uuuu), 1); 1684 index[2] = Extract(As<Int2>(uuu2), 0); 1685 index[3] = Extract(As<Int2>(uuu2), 1); 1686 } 1687 sampleTexel(Vector4s & c,Short4 & uuuu,Short4 & vvvv,Short4 & wwww,Pointer<Byte> & mipmap,Pointer<Byte> buffer[4])1688 void SamplerCore::sampleTexel(Vector4s &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]) 1689 { 1690 Int index[4]; 1691 1692 computeIndices(index, uuuu, vvvv, wwww, mipmap); 1693 1694 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0; 1695 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0; 1696 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0; 1697 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0; 1698 1699 if(has16bitTextureFormat()) 1700 { 1701 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0); 1702 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1); 1703 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2); 1704 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3); 1705 1706 switch(state.textureFormat) 1707 { 1708 case FORMAT_R5G6B5: 1709 c.z = (c.x & Short4(0x001Fu)) << 11; 1710 c.y = (c.x & Short4(0x07E0u)) << 5; 1711 c.x = (c.x & Short4(0xF800u)); 1712 break; 1713 default: 1714 ASSERT(false); 1715 } 1716 } 1717 else if(has8bitTextureComponents()) 1718 { 1719 switch(textureComponentCount()) 1720 { 1721 case 4: 1722 { 1723 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]); 1724 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]); 1725 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]); 1726 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]); 1727 c.x = UnpackLow(c0, c1); 1728 c.y = UnpackLow(c2, c3); 1729 1730 switch(state.textureFormat) 1731 { 1732 case FORMAT_A8R8G8B8: 1733 c.z = c.x; 1734 c.z = As<Short4>(UnpackLow(c.z, c.y)); 1735 c.x = As<Short4>(UnpackHigh(c.x, c.y)); 1736 c.y = c.z; 1737 c.w = c.x; 1738 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z)); 1739 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y)); 1740 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x)); 1741 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w)); 1742 break; 1743 case FORMAT_A8B8G8R8: 1744 case FORMAT_A8B8G8R8I: 1745 case FORMAT_A8B8G8R8UI: 1746 case FORMAT_A8B8G8R8I_SNORM: 1747 case FORMAT_Q8W8V8U8: 1748 case FORMAT_SRGB8_A8: 1749 c.z = c.x; 1750 c.x = As<Short4>(UnpackLow(c.x, c.y)); 1751 c.z = As<Short4>(UnpackHigh(c.z, c.y)); 1752 c.y = c.x; 1753 c.w = c.z; 1754 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x)); 1755 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y)); 1756 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z)); 1757 c.w = UnpackHigh(As<Byte8>(c.w), As<Byte8>(c.w)); 1758 break; 1759 default: 1760 ASSERT(false); 1761 } 1762 } 1763 break; 1764 case 3: 1765 { 1766 Byte8 c0 = *Pointer<Byte8>(buffer[f0] + 4 * index[0]); 1767 Byte8 c1 = *Pointer<Byte8>(buffer[f1] + 4 * index[1]); 1768 Byte8 c2 = *Pointer<Byte8>(buffer[f2] + 4 * index[2]); 1769 Byte8 c3 = *Pointer<Byte8>(buffer[f3] + 4 * index[3]); 1770 c.x = UnpackLow(c0, c1); 1771 c.y = UnpackLow(c2, c3); 1772 1773 switch(state.textureFormat) 1774 { 1775 case FORMAT_X8R8G8B8: 1776 c.z = c.x; 1777 c.z = As<Short4>(UnpackLow(c.z, c.y)); 1778 c.x = As<Short4>(UnpackHigh(c.x, c.y)); 1779 c.y = c.z; 1780 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z)); 1781 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y)); 1782 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x)); 1783 break; 1784 case FORMAT_X8B8G8R8I_SNORM: 1785 case FORMAT_X8B8G8R8UI: 1786 case FORMAT_X8B8G8R8I: 1787 case FORMAT_X8B8G8R8: 1788 case FORMAT_X8L8V8U8: 1789 case FORMAT_SRGB8_X8: 1790 c.z = c.x; 1791 c.x = As<Short4>(UnpackLow(c.x, c.y)); 1792 c.z = As<Short4>(UnpackHigh(c.z, c.y)); 1793 c.y = c.x; 1794 c.x = UnpackLow(As<Byte8>(c.x), As<Byte8>(c.x)); 1795 c.y = UnpackHigh(As<Byte8>(c.y), As<Byte8>(c.y)); 1796 c.z = UnpackLow(As<Byte8>(c.z), As<Byte8>(c.z)); 1797 break; 1798 default: 1799 ASSERT(false); 1800 } 1801 } 1802 break; 1803 case 2: 1804 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0); 1805 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1); 1806 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2); 1807 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3); 1808 1809 switch(state.textureFormat) 1810 { 1811 case FORMAT_G8R8: 1812 case FORMAT_G8R8I: 1813 case FORMAT_G8R8UI: 1814 case FORMAT_G8R8I_SNORM: 1815 case FORMAT_V8U8: 1816 case FORMAT_A8L8: 1817 c.y = (c.x & Short4(0xFF00u, 0xFF00u, 0xFF00u, 0xFF00u)) | As<Short4>(As<UShort4>(c.x) >> 8); 1818 c.x = (c.x & Short4(0x00FFu, 0x00FFu, 0x00FFu, 0x00FFu)) | (c.x << 8); 1819 break; 1820 default: 1821 ASSERT(false); 1822 } 1823 break; 1824 case 1: 1825 { 1826 Int c0 = Int(*Pointer<Byte>(buffer[f0] + index[0])); 1827 Int c1 = Int(*Pointer<Byte>(buffer[f1] + index[1])); 1828 Int c2 = Int(*Pointer<Byte>(buffer[f2] + index[2])); 1829 Int c3 = Int(*Pointer<Byte>(buffer[f3] + index[3])); 1830 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24); 1831 c.x = Unpack(As<Byte4>(c0)); 1832 } 1833 break; 1834 default: 1835 ASSERT(false); 1836 } 1837 } 1838 else if(has16bitTextureComponents()) 1839 { 1840 switch(textureComponentCount()) 1841 { 1842 case 4: 1843 c.x = *Pointer<Short4>(buffer[f0] + 8 * index[0]); 1844 c.y = *Pointer<Short4>(buffer[f1] + 8 * index[1]); 1845 c.z = *Pointer<Short4>(buffer[f2] + 8 * index[2]); 1846 c.w = *Pointer<Short4>(buffer[f3] + 8 * index[3]); 1847 transpose4x4(c.x, c.y, c.z, c.w); 1848 break; 1849 case 2: 1850 c.x = *Pointer<Short4>(buffer[f0] + 4 * index[0]); 1851 c.x = As<Short4>(UnpackLow(c.x, *Pointer<Short4>(buffer[f1] + 4 * index[1]))); 1852 c.z = *Pointer<Short4>(buffer[f2] + 4 * index[2]); 1853 c.z = As<Short4>(UnpackLow(c.z, *Pointer<Short4>(buffer[f3] + 4 * index[3]))); 1854 c.y = c.x; 1855 c.x = As<Short4>(UnpackLow(As<Int2>(c.x), As<Int2>(c.z))); 1856 c.y = As<Short4>(UnpackHigh(As<Int2>(c.y), As<Int2>(c.z))); 1857 break; 1858 case 1: 1859 c.x = Insert(c.x, *Pointer<Short>(buffer[f0] + 2 * index[0]), 0); 1860 c.x = Insert(c.x, *Pointer<Short>(buffer[f1] + 2 * index[1]), 1); 1861 c.x = Insert(c.x, *Pointer<Short>(buffer[f2] + 2 * index[2]), 2); 1862 c.x = Insert(c.x, *Pointer<Short>(buffer[f3] + 2 * index[3]), 3); 1863 break; 1864 default: 1865 ASSERT(false); 1866 } 1867 } 1868 else if(hasYuvFormat()) 1869 { 1870 // Generic YPbPr to RGB transformation 1871 // R = Y + 2 * (1 - Kr) * Pr 1872 // G = Y - 2 * Kb * (1 - Kb) / Kg * Pb - 2 * Kr * (1 - Kr) / Kg * Pr 1873 // B = Y + 2 * (1 - Kb) * Pb 1874 1875 float Kb = 0.114f; 1876 float Kr = 0.299f; 1877 int studioSwing = 1; 1878 1879 switch(state.textureFormat) 1880 { 1881 case FORMAT_YV12_BT601: 1882 Kb = 0.114f; 1883 Kr = 0.299f; 1884 studioSwing = 1; 1885 break; 1886 case FORMAT_YV12_BT709: 1887 Kb = 0.0722f; 1888 Kr = 0.2126f; 1889 studioSwing = 1; 1890 break; 1891 case FORMAT_YV12_JFIF: 1892 Kb = 0.114f; 1893 Kr = 0.299f; 1894 studioSwing = 0; 1895 break; 1896 default: 1897 ASSERT(false); 1898 } 1899 1900 const float Kg = 1.0f - Kr - Kb; 1901 1902 const float Rr = 2 * (1 - Kr); 1903 const float Gb = -2 * Kb * (1 - Kb) / Kg; 1904 const float Gr = -2 * Kr * (1 - Kr) / Kg; 1905 const float Bb = 2 * (1 - Kb); 1906 1907 // Scaling and bias for studio-swing range: Y = [16 .. 235], U/V = [16 .. 240] 1908 const float Yy = studioSwing ? 255.0f / (235 - 16) : 1.0f; 1909 const float Uu = studioSwing ? 255.0f / (240 - 16) : 1.0f; 1910 const float Vv = studioSwing ? 255.0f / (240 - 16) : 1.0f; 1911 1912 const float Rv = Vv * Rr; 1913 const float Gu = Uu * Gb; 1914 const float Gv = Vv * Gr; 1915 const float Bu = Uu * Bb; 1916 1917 const float R0 = (studioSwing * -16 * Yy - 128 * Rv) / 255; 1918 const float G0 = (studioSwing * -16 * Yy - 128 * Gu - 128 * Gv) / 255; 1919 const float B0 = (studioSwing * -16 * Yy - 128 * Bu) / 255; 1920 1921 Int c0 = Int(*Pointer<Byte>(buffer[0] + index[0])); 1922 Int c1 = Int(*Pointer<Byte>(buffer[0] + index[1])); 1923 Int c2 = Int(*Pointer<Byte>(buffer[0] + index[2])); 1924 Int c3 = Int(*Pointer<Byte>(buffer[0] + index[3])); 1925 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24); 1926 UShort4 Y = As<UShort4>(Unpack(As<Byte4>(c0))); 1927 1928 computeIndices(index, uuuu, vvvv, wwww, mipmap + sizeof(Mipmap)); 1929 c0 = Int(*Pointer<Byte>(buffer[1] + index[0])); 1930 c1 = Int(*Pointer<Byte>(buffer[1] + index[1])); 1931 c2 = Int(*Pointer<Byte>(buffer[1] + index[2])); 1932 c3 = Int(*Pointer<Byte>(buffer[1] + index[3])); 1933 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24); 1934 UShort4 V = As<UShort4>(Unpack(As<Byte4>(c0))); 1935 1936 c0 = Int(*Pointer<Byte>(buffer[2] + index[0])); 1937 c1 = Int(*Pointer<Byte>(buffer[2] + index[1])); 1938 c2 = Int(*Pointer<Byte>(buffer[2] + index[2])); 1939 c3 = Int(*Pointer<Byte>(buffer[2] + index[3])); 1940 c0 = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24); 1941 UShort4 U = As<UShort4>(Unpack(As<Byte4>(c0))); 1942 1943 const UShort4 yY = UShort4(iround(Yy * 0x4000)); 1944 const UShort4 rV = UShort4(iround(Rv * 0x4000)); 1945 const UShort4 gU = UShort4(iround(-Gu * 0x4000)); 1946 const UShort4 gV = UShort4(iround(-Gv * 0x4000)); 1947 const UShort4 bU = UShort4(iround(Bu * 0x4000)); 1948 1949 const UShort4 r0 = UShort4(iround(-R0 * 0x4000)); 1950 const UShort4 g0 = UShort4(iround(G0 * 0x4000)); 1951 const UShort4 b0 = UShort4(iround(-B0 * 0x4000)); 1952 1953 UShort4 y = MulHigh(Y, yY); 1954 UShort4 r = SubSat(y + MulHigh(V, rV), r0); 1955 UShort4 g = SubSat(y + g0, MulHigh(U, gU) + MulHigh(V, gV)); 1956 UShort4 b = SubSat(y + MulHigh(U, bU), b0); 1957 1958 c.x = Min(r, UShort4(0x3FFF)) << 2; 1959 c.y = Min(g, UShort4(0x3FFF)) << 2; 1960 c.z = Min(b, UShort4(0x3FFF)) << 2; 1961 } 1962 else ASSERT(false); 1963 } 1964 sampleTexel(Vector4f & c,Short4 & uuuu,Short4 & vvvv,Short4 & wwww,Float4 & z,Pointer<Byte> & mipmap,Pointer<Byte> buffer[4])1965 void SamplerCore::sampleTexel(Vector4f &c, Short4 &uuuu, Short4 &vvvv, Short4 &wwww, Float4 &z, Pointer<Byte> &mipmap, Pointer<Byte> buffer[4]) 1966 { 1967 Int index[4]; 1968 1969 computeIndices(index, uuuu, vvvv, wwww, mipmap); 1970 1971 int f0 = state.textureType == TEXTURE_CUBE ? 0 : 0; 1972 int f1 = state.textureType == TEXTURE_CUBE ? 1 : 0; 1973 int f2 = state.textureType == TEXTURE_CUBE ? 2 : 0; 1974 int f3 = state.textureType == TEXTURE_CUBE ? 3 : 0; 1975 1976 // Read texels 1977 switch(textureComponentCount()) 1978 { 1979 case 4: 1980 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16); 1981 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16); 1982 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16); 1983 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16); 1984 transpose4x4(c.x, c.y, c.z, c.w); 1985 break; 1986 case 3: 1987 ASSERT(state.textureFormat == FORMAT_X32B32G32R32F); 1988 c.x = *Pointer<Float4>(buffer[f0] + index[0] * 16, 16); 1989 c.y = *Pointer<Float4>(buffer[f1] + index[1] * 16, 16); 1990 c.z = *Pointer<Float4>(buffer[f2] + index[2] * 16, 16); 1991 c.w = *Pointer<Float4>(buffer[f3] + index[3] * 16, 16); 1992 transpose4x3(c.x, c.y, c.z, c.w); 1993 c.w = Float4(1.0f); 1994 break; 1995 case 2: 1996 // FIXME: Optimal shuffling? 1997 c.x.xy = *Pointer<Float4>(buffer[f0] + index[0] * 8); 1998 c.x.zw = *Pointer<Float4>(buffer[f1] + index[1] * 8 - 8); 1999 c.z.xy = *Pointer<Float4>(buffer[f2] + index[2] * 8); 2000 c.z.zw = *Pointer<Float4>(buffer[f3] + index[3] * 8 - 8); 2001 c.y = c.x; 2002 c.x = Float4(c.x.xz, c.z.xz); 2003 c.y = Float4(c.y.yw, c.z.yw); 2004 break; 2005 case 1: 2006 // FIXME: Optimal shuffling? 2007 c.x.x = *Pointer<Float>(buffer[f0] + index[0] * 4); 2008 c.x.y = *Pointer<Float>(buffer[f1] + index[1] * 4); 2009 c.x.z = *Pointer<Float>(buffer[f2] + index[2] * 4); 2010 c.x.w = *Pointer<Float>(buffer[f3] + index[3] * 4); 2011 2012 if(state.textureFormat == FORMAT_D32FS8_SHADOW && state.textureFilter != FILTER_GATHER) 2013 { 2014 Float4 d = Min(Max(z, Float4(0.0f)), Float4(1.0f)); 2015 2016 c.x = As<Float4>(As<Int4>(CmpNLT(c.x, d)) & As<Int4>(Float4(1.0f))); // FIXME: Only less-equal? 2017 } 2018 break; 2019 default: 2020 ASSERT(false); 2021 } 2022 } 2023 selectMipmap(Pointer<Byte> & texture,Pointer<Byte> buffer[4],Pointer<Byte> & mipmap,Float & lod,Int face[4],bool secondLOD)2024 void SamplerCore::selectMipmap(Pointer<Byte> &texture, Pointer<Byte> buffer[4], Pointer<Byte> &mipmap, Float &lod, Int face[4], bool secondLOD) 2025 { 2026 if(state.mipmapFilter < MIPMAP_POINT) 2027 { 2028 mipmap = texture + OFFSET(Texture,mipmap[0]); 2029 } 2030 else 2031 { 2032 Int ilod; 2033 2034 if(state.mipmapFilter == MIPMAP_POINT) 2035 { 2036 ilod = RoundInt(lod); 2037 } 2038 else // Linear 2039 { 2040 ilod = Int(lod); 2041 } 2042 2043 mipmap = texture + OFFSET(Texture,mipmap) + ilod * sizeof(Mipmap) + secondLOD * sizeof(Mipmap); 2044 } 2045 2046 if(state.textureType != TEXTURE_CUBE) 2047 { 2048 buffer[0] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[0])); 2049 2050 if(hasYuvFormat()) 2051 { 2052 buffer[1] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[1])); 2053 buffer[2] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer[2])); 2054 } 2055 } 2056 else 2057 { 2058 for(int i = 0; i < 4; i++) 2059 { 2060 buffer[i] = *Pointer<Pointer<Byte> >(mipmap + OFFSET(Mipmap,buffer) + face[i] * sizeof(void*)); 2061 } 2062 } 2063 } 2064 address(Float4 & uw,AddressingMode addressingMode,Pointer<Byte> & mipmap)2065 Short4 SamplerCore::address(Float4 &uw, AddressingMode addressingMode, Pointer<Byte>& mipmap) 2066 { 2067 if(addressingMode == ADDRESSING_LAYER && state.textureType != TEXTURE_2D_ARRAY) 2068 { 2069 return Short4(); // Unused 2070 } 2071 else if(addressingMode == ADDRESSING_LAYER && state.textureType == TEXTURE_2D_ARRAY) 2072 { 2073 return Min(Max(Short4(RoundInt(uw)), Short4(0)), *Pointer<Short4>(mipmap + OFFSET(Mipmap, depth)) - Short4(1)); 2074 } 2075 else if(addressingMode == ADDRESSING_CLAMP) 2076 { 2077 Float4 clamp = Min(Max(uw, Float4(0.0f)), Float4(65535.0f / 65536.0f)); 2078 2079 return Short4(Int4(clamp * Float4(1 << 16))); 2080 } 2081 else if(addressingMode == ADDRESSING_MIRROR) 2082 { 2083 Int4 convert = Int4(uw * Float4(1 << 16)); 2084 Int4 mirror = (convert << 15) >> 31; 2085 2086 convert ^= mirror; 2087 2088 return Short4(convert); 2089 } 2090 else if(addressingMode == ADDRESSING_MIRRORONCE) 2091 { 2092 // Absolute value 2093 Int4 convert = Int4(Abs(uw * Float4(1 << 16))); 2094 2095 // Clamp 2096 convert -= Int4(0x00008000, 0x00008000, 0x00008000, 0x00008000); 2097 convert = As<Int4>(Pack(convert, convert)); 2098 2099 return As<Short4>(Int2(convert)) + Short4((short)0x8000, (short)0x8000, (short)0x8000, (short)0x8000); 2100 } 2101 else // Wrap (or border) 2102 { 2103 return Short4(Int4(uw * Float4(1 << 16))); 2104 } 2105 } 2106 convertFixed12(Short4 & cs,Float4 & cf)2107 void SamplerCore::convertFixed12(Short4 &cs, Float4 &cf) 2108 { 2109 cs = RoundShort4(cf * Float4(0x1000)); 2110 } 2111 convertFixed12(Vector4s & cs,Vector4f & cf)2112 void SamplerCore::convertFixed12(Vector4s &cs, Vector4f &cf) 2113 { 2114 convertFixed12(cs.x, cf.x); 2115 convertFixed12(cs.y, cf.y); 2116 convertFixed12(cs.z, cf.z); 2117 convertFixed12(cs.w, cf.w); 2118 } 2119 convertSigned12(Float4 & cf,Short4 & cs)2120 void SamplerCore::convertSigned12(Float4 &cf, Short4 &cs) 2121 { 2122 cf = Float4(cs) * Float4(1.0f / 0x0FFE); 2123 } 2124 2125 // void SamplerCore::convertSigned12(Vector4f &cf, Vector4s &cs) 2126 // { 2127 // convertSigned12(cf.x, cs.x); 2128 // convertSigned12(cf.y, cs.y); 2129 // convertSigned12(cf.z, cs.z); 2130 // convertSigned12(cf.w, cs.w); 2131 // } 2132 convertSigned15(Float4 & cf,Short4 & cs)2133 void SamplerCore::convertSigned15(Float4 &cf, Short4 &cs) 2134 { 2135 cf = Float4(cs) * Float4(1.0f / 0x7FFF); 2136 } 2137 convertUnsigned16(Float4 & cf,Short4 & cs)2138 void SamplerCore::convertUnsigned16(Float4 &cf, Short4 &cs) 2139 { 2140 cf = Float4(As<UShort4>(cs)) * Float4(1.0f / 0xFFFF); 2141 } 2142 sRGBtoLinear16_8_12(Short4 & c)2143 void SamplerCore::sRGBtoLinear16_8_12(Short4 &c) 2144 { 2145 c = As<UShort4>(c) >> 8; 2146 2147 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear8_12)); 2148 2149 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0); 2150 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1); 2151 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2); 2152 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3); 2153 } 2154 sRGBtoLinear16_6_12(Short4 & c)2155 void SamplerCore::sRGBtoLinear16_6_12(Short4 &c) 2156 { 2157 c = As<UShort4>(c) >> 10; 2158 2159 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear6_12)); 2160 2161 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0); 2162 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1); 2163 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2); 2164 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3); 2165 } 2166 sRGBtoLinear16_5_12(Short4 & c)2167 void SamplerCore::sRGBtoLinear16_5_12(Short4 &c) 2168 { 2169 c = As<UShort4>(c) >> 11; 2170 2171 Pointer<Byte> LUT = Pointer<Byte>(constants + OFFSET(Constants,sRGBtoLinear5_12)); 2172 2173 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 0))), 0); 2174 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 1))), 1); 2175 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 2))), 2); 2176 c = Insert(c, *Pointer<Short>(LUT + 2 * Int(Extract(c, 3))), 3); 2177 } 2178 hasFloatTexture() const2179 bool SamplerCore::hasFloatTexture() const 2180 { 2181 return Surface::isFloatFormat(state.textureFormat); 2182 } 2183 hasUnsignedTextureComponent(int component) const2184 bool SamplerCore::hasUnsignedTextureComponent(int component) const 2185 { 2186 return Surface::isUnsignedComponent(state.textureFormat, component); 2187 } 2188 textureComponentCount() const2189 int SamplerCore::textureComponentCount() const 2190 { 2191 return Surface::componentCount(state.textureFormat); 2192 } 2193 has16bitTextureFormat() const2194 bool SamplerCore::has16bitTextureFormat() const 2195 { 2196 switch(state.textureFormat) 2197 { 2198 case FORMAT_R5G6B5: 2199 return true; 2200 case FORMAT_R8I_SNORM: 2201 case FORMAT_G8R8I_SNORM: 2202 case FORMAT_X8B8G8R8I_SNORM: 2203 case FORMAT_A8B8G8R8I_SNORM: 2204 case FORMAT_R8I: 2205 case FORMAT_R8UI: 2206 case FORMAT_G8R8I: 2207 case FORMAT_G8R8UI: 2208 case FORMAT_X8B8G8R8I: 2209 case FORMAT_X8B8G8R8UI: 2210 case FORMAT_A8B8G8R8I: 2211 case FORMAT_A8B8G8R8UI: 2212 case FORMAT_R32I: 2213 case FORMAT_R32UI: 2214 case FORMAT_G32R32I: 2215 case FORMAT_G32R32UI: 2216 case FORMAT_X32B32G32R32I: 2217 case FORMAT_X32B32G32R32UI: 2218 case FORMAT_A32B32G32R32I: 2219 case FORMAT_A32B32G32R32UI: 2220 case FORMAT_G8R8: 2221 case FORMAT_X8R8G8B8: 2222 case FORMAT_X8B8G8R8: 2223 case FORMAT_A8R8G8B8: 2224 case FORMAT_A8B8G8R8: 2225 case FORMAT_SRGB8_X8: 2226 case FORMAT_SRGB8_A8: 2227 case FORMAT_V8U8: 2228 case FORMAT_Q8W8V8U8: 2229 case FORMAT_X8L8V8U8: 2230 case FORMAT_R32F: 2231 case FORMAT_G32R32F: 2232 case FORMAT_X32B32G32R32F: 2233 case FORMAT_A32B32G32R32F: 2234 case FORMAT_A8: 2235 case FORMAT_R8: 2236 case FORMAT_L8: 2237 case FORMAT_A8L8: 2238 case FORMAT_D32F: 2239 case FORMAT_D32F_LOCKABLE: 2240 case FORMAT_D32FS8_TEXTURE: 2241 case FORMAT_D32FS8_SHADOW: 2242 case FORMAT_L16: 2243 case FORMAT_G16R16: 2244 case FORMAT_A16B16G16R16: 2245 case FORMAT_V16U16: 2246 case FORMAT_A16W16V16U16: 2247 case FORMAT_Q16W16V16U16: 2248 case FORMAT_R16I: 2249 case FORMAT_R16UI: 2250 case FORMAT_G16R16I: 2251 case FORMAT_G16R16UI: 2252 case FORMAT_X16B16G16R16I: 2253 case FORMAT_X16B16G16R16UI: 2254 case FORMAT_A16B16G16R16I: 2255 case FORMAT_A16B16G16R16UI: 2256 case FORMAT_YV12_BT601: 2257 case FORMAT_YV12_BT709: 2258 case FORMAT_YV12_JFIF: 2259 return false; 2260 default: 2261 ASSERT(false); 2262 } 2263 2264 return false; 2265 } 2266 has8bitTextureComponents() const2267 bool SamplerCore::has8bitTextureComponents() const 2268 { 2269 switch(state.textureFormat) 2270 { 2271 case FORMAT_G8R8: 2272 case FORMAT_X8R8G8B8: 2273 case FORMAT_X8B8G8R8: 2274 case FORMAT_A8R8G8B8: 2275 case FORMAT_A8B8G8R8: 2276 case FORMAT_SRGB8_X8: 2277 case FORMAT_SRGB8_A8: 2278 case FORMAT_V8U8: 2279 case FORMAT_Q8W8V8U8: 2280 case FORMAT_X8L8V8U8: 2281 case FORMAT_A8: 2282 case FORMAT_R8: 2283 case FORMAT_L8: 2284 case FORMAT_A8L8: 2285 case FORMAT_R8I_SNORM: 2286 case FORMAT_G8R8I_SNORM: 2287 case FORMAT_X8B8G8R8I_SNORM: 2288 case FORMAT_A8B8G8R8I_SNORM: 2289 case FORMAT_R8I: 2290 case FORMAT_R8UI: 2291 case FORMAT_G8R8I: 2292 case FORMAT_G8R8UI: 2293 case FORMAT_X8B8G8R8I: 2294 case FORMAT_X8B8G8R8UI: 2295 case FORMAT_A8B8G8R8I: 2296 case FORMAT_A8B8G8R8UI: 2297 return true; 2298 case FORMAT_R5G6B5: 2299 case FORMAT_R32F: 2300 case FORMAT_G32R32F: 2301 case FORMAT_X32B32G32R32F: 2302 case FORMAT_A32B32G32R32F: 2303 case FORMAT_D32F: 2304 case FORMAT_D32F_LOCKABLE: 2305 case FORMAT_D32FS8_TEXTURE: 2306 case FORMAT_D32FS8_SHADOW: 2307 case FORMAT_L16: 2308 case FORMAT_G16R16: 2309 case FORMAT_A16B16G16R16: 2310 case FORMAT_V16U16: 2311 case FORMAT_A16W16V16U16: 2312 case FORMAT_Q16W16V16U16: 2313 case FORMAT_R32I: 2314 case FORMAT_R32UI: 2315 case FORMAT_G32R32I: 2316 case FORMAT_G32R32UI: 2317 case FORMAT_X32B32G32R32I: 2318 case FORMAT_X32B32G32R32UI: 2319 case FORMAT_A32B32G32R32I: 2320 case FORMAT_A32B32G32R32UI: 2321 case FORMAT_R16I: 2322 case FORMAT_R16UI: 2323 case FORMAT_G16R16I: 2324 case FORMAT_G16R16UI: 2325 case FORMAT_X16B16G16R16I: 2326 case FORMAT_X16B16G16R16UI: 2327 case FORMAT_A16B16G16R16I: 2328 case FORMAT_A16B16G16R16UI: 2329 case FORMAT_YV12_BT601: 2330 case FORMAT_YV12_BT709: 2331 case FORMAT_YV12_JFIF: 2332 return false; 2333 default: 2334 ASSERT(false); 2335 } 2336 2337 return false; 2338 } 2339 has16bitTextureComponents() const2340 bool SamplerCore::has16bitTextureComponents() const 2341 { 2342 switch(state.textureFormat) 2343 { 2344 case FORMAT_R5G6B5: 2345 case FORMAT_R8I_SNORM: 2346 case FORMAT_G8R8I_SNORM: 2347 case FORMAT_X8B8G8R8I_SNORM: 2348 case FORMAT_A8B8G8R8I_SNORM: 2349 case FORMAT_R8I: 2350 case FORMAT_R8UI: 2351 case FORMAT_G8R8I: 2352 case FORMAT_G8R8UI: 2353 case FORMAT_X8B8G8R8I: 2354 case FORMAT_X8B8G8R8UI: 2355 case FORMAT_A8B8G8R8I: 2356 case FORMAT_A8B8G8R8UI: 2357 case FORMAT_R32I: 2358 case FORMAT_R32UI: 2359 case FORMAT_G32R32I: 2360 case FORMAT_G32R32UI: 2361 case FORMAT_X32B32G32R32I: 2362 case FORMAT_X32B32G32R32UI: 2363 case FORMAT_A32B32G32R32I: 2364 case FORMAT_A32B32G32R32UI: 2365 case FORMAT_G8R8: 2366 case FORMAT_X8R8G8B8: 2367 case FORMAT_X8B8G8R8: 2368 case FORMAT_A8R8G8B8: 2369 case FORMAT_A8B8G8R8: 2370 case FORMAT_SRGB8_X8: 2371 case FORMAT_SRGB8_A8: 2372 case FORMAT_V8U8: 2373 case FORMAT_Q8W8V8U8: 2374 case FORMAT_X8L8V8U8: 2375 case FORMAT_R32F: 2376 case FORMAT_G32R32F: 2377 case FORMAT_X32B32G32R32F: 2378 case FORMAT_A32B32G32R32F: 2379 case FORMAT_A8: 2380 case FORMAT_R8: 2381 case FORMAT_L8: 2382 case FORMAT_A8L8: 2383 case FORMAT_D32F: 2384 case FORMAT_D32F_LOCKABLE: 2385 case FORMAT_D32FS8_TEXTURE: 2386 case FORMAT_D32FS8_SHADOW: 2387 case FORMAT_YV12_BT601: 2388 case FORMAT_YV12_BT709: 2389 case FORMAT_YV12_JFIF: 2390 return false; 2391 case FORMAT_L16: 2392 case FORMAT_G16R16: 2393 case FORMAT_A16B16G16R16: 2394 case FORMAT_R16I: 2395 case FORMAT_R16UI: 2396 case FORMAT_G16R16I: 2397 case FORMAT_G16R16UI: 2398 case FORMAT_X16B16G16R16I: 2399 case FORMAT_X16B16G16R16UI: 2400 case FORMAT_A16B16G16R16I: 2401 case FORMAT_A16B16G16R16UI: 2402 case FORMAT_V16U16: 2403 case FORMAT_A16W16V16U16: 2404 case FORMAT_Q16W16V16U16: 2405 return true; 2406 default: 2407 ASSERT(false); 2408 } 2409 2410 return false; 2411 } 2412 hasYuvFormat() const2413 bool SamplerCore::hasYuvFormat() const 2414 { 2415 switch(state.textureFormat) 2416 { 2417 case FORMAT_YV12_BT601: 2418 case FORMAT_YV12_BT709: 2419 case FORMAT_YV12_JFIF: 2420 return true; 2421 case FORMAT_R5G6B5: 2422 case FORMAT_R8I_SNORM: 2423 case FORMAT_G8R8I_SNORM: 2424 case FORMAT_X8B8G8R8I_SNORM: 2425 case FORMAT_A8B8G8R8I_SNORM: 2426 case FORMAT_R8I: 2427 case FORMAT_R8UI: 2428 case FORMAT_G8R8I: 2429 case FORMAT_G8R8UI: 2430 case FORMAT_X8B8G8R8I: 2431 case FORMAT_X8B8G8R8UI: 2432 case FORMAT_A8B8G8R8I: 2433 case FORMAT_A8B8G8R8UI: 2434 case FORMAT_R32I: 2435 case FORMAT_R32UI: 2436 case FORMAT_G32R32I: 2437 case FORMAT_G32R32UI: 2438 case FORMAT_X32B32G32R32I: 2439 case FORMAT_X32B32G32R32UI: 2440 case FORMAT_A32B32G32R32I: 2441 case FORMAT_A32B32G32R32UI: 2442 case FORMAT_G8R8: 2443 case FORMAT_X8R8G8B8: 2444 case FORMAT_X8B8G8R8: 2445 case FORMAT_A8R8G8B8: 2446 case FORMAT_A8B8G8R8: 2447 case FORMAT_SRGB8_X8: 2448 case FORMAT_SRGB8_A8: 2449 case FORMAT_V8U8: 2450 case FORMAT_Q8W8V8U8: 2451 case FORMAT_X8L8V8U8: 2452 case FORMAT_R32F: 2453 case FORMAT_G32R32F: 2454 case FORMAT_X32B32G32R32F: 2455 case FORMAT_A32B32G32R32F: 2456 case FORMAT_A8: 2457 case FORMAT_R8: 2458 case FORMAT_L8: 2459 case FORMAT_A8L8: 2460 case FORMAT_D32F: 2461 case FORMAT_D32F_LOCKABLE: 2462 case FORMAT_D32FS8_TEXTURE: 2463 case FORMAT_D32FS8_SHADOW: 2464 case FORMAT_L16: 2465 case FORMAT_G16R16: 2466 case FORMAT_A16B16G16R16: 2467 case FORMAT_R16I: 2468 case FORMAT_R16UI: 2469 case FORMAT_G16R16I: 2470 case FORMAT_G16R16UI: 2471 case FORMAT_X16B16G16R16I: 2472 case FORMAT_X16B16G16R16UI: 2473 case FORMAT_A16B16G16R16I: 2474 case FORMAT_A16B16G16R16UI: 2475 case FORMAT_V16U16: 2476 case FORMAT_A16W16V16U16: 2477 case FORMAT_Q16W16V16U16: 2478 return false; 2479 default: 2480 ASSERT(false); 2481 } 2482 2483 return false; 2484 } 2485 isRGBComponent(int component) const2486 bool SamplerCore::isRGBComponent(int component) const 2487 { 2488 switch(state.textureFormat) 2489 { 2490 case FORMAT_R5G6B5: return component < 3; 2491 case FORMAT_R8I_SNORM: return component < 1; 2492 case FORMAT_G8R8I_SNORM: return component < 2; 2493 case FORMAT_X8B8G8R8I_SNORM: return component < 3; 2494 case FORMAT_A8B8G8R8I_SNORM: return component < 3; 2495 case FORMAT_R8I: return component < 1; 2496 case FORMAT_R8UI: return component < 1; 2497 case FORMAT_G8R8I: return component < 2; 2498 case FORMAT_G8R8UI: return component < 2; 2499 case FORMAT_X8B8G8R8I: return component < 3; 2500 case FORMAT_X8B8G8R8UI: return component < 3; 2501 case FORMAT_A8B8G8R8I: return component < 3; 2502 case FORMAT_A8B8G8R8UI: return component < 3; 2503 case FORMAT_R32I: return component < 1; 2504 case FORMAT_R32UI: return component < 1; 2505 case FORMAT_G32R32I: return component < 2; 2506 case FORMAT_G32R32UI: return component < 2; 2507 case FORMAT_X32B32G32R32I: return component < 3; 2508 case FORMAT_X32B32G32R32UI: return component < 3; 2509 case FORMAT_A32B32G32R32I: return component < 3; 2510 case FORMAT_A32B32G32R32UI: return component < 3; 2511 case FORMAT_G8R8: return component < 2; 2512 case FORMAT_X8R8G8B8: return component < 3; 2513 case FORMAT_X8B8G8R8: return component < 3; 2514 case FORMAT_A8R8G8B8: return component < 3; 2515 case FORMAT_A8B8G8R8: return component < 3; 2516 case FORMAT_SRGB8_X8: return component < 3; 2517 case FORMAT_SRGB8_A8: return component < 3; 2518 case FORMAT_V8U8: return false; 2519 case FORMAT_Q8W8V8U8: return false; 2520 case FORMAT_X8L8V8U8: return false; 2521 case FORMAT_R32F: return component < 1; 2522 case FORMAT_G32R32F: return component < 2; 2523 case FORMAT_X32B32G32R32F: return component < 3; 2524 case FORMAT_A32B32G32R32F: return component < 3; 2525 case FORMAT_A8: return false; 2526 case FORMAT_R8: return component < 1; 2527 case FORMAT_L8: return component < 1; 2528 case FORMAT_A8L8: return component < 1; 2529 case FORMAT_D32F: return false; 2530 case FORMAT_D32F_LOCKABLE: return false; 2531 case FORMAT_D32FS8_TEXTURE: return false; 2532 case FORMAT_D32FS8_SHADOW: return false; 2533 case FORMAT_L16: return component < 1; 2534 case FORMAT_G16R16: return component < 2; 2535 case FORMAT_A16B16G16R16: return component < 3; 2536 case FORMAT_R16I: return component < 1; 2537 case FORMAT_R16UI: return component < 1; 2538 case FORMAT_G16R16I: return component < 2; 2539 case FORMAT_G16R16UI: return component < 2; 2540 case FORMAT_X16B16G16R16I: return component < 3; 2541 case FORMAT_X16B16G16R16UI: return component < 3; 2542 case FORMAT_A16B16G16R16I: return component < 3; 2543 case FORMAT_A16B16G16R16UI: return component < 3; 2544 case FORMAT_V16U16: return false; 2545 case FORMAT_A16W16V16U16: return false; 2546 case FORMAT_Q16W16V16U16: return false; 2547 case FORMAT_YV12_BT601: return component < 3; 2548 case FORMAT_YV12_BT709: return component < 3; 2549 case FORMAT_YV12_JFIF: return component < 3; 2550 default: 2551 ASSERT(false); 2552 } 2553 2554 return false; 2555 } 2556 } 2557