Home | History | Annotate | Download | only in memory
      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 Convert.h
     24 *
     25 * @brief Conversion utility functions
     26 *
     27 ******************************************************************************/
     28 #pragma once
     29 
     30 #if defined(_WIN32)
     31 // disable "potential divide by 0"
     32 #pragma warning(disable: 4723)
     33 #endif
     34 
     35 #include <cmath>
     36 
     37 //////////////////////////////////////////////////////////////////////////
     38 /// @brief Convert an IEEE 754 16-bit float to an 32-bit single precision
     39 ///        float
     40 /// @param val - 16-bit float
     41 /// @todo Maybe move this outside of this file into a header?
     42 static INLINE float ConvertSmallFloatTo32(UINT val)
     43 {
     44     UINT result;
     45     if ((val & 0x7fff) == 0)
     46     {
     47         result = ((uint32_t)(val & 0x8000)) << 16;
     48     }
     49     else if ((val & 0x7c00) == 0x7c00)
     50     {
     51         result = ((val & 0x3ff) == 0) ? 0x7f800000 : 0x7fc00000;
     52         result |= ((uint32_t)val & 0x8000) << 16;
     53     }
     54     else
     55     {
     56         uint32_t sign = (val & 0x8000) << 16;
     57         uint32_t mant = (val & 0x3ff) << 13;
     58         uint32_t exp = (val >> 10) & 0x1f;
     59         if ((exp == 0) && (mant != 0)) // Adjust exponent and mantissa for denormals
     60         {
     61             mant <<= 1;
     62             while (mant < (0x400 << 13))
     63             {
     64                 exp--;
     65                 mant <<= 1;
     66             }
     67             mant &= (0x3ff << 13);
     68         }
     69         exp = ((exp - 15 + 127) & 0xff) << 23;
     70         result = sign | exp | mant;
     71     }
     72 
     73     return *(float*)&result;
     74 }
     75 
     76 //////////////////////////////////////////////////////////////////////////
     77 /// @brief Convert an IEEE 754 32-bit single precision float to an
     78 ///        unsigned small float with 5 exponent bits and a variable
     79 ///        number of mantissa bits.
     80 /// @param val - 32-bit float
     81 /// @todo Maybe move this outside of this file into a header?
     82 template<UINT numMantissaBits>
     83 static UINT Convert32ToSmallFloat(float val)
     84 {
     85     uint32_t sign, exp, mant;
     86     uint32_t roundBits;
     87 
     88     // Extract the sign, exponent, and mantissa
     89     UINT uf = *(UINT*)&val;
     90 
     91     sign = (uf & 0x80000000) >> 31;
     92     exp = (uf & 0x7F800000) >> 23;
     93     mant = uf & 0x007FFFFF;
     94 
     95     // 10/11 bit floats are unsigned.  Negative values are clamped to 0.
     96     if (sign != 0)
     97     {
     98         exp = mant = 0;
     99     }
    100     // Check for out of range
    101     else if ((exp == 0xFF) && (mant != 0)) // NaN
    102     {
    103         exp = 0x1F;
    104         mant = 1 << numMantissaBits;
    105     }
    106     else if ((exp == 0xFF) && (mant == 0)) // INF
    107     {
    108         exp = 0x1F;
    109         mant = 0;
    110     }
    111     else if (exp > (0x70 + 0x1E)) // Too big to represent
    112     {
    113         exp = 0x1Eu;
    114         mant = (1 << numMantissaBits) - 1;  // 0x3F for 6 bit mantissa.
    115     }
    116     else if ((exp <= 0x70) && (exp >= 0x66)) // It's a denorm
    117     {
    118         mant |= 0x00800000;
    119         for (; exp <= 0x70; mant >>= 1, exp++)
    120             ;
    121         exp = 0;
    122         mant = mant >> (23 - numMantissaBits);
    123     }
    124     else if (exp < 0x66) // Too small to represent -> Zero
    125     {
    126         exp = 0;
    127         mant = 0;
    128     }
    129     else
    130     {
    131         // Saves bits that will be shifted off for rounding
    132         roundBits = mant & 0x1FFFu;
    133         // convert exponent and mantissa to 16 bit format
    134         exp = exp - 0x70u;
    135         mant = mant >> (23 - numMantissaBits);
    136 
    137         // Essentially RTZ, but round up if off by only 1 lsb
    138         if (roundBits == 0x1FFFu)
    139         {
    140             mant++;
    141             // check for overflow
    142             if ((mant & (0x3 << numMantissaBits)) != 0) // 0x60 = 0x3 << (num Mantissa Bits)
    143                 exp++;
    144             // make sure only the needed bits are used
    145             mant &= (1 << numMantissaBits) - 1;
    146         }
    147     }
    148 
    149     UINT tmpVal = (exp << numMantissaBits) | mant;
    150     return tmpVal;
    151 }
    152 
    153 #if KNOB_ARCH == KNOB_ARCH_AVX
    154 //////////////////////////////////////////////////////////////////////////
    155 /// @brief Convert an IEEE 754 32-bit single precision float to an
    156 ///        16 bit float with 5 exponent bits and a variable
    157 ///        number of mantissa bits.
    158 /// @param val - 32-bit float
    159 /// @todo Maybe move this outside of this file into a header?
    160 static uint16_t Convert32To16Float(float val)
    161 {
    162     uint32_t sign, exp, mant;
    163     uint32_t roundBits;
    164 
    165     // Extract the sign, exponent, and mantissa
    166     uint32_t uf = *(uint32_t*)&val;
    167     sign = (uf & 0x80000000) >> 31;
    168     exp = (uf & 0x7F800000) >> 23;
    169     mant = uf & 0x007FFFFF;
    170 
    171     // Check for out of range
    172     if (std::isnan(val))
    173     {
    174         exp = 0x1F;
    175         mant = 0x200;
    176         sign = 1;                     // set the sign bit for NANs
    177     }
    178     else if (std::isinf(val))
    179     {
    180         exp = 0x1f;
    181         mant = 0x0;
    182     }
    183     else if (exp > (0x70 + 0x1E)) // Too big to represent -> max representable value
    184     {
    185         exp = 0x1E;
    186         mant = 0x3FF;
    187     }
    188     else if ((exp <= 0x70) && (exp >= 0x66)) // It's a denorm
    189     {
    190         mant |= 0x00800000;
    191         for (; exp <= 0x70; mant >>= 1, exp++)
    192             ;
    193         exp = 0;
    194         mant = mant >> 13;
    195     }
    196     else if (exp < 0x66) // Too small to represent -> Zero
    197     {
    198         exp = 0;
    199         mant = 0;
    200     }
    201     else
    202     {
    203         // Saves bits that will be shifted off for rounding
    204         roundBits = mant & 0x1FFFu;
    205         // convert exponent and mantissa to 16 bit format
    206         exp = exp - 0x70;
    207         mant = mant >> 13;
    208 
    209         // Essentially RTZ, but round up if off by only 1 lsb
    210         if (roundBits == 0x1FFFu)
    211         {
    212             mant++;
    213             // check for overflow
    214             if ((mant & 0xC00u) != 0)
    215                 exp++;
    216             // make sure only the needed bits are used
    217             mant &= 0x3FF;
    218         }
    219     }
    220 
    221     uint32_t tmpVal = (sign << 15) | (exp << 10) | mant;
    222     return (uint16_t)tmpVal;
    223 }
    224 #endif
    225 
    226 //////////////////////////////////////////////////////////////////////////
    227 /// @brief Retrieve color from hot tile source which is always float.
    228 /// @param pDstPixel - Pointer to destination pixel.
    229 /// @param srcPixel - Pointer to source pixel (pre-swizzled according to dest).
    230 template<SWR_FORMAT DstFormat>
    231 static void ConvertPixelFromFloat(
    232     uint8_t* pDstPixel,
    233     const float srcPixel[4])
    234 {
    235     uint32_t outColor[4] = { 0 };  // typeless bits
    236 
    237     // Store component
    238     for (UINT comp = 0; comp < FormatTraits<DstFormat>::numComps; ++comp)
    239     {
    240         SWR_TYPE type = FormatTraits<DstFormat>::GetType(comp);
    241 
    242         float src = srcPixel[comp];
    243 
    244         switch (type)
    245         {
    246         case SWR_TYPE_UNORM:
    247         {
    248             // Force NaN to 0. IEEE standard, comparisons involving NaN always evaluate to false.
    249             src = (src != src) ? 0.0f : src;
    250 
    251             // Clamp [0, 1]
    252             src = std::max(src, 0.0f);
    253             src = std::min(src, 1.0f);
    254 
    255             // SRGB
    256             if (FormatTraits<DstFormat>::isSRGB && comp != 3)
    257             {
    258                 src = (src <= 0.0031308f) ? (12.92f * src) : (1.055f * powf(src, (1.0f / 2.4f)) - 0.055f);
    259             }
    260 
    261             // Float scale to integer scale.
    262             UINT scale = (1 << FormatTraits<DstFormat>::GetBPC(comp)) - 1;
    263             src = (float)scale * src;
    264             src = roundf(src);
    265             outColor[comp] = (UINT)src; // Drop fractional part.
    266             break;
    267         }
    268         case SWR_TYPE_SNORM:
    269         {
    270             SWR_ASSERT(!FormatTraits<DstFormat>::isSRGB);
    271 
    272             // Force NaN to 0. IEEE standard, comparisons involving NaN always evaluate to false.
    273             src = (src != src) ? 0.0f : src;
    274 
    275             // Clamp [-1, 1]
    276             src = std::max(src, -1.0f);
    277             src = std::min(src, 1.0f);
    278 
    279             // Float scale to integer scale.
    280             UINT scale = (1 << (FormatTraits<DstFormat>::GetBPC(comp) - 1)) - 1;
    281             src = (float)scale * src;
    282 
    283             // Round
    284             src += (src >= 0) ? 0.5f : -0.5f;
    285 
    286             INT out = (INT)src;
    287 
    288             outColor[comp] = *(UINT*)&out;
    289 
    290             break;
    291         }
    292         case SWR_TYPE_UINT:
    293         {
    294             ///@note The *(UINT*)& is currently necessary as the hot tile appears to always be float.
    295             //       However, the number in the hot tile should be unsigned integer. So doing this
    296             //       to preserve bits intead of doing a float -> integer conversion.
    297             if (FormatTraits<DstFormat>::GetBPC(comp) == 32)
    298             {
    299                 outColor[comp] = *(UINT*)&src;
    300             }
    301             else
    302             {
    303                 outColor[comp] = *(UINT*)&src;
    304                 UINT max = (1 << FormatTraits<DstFormat>::GetBPC(comp)) - 1;  // 2^numBits - 1
    305 
    306                 outColor[comp] = std::min(max, outColor[comp]);
    307             }
    308             break;
    309         }
    310         case SWR_TYPE_SINT:
    311         {
    312             if (FormatTraits<DstFormat>::GetBPC(comp) == 32)
    313             {
    314                 outColor[comp] = *(UINT*)&src;
    315             }
    316             else
    317             {
    318                 INT out = *(INT*)&src;  // Hot tile format is SINT?
    319                 INT max = (1 << (FormatTraits<DstFormat>::GetBPC(comp) - 1)) - 1;
    320                 INT min = -1 - max;
    321 
    322                 ///@note The output is unsigned integer (bag of bits) and so performing
    323                 //       the clamping here based on range of output component. Also, manually adding
    324                 //       the sign bit in the appropriate spot. Maybe a better way?
    325                 out = std::max(out, min);
    326                 out = std::min(out, max);
    327 
    328                 outColor[comp] = *(UINT*)&out;
    329             }
    330             break;
    331         }
    332         case SWR_TYPE_FLOAT:
    333         {
    334             if (FormatTraits<DstFormat>::GetBPC(comp) == 16)
    335             {
    336                 // Convert from 32-bit float to 16-bit float using _mm_cvtps_ph
    337                 // @todo 16bit float instruction support is orthogonal to avx support.  need to
    338                 // add check for F16C support instead.
    339 #if KNOB_ARCH >= KNOB_ARCH_AVX2
    340                 __m128 src128 = _mm_set1_ps(src);
    341                 __m128i srci128 = _mm_cvtps_ph(src128, _MM_FROUND_TRUNC);
    342                 UINT value = _mm_extract_epi16(srci128, 0);
    343 #else
    344                 UINT value = Convert32To16Float(src);
    345 #endif
    346 
    347                 outColor[comp] = value;
    348             }
    349             else if (FormatTraits<DstFormat>::GetBPC(comp) == 11)
    350             {
    351                 outColor[comp] = Convert32ToSmallFloat<6>(src);
    352             }
    353             else if (FormatTraits<DstFormat>::GetBPC(comp) == 10)
    354             {
    355                 outColor[comp] = Convert32ToSmallFloat<5>(src);
    356             }
    357             else
    358             {
    359                 outColor[comp] = *(UINT*)&src;
    360             }
    361 
    362             break;
    363         }
    364         default:
    365             SWR_ASSERT(0);
    366             break;
    367         }
    368     }
    369 
    370     typename FormatTraits<DstFormat>::FormatT* pPixel = (typename FormatTraits<DstFormat>::FormatT*)pDstPixel;
    371 
    372     switch (FormatTraits<DstFormat>::numComps)
    373     {
    374     case 4:
    375         pPixel->a = outColor[3];
    376     case 3:
    377         pPixel->b = outColor[2];
    378     case 2:
    379         pPixel->g = outColor[1];
    380     case 1:
    381         pPixel->r = outColor[0];
    382         break;
    383     default:
    384         SWR_ASSERT(0);
    385     }
    386 }
    387 
    388 //////////////////////////////////////////////////////////////////////////
    389 /// @brief Convert pixel in any format to float32
    390 /// @param pDstPixel - Pointer to destination pixel.
    391 /// @param srcPixel - Pointer to source pixel
    392 template<SWR_FORMAT SrcFormat>
    393 INLINE static void ConvertPixelToFloat(
    394     float dstPixel[4],
    395     const uint8_t* pSrc)
    396 {
    397     uint32_t srcColor[4];  // typeless bits
    398 
    399     // unpack src pixel
    400     typename FormatTraits<SrcFormat>::FormatT* pPixel = (typename FormatTraits<SrcFormat>::FormatT*)pSrc;
    401 
    402     // apply format defaults
    403     for (uint32_t comp = 0; comp < 4; ++comp)
    404     {
    405         uint32_t def = FormatTraits<SrcFormat>::GetDefault(comp);
    406         dstPixel[comp] = *(float*)&def;
    407     }
    408 
    409     // load format data
    410     switch (FormatTraits<SrcFormat>::numComps)
    411     {
    412     case 4:
    413         srcColor[3] = pPixel->a;
    414     case 3:
    415         srcColor[2] = pPixel->b;
    416     case 2:
    417         srcColor[1] = pPixel->g;
    418     case 1:
    419         srcColor[0] = pPixel->r;
    420         break;
    421     default:
    422         SWR_ASSERT(0);
    423     }
    424 
    425     // Convert components
    426     for (uint32_t comp = 0; comp < FormatTraits<SrcFormat>::numComps; ++comp)
    427     {
    428         SWR_TYPE type = FormatTraits<SrcFormat>::GetType(comp);
    429 
    430         uint32_t src = srcColor[comp];
    431 
    432         switch (type)
    433         {
    434         case SWR_TYPE_UNORM:
    435         {
    436             float dst;
    437             if (FormatTraits<SrcFormat>::isSRGB && comp != 3)
    438             {
    439                 dst = *(float*)&srgb8Table[src];
    440             }
    441             else
    442             {
    443                 // component sizes > 16 must use fp divide to maintain ulp requirements
    444                 if (FormatTraits<SrcFormat>::GetBPC(comp) > 16)
    445                 {
    446                     dst = (float)src / (float)((1 << FormatTraits<SrcFormat>::GetBPC(comp)) - 1);
    447                 }
    448                 else
    449                 {
    450                     const float scale = (1.0f / (float)((1 << FormatTraits<SrcFormat>::GetBPC(comp)) - 1));
    451                     dst = (float)src * scale;
    452                 }
    453             }
    454             dstPixel[FormatTraits<SrcFormat>::swizzle(comp)] = dst;
    455             break;
    456         }
    457         case SWR_TYPE_SNORM:
    458         {
    459             SWR_ASSERT(!FormatTraits<SrcFormat>::isSRGB);
    460 
    461             float dst;
    462             if (src == 0x10)
    463             {
    464                 dst = -1.0f;
    465             }
    466             else
    467             {
    468                 switch (FormatTraits<SrcFormat>::GetBPC(comp))
    469                 {
    470                 case 8:
    471                     dst = (float)((int8_t)src);
    472                     break;
    473                 case 16:
    474                     dst = (float)((int16_t)src);
    475                     break;
    476                 case 32:
    477                     dst = (float)((int32_t)src);
    478                     break;
    479                 default:
    480                     assert(0 && "attempted to load from SNORM with unsupported bpc");
    481                     dst = 0.0f;
    482                     break;
    483                 }
    484                 dst = dst * (1.0f / ((1 << (FormatTraits<SrcFormat>::GetBPC(comp) - 1)) - 1));
    485             }
    486             dstPixel[FormatTraits<SrcFormat>::swizzle(comp)] = dst;
    487             break;
    488         }
    489         case SWR_TYPE_UINT:
    490         {
    491             uint32_t dst = (uint32_t)src;
    492             dstPixel[FormatTraits<SrcFormat>::swizzle(comp)] = *(float*)&dst;
    493             break;
    494         }
    495         case SWR_TYPE_SINT:
    496         {
    497             int dst;
    498             switch (FormatTraits<SrcFormat>::GetBPC(comp))
    499             {
    500             case 8:
    501                 dst = (int8_t)src;
    502                 break;
    503             case 16:
    504                 dst = (int16_t)src;
    505                 break;
    506             case 32:
    507                 dst = (int32_t)src;
    508                 break;
    509             default:
    510                 assert(0 && "attempted to load from SINT with unsupported bpc");
    511                 dst = 0;
    512                 break;
    513             }
    514             dstPixel[FormatTraits<SrcFormat>::swizzle(comp)] = *(float*)&dst;
    515             break;
    516         }
    517         case SWR_TYPE_FLOAT:
    518         {
    519             float dst;
    520             if (FormatTraits<SrcFormat>::GetBPC(comp) == 16)
    521             {
    522 #if KNOB_ARCH >= KNOB_ARCH_AVX2
    523                 // Convert from 16-bit float to 32-bit float using _mm_cvtph_ps
    524                 // @todo 16bit float instruction support is orthogonal to avx support.  need to
    525                 // add check for F16C support instead.
    526                 __m128i src128 = _mm_set1_epi32(src);
    527                 __m128 res = _mm_cvtph_ps(src128);
    528                 _mm_store_ss(&dst, res);
    529 #else
    530                 dst = ConvertSmallFloatTo32(src);
    531 #endif
    532             }
    533             else if (FormatTraits<SrcFormat>::GetBPC(comp) == 11)
    534             {
    535                 dst = ConvertSmallFloatTo32(src << 4);
    536             }
    537             else if (FormatTraits<SrcFormat>::GetBPC(comp) == 10)
    538             {
    539                 dst = ConvertSmallFloatTo32(src << 5);
    540             }
    541             else
    542             {
    543                 dst = *(float*)&src;
    544             }
    545 
    546             dstPixel[FormatTraits<SrcFormat>::swizzle(comp)] = *(float*)&dst;
    547             break;
    548         }
    549         default:
    550             SWR_ASSERT(0);
    551             break;
    552         }
    553     }
    554 }
    555 
    556 // non-templated version of conversion functions
    557 INLINE static void ConvertPixelFromFloat(
    558     SWR_FORMAT format,
    559     uint8_t* pDst,
    560     const float srcPixel[4])
    561 {
    562     switch (format)
    563     {
    564     case R32G32B32A32_FLOAT: ConvertPixelFromFloat<R32G32B32A32_FLOAT>(pDst, srcPixel); break;
    565     case R32G32B32A32_SINT: ConvertPixelFromFloat<R32G32B32A32_SINT>(pDst, srcPixel); break;
    566     case R32G32B32A32_UINT: ConvertPixelFromFloat<R32G32B32A32_UINT>(pDst, srcPixel); break;
    567     case R32G32B32X32_FLOAT: ConvertPixelFromFloat<R32G32B32X32_FLOAT>(pDst, srcPixel); break;
    568     case R32G32B32A32_SSCALED: ConvertPixelFromFloat<R32G32B32A32_SSCALED>(pDst, srcPixel); break;
    569     case R32G32B32A32_USCALED: ConvertPixelFromFloat<R32G32B32A32_USCALED>(pDst, srcPixel); break;
    570     case R32G32B32_FLOAT: ConvertPixelFromFloat<R32G32B32_FLOAT>(pDst, srcPixel); break;
    571     case R32G32B32_SINT: ConvertPixelFromFloat<R32G32B32_SINT>(pDst, srcPixel); break;
    572     case R32G32B32_UINT: ConvertPixelFromFloat<R32G32B32_UINT>(pDst, srcPixel); break;
    573     case R32G32B32_SSCALED: ConvertPixelFromFloat<R32G32B32_SSCALED>(pDst, srcPixel); break;
    574     case R32G32B32_USCALED: ConvertPixelFromFloat<R32G32B32_USCALED>(pDst, srcPixel); break;
    575     case R16G16B16A16_UNORM: ConvertPixelFromFloat<R16G16B16A16_UNORM>(pDst, srcPixel); break;
    576     case R16G16B16A16_SNORM: ConvertPixelFromFloat<R16G16B16A16_SNORM>(pDst, srcPixel); break;
    577     case R16G16B16A16_SINT: ConvertPixelFromFloat<R16G16B16A16_SINT>(pDst, srcPixel); break;
    578     case R16G16B16A16_UINT: ConvertPixelFromFloat<R16G16B16A16_UINT>(pDst, srcPixel); break;
    579     case R16G16B16A16_FLOAT: ConvertPixelFromFloat<R16G16B16A16_FLOAT>(pDst, srcPixel); break;
    580     case R32G32_FLOAT: ConvertPixelFromFloat<R32G32_FLOAT>(pDst, srcPixel); break;
    581     case R32G32_SINT: ConvertPixelFromFloat<R32G32_SINT>(pDst, srcPixel); break;
    582     case R32G32_UINT: ConvertPixelFromFloat<R32G32_UINT>(pDst, srcPixel); break;
    583     case R32_FLOAT_X8X24_TYPELESS: ConvertPixelFromFloat<R32_FLOAT_X8X24_TYPELESS>(pDst, srcPixel); break;
    584     case X32_TYPELESS_G8X24_UINT: ConvertPixelFromFloat<X32_TYPELESS_G8X24_UINT>(pDst, srcPixel); break;
    585     case L32A32_FLOAT: ConvertPixelFromFloat<L32A32_FLOAT>(pDst, srcPixel); break;
    586     case R16G16B16X16_UNORM: ConvertPixelFromFloat<R16G16B16X16_UNORM>(pDst, srcPixel); break;
    587     case R16G16B16X16_FLOAT: ConvertPixelFromFloat<R16G16B16X16_FLOAT>(pDst, srcPixel); break;
    588     case L32X32_FLOAT: ConvertPixelFromFloat<L32X32_FLOAT>(pDst, srcPixel); break;
    589     case I32X32_FLOAT: ConvertPixelFromFloat<I32X32_FLOAT>(pDst, srcPixel); break;
    590     case R16G16B16A16_SSCALED: ConvertPixelFromFloat<R16G16B16A16_SSCALED>(pDst, srcPixel); break;
    591     case R16G16B16A16_USCALED: ConvertPixelFromFloat<R16G16B16A16_USCALED>(pDst, srcPixel); break;
    592     case R32G32_SSCALED: ConvertPixelFromFloat<R32G32_SSCALED>(pDst, srcPixel); break;
    593     case R32G32_USCALED: ConvertPixelFromFloat<R32G32_USCALED>(pDst, srcPixel); break;
    594     case B8G8R8A8_UNORM: ConvertPixelFromFloat<B8G8R8A8_UNORM>(pDst, srcPixel); break;
    595     case B8G8R8A8_UNORM_SRGB: ConvertPixelFromFloat<B8G8R8A8_UNORM_SRGB>(pDst, srcPixel); break;
    596     case R10G10B10A2_UNORM: ConvertPixelFromFloat<R10G10B10A2_UNORM>(pDst, srcPixel); break;
    597     case R10G10B10A2_UNORM_SRGB: ConvertPixelFromFloat<R10G10B10A2_UNORM_SRGB>(pDst, srcPixel); break;
    598     case R10G10B10A2_UINT: ConvertPixelFromFloat<R10G10B10A2_UINT>(pDst, srcPixel); break;
    599     case R8G8B8A8_UNORM: ConvertPixelFromFloat<R8G8B8A8_UNORM>(pDst, srcPixel); break;
    600     case R8G8B8A8_UNORM_SRGB: ConvertPixelFromFloat<R8G8B8A8_UNORM_SRGB>(pDst, srcPixel); break;
    601     case R8G8B8A8_SNORM: ConvertPixelFromFloat<R8G8B8A8_SNORM>(pDst, srcPixel); break;
    602     case R8G8B8A8_SINT: ConvertPixelFromFloat<R8G8B8A8_SINT>(pDst, srcPixel); break;
    603     case R8G8B8A8_UINT: ConvertPixelFromFloat<R8G8B8A8_UINT>(pDst, srcPixel); break;
    604     case R16G16_UNORM: ConvertPixelFromFloat<R16G16_UNORM>(pDst, srcPixel); break;
    605     case R16G16_SNORM: ConvertPixelFromFloat<R16G16_SNORM>(pDst, srcPixel); break;
    606     case R16G16_SINT: ConvertPixelFromFloat<R16G16_SINT>(pDst, srcPixel); break;
    607     case R16G16_UINT: ConvertPixelFromFloat<R16G16_UINT>(pDst, srcPixel); break;
    608     case R16G16_FLOAT: ConvertPixelFromFloat<R16G16_FLOAT>(pDst, srcPixel); break;
    609     case B10G10R10A2_UNORM: ConvertPixelFromFloat<B10G10R10A2_UNORM>(pDst, srcPixel); break;
    610     case B10G10R10A2_UNORM_SRGB: ConvertPixelFromFloat<B10G10R10A2_UNORM_SRGB>(pDst, srcPixel); break;
    611     case R11G11B10_FLOAT: ConvertPixelFromFloat<R11G11B10_FLOAT>(pDst, srcPixel); break;
    612     case R10G10B10_FLOAT_A2_UNORM: ConvertPixelFromFloat<R10G10B10_FLOAT_A2_UNORM>(pDst, srcPixel); break;
    613     case R32_SINT: ConvertPixelFromFloat<R32_SINT>(pDst, srcPixel); break;
    614     case R32_UINT: ConvertPixelFromFloat<R32_UINT>(pDst, srcPixel); break;
    615     case R32_FLOAT: ConvertPixelFromFloat<R32_FLOAT>(pDst, srcPixel); break;
    616     case R24_UNORM_X8_TYPELESS: ConvertPixelFromFloat<R24_UNORM_X8_TYPELESS>(pDst, srcPixel); break;
    617     case X24_TYPELESS_G8_UINT: ConvertPixelFromFloat<X24_TYPELESS_G8_UINT>(pDst, srcPixel); break;
    618     case L32_UNORM: ConvertPixelFromFloat<L32_UNORM>(pDst, srcPixel); break;
    619     case L16A16_UNORM: ConvertPixelFromFloat<L16A16_UNORM>(pDst, srcPixel); break;
    620     case I24X8_UNORM: ConvertPixelFromFloat<I24X8_UNORM>(pDst, srcPixel); break;
    621     case L24X8_UNORM: ConvertPixelFromFloat<L24X8_UNORM>(pDst, srcPixel); break;
    622     case I32_FLOAT: ConvertPixelFromFloat<I32_FLOAT>(pDst, srcPixel); break;
    623     case L32_FLOAT: ConvertPixelFromFloat<L32_FLOAT>(pDst, srcPixel); break;
    624     case A32_FLOAT: ConvertPixelFromFloat<A32_FLOAT>(pDst, srcPixel); break;
    625     case B8G8R8X8_UNORM: ConvertPixelFromFloat<B8G8R8X8_UNORM>(pDst, srcPixel); break;
    626     case B8G8R8X8_UNORM_SRGB: ConvertPixelFromFloat<B8G8R8X8_UNORM_SRGB>(pDst, srcPixel); break;
    627     case R8G8B8X8_UNORM: ConvertPixelFromFloat<R8G8B8X8_UNORM>(pDst, srcPixel); break;
    628     case R8G8B8X8_UNORM_SRGB: ConvertPixelFromFloat<R8G8B8X8_UNORM_SRGB>(pDst, srcPixel); break;
    629     case R9G9B9E5_SHAREDEXP: ConvertPixelFromFloat<R9G9B9E5_SHAREDEXP>(pDst, srcPixel); break;
    630     case B10G10R10X2_UNORM: ConvertPixelFromFloat<B10G10R10X2_UNORM>(pDst, srcPixel); break;
    631     case L16A16_FLOAT: ConvertPixelFromFloat<L16A16_FLOAT>(pDst, srcPixel); break;
    632     case R10G10B10X2_USCALED: ConvertPixelFromFloat<R10G10B10X2_USCALED>(pDst, srcPixel); break;
    633     case R8G8B8A8_SSCALED: ConvertPixelFromFloat<R8G8B8A8_SSCALED>(pDst, srcPixel); break;
    634     case R8G8B8A8_USCALED: ConvertPixelFromFloat<R8G8B8A8_USCALED>(pDst, srcPixel); break;
    635     case R16G16_SSCALED: ConvertPixelFromFloat<R16G16_SSCALED>(pDst, srcPixel); break;
    636     case R16G16_USCALED: ConvertPixelFromFloat<R16G16_USCALED>(pDst, srcPixel); break;
    637     case R32_SSCALED: ConvertPixelFromFloat<R32_SSCALED>(pDst, srcPixel); break;
    638     case R32_USCALED: ConvertPixelFromFloat<R32_USCALED>(pDst, srcPixel); break;
    639     case B5G6R5_UNORM: ConvertPixelFromFloat<B5G6R5_UNORM>(pDst, srcPixel); break;
    640     case B5G6R5_UNORM_SRGB: ConvertPixelFromFloat<B5G6R5_UNORM_SRGB>(pDst, srcPixel); break;
    641     case B5G5R5A1_UNORM: ConvertPixelFromFloat<B5G5R5A1_UNORM>(pDst, srcPixel); break;
    642     case B5G5R5A1_UNORM_SRGB: ConvertPixelFromFloat<B5G5R5A1_UNORM_SRGB>(pDst, srcPixel); break;
    643     case B4G4R4A4_UNORM: ConvertPixelFromFloat<B4G4R4A4_UNORM>(pDst, srcPixel); break;
    644     case B4G4R4A4_UNORM_SRGB: ConvertPixelFromFloat<B4G4R4A4_UNORM_SRGB>(pDst, srcPixel); break;
    645     case R8G8_UNORM: ConvertPixelFromFloat<R8G8_UNORM>(pDst, srcPixel); break;
    646     case R8G8_SNORM: ConvertPixelFromFloat<R8G8_SNORM>(pDst, srcPixel); break;
    647     case R8G8_SINT: ConvertPixelFromFloat<R8G8_SINT>(pDst, srcPixel); break;
    648     case R8G8_UINT: ConvertPixelFromFloat<R8G8_UINT>(pDst, srcPixel); break;
    649     case R16_UNORM: ConvertPixelFromFloat<R16_UNORM>(pDst, srcPixel); break;
    650     case R16_SNORM: ConvertPixelFromFloat<R16_SNORM>(pDst, srcPixel); break;
    651     case R16_SINT: ConvertPixelFromFloat<R16_SINT>(pDst, srcPixel); break;
    652     case R16_UINT: ConvertPixelFromFloat<R16_UINT>(pDst, srcPixel); break;
    653     case R16_FLOAT: ConvertPixelFromFloat<R16_FLOAT>(pDst, srcPixel); break;
    654     case I16_UNORM: ConvertPixelFromFloat<I16_UNORM>(pDst, srcPixel); break;
    655     case L16_UNORM: ConvertPixelFromFloat<L16_UNORM>(pDst, srcPixel); break;
    656     case A16_UNORM: ConvertPixelFromFloat<A16_UNORM>(pDst, srcPixel); break;
    657     case L8A8_UNORM: ConvertPixelFromFloat<L8A8_UNORM>(pDst, srcPixel); break;
    658     case I16_FLOAT: ConvertPixelFromFloat<I16_FLOAT>(pDst, srcPixel); break;
    659     case L16_FLOAT: ConvertPixelFromFloat<L16_FLOAT>(pDst, srcPixel); break;
    660     case A16_FLOAT: ConvertPixelFromFloat<A16_FLOAT>(pDst, srcPixel); break;
    661     case L8A8_UNORM_SRGB: ConvertPixelFromFloat<L8A8_UNORM_SRGB>(pDst, srcPixel); break;
    662     case B5G5R5X1_UNORM: ConvertPixelFromFloat<B5G5R5X1_UNORM>(pDst, srcPixel); break;
    663     case B5G5R5X1_UNORM_SRGB: ConvertPixelFromFloat<B5G5R5X1_UNORM_SRGB>(pDst, srcPixel); break;
    664     case R8G8_SSCALED: ConvertPixelFromFloat<R8G8_SSCALED>(pDst, srcPixel); break;
    665     case R8G8_USCALED: ConvertPixelFromFloat<R8G8_USCALED>(pDst, srcPixel); break;
    666     case R16_SSCALED: ConvertPixelFromFloat<R16_SSCALED>(pDst, srcPixel); break;
    667     case R16_USCALED: ConvertPixelFromFloat<R16_USCALED>(pDst, srcPixel); break;
    668     case A1B5G5R5_UNORM: ConvertPixelFromFloat<A1B5G5R5_UNORM>(pDst, srcPixel); break;
    669     case A4B4G4R4_UNORM: ConvertPixelFromFloat<A4B4G4R4_UNORM>(pDst, srcPixel); break;
    670     case L8A8_UINT: ConvertPixelFromFloat<L8A8_UINT>(pDst, srcPixel); break;
    671     case L8A8_SINT: ConvertPixelFromFloat<L8A8_SINT>(pDst, srcPixel); break;
    672     case R8_UNORM: ConvertPixelFromFloat<R8_UNORM>(pDst, srcPixel); break;
    673     case R8_SNORM: ConvertPixelFromFloat<R8_SNORM>(pDst, srcPixel); break;
    674     case R8_SINT: ConvertPixelFromFloat<R8_SINT>(pDst, srcPixel); break;
    675     case R8_UINT: ConvertPixelFromFloat<R8_UINT>(pDst, srcPixel); break;
    676     case A8_UNORM: ConvertPixelFromFloat<A8_UNORM>(pDst, srcPixel); break;
    677     case I8_UNORM: ConvertPixelFromFloat<I8_UNORM>(pDst, srcPixel); break;
    678     case L8_UNORM: ConvertPixelFromFloat<L8_UNORM>(pDst, srcPixel); break;
    679     case R8_SSCALED: ConvertPixelFromFloat<R8_SSCALED>(pDst, srcPixel); break;
    680     case R8_USCALED: ConvertPixelFromFloat<R8_USCALED>(pDst, srcPixel); break;
    681     case L8_UNORM_SRGB: ConvertPixelFromFloat<L8_UNORM_SRGB>(pDst, srcPixel); break;
    682     case L8_UINT: ConvertPixelFromFloat<L8_UINT>(pDst, srcPixel); break;
    683     case L8_SINT: ConvertPixelFromFloat<L8_SINT>(pDst, srcPixel); break;
    684     case I8_UINT: ConvertPixelFromFloat<I8_UINT>(pDst, srcPixel); break;
    685     case I8_SINT: ConvertPixelFromFloat<I8_SINT>(pDst, srcPixel); break;
    686     case YCRCB_SWAPUVY: ConvertPixelFromFloat<YCRCB_SWAPUVY>(pDst, srcPixel); break;
    687     case BC1_UNORM: ConvertPixelFromFloat<BC1_UNORM>(pDst, srcPixel); break;
    688     case BC2_UNORM: ConvertPixelFromFloat<BC2_UNORM>(pDst, srcPixel); break;
    689     case BC3_UNORM: ConvertPixelFromFloat<BC3_UNORM>(pDst, srcPixel); break;
    690     case BC4_UNORM: ConvertPixelFromFloat<BC4_UNORM>(pDst, srcPixel); break;
    691     case BC5_UNORM: ConvertPixelFromFloat<BC5_UNORM>(pDst, srcPixel); break;
    692     case BC1_UNORM_SRGB: ConvertPixelFromFloat<BC1_UNORM_SRGB>(pDst, srcPixel); break;
    693     case BC2_UNORM_SRGB: ConvertPixelFromFloat<BC2_UNORM_SRGB>(pDst, srcPixel); break;
    694     case BC3_UNORM_SRGB: ConvertPixelFromFloat<BC3_UNORM_SRGB>(pDst, srcPixel); break;
    695     case YCRCB_SWAPUV: ConvertPixelFromFloat<YCRCB_SWAPUV>(pDst, srcPixel); break;
    696     case R8G8B8_UNORM: ConvertPixelFromFloat<R8G8B8_UNORM>(pDst, srcPixel); break;
    697     case R8G8B8_SNORM: ConvertPixelFromFloat<R8G8B8_SNORM>(pDst, srcPixel); break;
    698     case R8G8B8_SSCALED: ConvertPixelFromFloat<R8G8B8_SSCALED>(pDst, srcPixel); break;
    699     case R8G8B8_USCALED: ConvertPixelFromFloat<R8G8B8_USCALED>(pDst, srcPixel); break;
    700     case BC4_SNORM: ConvertPixelFromFloat<BC4_SNORM>(pDst, srcPixel); break;
    701     case BC5_SNORM: ConvertPixelFromFloat<BC5_SNORM>(pDst, srcPixel); break;
    702     case R16G16B16_FLOAT: ConvertPixelFromFloat<R16G16B16_FLOAT>(pDst, srcPixel); break;
    703     case R16G16B16_UNORM: ConvertPixelFromFloat<R16G16B16_UNORM>(pDst, srcPixel); break;
    704     case R16G16B16_SNORM: ConvertPixelFromFloat<R16G16B16_SNORM>(pDst, srcPixel); break;
    705     case R16G16B16_SSCALED: ConvertPixelFromFloat<R16G16B16_SSCALED>(pDst, srcPixel); break;
    706     case R16G16B16_USCALED: ConvertPixelFromFloat<R16G16B16_USCALED>(pDst, srcPixel); break;
    707     case BC6H_SF16: ConvertPixelFromFloat<BC6H_SF16>(pDst, srcPixel); break;
    708     case BC7_UNORM: ConvertPixelFromFloat<BC7_UNORM>(pDst, srcPixel); break;
    709     case BC7_UNORM_SRGB: ConvertPixelFromFloat<BC7_UNORM_SRGB>(pDst, srcPixel); break;
    710     case BC6H_UF16: ConvertPixelFromFloat<BC6H_UF16>(pDst, srcPixel); break;
    711     case R8G8B8_UNORM_SRGB: ConvertPixelFromFloat<R8G8B8_UNORM_SRGB>(pDst, srcPixel); break;
    712     case R16G16B16_UINT: ConvertPixelFromFloat<R16G16B16_UINT>(pDst, srcPixel); break;
    713     case R16G16B16_SINT: ConvertPixelFromFloat<R16G16B16_SINT>(pDst, srcPixel); break;
    714     case R10G10B10A2_SNORM: ConvertPixelFromFloat<R10G10B10A2_SNORM>(pDst, srcPixel); break;
    715     case R10G10B10A2_USCALED: ConvertPixelFromFloat<R10G10B10A2_USCALED>(pDst, srcPixel); break;
    716     case R10G10B10A2_SSCALED: ConvertPixelFromFloat<R10G10B10A2_SSCALED>(pDst, srcPixel); break;
    717     case R10G10B10A2_SINT: ConvertPixelFromFloat<R10G10B10A2_SINT>(pDst, srcPixel); break;
    718     case B10G10R10A2_SNORM: ConvertPixelFromFloat<B10G10R10A2_SNORM>(pDst, srcPixel); break;
    719     case B10G10R10A2_USCALED: ConvertPixelFromFloat<B10G10R10A2_USCALED>(pDst, srcPixel); break;
    720     case B10G10R10A2_SSCALED: ConvertPixelFromFloat<B10G10R10A2_SSCALED>(pDst, srcPixel); break;
    721     case B10G10R10A2_UINT: ConvertPixelFromFloat<B10G10R10A2_UINT>(pDst, srcPixel); break;
    722     case B10G10R10A2_SINT: ConvertPixelFromFloat<B10G10R10A2_SINT>(pDst, srcPixel); break;
    723     case R8G8B8_UINT: ConvertPixelFromFloat<R8G8B8_UINT>(pDst, srcPixel); break;
    724     case R8G8B8_SINT: ConvertPixelFromFloat<R8G8B8_SINT>(pDst, srcPixel); break;
    725     case RAW: ConvertPixelFromFloat<RAW>(pDst, srcPixel); break;
    726     default:
    727         SWR_ASSERT(0);
    728         break;
    729     }
    730 }
    731