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: return SWR_MULTISAMPLE_1X;
42 case 2: return SWR_MULTISAMPLE_2X;
43 case 4: return SWR_MULTISAMPLE_4X;
44 case 8: return SWR_MULTISAMPLE_8X;
45 case 16: return SWR_MULTISAMPLE_16X;
46 default: assert(0); return SWR_MULTISAMPLE_1X;
47 }
48 }
49
50 // hardcoded offsets based on Direct3d standard multisample positions
51 // 8 x 8 pixel grid ranging from (0, 0) to (15, 15), with (0, 0) = UL pixel corner
52 // coords are 0.8 fixed point offsets from (0, 0)
53 template<SWR_MULTISAMPLE_COUNT sampleCount, bool isCenter = false>
54 struct MultisampleTraits
55 {
56 INLINE static float X(uint32_t sampleNum) = delete;
57 INLINE static float Y(uint32_t sampleNum) = delete;
58 INLINE static simdscalari FullSampleMask() = delete;
59
60 static const uint32_t numSamples = 0;
61 };
62
63 template<>
64 struct MultisampleTraits<SWR_MULTISAMPLE_1X, false>
65 {
66 INLINE static float X(uint32_t sampleNum) {return samplePosX[sampleNum];};
67 INLINE static float Y(uint32_t sampleNum) {return samplePosY[sampleNum];};
68 INLINE static simdscalari FullSampleMask(){return _simd_set1_epi32(0x1);};
69
70 static const uint32_t numSamples = 1;
71 static const uint32_t numCoverageSamples = 1;
72 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X;
73 static constexpr uint32_t samplePosXi[1] = { 0x80 };
74 static constexpr uint32_t samplePosYi[1] = { 0x80 };
75 static constexpr float samplePosX[1] = { 0.5f };
76 static constexpr float samplePosY[1] = { 0.5f };
77 };
78
79 template<>
80 struct MultisampleTraits<SWR_MULTISAMPLE_1X, true>
81 {
82 INLINE static float X(uint32_t sampleNum) {return 0.5f;};
83 INLINE static float Y(uint32_t sampleNum) {return 0.5f;};
84 INLINE static simdscalari FullSampleMask(){return _simd_set1_epi32(0x1);};
85
86 static const uint32_t numSamples = 1;
87 static const uint32_t numCoverageSamples = 1;
88 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X;
89 static constexpr uint32_t samplePosXi[1] = { 0x80 };
90 static constexpr uint32_t samplePosYi[1] = { 0x80 };
91 static constexpr float samplePosX[1] = { 0.5f };
92 static constexpr float samplePosY[1] = { 0.5f };
93 };
94
95 template<>
96 struct MultisampleTraits<SWR_MULTISAMPLE_2X, false>
97 {
98 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; };
99 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; };
100 INLINE static simdscalari FullSampleMask()
101 {
102 static const simdscalari mask =_simd_set1_epi32(0x3);
103 return mask;
104 }
105
106 static const uint32_t numSamples = 2;
107 static const uint32_t numCoverageSamples = 2;
108 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X;
109 static constexpr uint32_t samplePosXi[2] = { 0xC0, 0x40 };
110 static constexpr uint32_t samplePosYi[2] = { 0xC0, 0x40 };
111 static constexpr float samplePosX[2] = {0.75f, 0.25f};
112 static constexpr float samplePosY[2] = {0.75f, 0.25f};
113 };
114
115 template<>
116 struct MultisampleTraits<SWR_MULTISAMPLE_2X, true>
117 {
118 INLINE static float X(uint32_t sampleNum) {return 0.5f;};
119 INLINE static float Y(uint32_t sampleNum) {return 0.5f;};
120 INLINE static simdscalari FullSampleMask()
121 {
122 static const simdscalari mask =_simd_set1_epi32(0x3);
123 return mask;
124 }
125 static const uint32_t numSamples = 2;
126 static const uint32_t numCoverageSamples = 1;
127 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X;
128 static constexpr uint32_t samplePosXi[2] = { 0x80 , 0x80 };
129 static constexpr uint32_t samplePosYi[2] = { 0x80 , 0x80 };
130 static constexpr float samplePosX[2] = { 0.5f, 0.5f };
131 static constexpr float samplePosY[2] = { 0.5f, 0.5f };
132 };
133
134 template<>
135 struct MultisampleTraits<SWR_MULTISAMPLE_4X, false>
136 {
137 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; };
138 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; };
139 INLINE static simdscalari FullSampleMask()
140 {
141 static const simdscalari mask = _simd_set1_epi32(0xF);
142 return mask;
143 }
144
145 static const uint32_t numSamples = 4;
146 static const uint32_t numCoverageSamples = 4;
147 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X;
148 static constexpr uint32_t samplePosXi[4] = { 0x60, 0xE0, 0x20, 0xA0 };
149 static constexpr uint32_t samplePosYi[4] = { 0x20, 0x60, 0xA0, 0xE0 };
150 static constexpr float samplePosX[4] = { 0.375f, 0.875f, 0.125f, 0.625f };
151 static constexpr float samplePosY[4] = { 0.125f, 0.375f, 0.625f, 0.875f };
152 };
153
154 template<>
155 struct MultisampleTraits<SWR_MULTISAMPLE_4X, true>
156 {
157 INLINE static float X(uint32_t sampleNum) {return 0.5f;};
158 INLINE static float Y(uint32_t sampleNum) {return 0.5f;};
159 INLINE static simdscalari FullSampleMask()
160 {
161 static const simdscalari mask = _simd_set1_epi32(0xF);
162 return mask;
163 }
164
165 static const uint32_t numSamples = 4;
166 static const uint32_t numCoverageSamples = 1;
167 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X;
168 static constexpr uint32_t samplePosXi[4] = { 0x80, 0x80, 0x80, 0x80 };
169 static constexpr uint32_t samplePosYi[4] = { 0x80, 0x80, 0x80, 0x80 };
170 static constexpr float samplePosX[4] = { 0.5f, 0.5f, 0.5f, 0.5f };
171 static constexpr float samplePosY[4] = { 0.5f, 0.5f, 0.5f, 0.5f };
172 };
173
174 template<>
175 struct MultisampleTraits<SWR_MULTISAMPLE_8X, false>
176 {
177 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; };
178 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; };
179 INLINE static simdscalari FullSampleMask()
180 {
181 static const simdscalari mask = _simd_set1_epi32(0xFF);
182 return mask;
183 }
184
185 static const uint32_t numSamples = 8;
186 static const uint32_t numCoverageSamples = 8;
187 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X;
188 static constexpr uint32_t samplePosXi[8] = { 0x90, 0x70, 0xD0, 0x50, 0x30, 0x10, 0xB0, 0xF0 };
189 static constexpr uint32_t samplePosYi[8] = { 0x50, 0xB0, 0x90, 0x30, 0xD0, 0x70, 0xF0, 0x10 };
190 static constexpr float samplePosX[8] = { 0.5625f, 0.4375f, 0.8125f, 0.3125f, 0.1875f, 0.0625f, 0.6875f, 0.9375f };
191 static constexpr float samplePosY[8] = { 0.3125f, 0.6875f, 0.5625f, 0.1875f, 0.8125f, 0.4375f, 0.9375f, 0.0625f };
192 };
193
194 template<>
195 struct MultisampleTraits<SWR_MULTISAMPLE_8X, true>
196 {
197 INLINE static float X(uint32_t sampleNum) {return 0.5f;};
198 INLINE static float Y(uint32_t sampleNum) {return 0.5f;};
199 INLINE static simdscalari FullSampleMask()
200 {
201 static const simdscalari mask = _simd_set1_epi32(0xFF);
202 return mask;
203 }
204 static const uint32_t numSamples = 8;
205 static const uint32_t numCoverageSamples = 1;
206 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X;
207 static constexpr uint32_t samplePosXi[8] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
208 static constexpr uint32_t samplePosYi[8] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
209 static constexpr float samplePosX[8] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
210 static constexpr float samplePosY[8] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
211 };
212
213 template<>
214 struct MultisampleTraits<SWR_MULTISAMPLE_16X, false>
215 {
216 INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; };
217 INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; };
218 INLINE static simdscalari FullSampleMask()
219 {
220 static const simdscalari mask = _simd_set1_epi32(0xFFFF);
221 return mask;
222 }
223
224 static const uint32_t numSamples = 16;
225 static const uint32_t numCoverageSamples = 16;
226 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X;
227 static constexpr uint32_t samplePosXi[16] = { 0x90, 0x70, 0x50, 0xC0, 0x30, 0xA0, 0xD0, 0xB0, 0x60, 0x80, 0x40, 0x20, 0x00, 0xF0, 0xE0, 0x10 };
228 static constexpr uint32_t samplePosYi[16] = { 0x90, 0x50, 0xA0, 0x70, 0x60, 0xD0, 0xB0, 0x30, 0xE0, 0x10, 0x20, 0xC0, 0x80, 0x40, 0xF0, 0x00 };
229 static constexpr float samplePosX[16] = { 0.5625f, 0.4375f, 0.3125f, 0.7500f, 0.1875f, 0.6250f, 0.8125f, 0.6875f, 0.3750f, 0.5000f, 0.2500f, 0.1250f, 0.0000f, 0.9375f, 0.8750f, 0.0625f };
230 static constexpr float samplePosY[16] = { 0.5625f, 0.3125f, 0.6250f, 0.4375f, 0.3750f, 0.8125f, 0.6875f, 0.1875f, 0.8750f, 0.0625f, 0.1250f, 0.7500f, 0.5000f, 0.2500f, 0.9375f, 0.0000f };
231 };
232
233 template<>
234 struct MultisampleTraits<SWR_MULTISAMPLE_16X, true>
235 {
236 INLINE static float X(uint32_t sampleNum) {return 0.5f;};
237 INLINE static float Y(uint32_t sampleNum) {return 0.5f;};
238 INLINE static simdscalari FullSampleMask()
239 {
240 static const simdscalari mask = _simd_set1_epi32(0xFFFF);
241 return mask;
242 }
243 static const uint32_t numSamples = 16;
244 static const uint32_t numCoverageSamples = 1;
245 static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X;
246 static constexpr uint32_t samplePosXi[16] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
247 static constexpr uint32_t samplePosYi[16] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
248 static constexpr float samplePosX[16] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
249 static constexpr float samplePosY[16] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };
250 };
251
252 INLINE
253 bool isNonStandardPattern(const SWR_MULTISAMPLE_COUNT sampleCount, const SWR_MULTISAMPLE_POS& samplePos)
254 {
255 // detect if we're using standard or center sample patterns
256 const uint32_t *standardPosX, *standardPosY;
257 switch(sampleCount)
258 {
259 case SWR_MULTISAMPLE_1X:
260 standardPosX = MultisampleTraits<SWR_MULTISAMPLE_1X>::samplePosXi;
261 standardPosY = MultisampleTraits<SWR_MULTISAMPLE_1X>::samplePosYi;
262 break;
263 case SWR_MULTISAMPLE_2X:
264 standardPosX = MultisampleTraits<SWR_MULTISAMPLE_2X>::samplePosXi;
265 standardPosY = MultisampleTraits<SWR_MULTISAMPLE_2X>::samplePosYi;
266 break;
267 case SWR_MULTISAMPLE_4X:
268 standardPosX = MultisampleTraits<SWR_MULTISAMPLE_4X>::samplePosXi;
269 standardPosY = MultisampleTraits<SWR_MULTISAMPLE_4X>::samplePosYi;
270 break;
271 case SWR_MULTISAMPLE_8X:
272 standardPosX = MultisampleTraits<SWR_MULTISAMPLE_8X>::samplePosXi;
273 standardPosY = MultisampleTraits<SWR_MULTISAMPLE_8X>::samplePosYi;
274 break;
275 case SWR_MULTISAMPLE_16X:
276 standardPosX = MultisampleTraits<SWR_MULTISAMPLE_16X>::samplePosXi;
277 standardPosY = MultisampleTraits<SWR_MULTISAMPLE_16X>::samplePosYi;
278 break;
279 default:
280 break;
281 }
282
283 // scan sample pattern for standard or center
284 uint32_t numSamples = GetNumSamples(sampleCount);
285 bool bIsStandard = true;
286 if(numSamples > 1)
287 {
288 for(uint32_t i = 0; i < numSamples; i++)
289 {
290 bIsStandard = (standardPosX[i] == samplePos.Xi(i)) ||
291 (standardPosY[i] == samplePos.Yi(i));
292 if(!bIsStandard)
293 break;
294 }
295 }
296 return !bIsStandard;
297 }
298