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 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