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
GetSampleCount(uint32_t numSamples)37 SWR_MULTISAMPLE_COUNT GetSampleCount(uint32_t numSamples)
38 {
39     switch (numSamples)
40     {
41     case 1:
42         return SWR_MULTISAMPLE_1X;
43     case 2:
44         return SWR_MULTISAMPLE_2X;
45     case 4:
46         return SWR_MULTISAMPLE_4X;
47     case 8:
48         return SWR_MULTISAMPLE_8X;
49     case 16:
50         return SWR_MULTISAMPLE_16X;
51     default:
52         assert(0);
53         return SWR_MULTISAMPLE_1X;
54     }
55 }
56 
57 // hardcoded offsets based on Direct3d standard multisample positions
58 // 8 x 8 pixel grid ranging from (0, 0) to (15, 15), with (0, 0) = UL pixel corner
59 // coords are 0.8 fixed point offsets from (0, 0)
60 template <SWR_MULTISAMPLE_COUNT sampleCount, bool isCenter = false>
61 struct MultisampleTraits
62 {
63     INLINE static float       X(uint32_t sampleNum) = delete;
64     INLINE static float       Y(uint32_t sampleNum) = delete;
65     INLINE static simdscalari FullSampleMask()      = delete;
66 
67     static const uint32_t numSamples = 0;
68 };
69 
70 template <>
71 struct MultisampleTraits<SWR_MULTISAMPLE_1X, false>
72 {
73     INLINE static float       X(uint32_t sampleNum) { return samplePosX[sampleNum]; };
74     INLINE static float       Y(uint32_t sampleNum) { return samplePosY[sampleNum]; };
75     INLINE static simdscalari FullSampleMask() { return _simd_set1_epi32(0x1); };
76 
77     static const uint32_t              numSamples         = 1;
78     static const uint32_t              numCoverageSamples = 1;
79     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_1X;
80     static constexpr uint32_t          samplePosXi[1]     = {0x80};
81     static constexpr uint32_t          samplePosYi[1]     = {0x80};
82     static constexpr float             samplePosX[1]      = {0.5f};
83     static constexpr float             samplePosY[1]      = {0.5f};
84 };
85 
86 template <>
87 struct MultisampleTraits<SWR_MULTISAMPLE_1X, true>
88 {
89     INLINE static float       X(uint32_t sampleNum) { return 0.5f; };
90     INLINE static float       Y(uint32_t sampleNum) { return 0.5f; };
91     INLINE static simdscalari FullSampleMask() { return _simd_set1_epi32(0x1); };
92 
93     static const uint32_t              numSamples         = 1;
94     static const uint32_t              numCoverageSamples = 1;
95     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_1X;
96     static constexpr uint32_t          samplePosXi[1]     = {0x80};
97     static constexpr uint32_t          samplePosYi[1]     = {0x80};
98     static constexpr float             samplePosX[1]      = {0.5f};
99     static constexpr float             samplePosY[1]      = {0.5f};
100 };
101 
102 template <>
103 struct MultisampleTraits<SWR_MULTISAMPLE_2X, false>
104 {
105     INLINE static float X(uint32_t sampleNum)
106     {
107         SWR_ASSERT(sampleNum < numSamples);
108         return samplePosX[sampleNum];
109     };
110     INLINE static float Y(uint32_t sampleNum)
111     {
112         SWR_ASSERT(sampleNum < numSamples);
113         return samplePosY[sampleNum];
114     };
115     INLINE static simdscalari FullSampleMask()
116     {
117         static const simdscalari mask = _simd_set1_epi32(0x3);
118         return mask;
119     }
120 
121     static const uint32_t              numSamples         = 2;
122     static const uint32_t              numCoverageSamples = 2;
123     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_2X;
124     static constexpr uint32_t          samplePosXi[2]     = {0xC0, 0x40};
125     static constexpr uint32_t          samplePosYi[2]     = {0xC0, 0x40};
126     static constexpr float             samplePosX[2]      = {0.75f, 0.25f};
127     static constexpr float             samplePosY[2]      = {0.75f, 0.25f};
128 };
129 
130 template <>
131 struct MultisampleTraits<SWR_MULTISAMPLE_2X, true>
132 {
133     INLINE static float       X(uint32_t sampleNum) { return 0.5f; };
134     INLINE static float       Y(uint32_t sampleNum) { return 0.5f; };
135     INLINE static simdscalari FullSampleMask()
136     {
137         static const simdscalari mask = _simd_set1_epi32(0x3);
138         return mask;
139     }
140     static const uint32_t              numSamples         = 2;
141     static const uint32_t              numCoverageSamples = 1;
142     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_2X;
143     static constexpr uint32_t          samplePosXi[2]     = {0x80, 0x80};
144     static constexpr uint32_t          samplePosYi[2]     = {0x80, 0x80};
145     static constexpr float             samplePosX[2]      = {0.5f, 0.5f};
146     static constexpr float             samplePosY[2]      = {0.5f, 0.5f};
147 };
148 
149 template <>
150 struct MultisampleTraits<SWR_MULTISAMPLE_4X, false>
151 {
152     INLINE static float X(uint32_t sampleNum)
153     {
154         SWR_ASSERT(sampleNum < numSamples);
155         return samplePosX[sampleNum];
156     };
157     INLINE static float Y(uint32_t sampleNum)
158     {
159         SWR_ASSERT(sampleNum < numSamples);
160         return samplePosY[sampleNum];
161     };
162     INLINE static simdscalari FullSampleMask()
163     {
164         static const simdscalari mask = _simd_set1_epi32(0xF);
165         return mask;
166     }
167 
168     static const uint32_t              numSamples         = 4;
169     static const uint32_t              numCoverageSamples = 4;
170     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_4X;
171     static constexpr uint32_t          samplePosXi[4]     = {0x60, 0xE0, 0x20, 0xA0};
172     static constexpr uint32_t          samplePosYi[4]     = {0x20, 0x60, 0xA0, 0xE0};
173     static constexpr float             samplePosX[4]      = {0.375f, 0.875f, 0.125f, 0.625f};
174     static constexpr float             samplePosY[4]      = {0.125f, 0.375f, 0.625f, 0.875f};
175 };
176 
177 template <>
178 struct MultisampleTraits<SWR_MULTISAMPLE_4X, true>
179 {
180     INLINE static float       X(uint32_t sampleNum) { return 0.5f; };
181     INLINE static float       Y(uint32_t sampleNum) { return 0.5f; };
182     INLINE static simdscalari FullSampleMask()
183     {
184         static const simdscalari mask = _simd_set1_epi32(0xF);
185         return mask;
186     }
187 
188     static const uint32_t              numSamples         = 4;
189     static const uint32_t              numCoverageSamples = 1;
190     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_4X;
191     static constexpr uint32_t          samplePosXi[4]     = {0x80, 0x80, 0x80, 0x80};
192     static constexpr uint32_t          samplePosYi[4]     = {0x80, 0x80, 0x80, 0x80};
193     static constexpr float             samplePosX[4]      = {0.5f, 0.5f, 0.5f, 0.5f};
194     static constexpr float             samplePosY[4]      = {0.5f, 0.5f, 0.5f, 0.5f};
195 };
196 
197 template <>
198 struct MultisampleTraits<SWR_MULTISAMPLE_8X, false>
199 {
200     INLINE static float X(uint32_t sampleNum)
201     {
202         SWR_ASSERT(sampleNum < numSamples);
203         return samplePosX[sampleNum];
204     };
205     INLINE static float Y(uint32_t sampleNum)
206     {
207         SWR_ASSERT(sampleNum < numSamples);
208         return samplePosY[sampleNum];
209     };
210     INLINE static simdscalari FullSampleMask()
211     {
212         static const simdscalari mask = _simd_set1_epi32(0xFF);
213         return mask;
214     }
215 
216     static const uint32_t              numSamples         = 8;
217     static const uint32_t              numCoverageSamples = 8;
218     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_8X;
219     static constexpr uint32_t samplePosXi[8] = {0x90, 0x70, 0xD0, 0x50, 0x30, 0x10, 0xB0, 0xF0};
220     static constexpr uint32_t samplePosYi[8] = {0x50, 0xB0, 0x90, 0x30, 0xD0, 0x70, 0xF0, 0x10};
221     static constexpr float    samplePosX[8]  = {
222         0.5625f, 0.4375f, 0.8125f, 0.3125f, 0.1875f, 0.0625f, 0.6875f, 0.9375f};
223     static constexpr float samplePosY[8] = {
224         0.3125f, 0.6875f, 0.5625f, 0.1875f, 0.8125f, 0.4375f, 0.9375f, 0.0625f};
225 };
226 
227 template <>
228 struct MultisampleTraits<SWR_MULTISAMPLE_8X, true>
229 {
230     INLINE static float       X(uint32_t sampleNum) { return 0.5f; };
231     INLINE static float       Y(uint32_t sampleNum) { return 0.5f; };
232     INLINE static simdscalari FullSampleMask()
233     {
234         static const simdscalari mask = _simd_set1_epi32(0xFF);
235         return mask;
236     }
237     static const uint32_t              numSamples         = 8;
238     static const uint32_t              numCoverageSamples = 1;
239     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_8X;
240     static constexpr uint32_t samplePosXi[8] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
241     static constexpr uint32_t samplePosYi[8] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80};
242     static constexpr float    samplePosX[8]  = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
243     static constexpr float    samplePosY[8]  = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f};
244 };
245 
246 template <>
247 struct MultisampleTraits<SWR_MULTISAMPLE_16X, false>
248 {
249     INLINE static float X(uint32_t sampleNum)
250     {
251         SWR_ASSERT(sampleNum < numSamples);
252         return samplePosX[sampleNum];
253     };
254     INLINE static float Y(uint32_t sampleNum)
255     {
256         SWR_ASSERT(sampleNum < numSamples);
257         return samplePosY[sampleNum];
258     };
259     INLINE static simdscalari FullSampleMask()
260     {
261         static const simdscalari mask = _simd_set1_epi32(0xFFFF);
262         return mask;
263     }
264 
265     static const uint32_t              numSamples         = 16;
266     static const uint32_t              numCoverageSamples = 16;
267     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_16X;
268     static constexpr uint32_t          samplePosXi[16]    = {0x90,
269                                                  0x70,
270                                                  0x50,
271                                                  0xC0,
272                                                  0x30,
273                                                  0xA0,
274                                                  0xD0,
275                                                  0xB0,
276                                                  0x60,
277                                                  0x80,
278                                                  0x40,
279                                                  0x20,
280                                                  0x00,
281                                                  0xF0,
282                                                  0xE0,
283                                                  0x10};
284     static constexpr uint32_t          samplePosYi[16]    = {0x90,
285                                                  0x50,
286                                                  0xA0,
287                                                  0x70,
288                                                  0x60,
289                                                  0xD0,
290                                                  0xB0,
291                                                  0x30,
292                                                  0xE0,
293                                                  0x10,
294                                                  0x20,
295                                                  0xC0,
296                                                  0x80,
297                                                  0x40,
298                                                  0xF0,
299                                                  0x00};
300     static constexpr float             samplePosX[16]     = {0.5625f,
301                                              0.4375f,
302                                              0.3125f,
303                                              0.7500f,
304                                              0.1875f,
305                                              0.6250f,
306                                              0.8125f,
307                                              0.6875f,
308                                              0.3750f,
309                                              0.5000f,
310                                              0.2500f,
311                                              0.1250f,
312                                              0.0000f,
313                                              0.9375f,
314                                              0.8750f,
315                                              0.0625f};
316     static constexpr float             samplePosY[16]     = {0.5625f,
317                                              0.3125f,
318                                              0.6250f,
319                                              0.4375f,
320                                              0.3750f,
321                                              0.8125f,
322                                              0.6875f,
323                                              0.1875f,
324                                              0.8750f,
325                                              0.0625f,
326                                              0.1250f,
327                                              0.7500f,
328                                              0.5000f,
329                                              0.2500f,
330                                              0.9375f,
331                                              0.0000f};
332 };
333 
334 template <>
335 struct MultisampleTraits<SWR_MULTISAMPLE_16X, true>
336 {
337     INLINE static float       X(uint32_t sampleNum) { return 0.5f; };
338     INLINE static float       Y(uint32_t sampleNum) { return 0.5f; };
339     INLINE static simdscalari FullSampleMask()
340     {
341         static const simdscalari mask = _simd_set1_epi32(0xFFFF);
342         return mask;
343     }
344     static const uint32_t              numSamples         = 16;
345     static const uint32_t              numCoverageSamples = 1;
346     static const SWR_MULTISAMPLE_COUNT sampleCount        = SWR_MULTISAMPLE_16X;
347     static constexpr uint32_t          samplePosXi[16]    = {0x80,
348                                                  0x80,
349                                                  0x80,
350                                                  0x80,
351                                                  0x80,
352                                                  0x80,
353                                                  0x80,
354                                                  0x80,
355                                                  0x80,
356                                                  0x80,
357                                                  0x80,
358                                                  0x80,
359                                                  0x80,
360                                                  0x80,
361                                                  0x80,
362                                                  0x80};
363     static constexpr uint32_t          samplePosYi[16]    = {0x80,
364                                                  0x80,
365                                                  0x80,
366                                                  0x80,
367                                                  0x80,
368                                                  0x80,
369                                                  0x80,
370                                                  0x80,
371                                                  0x80,
372                                                  0x80,
373                                                  0x80,
374                                                  0x80,
375                                                  0x80,
376                                                  0x80,
377                                                  0x80,
378                                                  0x80};
379     static constexpr float             samplePosX[16]     = {0.5f,
380                                              0.5f,
381                                              0.5f,
382                                              0.5f,
383                                              0.5f,
384                                              0.5f,
385                                              0.5f,
386                                              0.5f,
387                                              0.5f,
388                                              0.5f,
389                                              0.5f,
390                                              0.5f,
391                                              0.5f,
392                                              0.5f,
393                                              0.5f,
394                                              0.5f};
395     static constexpr float             samplePosY[16]     = {0.5f,
396                                              0.5f,
397                                              0.5f,
398                                              0.5f,
399                                              0.5f,
400                                              0.5f,
401                                              0.5f,
402                                              0.5f,
403                                              0.5f,
404                                              0.5f,
405                                              0.5f,
406                                              0.5f,
407                                              0.5f,
408                                              0.5f,
409                                              0.5f,
410                                              0.5f};
411 };
412 
413 INLINE
414 bool isNonStandardPattern(const SWR_MULTISAMPLE_COUNT sampleCount,
415                           const SWR_MULTISAMPLE_POS&  samplePos)
416 {
417     // detect if we're using standard or center sample patterns
418     const uint32_t *standardPosX, *standardPosY;
419     switch (sampleCount)
420     {
421     case SWR_MULTISAMPLE_1X:
422         standardPosX = MultisampleTraits<SWR_MULTISAMPLE_1X>::samplePosXi;
423         standardPosY = MultisampleTraits<SWR_MULTISAMPLE_1X>::samplePosYi;
424         break;
425     case SWR_MULTISAMPLE_2X:
426         standardPosX = MultisampleTraits<SWR_MULTISAMPLE_2X>::samplePosXi;
427         standardPosY = MultisampleTraits<SWR_MULTISAMPLE_2X>::samplePosYi;
428         break;
429     case SWR_MULTISAMPLE_4X:
430         standardPosX = MultisampleTraits<SWR_MULTISAMPLE_4X>::samplePosXi;
431         standardPosY = MultisampleTraits<SWR_MULTISAMPLE_4X>::samplePosYi;
432         break;
433     case SWR_MULTISAMPLE_8X:
434         standardPosX = MultisampleTraits<SWR_MULTISAMPLE_8X>::samplePosXi;
435         standardPosY = MultisampleTraits<SWR_MULTISAMPLE_8X>::samplePosYi;
436         break;
437     case SWR_MULTISAMPLE_16X:
438         standardPosX = MultisampleTraits<SWR_MULTISAMPLE_16X>::samplePosXi;
439         standardPosY = MultisampleTraits<SWR_MULTISAMPLE_16X>::samplePosYi;
440         break;
441     default:
442         break;
443     }
444 
445     // scan sample pattern for standard or center
446     uint32_t numSamples  = GetNumSamples(sampleCount);
447     bool     bIsStandard = true;
448     if (numSamples > 1)
449     {
450         for (uint32_t i = 0; i < numSamples; i++)
451         {
452             bIsStandard =
453                 (standardPosX[i] == samplePos.Xi(i)) || (standardPosY[i] == samplePos.Yi(i));
454             if (!bIsStandard)
455                 break;
456         }
457     }
458     return !bIsStandard;
459 }
460