/**************************************************************************** * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * @file multisample.h * ******************************************************************************/ #pragma once #include "context.h" #include "format_traits.h" ////////////////////////////////////////////////////////////////////////// /// @brief convenience typedef for testing for single sample case typedef std::integral_constant SingleSampleT; INLINE SWR_MULTISAMPLE_COUNT GetSampleCount(uint32_t numSamples) { switch (numSamples) { case 1: return SWR_MULTISAMPLE_1X; case 2: return SWR_MULTISAMPLE_2X; case 4: return SWR_MULTISAMPLE_4X; case 8: return SWR_MULTISAMPLE_8X; case 16: return SWR_MULTISAMPLE_16X; default: assert(0); return SWR_MULTISAMPLE_1X; } } // hardcoded offsets based on Direct3d standard multisample positions // 8 x 8 pixel grid ranging from (0, 0) to (15, 15), with (0, 0) = UL pixel corner // coords are 0.8 fixed point offsets from (0, 0) template struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) = delete; INLINE static float Y(uint32_t sampleNum) = delete; INLINE static simdscalari FullSampleMask() = delete; static const uint32_t numSamples = 0; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return samplePosX[sampleNum]; }; INLINE static float Y(uint32_t sampleNum) { return samplePosY[sampleNum]; }; INLINE static simdscalari FullSampleMask() { return _simd_set1_epi32(0x1); }; static const uint32_t numSamples = 1; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X; static constexpr uint32_t samplePosXi[1] = {0x80}; static constexpr uint32_t samplePosYi[1] = {0x80}; static constexpr float samplePosX[1] = {0.5f}; static constexpr float samplePosY[1] = {0.5f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return 0.5f; }; INLINE static float Y(uint32_t sampleNum) { return 0.5f; }; INLINE static simdscalari FullSampleMask() { return _simd_set1_epi32(0x1); }; static const uint32_t numSamples = 1; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_1X; static constexpr uint32_t samplePosXi[1] = {0x80}; static constexpr uint32_t samplePosYi[1] = {0x80}; static constexpr float samplePosX[1] = {0.5f}; static constexpr float samplePosY[1] = {0.5f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0x3); return mask; } static const uint32_t numSamples = 2; static const uint32_t numCoverageSamples = 2; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X; static constexpr uint32_t samplePosXi[2] = {0xC0, 0x40}; static constexpr uint32_t samplePosYi[2] = {0xC0, 0x40}; static constexpr float samplePosX[2] = {0.75f, 0.25f}; static constexpr float samplePosY[2] = {0.75f, 0.25f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return 0.5f; }; INLINE static float Y(uint32_t sampleNum) { return 0.5f; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0x3); return mask; } static const uint32_t numSamples = 2; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_2X; static constexpr uint32_t samplePosXi[2] = {0x80, 0x80}; static constexpr uint32_t samplePosYi[2] = {0x80, 0x80}; static constexpr float samplePosX[2] = {0.5f, 0.5f}; static constexpr float samplePosY[2] = {0.5f, 0.5f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xF); return mask; } static const uint32_t numSamples = 4; static const uint32_t numCoverageSamples = 4; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X; static constexpr uint32_t samplePosXi[4] = {0x60, 0xE0, 0x20, 0xA0}; static constexpr uint32_t samplePosYi[4] = {0x20, 0x60, 0xA0, 0xE0}; static constexpr float samplePosX[4] = {0.375f, 0.875f, 0.125f, 0.625f}; static constexpr float samplePosY[4] = {0.125f, 0.375f, 0.625f, 0.875f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return 0.5f; }; INLINE static float Y(uint32_t sampleNum) { return 0.5f; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xF); return mask; } static const uint32_t numSamples = 4; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_4X; static constexpr uint32_t samplePosXi[4] = {0x80, 0x80, 0x80, 0x80}; static constexpr uint32_t samplePosYi[4] = {0x80, 0x80, 0x80, 0x80}; static constexpr float samplePosX[4] = {0.5f, 0.5f, 0.5f, 0.5f}; static constexpr float samplePosY[4] = {0.5f, 0.5f, 0.5f, 0.5f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xFF); return mask; } static const uint32_t numSamples = 8; static const uint32_t numCoverageSamples = 8; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X; static constexpr uint32_t samplePosXi[8] = {0x90, 0x70, 0xD0, 0x50, 0x30, 0x10, 0xB0, 0xF0}; static constexpr uint32_t samplePosYi[8] = {0x50, 0xB0, 0x90, 0x30, 0xD0, 0x70, 0xF0, 0x10}; static constexpr float samplePosX[8] = { 0.5625f, 0.4375f, 0.8125f, 0.3125f, 0.1875f, 0.0625f, 0.6875f, 0.9375f}; static constexpr float samplePosY[8] = { 0.3125f, 0.6875f, 0.5625f, 0.1875f, 0.8125f, 0.4375f, 0.9375f, 0.0625f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return 0.5f; }; INLINE static float Y(uint32_t sampleNum) { return 0.5f; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xFF); return mask; } static const uint32_t numSamples = 8; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_8X; static constexpr uint32_t samplePosXi[8] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; static constexpr uint32_t samplePosYi[8] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; static constexpr float samplePosX[8] = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; static constexpr float samplePosY[8] = {0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosX[sampleNum]; }; INLINE static float Y(uint32_t sampleNum) { SWR_ASSERT(sampleNum < numSamples); return samplePosY[sampleNum]; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xFFFF); return mask; } static const uint32_t numSamples = 16; static const uint32_t numCoverageSamples = 16; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X; static constexpr uint32_t samplePosXi[16] = {0x90, 0x70, 0x50, 0xC0, 0x30, 0xA0, 0xD0, 0xB0, 0x60, 0x80, 0x40, 0x20, 0x00, 0xF0, 0xE0, 0x10}; static constexpr uint32_t samplePosYi[16] = {0x90, 0x50, 0xA0, 0x70, 0x60, 0xD0, 0xB0, 0x30, 0xE0, 0x10, 0x20, 0xC0, 0x80, 0x40, 0xF0, 0x00}; 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}; 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}; }; template <> struct MultisampleTraits { INLINE static float X(uint32_t sampleNum) { return 0.5f; }; INLINE static float Y(uint32_t sampleNum) { return 0.5f; }; INLINE static simdscalari FullSampleMask() { static const simdscalari mask = _simd_set1_epi32(0xFFFF); return mask; } static const uint32_t numSamples = 16; static const uint32_t numCoverageSamples = 1; static const SWR_MULTISAMPLE_COUNT sampleCount = SWR_MULTISAMPLE_16X; static constexpr uint32_t samplePosXi[16] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; static constexpr uint32_t samplePosYi[16] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}; 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}; 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}; }; INLINE bool isNonStandardPattern(const SWR_MULTISAMPLE_COUNT sampleCount, const SWR_MULTISAMPLE_POS& samplePos) { // detect if we're using standard or center sample patterns const uint32_t *standardPosX, *standardPosY; switch (sampleCount) { case SWR_MULTISAMPLE_1X: standardPosX = MultisampleTraits::samplePosXi; standardPosY = MultisampleTraits::samplePosYi; break; case SWR_MULTISAMPLE_2X: standardPosX = MultisampleTraits::samplePosXi; standardPosY = MultisampleTraits::samplePosYi; break; case SWR_MULTISAMPLE_4X: standardPosX = MultisampleTraits::samplePosXi; standardPosY = MultisampleTraits::samplePosYi; break; case SWR_MULTISAMPLE_8X: standardPosX = MultisampleTraits::samplePosXi; standardPosY = MultisampleTraits::samplePosYi; break; case SWR_MULTISAMPLE_16X: standardPosX = MultisampleTraits::samplePosXi; standardPosY = MultisampleTraits::samplePosYi; break; default: break; } // scan sample pattern for standard or center uint32_t numSamples = GetNumSamples(sampleCount); bool bIsStandard = true; if (numSamples > 1) { for (uint32_t i = 0; i < numSamples; i++) { bIsStandard = (standardPosX[i] == samplePos.Xi(i)) || (standardPosY[i] == samplePos.Yi(i)); if (!bIsStandard) break; } } return !bIsStandard; }