Home | History | Annotate | Download | only in core
      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