• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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