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 multisample.h 24 * 25 ******************************************************************************/ 26 27 #pragma once 28 29 #include "context.h" 30 #include "format_traits.h" 31 32 ////////////////////////////////////////////////////////////////////////// 33 /// @brief convenience typedef for testing for single sample case 34 typedef std::integral_constant<int, 1> SingleSampleT; 35 36 INLINE 37 uint32_t GetNumSamples(SWR_MULTISAMPLE_COUNT sampleCount) 38 { 39 static const uint32_t sampleCountLUT[SWR_MULTISAMPLE_TYPE_COUNT] {1, 2, 4, 8, 16}; 40 assert(sampleCount < SWR_MULTISAMPLE_TYPE_COUNT); 41 return sampleCountLUT[sampleCount]; 42 } 43 44 INLINE 45 SWR_MULTISAMPLE_COUNT GetSampleCount(uint32_t numSamples) 46 { 47 switch(numSamples) 48 { 49 case 1: return SWR_MULTISAMPLE_1X; 50 case 2: return SWR_MULTISAMPLE_2X; 51 case 4: return SWR_MULTISAMPLE_4X; 52 case 8: return SWR_MULTISAMPLE_8X; 53 case 16: return SWR_MULTISAMPLE_16X; 54 default: assert(0); return SWR_MULTISAMPLE_1X; 55 } 56 } 57 58 // hardcoded offsets based on Direct3d standard multisample positions 59 // 8 x 8 pixel grid ranging from (0, 0) to (15, 15), with (0, 0) = UL pixel corner 60 // coords are 0.8 fixed point offsets from (0, 0) 61 template<SWR_MULTISAMPLE_COUNT sampleCount, SWR_MSAA_SAMPLE_PATTERN samplePattern = SWR_MSAA_STANDARD_PATTERN> 62 struct MultisampleTraits 63 { 64 INLINE static __m128i vXi(uint32_t sampleNum) = delete; 65 INLINE static __m128i vYi(uint32_t sampleNum) = delete; 66 INLINE static simdscalar vX(uint32_t sampleNum) = delete; 67 INLINE static simdscalar vY(uint32_t sampleNum) = delete; 68 INLINE static float X(uint32_t sampleNum) = delete; 69 INLINE static float Y(uint32_t sampleNum) = delete; 70 INLINE static __m128i TileSampleOffsetsX() = delete; 71 INLINE static __m128i TileSampleOffsetsY() = delete; 72 INLINE static simdscalari FullSampleMask() = delete; 73 74 static const uint32_t numSamples = 0; 75 }; 76 77 template<> 78 struct MultisampleTraits<SWR_MULTISAMPLE_1X, SWR_MSAA_STANDARD_PATTERN> 79 { 80 INLINE static __m128i vXi(uint32_t sampleNum) 81 { 82 static const __m128i X = _mm_set1_epi32(samplePosXi); 83 return X; 84 } 85 86 INLINE static __m128i vYi(uint32_t sampleNum) 87 { 88 static const __m128i Y = _mm_set1_epi32(samplePosYi); 89 return Y; 90 } 91 92 INLINE static simdscalar vX(uint32_t sampleNum) 93 { 94 static const simdscalar X = _simd_set1_ps(0.5f); 95 return X; 96 } 97 98 INLINE static simdscalar vY(uint32_t sampleNum) 99 { 100 static const simdscalar Y = _simd_set1_ps(0.5f); 101 return Y; 102 } 103 104 INLINE static float X(uint32_t sampleNum) {return samplePosX;}; 105 INLINE static float Y(uint32_t sampleNum) {return samplePosY;}; 106 107 INLINE static __m128i TileSampleOffsetsX() 108 { 109 static const uint32_t bboxLeftEdge = 0x80; 110 static const uint32_t bboxRightEdge = 0x80; 111 // BR, BL, UR, UL 112 static const __m128i tileSampleOffsetX = _mm_set_epi32(bboxRightEdge, bboxLeftEdge, bboxRightEdge, bboxLeftEdge); 113 return tileSampleOffsetX; 114 } 115 116 INLINE static __m128i TileSampleOffsetsY() 117 { 118 static const uint32_t bboxTopEdge = 0x80; 119 static const uint32_t bboxBottomEdge = 0x80; 120 // BR, BL, UR, UL 121 static const __m128i tileSampleOffsetY = _mm_set_epi32(bboxBottomEdge, bboxBottomEdge, bboxTopEdge, bboxTopEdge); 122 return tileSampleOffsetY; 123 } 124 125 INLINE static simdscalari FullSampleMask(){return _simd_set1_epi32(0x1);}; 126 127 static const uint32_t samplePosXi; 128 static const uint32_t samplePosYi; 129 static const float samplePosX; 130 static const float samplePosY; 131 static const uint32_t numSamples = 1; 132 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X; 133 static const uint32_t numCoverageSamples = 1; 134 }; 135 136 template<> 137 struct MultisampleTraits<SWR_MULTISAMPLE_1X, SWR_MSAA_CENTER_PATTERN> 138 { 139 INLINE static __m128i vXi(uint32_t sampleNum) 140 { 141 return _mm_set1_epi32(0x80); 142 } 143 144 INLINE static __m128i vYi(uint32_t sampleNum) 145 { 146 return _mm_set1_epi32(0x80); 147 } 148 149 INLINE static simdscalar vX(uint32_t sampleNum) 150 { 151 return _simd_set1_ps(0.5f); 152 } 153 154 INLINE static simdscalar vY(uint32_t sampleNum) 155 { 156 return _simd_set1_ps(0.5f); 157 } 158 159 INLINE static float X(uint32_t sampleNum) {return 0.5f;}; 160 INLINE static float Y(uint32_t sampleNum) {return 0.5f;}; 161 162 INLINE static __m128i TileSampleOffsetsX() 163 { 164 // BR, BL, UR, UL 165 return _mm_set1_epi32(0x80); 166 } 167 168 INLINE static __m128i TileSampleOffsetsY() 169 { 170 // BR, BL, UR, UL 171 return _mm_set1_epi32(0x80); 172 } 173 174 INLINE static simdscalari FullSampleMask(){return _simd_set1_epi32(0x1);}; 175 176 static const uint32_t numSamples = 1; 177 static const float samplePosX; 178 static const float samplePosY; 179 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X; 180 static const uint32_t numCoverageSamples = 1; 181 }; 182 183 template<> 184 struct MultisampleTraits<SWR_MULTISAMPLE_2X, SWR_MSAA_STANDARD_PATTERN> 185 { 186 INLINE static __m128i vXi(uint32_t sampleNum) 187 { 188 SWR_ASSERT(sampleNum < numSamples); 189 static const __m128i X[numSamples] {_mm_set1_epi32(samplePosXi[0]), _mm_set1_epi32(samplePosXi[1])}; 190 return X[sampleNum]; 191 } 192 193 INLINE static __m128i vYi(uint32_t sampleNum) 194 { 195 SWR_ASSERT(sampleNum < numSamples); 196 static const __m128i Y[numSamples] {_mm_set1_epi32(samplePosYi[0]), _mm_set1_epi32(samplePosYi[1])}; 197 return Y[sampleNum]; 198 } 199 200 INLINE static simdscalar vX(uint32_t sampleNum) 201 { 202 static const simdscalar X[numSamples] {_simd_set1_ps(0.75f), _simd_set1_ps(0.25f)}; 203 assert(sampleNum < numSamples); 204 return X[sampleNum]; 205 } 206 207 INLINE static simdscalar vY(uint32_t sampleNum) 208 { 209 static const simdscalar Y[numSamples] {_simd_set1_ps(0.75f), _simd_set1_ps(0.25f)}; 210 assert(sampleNum < numSamples); 211 return Y[sampleNum]; 212 } 213 214 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; 215 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; 216 217 INLINE static __m128i TileSampleOffsetsX() 218 { 219 static const uint32_t bboxLeftEdge = 0x40; 220 static const uint32_t bboxRightEdge = 0xC0; 221 // BR, BL, UR, UL 222 static const __m128i tileSampleOffsetX = _mm_set_epi32(bboxRightEdge, bboxLeftEdge, bboxRightEdge, bboxLeftEdge); 223 return tileSampleOffsetX; 224 } 225 226 INLINE static __m128i TileSampleOffsetsY() 227 { 228 static const uint32_t bboxTopEdge = 0x40; 229 static const uint32_t bboxBottomEdge = 0xC0; 230 // BR, BL, UR, UL 231 static const __m128i tileSampleOffsetY = _mm_set_epi32(bboxBottomEdge, bboxBottomEdge, bboxTopEdge, bboxTopEdge); 232 return tileSampleOffsetY; 233 } 234 235 INLINE static simdscalari FullSampleMask() 236 { 237 static const simdscalari mask =_simd_set1_epi32(0x3); 238 return mask; 239 } 240 241 static const uint32_t samplePosXi[2]; 242 static const uint32_t samplePosYi[2]; 243 static const float samplePosX[2]; 244 static const float samplePosY[2]; 245 static const uint32_t numSamples = 2; 246 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X; 247 static const uint32_t numCoverageSamples = 2; 248 }; 249 250 template<> 251 struct MultisampleTraits<SWR_MULTISAMPLE_2X, SWR_MSAA_CENTER_PATTERN> 252 { 253 INLINE static __m128i vXi(uint32_t sampleNum) 254 { 255 return _mm_set1_epi32(0x80); 256 } 257 258 INLINE static __m128i vYi(uint32_t sampleNum) 259 { 260 return _mm_set1_epi32(0x80); 261 } 262 263 INLINE static simdscalar vX(uint32_t sampleNum) 264 { 265 return _simd_set1_ps(0.5f); 266 } 267 268 INLINE static simdscalar vY(uint32_t sampleNum) 269 { 270 return _simd_set1_ps(0.5f); 271 } 272 273 INLINE static float X(uint32_t sampleNum) {return 0.5f;}; 274 INLINE static float Y(uint32_t sampleNum) {return 0.5f;}; 275 276 INLINE static __m128i TileSampleOffsetsX() 277 { 278 // BR, BL, UR, UL 279 return _mm_set1_epi32(0x80); 280 } 281 282 INLINE static __m128i TileSampleOffsetsY() 283 { 284 // BR, BL, UR, UL 285 return _mm_set1_epi32(0x80); 286 } 287 288 INLINE static simdscalari FullSampleMask() 289 { 290 static const simdscalari mask =_simd_set1_epi32(0x3); 291 return mask; 292 } 293 static const uint32_t numSamples = 2; 294 static const float samplePosX[2]; 295 static const float samplePosY[2]; 296 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X; 297 static const uint32_t numCoverageSamples = 1; 298 }; 299 300 template<> 301 struct MultisampleTraits<SWR_MULTISAMPLE_4X, SWR_MSAA_STANDARD_PATTERN> 302 { 303 INLINE static __m128i vXi(uint32_t sampleNum) 304 { 305 static const __m128i X[numSamples] 306 {_mm_set1_epi32(samplePosXi[0]), _mm_set1_epi32(samplePosXi[1]), _mm_set1_epi32(samplePosXi[2]), _mm_set1_epi32(samplePosXi[3])}; 307 SWR_ASSERT(sampleNum < numSamples); 308 return X[sampleNum]; 309 } 310 311 INLINE static __m128i vYi(uint32_t sampleNum) 312 { 313 static const __m128i Y[numSamples] 314 {_mm_set1_epi32(samplePosYi[0]), _mm_set1_epi32(samplePosYi[1]), _mm_set1_epi32(samplePosYi[2]), _mm_set1_epi32(samplePosYi[3])}; 315 SWR_ASSERT(sampleNum < numSamples); 316 return Y[sampleNum]; 317 } 318 319 INLINE static simdscalar vX(uint32_t sampleNum) 320 { 321 static const simdscalar X[numSamples] 322 {_simd_set1_ps(0.375f), _simd_set1_ps(0.875), _simd_set1_ps(0.125), _simd_set1_ps(0.625)}; 323 assert(sampleNum < numSamples); 324 return X[sampleNum]; 325 } 326 327 INLINE static simdscalar vY(uint32_t sampleNum) 328 { 329 static const simdscalar Y[numSamples] 330 {_simd_set1_ps(0.125), _simd_set1_ps(0.375f), _simd_set1_ps(0.625), _simd_set1_ps(0.875)}; 331 assert(sampleNum < numSamples); 332 return Y[sampleNum]; 333 } 334 335 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; 336 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; 337 338 INLINE static __m128i TileSampleOffsetsX() 339 { 340 static const uint32_t bboxLeftEdge = 0x20; 341 static const uint32_t bboxRightEdge = 0xE0; 342 // BR, BL, UR, UL 343 static const __m128i tileSampleOffsetX = _mm_set_epi32(bboxRightEdge, bboxLeftEdge, bboxRightEdge, bboxLeftEdge); 344 return tileSampleOffsetX; 345 } 346 347 INLINE static __m128i TileSampleOffsetsY() 348 { 349 static const uint32_t bboxTopEdge = 0x20; 350 static const uint32_t bboxBottomEdge = 0xE0; 351 // BR, BL, UR, UL 352 static const __m128i tileSampleOffsetY = _mm_set_epi32(bboxBottomEdge, bboxBottomEdge, bboxTopEdge, bboxTopEdge); 353 return tileSampleOffsetY; 354 } 355 356 INLINE static simdscalari FullSampleMask() 357 { 358 static const simdscalari mask = _simd_set1_epi32(0xF); 359 return mask; 360 } 361 362 static const uint32_t samplePosXi[4]; 363 static const uint32_t samplePosYi[4]; 364 static const float samplePosX[4]; 365 static const float samplePosY[4]; 366 static const uint32_t numSamples = 4; 367 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X; 368 static const uint32_t numCoverageSamples = 4; 369 }; 370 371 template<> 372 struct MultisampleTraits<SWR_MULTISAMPLE_4X, SWR_MSAA_CENTER_PATTERN> 373 { 374 INLINE static __m128i vXi(uint32_t sampleNum) 375 { 376 return _mm_set1_epi32(0x80); 377 } 378 379 INLINE static __m128i vYi(uint32_t sampleNum) 380 { 381 return _mm_set1_epi32(0x80); 382 } 383 384 INLINE static simdscalar vX(uint32_t sampleNum) 385 { 386 return _simd_set1_ps(0.5f); 387 } 388 389 INLINE static simdscalar vY(uint32_t sampleNum) 390 { 391 return _simd_set1_ps(0.5f); 392 } 393 394 INLINE static float X(uint32_t sampleNum) {return 0.5f;}; 395 INLINE static float Y(uint32_t sampleNum) {return 0.5f;}; 396 397 INLINE static __m128i TileSampleOffsetsX() 398 { 399 // BR, BL, UR, UL 400 return _mm_set1_epi32(0x80); 401 } 402 403 INLINE static __m128i TileSampleOffsetsY() 404 { 405 // BR, BL, UR, UL 406 return _mm_set1_epi32(0x80); 407 } 408 409 INLINE static simdscalari FullSampleMask() 410 { 411 static const simdscalari mask = _simd_set1_epi32(0xF); 412 return mask; 413 } 414 static const uint32_t numSamples = 4; 415 static const float samplePosX[4]; 416 static const float samplePosY[4]; 417 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X; 418 static const uint32_t numCoverageSamples = 1; 419 }; 420 421 template<> 422 struct MultisampleTraits<SWR_MULTISAMPLE_8X, SWR_MSAA_STANDARD_PATTERN> 423 { 424 INLINE static __m128i vXi(uint32_t sampleNum) 425 { 426 static const __m128i X[numSamples] 427 {_mm_set1_epi32(samplePosXi[0]), _mm_set1_epi32(samplePosXi[1]), _mm_set1_epi32(samplePosXi[2]), _mm_set1_epi32(samplePosXi[3]), 428 _mm_set1_epi32(samplePosXi[4]), _mm_set1_epi32(samplePosXi[5]), _mm_set1_epi32(samplePosXi[6]), _mm_set1_epi32(samplePosXi[7])}; 429 SWR_ASSERT(sampleNum < numSamples); 430 return X[sampleNum]; 431 } 432 433 INLINE static __m128i vYi(uint32_t sampleNum) 434 { 435 static const __m128i Y[numSamples] 436 {_mm_set1_epi32(samplePosYi[0]), _mm_set1_epi32(samplePosYi[1]), _mm_set1_epi32(samplePosYi[2]), _mm_set1_epi32(samplePosYi[3]), 437 _mm_set1_epi32(samplePosYi[4]), _mm_set1_epi32(samplePosYi[5]), _mm_set1_epi32(samplePosYi[6]), _mm_set1_epi32(samplePosYi[7])}; 438 SWR_ASSERT(sampleNum < numSamples); 439 return Y[sampleNum]; 440 } 441 442 INLINE static simdscalar vX(uint32_t sampleNum) 443 { 444 static const simdscalar X[numSamples] 445 {_simd_set1_ps(0.5625), _simd_set1_ps(0.4375), _simd_set1_ps(0.8125), _simd_set1_ps(0.3125), 446 _simd_set1_ps(0.1875), _simd_set1_ps(0.0625), _simd_set1_ps(0.6875), _simd_set1_ps(0.9375)}; 447 assert(sampleNum < numSamples); 448 return X[sampleNum]; 449 } 450 451 INLINE static simdscalar vY(uint32_t sampleNum) 452 { 453 static const simdscalar Y[numSamples] 454 {_simd_set1_ps(0.3125), _simd_set1_ps(0.6875), _simd_set1_ps(0.5625), _simd_set1_ps(0.1875), 455 _simd_set1_ps(0.8125), _simd_set1_ps(0.4375), _simd_set1_ps(0.9375), _simd_set1_ps(0.0625)}; 456 assert(sampleNum < numSamples); 457 return Y[sampleNum]; 458 } 459 460 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; 461 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; 462 463 INLINE static __m128i TileSampleOffsetsX() 464 { 465 static const uint32_t bboxLeftEdge = 0x10; 466 static const uint32_t bboxRightEdge = 0xF0; 467 // BR, BL, UR, UL 468 static const __m128i tileSampleOffsetX = _mm_set_epi32(bboxRightEdge, bboxLeftEdge, bboxRightEdge, bboxLeftEdge); 469 return tileSampleOffsetX; 470 } 471 472 INLINE static __m128i TileSampleOffsetsY() 473 { 474 static const uint32_t bboxTopEdge = 0x10; 475 static const uint32_t bboxBottomEdge = 0xF0; 476 // BR, BL, UR, UL 477 static const __m128i tileSampleOffsetY = _mm_set_epi32(bboxBottomEdge, bboxBottomEdge, bboxTopEdge, bboxTopEdge); 478 return tileSampleOffsetY; 479 } 480 481 INLINE static simdscalari FullSampleMask() 482 { 483 static const simdscalari mask = _simd_set1_epi32(0xFF); 484 return mask; 485 } 486 487 static const uint32_t samplePosXi[8]; 488 static const uint32_t samplePosYi[8]; 489 static const float samplePosX[8]; 490 static const float samplePosY[8]; 491 static const uint32_t numSamples = 8; 492 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X; 493 static const uint32_t numCoverageSamples = 8; 494 }; 495 496 template<> 497 struct MultisampleTraits<SWR_MULTISAMPLE_8X, SWR_MSAA_CENTER_PATTERN> 498 { 499 INLINE static __m128i vXi(uint32_t sampleNum) 500 { 501 return _mm_set1_epi32(0x80); 502 } 503 504 INLINE static __m128i vYi(uint32_t sampleNum) 505 { 506 return _mm_set1_epi32(0x80); 507 } 508 509 INLINE static simdscalar vX(uint32_t sampleNum) 510 { 511 return _simd_set1_ps(0.5f); 512 } 513 514 INLINE static simdscalar vY(uint32_t sampleNum) 515 { 516 return _simd_set1_ps(0.5f); 517 } 518 519 INLINE static float X(uint32_t sampleNum) {return 0.5f;}; 520 INLINE static float Y(uint32_t sampleNum) {return 0.5f;}; 521 522 INLINE static __m128i TileSampleOffsetsX() 523 { 524 // BR, BL, UR, UL 525 return _mm_set1_epi32(0x80); 526 } 527 528 INLINE static __m128i TileSampleOffsetsY() 529 { 530 // BR, BL, UR, UL 531 return _mm_set1_epi32(0x80); 532 } 533 534 INLINE static simdscalari FullSampleMask() 535 { 536 static const simdscalari mask = _simd_set1_epi32(0xFF); 537 return mask; 538 } 539 static const uint32_t numSamples = 8; 540 static const float samplePosX[8]; 541 static const float samplePosY[8]; 542 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X; 543 static const uint32_t numCoverageSamples = 1; 544 }; 545 546 template<> 547 struct MultisampleTraits<SWR_MULTISAMPLE_16X, SWR_MSAA_STANDARD_PATTERN> 548 { 549 INLINE static __m128i vXi(uint32_t sampleNum) 550 { 551 static const __m128i X[numSamples] 552 {_mm_set1_epi32(samplePosXi[0]), _mm_set1_epi32(samplePosXi[1]), _mm_set1_epi32(samplePosXi[2]), _mm_set1_epi32(samplePosXi[3]), 553 _mm_set1_epi32(samplePosXi[4]), _mm_set1_epi32(samplePosXi[5]), _mm_set1_epi32(samplePosXi[6]), _mm_set1_epi32(samplePosXi[7]), 554 _mm_set1_epi32(samplePosXi[8]), _mm_set1_epi32(samplePosXi[9]), _mm_set1_epi32(samplePosXi[10]), _mm_set1_epi32(samplePosXi[11]), 555 _mm_set1_epi32(samplePosXi[12]), _mm_set1_epi32(samplePosXi[13]), _mm_set1_epi32(samplePosXi[14]), _mm_set1_epi32(samplePosXi[15])}; 556 SWR_ASSERT(sampleNum < numSamples); 557 return X[sampleNum]; 558 } 559 560 INLINE static __m128i vYi(uint32_t sampleNum) 561 { 562 static const __m128i Y[numSamples] 563 {_mm_set1_epi32(samplePosYi[0]), _mm_set1_epi32(samplePosYi[1]), _mm_set1_epi32(samplePosYi[2]), _mm_set1_epi32(samplePosYi[3]), 564 _mm_set1_epi32(samplePosYi[4]), _mm_set1_epi32(samplePosYi[5]), _mm_set1_epi32(samplePosYi[6]), _mm_set1_epi32(samplePosYi[7]), 565 _mm_set1_epi32(samplePosYi[8]), _mm_set1_epi32(samplePosYi[9]), _mm_set1_epi32(samplePosYi[10]), _mm_set1_epi32(samplePosYi[11]), 566 _mm_set1_epi32(samplePosYi[12]), _mm_set1_epi32(samplePosYi[13]), _mm_set1_epi32(samplePosYi[14]), _mm_set1_epi32(samplePosYi[15])}; 567 SWR_ASSERT(sampleNum < numSamples); 568 return Y[sampleNum]; 569 } 570 571 INLINE static simdscalar vX(uint32_t sampleNum) 572 { 573 static const simdscalar X[numSamples] 574 {_simd_set1_ps(0.5625), _simd_set1_ps(0.4375), _simd_set1_ps(0.3125), _simd_set1_ps(0.7500), 575 _simd_set1_ps(0.1875), _simd_set1_ps(0.6250), _simd_set1_ps(0.8125), _simd_set1_ps(0.6875), 576 _simd_set1_ps(0.3750), _simd_set1_ps(0.5000), _simd_set1_ps(0.2500), _simd_set1_ps(0.1250), 577 _simd_set1_ps(0.0000), _simd_set1_ps(0.9375), _simd_set1_ps(0.8750), _simd_set1_ps(0.0625)}; 578 assert(sampleNum < numSamples); 579 return X[sampleNum]; 580 } 581 582 INLINE static simdscalar vY(uint32_t sampleNum) 583 { 584 static const simdscalar Y[numSamples] 585 {_simd_set1_ps(0.5625), _simd_set1_ps(0.3125), _simd_set1_ps(0.6250), _simd_set1_ps(0.4375), 586 _simd_set1_ps(0.3750), _simd_set1_ps(0.8125), _simd_set1_ps(0.6875), _simd_set1_ps(0.1875), 587 _simd_set1_ps(0.8750), _simd_set1_ps(0.0625), _simd_set1_ps(0.1250), _simd_set1_ps(0.7500), 588 _simd_set1_ps(0.5000), _simd_set1_ps(0.2500), _simd_set1_ps(0.9375), _simd_set1_ps(0.0000)}; 589 assert(sampleNum < numSamples); 590 return Y[sampleNum]; 591 } 592 593 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; 594 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; 595 596 INLINE static __m128i TileSampleOffsetsX() 597 { 598 static const uint32_t bboxLeftEdge = 0x00; 599 static const uint32_t bboxRightEdge = 0xF0; 600 // BR, BL, UR, UL 601 static const __m128i tileSampleOffsetX = _mm_set_epi32(bboxRightEdge, bboxLeftEdge, bboxRightEdge, bboxLeftEdge); 602 return tileSampleOffsetX; 603 } 604 605 INLINE static __m128i TileSampleOffsetsY() 606 { 607 static const uint32_t bboxTopEdge = 0x00; 608 static const uint32_t bboxBottomEdge = 0xF0; 609 // BR, BL, UR, UL 610 static const __m128i tileSampleOffsetY = _mm_set_epi32(bboxBottomEdge, bboxBottomEdge, bboxTopEdge, bboxTopEdge); 611 return tileSampleOffsetY; 612 } 613 614 INLINE static simdscalari FullSampleMask() 615 { 616 static const simdscalari mask = _simd_set1_epi32(0xFFFF); 617 return mask; 618 } 619 620 static const uint32_t samplePosXi[16]; 621 static const uint32_t samplePosYi[16]; 622 static const float samplePosX[16]; 623 static const float samplePosY[16]; 624 static const uint32_t numSamples = 16; 625 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X; 626 static const uint32_t numCoverageSamples = 16; 627 }; 628 629 template<> 630 struct MultisampleTraits<SWR_MULTISAMPLE_16X, SWR_MSAA_CENTER_PATTERN> 631 { 632 INLINE static __m128i vXi(uint32_t sampleNum) 633 { 634 return _mm_set1_epi32(0x80); 635 } 636 637 INLINE static __m128i vYi(uint32_t sampleNum) 638 { 639 return _mm_set1_epi32(0x80); 640 } 641 642 INLINE static simdscalar vX(uint32_t sampleNum) 643 { 644 return _simd_set1_ps(0.5f); 645 } 646 647 INLINE static simdscalar vY(uint32_t sampleNum) 648 { 649 return _simd_set1_ps(0.5f); 650 } 651 652 INLINE static float X(uint32_t sampleNum) {return 0.5f;}; 653 INLINE static float Y(uint32_t sampleNum) {return 0.5f;}; 654 655 INLINE static __m128i TileSampleOffsetsX() 656 { 657 // BR, BL, UR, UL 658 return _mm_set1_epi32(0x80); 659 } 660 661 INLINE static __m128i TileSampleOffsetsY() 662 { 663 // BR, BL, UR, UL 664 return _mm_set1_epi32(0x80); 665 } 666 667 INLINE static simdscalari FullSampleMask() 668 { 669 static const simdscalari mask = _simd_set1_epi32(0xFFFF); 670 return mask; 671 } 672 static const uint32_t numSamples = 16; 673 static const float samplePosX[16]; 674 static const float samplePosY[16]; 675 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X; 676 static const uint32_t numCoverageSamples = 1; 677 }; 678