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 "Sampler.hpp" 16 17 #include "Context.hpp" 18 #include "Surface.hpp" 19 #include "Pipeline/PixelRoutine.hpp" 20 #include "Vulkan/VkDebug.hpp" 21 22 #include <cstring> 23 24 namespace sw 25 { 26 FilterType Sampler::maximumTextureFilterQuality = FILTER_LINEAR; 27 MipmapType Sampler::maximumMipmapFilterQuality = MIPMAP_POINT; 28 State()29 Sampler::State::State() 30 { 31 memset(this, 0, sizeof(State)); 32 } 33 Sampler()34 Sampler::Sampler() 35 { 36 // FIXME: Mipmap::init 37 static const unsigned int zero = 0x00FF00FF; 38 39 for(int level = 0; level < MIPMAP_LEVELS; level++) 40 { 41 Mipmap &mipmap = texture.mipmap[level]; 42 43 memset(&mipmap, 0, sizeof(Mipmap)); 44 45 for(int face = 0; face < 6; face++) 46 { 47 mipmap.buffer[face] = &zero; 48 } 49 } 50 51 externalTextureFormat = VK_FORMAT_UNDEFINED; 52 internalTextureFormat = VK_FORMAT_UNDEFINED; 53 textureType = TEXTURE_NULL; 54 55 textureFilter = FILTER_LINEAR; 56 addressingModeU = ADDRESSING_WRAP; 57 addressingModeV = ADDRESSING_WRAP; 58 addressingModeW = ADDRESSING_WRAP; 59 mipmapFilterState = MIPMAP_NONE; 60 sRGB = false; 61 gather = false; 62 highPrecisionFiltering = false; 63 border = 0; 64 65 swizzleR = SWIZZLE_RED; 66 swizzleG = SWIZZLE_GREEN; 67 swizzleB = SWIZZLE_BLUE; 68 swizzleA = SWIZZLE_ALPHA; 69 70 compare = COMPARE_BYPASS; 71 72 texture.LOD = 0.0f; 73 exp2LOD = 1.0f; 74 75 texture.baseLevel = 0; 76 texture.maxLevel = 1000; 77 texture.maxLod = MAX_TEXTURE_LOD; 78 texture.minLod = 0; 79 } 80 ~Sampler()81 Sampler::~Sampler() 82 { 83 } 84 samplerState() const85 Sampler::State Sampler::samplerState() const 86 { 87 State state; 88 89 if(textureType != TEXTURE_NULL) 90 { 91 state.textureType = textureType; 92 state.textureFormat = internalTextureFormat; 93 state.textureFilter = getTextureFilter(); 94 state.addressingModeU = getAddressingModeU(); 95 state.addressingModeV = getAddressingModeV(); 96 state.addressingModeW = getAddressingModeW(); 97 state.mipmapFilter = mipmapFilter(); 98 state.sRGB = (sRGB && Surface::isSRGBreadable(externalTextureFormat)) || Surface::isSRGBformat(internalTextureFormat); 99 state.swizzleR = swizzleR; 100 state.swizzleG = swizzleG; 101 state.swizzleB = swizzleB; 102 state.swizzleA = swizzleA; 103 state.highPrecisionFiltering = highPrecisionFiltering; 104 state.compare = getCompareFunc(); 105 106 #if PERF_PROFILE 107 state.compressedFormat = Surface::isCompressed(externalTextureFormat); 108 #endif 109 } 110 111 return state; 112 } 113 setTextureLevel(int face,int level,Surface * surface,TextureType type)114 void Sampler::setTextureLevel(int face, int level, Surface *surface, TextureType type) 115 { 116 if(surface) 117 { 118 Mipmap &mipmap = texture.mipmap[level]; 119 120 border = surface->getBorder(); 121 mipmap.buffer[face] = surface->lockInternal(-border, -border, 0, LOCK_UNLOCKED, PRIVATE); 122 123 if(face == 0) 124 { 125 externalTextureFormat = surface->getExternalFormat(); 126 internalTextureFormat = surface->getInternalFormat(); 127 128 int width = surface->getWidth(); 129 int height = surface->getHeight(); 130 int depth = surface->getDepth(); 131 int pitchP = surface->getInternalPitchP(); 132 int sliceP = surface->getInternalSliceP(); 133 134 if(level == 0) 135 { 136 texture.widthHeightLOD[0] = width * exp2LOD; 137 texture.widthHeightLOD[1] = width * exp2LOD; 138 texture.widthHeightLOD[2] = height * exp2LOD; 139 texture.widthHeightLOD[3] = height * exp2LOD; 140 141 texture.widthLOD[0] = width * exp2LOD; 142 texture.widthLOD[1] = width * exp2LOD; 143 texture.widthLOD[2] = width * exp2LOD; 144 texture.widthLOD[3] = width * exp2LOD; 145 146 texture.heightLOD[0] = height * exp2LOD; 147 texture.heightLOD[1] = height * exp2LOD; 148 texture.heightLOD[2] = height * exp2LOD; 149 texture.heightLOD[3] = height * exp2LOD; 150 151 texture.depthLOD[0] = depth * exp2LOD; 152 texture.depthLOD[1] = depth * exp2LOD; 153 texture.depthLOD[2] = depth * exp2LOD; 154 texture.depthLOD[3] = depth * exp2LOD; 155 } 156 157 if(Surface::isFloatFormat(internalTextureFormat)) 158 { 159 mipmap.fWidth[0] = (float)width / 65536.0f; 160 mipmap.fWidth[1] = (float)width / 65536.0f; 161 mipmap.fWidth[2] = (float)width / 65536.0f; 162 mipmap.fWidth[3] = (float)width / 65536.0f; 163 164 mipmap.fHeight[0] = (float)height / 65536.0f; 165 mipmap.fHeight[1] = (float)height / 65536.0f; 166 mipmap.fHeight[2] = (float)height / 65536.0f; 167 mipmap.fHeight[3] = (float)height / 65536.0f; 168 169 mipmap.fDepth[0] = (float)depth / 65536.0f; 170 mipmap.fDepth[1] = (float)depth / 65536.0f; 171 mipmap.fDepth[2] = (float)depth / 65536.0f; 172 mipmap.fDepth[3] = (float)depth / 65536.0f; 173 } 174 175 short halfTexelU = 0x8000 / width; 176 short halfTexelV = 0x8000 / height; 177 short halfTexelW = 0x8000 / depth; 178 179 mipmap.uHalf[0] = halfTexelU; 180 mipmap.uHalf[1] = halfTexelU; 181 mipmap.uHalf[2] = halfTexelU; 182 mipmap.uHalf[3] = halfTexelU; 183 184 mipmap.vHalf[0] = halfTexelV; 185 mipmap.vHalf[1] = halfTexelV; 186 mipmap.vHalf[2] = halfTexelV; 187 mipmap.vHalf[3] = halfTexelV; 188 189 mipmap.wHalf[0] = halfTexelW; 190 mipmap.wHalf[1] = halfTexelW; 191 mipmap.wHalf[2] = halfTexelW; 192 mipmap.wHalf[3] = halfTexelW; 193 194 mipmap.width[0] = width; 195 mipmap.width[1] = width; 196 mipmap.width[2] = width; 197 mipmap.width[3] = width; 198 199 mipmap.height[0] = height; 200 mipmap.height[1] = height; 201 mipmap.height[2] = height; 202 mipmap.height[3] = height; 203 204 mipmap.depth[0] = depth; 205 mipmap.depth[1] = depth; 206 mipmap.depth[2] = depth; 207 mipmap.depth[3] = depth; 208 209 mipmap.onePitchP[0] = 1; 210 mipmap.onePitchP[1] = pitchP; 211 mipmap.onePitchP[2] = 1; 212 mipmap.onePitchP[3] = pitchP; 213 214 mipmap.pitchP[0] = pitchP; 215 mipmap.pitchP[1] = pitchP; 216 mipmap.pitchP[2] = pitchP; 217 mipmap.pitchP[3] = pitchP; 218 219 mipmap.sliceP[0] = sliceP; 220 mipmap.sliceP[1] = sliceP; 221 mipmap.sliceP[2] = sliceP; 222 mipmap.sliceP[3] = sliceP; 223 224 if(internalTextureFormat == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) 225 { 226 unsigned int YStride = pitchP; 227 unsigned int YSize = YStride * height; 228 unsigned int CStride = align<16>(YStride / 2); 229 unsigned int CSize = CStride * height / 2; 230 231 mipmap.buffer[1] = (byte*)mipmap.buffer[0] + YSize; 232 mipmap.buffer[2] = (byte*)mipmap.buffer[1] + CSize; 233 234 texture.mipmap[1].width[0] = width / 2; 235 texture.mipmap[1].width[1] = width / 2; 236 texture.mipmap[1].width[2] = width / 2; 237 texture.mipmap[1].width[3] = width / 2; 238 texture.mipmap[1].height[0] = height / 2; 239 texture.mipmap[1].height[1] = height / 2; 240 texture.mipmap[1].height[2] = height / 2; 241 texture.mipmap[1].height[3] = height / 2; 242 texture.mipmap[1].onePitchP[0] = 1; 243 texture.mipmap[1].onePitchP[1] = CStride; 244 texture.mipmap[1].onePitchP[2] = 1; 245 texture.mipmap[1].onePitchP[3] = CStride; 246 } 247 } 248 } 249 250 textureType = type; 251 } 252 setTextureFilter(FilterType textureFilter)253 void Sampler::setTextureFilter(FilterType textureFilter) 254 { 255 this->textureFilter = (FilterType)min(textureFilter, maximumTextureFilterQuality); 256 } 257 setMipmapFilter(MipmapType mipmapFilter)258 void Sampler::setMipmapFilter(MipmapType mipmapFilter) 259 { 260 mipmapFilterState = (MipmapType)min(mipmapFilter, maximumMipmapFilterQuality); 261 } 262 setGatherEnable(bool enable)263 void Sampler::setGatherEnable(bool enable) 264 { 265 gather = enable; 266 } 267 setAddressingModeU(AddressingMode addressingMode)268 void Sampler::setAddressingModeU(AddressingMode addressingMode) 269 { 270 addressingModeU = addressingMode; 271 } 272 setAddressingModeV(AddressingMode addressingMode)273 void Sampler::setAddressingModeV(AddressingMode addressingMode) 274 { 275 addressingModeV = addressingMode; 276 } 277 setAddressingModeW(AddressingMode addressingMode)278 void Sampler::setAddressingModeW(AddressingMode addressingMode) 279 { 280 addressingModeW = addressingMode; 281 } 282 setReadSRGB(bool sRGB)283 void Sampler::setReadSRGB(bool sRGB) 284 { 285 this->sRGB = sRGB; 286 } 287 setBorderColor(const Color<float> & borderColor)288 void Sampler::setBorderColor(const Color<float> &borderColor) 289 { 290 // FIXME: Compact into generic function // FIXME: Clamp 291 short r = iround(0xFFFF * borderColor.r); 292 short g = iround(0xFFFF * borderColor.g); 293 short b = iround(0xFFFF * borderColor.b); 294 short a = iround(0xFFFF * borderColor.a); 295 296 texture.borderColor4[0][0] = texture.borderColor4[0][1] = texture.borderColor4[0][2] = texture.borderColor4[0][3] = r; 297 texture.borderColor4[1][0] = texture.borderColor4[1][1] = texture.borderColor4[1][2] = texture.borderColor4[1][3] = g; 298 texture.borderColor4[2][0] = texture.borderColor4[2][1] = texture.borderColor4[2][2] = texture.borderColor4[2][3] = b; 299 texture.borderColor4[3][0] = texture.borderColor4[3][1] = texture.borderColor4[3][2] = texture.borderColor4[3][3] = a; 300 301 texture.borderColorF[0][0] = texture.borderColorF[0][1] = texture.borderColorF[0][2] = texture.borderColorF[0][3] = borderColor.r; 302 texture.borderColorF[1][0] = texture.borderColorF[1][1] = texture.borderColorF[1][2] = texture.borderColorF[1][3] = borderColor.g; 303 texture.borderColorF[2][0] = texture.borderColorF[2][1] = texture.borderColorF[2][2] = texture.borderColorF[2][3] = borderColor.b; 304 texture.borderColorF[3][0] = texture.borderColorF[3][1] = texture.borderColorF[3][2] = texture.borderColorF[3][3] = borderColor.a; 305 } 306 setMaxAnisotropy(float maxAnisotropy)307 void Sampler::setMaxAnisotropy(float maxAnisotropy) 308 { 309 texture.maxAnisotropy = maxAnisotropy; 310 } 311 setHighPrecisionFiltering(bool highPrecisionFiltering)312 void Sampler::setHighPrecisionFiltering(bool highPrecisionFiltering) 313 { 314 this->highPrecisionFiltering = highPrecisionFiltering; 315 } 316 setSwizzleR(SwizzleType swizzleR)317 void Sampler::setSwizzleR(SwizzleType swizzleR) 318 { 319 this->swizzleR = swizzleR; 320 } 321 setSwizzleG(SwizzleType swizzleG)322 void Sampler::setSwizzleG(SwizzleType swizzleG) 323 { 324 this->swizzleG = swizzleG; 325 } 326 setSwizzleB(SwizzleType swizzleB)327 void Sampler::setSwizzleB(SwizzleType swizzleB) 328 { 329 this->swizzleB = swizzleB; 330 } 331 setSwizzleA(SwizzleType swizzleA)332 void Sampler::setSwizzleA(SwizzleType swizzleA) 333 { 334 this->swizzleA = swizzleA; 335 } 336 setCompareFunc(CompareFunc compare)337 void Sampler::setCompareFunc(CompareFunc compare) 338 { 339 this->compare = compare; 340 } 341 setBaseLevel(int baseLevel)342 void Sampler::setBaseLevel(int baseLevel) 343 { 344 texture.baseLevel = baseLevel; 345 } 346 setMaxLevel(int maxLevel)347 void Sampler::setMaxLevel(int maxLevel) 348 { 349 texture.maxLevel = maxLevel; 350 } 351 setMinLod(float minLod)352 void Sampler::setMinLod(float minLod) 353 { 354 texture.minLod = clamp(minLod, 0.0f, (float)(MAX_TEXTURE_LOD)); 355 } 356 setMaxLod(float maxLod)357 void Sampler::setMaxLod(float maxLod) 358 { 359 texture.maxLod = clamp(maxLod, 0.0f, (float)(MAX_TEXTURE_LOD)); 360 } 361 setFilterQuality(FilterType maximumFilterQuality)362 void Sampler::setFilterQuality(FilterType maximumFilterQuality) 363 { 364 Sampler::maximumTextureFilterQuality = maximumFilterQuality; 365 } 366 setMipmapQuality(MipmapType maximumFilterQuality)367 void Sampler::setMipmapQuality(MipmapType maximumFilterQuality) 368 { 369 Sampler::maximumMipmapFilterQuality = maximumFilterQuality; 370 } 371 setMipmapLOD(float LOD)372 void Sampler::setMipmapLOD(float LOD) 373 { 374 texture.LOD = LOD; 375 exp2LOD = exp2(LOD); 376 } 377 hasTexture() const378 bool Sampler::hasTexture() const 379 { 380 return textureType != TEXTURE_NULL; 381 } 382 hasUnsignedTexture() const383 bool Sampler::hasUnsignedTexture() const 384 { 385 return Surface::isUnsignedComponent(internalTextureFormat, 0) && 386 Surface::isUnsignedComponent(internalTextureFormat, 1) && 387 Surface::isUnsignedComponent(internalTextureFormat, 2) && 388 Surface::isUnsignedComponent(internalTextureFormat, 3); 389 } 390 hasCubeTexture() const391 bool Sampler::hasCubeTexture() const 392 { 393 return textureType == TEXTURE_CUBE; 394 } 395 hasVolumeTexture() const396 bool Sampler::hasVolumeTexture() const 397 { 398 return textureType == TEXTURE_3D || textureType == TEXTURE_2D_ARRAY; 399 } 400 getTextureData()401 const Texture &Sampler::getTextureData() 402 { 403 return texture; 404 } 405 mipmapFilter() const406 MipmapType Sampler::mipmapFilter() const 407 { 408 if(mipmapFilterState != MIPMAP_NONE) 409 { 410 for(int i = 1; i < MIPMAP_LEVELS; i++) 411 { 412 if(texture.mipmap[0].buffer[0] != texture.mipmap[i].buffer[0]) 413 { 414 return mipmapFilterState; 415 } 416 } 417 } 418 419 // Only one mipmap level 420 return MIPMAP_NONE; 421 } 422 getTextureType() const423 TextureType Sampler::getTextureType() const 424 { 425 return textureType; 426 } 427 getTextureFilter() const428 FilterType Sampler::getTextureFilter() const 429 { 430 // Don't filter 1x1 textures. 431 if(texture.mipmap[0].width[0] == 1 && texture.mipmap[0].height[0] == 1 && texture.mipmap[0].depth[0] == 1) 432 { 433 if(mipmapFilter() == MIPMAP_NONE) 434 { 435 return FILTER_POINT; 436 } 437 } 438 439 FilterType filter = textureFilter; 440 441 if(gather && Surface::componentCount(internalTextureFormat) == 1) 442 { 443 filter = FILTER_GATHER; 444 } 445 446 if(textureType != TEXTURE_2D || texture.maxAnisotropy == 1.0f) 447 { 448 return (FilterType)min(filter, FILTER_LINEAR); 449 } 450 451 return filter; 452 } 453 getAddressingModeU() const454 AddressingMode Sampler::getAddressingModeU() const 455 { 456 if(textureType == TEXTURE_CUBE) 457 { 458 return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP; 459 } 460 461 return addressingModeU; 462 } 463 getAddressingModeV() const464 AddressingMode Sampler::getAddressingModeV() const 465 { 466 if(textureType == TEXTURE_CUBE) 467 { 468 return border ? ADDRESSING_SEAMLESS : ADDRESSING_CLAMP; 469 } 470 471 return addressingModeV; 472 } 473 getAddressingModeW() const474 AddressingMode Sampler::getAddressingModeW() const 475 { 476 if(textureType == TEXTURE_2D_ARRAY || 477 textureType == TEXTURE_2D || 478 textureType == TEXTURE_CUBE || 479 textureType == TEXTURE_RECTANGLE) 480 { 481 return ADDRESSING_LAYER; 482 } 483 484 return addressingModeW; 485 } 486 getCompareFunc() const487 CompareFunc Sampler::getCompareFunc() const 488 { 489 if(getTextureFilter() == FILTER_GATHER) 490 { 491 return COMPARE_BYPASS; 492 } 493 494 return compare; 495 } 496 } 497