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
GetNumSamples(SWR_MULTISAMPLE_COUNT sampleCount)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
GetSampleCount(uint32_t numSamples)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