1 /**************************************************************************** 2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * @file TilingFunctions.h 24 * 25 * @brief Tiling functions. 26 * 27 ******************************************************************************/ 28 #pragma once 29 30 #include "core/state.h" 31 #include "core/format_traits.h" 32 #include "memory/tilingtraits.h" 33 34 #include <algorithm> 35 36 #define MAX_NUM_LOD 15 37 38 #define GFX_ALIGN(x, a) (((x) + ((a) - 1)) - (((x) + ((a) - 1)) & ((a) - 1))) // Alt implementation with bitwise not (~) has issue with uint32 align used with 64-bit value, since ~'ed value will remain 32-bit. 39 40 ////////////////////////////////////////////////////////////////////////// 41 /// SimdTile SSE(2x2), AVX(4x2), or AVX-512(4x4?) 42 ////////////////////////////////////////////////////////////////////////// 43 template<SWR_FORMAT HotTileFormat, SWR_FORMAT SrcOrDstFormat> 44 struct SimdTile 45 { 46 // SimdTile is SOA (e.g. rrrrrrrr gggggggg bbbbbbbb aaaaaaaa ) 47 float color[FormatTraits<HotTileFormat>::numComps][KNOB_SIMD_WIDTH]; 48 49 ////////////////////////////////////////////////////////////////////////// 50 /// @brief Retrieve color from simd. 51 /// @param index - linear index to color within simd. 52 /// @param outputColor - output color GetSwizzledColorSimdTile53 INLINE void GetSwizzledColor( 54 uint32_t index, 55 float outputColor[4]) 56 { 57 // SOA pattern for 2x2 is a subset of 4x2. 58 // 0 1 4 5 59 // 2 3 6 7 60 // The offset converts pattern to linear 61 #if (SIMD_TILE_X_DIM == 4) 62 static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 }; 63 #elif (SIMD_TILE_X_DIM == 2) 64 static const uint32_t offset[] = { 0, 1, 2, 3 }; 65 #endif 66 67 for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i) 68 { 69 outputColor[i] = this->color[FormatTraits<SrcOrDstFormat>::swizzle(i)][offset[index]]; 70 } 71 } 72 73 ////////////////////////////////////////////////////////////////////////// 74 /// @brief Retrieve color from simd. 75 /// @param index - linear index to color within simd. 76 /// @param outputColor - output color SetSwizzledColorSimdTile77 INLINE void SetSwizzledColor( 78 uint32_t index, 79 const float src[4]) 80 { 81 // SOA pattern for 2x2 is a subset of 4x2. 82 // 0 1 4 5 83 // 2 3 6 7 84 // The offset converts pattern to linear 85 #if (SIMD_TILE_X_DIM == 4) 86 static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 }; 87 #elif (SIMD_TILE_X_DIM == 2) 88 static const uint32_t offset[] = { 0, 1, 2, 3 }; 89 #endif 90 91 // Only loop over the components needed for destination. 92 for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i) 93 { 94 this->color[i][offset[index]] = src[i]; 95 } 96 } 97 }; 98 99 template<> 100 struct SimdTile <R8_UINT,R8_UINT> 101 { 102 // SimdTile is SOA (e.g. rrrrrrrr gggggggg bbbbbbbb aaaaaaaa ) 103 uint8_t color[FormatTraits<R8_UINT>::numComps][KNOB_SIMD_WIDTH]; 104 105 ////////////////////////////////////////////////////////////////////////// 106 /// @brief Retrieve color from simd. 107 /// @param index - linear index to color within simd. 108 /// @param outputColor - output color 109 INLINE void GetSwizzledColor( 110 uint32_t index, 111 float outputColor[4]) 112 { 113 // SOA pattern for 2x2 is a subset of 4x2. 114 // 0 1 4 5 115 // 2 3 6 7 116 // The offset converts pattern to linear 117 #if (SIMD_TILE_X_DIM == 4) 118 static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 }; 119 #elif (SIMD_TILE_X_DIM == 2) 120 static const uint32_t offset[] = { 0, 1, 2, 3 }; 121 #endif 122 123 for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i) 124 { 125 uint32_t src = this->color[FormatTraits<R8_UINT>::swizzle(i)][offset[index]]; 126 outputColor[i] = *(float*)&src; 127 } 128 } 129 130 ////////////////////////////////////////////////////////////////////////// 131 /// @brief Retrieve color from simd. 132 /// @param index - linear index to color within simd. 133 /// @param outputColor - output color 134 INLINE void SetSwizzledColor( 135 uint32_t index, 136 const float src[4]) 137 { 138 // SOA pattern for 2x2 is a subset of 4x2. 139 // 0 1 4 5 140 // 2 3 6 7 141 // The offset converts pattern to linear 142 #if (SIMD_TILE_X_DIM == 4) 143 static const uint32_t offset[] = { 0, 1, 4, 5, 2, 3, 6, 7 }; 144 #elif (SIMD_TILE_X_DIM == 2) 145 static const uint32_t offset[] = { 0, 1, 2, 3 }; 146 #endif 147 148 // Only loop over the components needed for destination. 149 for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i) 150 { 151 this->color[i][offset[index]] = *(uint8_t*)&src[i]; 152 } 153 } 154 }; 155 156 #if ENABLE_AVX512_SIMD16 157 ////////////////////////////////////////////////////////////////////////// 158 /// SimdTile 8x2 for AVX-512 159 ////////////////////////////////////////////////////////////////////////// 160 161 template<SWR_FORMAT HotTileFormat, SWR_FORMAT SrcOrDstFormat> 162 struct SimdTile_16 163 { 164 // SimdTile is SOA (e.g. rrrrrrrrrrrrrrrr gggggggggggggggg bbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaa ) 165 float color[FormatTraits<HotTileFormat>::numComps][KNOB_SIMD16_WIDTH]; 166 167 ////////////////////////////////////////////////////////////////////////// 168 /// @brief Retrieve color from simd. 169 /// @param index - linear index to color within simd. 170 /// @param outputColor - output color 171 INLINE void GetSwizzledColor( 172 uint32_t index, 173 float outputColor[4]) 174 { 175 // SOA pattern for 8x2.. 176 // 0 1 4 5 8 9 C D 177 // 2 3 6 7 A B E F 178 // The offset converts pattern to linear 179 static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 }; 180 181 for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i) 182 { 183 outputColor[i] = this->color[FormatTraits<SrcOrDstFormat>::swizzle(i)][offset[index]]; 184 } 185 } 186 187 ////////////////////////////////////////////////////////////////////////// 188 /// @brief Retrieve color from simd. 189 /// @param index - linear index to color within simd. 190 /// @param outputColor - output color 191 INLINE void SetSwizzledColor( 192 uint32_t index, 193 const float src[4]) 194 { 195 // SOA pattern for 8x2.. 196 // 0 1 4 5 8 9 C D 197 // 2 3 6 7 A B E F 198 // The offset converts pattern to linear 199 static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 }; 200 201 for (uint32_t i = 0; i < FormatTraits<SrcOrDstFormat>::numComps; ++i) 202 { 203 this->color[i][offset[index]] = src[i]; 204 } 205 } 206 }; 207 208 template<> 209 struct SimdTile_16 <R8_UINT, R8_UINT> 210 { 211 // SimdTile is SOA (e.g. rrrrrrrrrrrrrrrr gggggggggggggggg bbbbbbbbbbbbbbbb aaaaaaaaaaaaaaaa ) 212 uint8_t color[FormatTraits<R8_UINT>::numComps][KNOB_SIMD16_WIDTH]; 213 214 ////////////////////////////////////////////////////////////////////////// 215 /// @brief Retrieve color from simd. 216 /// @param index - linear index to color within simd. 217 /// @param outputColor - output color 218 INLINE void GetSwizzledColor( 219 uint32_t index, 220 float outputColor[4]) 221 { 222 // SOA pattern for 8x2.. 223 // 0 1 4 5 8 9 C D 224 // 2 3 6 7 A B E F 225 // The offset converts pattern to linear 226 static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 }; 227 228 for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i) 229 { 230 uint32_t src = this->color[FormatTraits<R8_UINT>::swizzle(i)][offset[index]]; 231 outputColor[i] = *(float*)&src; 232 } 233 } 234 235 ////////////////////////////////////////////////////////////////////////// 236 /// @brief Retrieve color from simd. 237 /// @param index - linear index to color within simd. 238 /// @param outputColor - output color 239 INLINE void SetSwizzledColor( 240 uint32_t index, 241 const float src[4]) 242 { 243 // SOA pattern for 8x2.. 244 // 0 1 4 5 8 9 C D 245 // 2 3 6 7 A B E F 246 // The offset converts pattern to linear 247 static const uint32_t offset[KNOB_SIMD16_WIDTH] = { 0, 1, 4, 5, 8, 9, 12, 13, 2, 3, 6, 7, 10, 11, 14, 15 }; 248 249 for (uint32_t i = 0; i < FormatTraits<R8_UINT>::numComps; ++i) 250 { 251 this->color[i][offset[index]] = *(uint8_t*)&src[i]; 252 } 253 } 254 }; 255 256 #endif 257 ////////////////////////////////////////////////////////////////////////// 258 /// @brief Computes lod offset for 1D surface at specified lod. 259 /// @param baseWidth - width of basemip (mip 0). 260 /// @param hAlign - horizontal alignment per miip, in texels 261 /// @param lod - lod index 262 /// @param offset - output offset. 263 INLINE void ComputeLODOffset1D( 264 const SWR_FORMAT_INFO& info, 265 uint32_t baseWidth, 266 uint32_t hAlign, 267 uint32_t lod, 268 uint32_t &offset) 269 { 270 if (lod == 0) 271 { 272 offset = 0; 273 } 274 else 275 { 276 uint32_t curWidth = baseWidth; 277 // @note hAlign is already in blocks for compressed formats so upconvert 278 // so that we have the desired alignment post-divide. 279 if (info.isBC) 280 { 281 hAlign *= info.bcWidth; 282 } 283 284 offset = GFX_ALIGN(curWidth, hAlign); 285 for (uint32_t l = 1; l < lod; ++l) 286 { 287 curWidth = std::max<uint32_t>(curWidth >> 1, 1U); 288 offset += GFX_ALIGN(curWidth, hAlign); 289 } 290 291 if (info.isSubsampled || info.isBC) 292 { 293 offset /= info.bcWidth; 294 } 295 } 296 } 297 298 ////////////////////////////////////////////////////////////////////////// 299 /// @brief Computes x lod offset for 2D surface at specified lod. 300 /// @param baseWidth - width of basemip (mip 0). 301 /// @param hAlign - horizontal alignment per mip, in texels 302 /// @param lod - lod index 303 /// @param offset - output offset. 304 INLINE void ComputeLODOffsetX( 305 const SWR_FORMAT_INFO& info, 306 uint32_t baseWidth, 307 uint32_t hAlign, 308 uint32_t lod, 309 uint32_t &offset) 310 { 311 if (lod < 2) 312 { 313 offset = 0; 314 } 315 else 316 { 317 uint32_t curWidth = baseWidth; 318 // @note hAlign is already in blocks for compressed formats so upconvert 319 // so that we have the desired alignment post-divide. 320 if (info.isBC) 321 { 322 hAlign *= info.bcWidth; 323 } 324 325 curWidth = std::max<uint32_t>(curWidth >> 1, 1U); 326 curWidth = GFX_ALIGN(curWidth, hAlign); 327 328 if (info.isSubsampled || info.isBC) 329 { 330 curWidth /= info.bcWidth; 331 } 332 333 offset = curWidth; 334 } 335 } 336 337 ////////////////////////////////////////////////////////////////////////// 338 /// @brief Computes y lod offset for 2D surface at specified lod. 339 /// @param baseWidth - width of basemip (mip 0). 340 /// @param vAlign - vertical alignment per mip, in rows 341 /// @param lod - lod index 342 /// @param offset - output offset. 343 INLINE void ComputeLODOffsetY( 344 const SWR_FORMAT_INFO& info, 345 uint32_t baseHeight, 346 uint32_t vAlign, 347 uint32_t lod, 348 uint32_t &offset) 349 { 350 if (lod == 0) 351 { 352 offset = 0; 353 } 354 else 355 { 356 offset = 0; 357 uint32_t mipHeight = baseHeight; 358 359 // @note vAlign is already in blocks for compressed formats so upconvert 360 // so that we have the desired alignment post-divide. 361 if (info.isBC) 362 { 363 vAlign *= info.bcHeight; 364 } 365 366 for (uint32_t l = 1; l <= lod; ++l) 367 { 368 uint32_t alignedMipHeight = GFX_ALIGN(mipHeight, vAlign); 369 offset += ((l != 2) ? alignedMipHeight : 0); 370 mipHeight = std::max<uint32_t>(mipHeight >> 1, 1U); 371 } 372 373 if (info.isBC) 374 { 375 offset /= info.bcHeight; 376 } 377 } 378 } 379 380 ////////////////////////////////////////////////////////////////////////// 381 /// @brief Computes 1D surface offset 382 /// @param x - offset from start of array slice at given lod. 383 /// @param array - array slice index 384 /// @param lod - lod index 385 /// @param pState - surface state 386 /// @param xOffsetBytes - output offset in bytes. 387 template<bool UseCachedOffsets> 388 INLINE void ComputeSurfaceOffset1D( 389 uint32_t x, 390 uint32_t array, 391 uint32_t lod, 392 const SWR_SURFACE_STATE *pState, 393 uint32_t &xOffsetBytes) 394 { 395 const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format); 396 uint32_t lodOffset; 397 398 if (UseCachedOffsets) 399 { 400 lodOffset = pState->lodOffsets[0][lod]; 401 } 402 else 403 { 404 ComputeLODOffset1D(info, pState->width, pState->halign, lod, lodOffset); 405 } 406 407 xOffsetBytes = (array * pState->qpitch + lodOffset + x) * info.Bpp; 408 } 409 410 ////////////////////////////////////////////////////////////////////////// 411 /// @brief Adjusts the array slice for legacy TileY MSAA 412 /// @param pState - surface state 413 /// @param array - array slice index 414 /// @param sampleNum - requested sample 415 INLINE void AdjustCoordsForMSAA(const SWR_SURFACE_STATE *pState, uint32_t& x, uint32_t& y, uint32_t& arrayIndex, uint32_t sampleNum) 416 { 417 /// @todo: might want to templatize adjusting for sample slices when we support tileYS/tileYF. 418 if((pState->tileMode == SWR_TILE_MODE_YMAJOR || 419 pState->tileMode == SWR_TILE_MODE_WMAJOR) && 420 pState->bInterleavedSamples) 421 { 422 uint32_t newX, newY, newSampleX, newSampleY; 423 switch(pState->numSamples) 424 { 425 case 1: 426 newX = x; 427 newY = y; 428 newSampleX = newSampleY = 0; 429 break; 430 case 2: 431 { 432 assert(pState->type == SURFACE_2D); 433 static const uint32_t xMask = 0xFFFFFFFD; 434 static const uint32_t sampleMaskX = 0x1; 435 newX = pdep_u32(x, xMask); 436 newY = y; 437 newSampleX = pext_u32(sampleNum, sampleMaskX); 438 newSampleY = 0; 439 } 440 break; 441 case 4: 442 { 443 assert(pState->type == SURFACE_2D); 444 static const uint32_t mask = 0xFFFFFFFD; 445 static const uint32_t sampleMaskX = 0x1; 446 static const uint32_t sampleMaskY = 0x2; 447 newX = pdep_u32(x, mask); 448 newY = pdep_u32(y, mask); 449 newSampleX = pext_u32(sampleNum, sampleMaskX); 450 newSampleY = pext_u32(sampleNum, sampleMaskY); 451 } 452 break; 453 case 8: 454 { 455 assert(pState->type == SURFACE_2D); 456 static const uint32_t xMask = 0xFFFFFFF9; 457 static const uint32_t yMask = 0xFFFFFFFD; 458 static const uint32_t sampleMaskX = 0x5; 459 static const uint32_t sampleMaskY = 0x2; 460 newX = pdep_u32(x, xMask); 461 newY = pdep_u32(y, yMask); 462 newSampleX = pext_u32(sampleNum, sampleMaskX); 463 newSampleY = pext_u32(sampleNum, sampleMaskY); 464 } 465 break; 466 case 16: 467 { 468 assert(pState->type == SURFACE_2D); 469 static const uint32_t mask = 0xFFFFFFF9; 470 static const uint32_t sampleMaskX = 0x5; 471 static const uint32_t sampleMaskY = 0xA; 472 newX = pdep_u32(x, mask); 473 newY = pdep_u32(y, mask); 474 newSampleX = pext_u32(sampleNum, sampleMaskX); 475 newSampleY = pext_u32(sampleNum, sampleMaskY); 476 } 477 break; 478 default: 479 assert(0 && "Unsupported sample count"); 480 newX = newY = 0; 481 newSampleX = newSampleY = 0; 482 break; 483 } 484 x = newX | (newSampleX << 1); 485 y = newY | (newSampleY << 1); 486 } 487 else if(pState->tileMode == SWR_TILE_MODE_YMAJOR || 488 pState->tileMode == SWR_TILE_NONE) 489 { 490 uint32_t sampleShift; 491 switch(pState->numSamples) 492 { 493 case 1: 494 assert(sampleNum == 0); 495 sampleShift = 0; 496 break; 497 case 2: 498 assert(pState->type == SURFACE_2D); 499 sampleShift = 1; 500 break; 501 case 4: 502 assert(pState->type == SURFACE_2D); 503 sampleShift = 2; 504 break; 505 case 8: 506 assert(pState->type == SURFACE_2D); 507 sampleShift = 3; 508 break; 509 case 16: 510 assert(pState->type == SURFACE_2D); 511 sampleShift = 4; 512 break; 513 default: 514 assert(0 && "Unsupported sample count"); 515 sampleShift = 0; 516 break; 517 } 518 arrayIndex = (arrayIndex << sampleShift) | sampleNum; 519 } 520 } 521 522 ////////////////////////////////////////////////////////////////////////// 523 /// @brief Computes 2D surface offset 524 /// @param x - horizontal offset from start of array slice and lod. 525 /// @param y - vertical offset from start of array slice and lod. 526 /// @param array - array slice index 527 /// @param lod - lod index 528 /// @param pState - surface state 529 /// @param xOffsetBytes - output x offset in bytes. 530 /// @param yOffsetRows - output y offset in bytes. 531 template<bool UseCachedOffsets> 532 INLINE void ComputeSurfaceOffset2D(uint32_t x, uint32_t y, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState, uint32_t &xOffsetBytes, uint32_t &yOffsetRows) 533 { 534 const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format); 535 uint32_t lodOffsetX, lodOffsetY; 536 537 if (UseCachedOffsets) 538 { 539 lodOffsetX = pState->lodOffsets[0][lod]; 540 lodOffsetY = pState->lodOffsets[1][lod]; 541 } 542 else 543 { 544 ComputeLODOffsetX(info, pState->width, pState->halign, lod, lodOffsetX); 545 ComputeLODOffsetY(info, pState->height, pState->valign, lod, lodOffsetY); 546 } 547 548 AdjustCoordsForMSAA(pState, x, y, array, sampleNum); 549 xOffsetBytes = (x + lodOffsetX + pState->xOffset) * info.Bpp; 550 yOffsetRows = (array * pState->qpitch) + lodOffsetY + y + pState->yOffset; 551 } 552 553 ////////////////////////////////////////////////////////////////////////// 554 /// @brief Computes 3D surface offset 555 /// @param x - horizontal offset from start of array slice and lod. 556 /// @param y - vertical offset from start of array slice and lod. 557 /// @param z - depth offset from start of array slice and lod. 558 /// @param lod - lod index 559 /// @param pState - surface state 560 /// @param xOffsetBytes - output x offset in bytes. 561 /// @param yOffsetRows - output y offset in rows. 562 /// @param zOffsetSlices - output y offset in slices. 563 template<bool UseCachedOffsets> 564 INLINE void ComputeSurfaceOffset3D(uint32_t x, uint32_t y, uint32_t z, uint32_t lod, const SWR_SURFACE_STATE *pState, uint32_t &xOffsetBytes, uint32_t &yOffsetRows, uint32_t &zOffsetSlices) 565 { 566 const SWR_FORMAT_INFO &info = GetFormatInfo(pState->format); 567 uint32_t lodOffsetX, lodOffsetY; 568 569 if (UseCachedOffsets) 570 { 571 lodOffsetX = pState->lodOffsets[0][lod]; 572 lodOffsetY = pState->lodOffsets[1][lod]; 573 } 574 else 575 { 576 ComputeLODOffsetX(info, pState->width, pState->halign, lod, lodOffsetX); 577 ComputeLODOffsetY(info, pState->height, pState->valign, lod, lodOffsetY); 578 } 579 580 xOffsetBytes = (x + lodOffsetX) * info.Bpp; 581 yOffsetRows = lodOffsetY + y; 582 zOffsetSlices = z; 583 } 584 585 ////////////////////////////////////////////////////////////////////////// 586 /// @brief Swizzles the linear x,y offsets depending on surface tiling mode 587 /// and returns final surface address 588 /// @param xOffsetBytes - x offset from base of surface in bytes 589 /// @param yOffsetRows - y offset from base of surface in rows 590 /// @param pState - pointer to the surface state 591 template<typename TTraits> 592 INLINE uint32_t ComputeTileSwizzle2D(uint32_t xOffsetBytes, uint32_t yOffsetRows, const SWR_SURFACE_STATE *pState) 593 { 594 return ComputeOffset2D<TTraits>(pState->pitch, xOffsetBytes, yOffsetRows); 595 } 596 597 ////////////////////////////////////////////////////////////////////////// 598 /// @brief Swizzles the linear x,y offsets depending on surface tiling mode 599 /// and returns final surface address 600 /// @param xOffsetBytes - x offset from base of surface in bytes 601 /// @param yOffsetRows - y offset from base of surface in rows 602 /// @param pState - pointer to the surface state 603 template<typename TTraits> 604 INLINE uint32_t ComputeTileSwizzle3D(uint32_t xOffsetBytes, uint32_t yOffsetRows, uint32_t zOffsetSlices, const SWR_SURFACE_STATE *pState) 605 { 606 return ComputeOffset3D<TTraits>(pState->qpitch, pState->pitch, xOffsetBytes, yOffsetRows, zOffsetSlices); 607 } 608 609 ////////////////////////////////////////////////////////////////////////// 610 /// @brief Swizzles the linear x,y offsets depending on surface tiling mode 611 /// and returns final surface address 612 /// @param xOffsetBytes - x offset from base of surface in bytes 613 /// @param yOffsetRows - y offset from base of surface in rows 614 /// @param pState - pointer to the surface state 615 INLINE 616 uint32_t TileSwizzle2D(uint32_t xOffsetBytes, uint32_t yOffsetRows, const SWR_SURFACE_STATE *pState) 617 { 618 switch (pState->tileMode) 619 { 620 case SWR_TILE_NONE: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_NONE, 32> >(xOffsetBytes, yOffsetRows, pState); 621 case SWR_TILE_SWRZ: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_SWRZ, 32> >(xOffsetBytes, yOffsetRows, pState); 622 case SWR_TILE_MODE_XMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_XMAJOR, 8> >(xOffsetBytes, yOffsetRows, pState); 623 case SWR_TILE_MODE_YMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_YMAJOR, 32> >(xOffsetBytes, yOffsetRows, pState); 624 case SWR_TILE_MODE_WMAJOR: return ComputeTileSwizzle2D<TilingTraits<SWR_TILE_MODE_WMAJOR, 8> >(xOffsetBytes, yOffsetRows, pState); 625 default: SWR_ASSERT(0, "Unsupported tiling mode"); 626 } 627 return (uint32_t) NULL; 628 } 629 630 ////////////////////////////////////////////////////////////////////////// 631 /// @brief Swizzles the linear x,y,z offsets depending on surface tiling mode 632 /// and returns final surface address 633 /// @param xOffsetBytes - x offset from base of surface in bytes 634 /// @param yOffsetRows - y offset from base of surface in rows 635 /// @param zOffsetSlices - z offset from base of surface in slices 636 /// @param pState - pointer to the surface state 637 INLINE 638 uint32_t TileSwizzle3D(uint32_t xOffsetBytes, uint32_t yOffsetRows, uint32_t zOffsetSlices, const SWR_SURFACE_STATE *pState) 639 { 640 switch (pState->tileMode) 641 { 642 case SWR_TILE_NONE: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_NONE, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState); 643 case SWR_TILE_SWRZ: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_SWRZ, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState); 644 case SWR_TILE_MODE_YMAJOR: return ComputeTileSwizzle3D<TilingTraits<SWR_TILE_MODE_YMAJOR, 32> >(xOffsetBytes, yOffsetRows, zOffsetSlices, pState); 645 default: SWR_ASSERT(0, "Unsupported tiling mode"); 646 } 647 return (uint32_t) NULL; 648 } 649 650 template<bool UseCachedOffsets> 651 INLINE 652 uint32_t ComputeSurfaceOffset(uint32_t x, uint32_t y, uint32_t z, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState) 653 { 654 uint32_t offsetX = 0, offsetY = 0, offsetZ = 0; 655 switch (pState->type) 656 { 657 case SURFACE_BUFFER: 658 case SURFACE_STRUCTURED_BUFFER: 659 offsetX = x * pState->pitch; 660 return offsetX; 661 break; 662 case SURFACE_1D: 663 ComputeSurfaceOffset1D<UseCachedOffsets>(x, array, lod, pState, offsetX); 664 return TileSwizzle2D(offsetX, 0, pState); 665 break; 666 case SURFACE_2D: 667 ComputeSurfaceOffset2D<UseCachedOffsets>(x, y, array, sampleNum, lod, pState, offsetX, offsetY); 668 return TileSwizzle2D(offsetX, offsetY, pState); 669 case SURFACE_3D: 670 ComputeSurfaceOffset3D<UseCachedOffsets>(x, y, z, lod, pState, offsetX, offsetY, offsetZ); 671 return TileSwizzle3D(offsetX, offsetY, offsetZ, pState); 672 break; 673 case SURFACE_CUBE: 674 ComputeSurfaceOffset2D<UseCachedOffsets>(x, y, array, sampleNum, lod, pState, offsetX, offsetY); 675 return TileSwizzle2D(offsetX, offsetY, pState); 676 break; 677 default: SWR_ASSERT(0, "Unsupported format"); 678 } 679 680 return (uint32_t) NULL; 681 } 682 683 typedef void*(*PFN_COMPUTESURFADDR)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, const SWR_SURFACE_STATE*); 684 685 ////////////////////////////////////////////////////////////////////////// 686 /// @brief Computes surface address at the given location and lod 687 /// @param x - x location in pixels 688 /// @param y - y location in rows 689 /// @param z - z location for 3D surfaces 690 /// @param array - array slice for 1D and 2D surfaces 691 /// @param lod - level of detail 692 /// @param pState - pointer to the surface state 693 template<bool UseCachedOffsets, bool IsRead> 694 INLINE 695 void* ComputeSurfaceAddress(uint32_t x, uint32_t y, uint32_t z, uint32_t array, uint32_t sampleNum, uint32_t lod, const SWR_SURFACE_STATE *pState) 696 { 697 return pState->pBaseAddress + ComputeSurfaceOffset<UseCachedOffsets>(x, y, z, array, sampleNum, lod, pState); 698 } 699