void DirectX::_ConvertScanline()

in DirectXTex/DirectXTexConvert.cpp [3011:3711]


void DirectX::_ConvertScanline(
    XMVECTOR* pBuffer,
    size_t count,
    DXGI_FORMAT outFormat,
    DXGI_FORMAT inFormat,
    TEX_FILTER_FLAGS flags) noexcept
{
    assert(pBuffer && count > 0 && ((reinterpret_cast<uintptr_t>(pBuffer) & 0xF) == 0));
    assert(IsValid(outFormat) && !IsTypeless(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat));
    assert(IsValid(inFormat) && !IsTypeless(inFormat) && !IsPlanar(inFormat) && !IsPalettized(inFormat));

    if (!pBuffer)
        return;

#ifdef _DEBUG
    // Ensure conversion table is in ascending order
    assert(std::size(g_ConvertTable) > 0);
    DXGI_FORMAT lastvalue = g_ConvertTable[0].format;
    for (size_t index = 1; index < std::size(g_ConvertTable); ++index)
    {
        assert(g_ConvertTable[index].format > lastvalue);
        lastvalue = g_ConvertTable[index].format;
    }
#endif

    // Determine conversion details about source and dest formats
    ConvertData key = { inFormat, 0, 0 };
    auto in = reinterpret_cast<const ConvertData*>(
        bsearch(&key, g_ConvertTable, std::size(g_ConvertTable), sizeof(ConvertData), ConvertCompare));
    key.format = outFormat;
    auto out = reinterpret_cast<const ConvertData*>(
        bsearch(&key, g_ConvertTable, std::size(g_ConvertTable), sizeof(ConvertData), ConvertCompare));
    if (!in || !out)
    {
        assert(false);
        return;
    }

    assert(_GetConvertFlags(inFormat) == in->flags);
    assert(_GetConvertFlags(outFormat) == out->flags);

    // Handle SRGB filtering modes
    switch (inFormat)
    {
    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
    case DXGI_FORMAT_BC1_UNORM_SRGB:
    case DXGI_FORMAT_BC2_UNORM_SRGB:
    case DXGI_FORMAT_BC3_UNORM_SRGB:
    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
    case DXGI_FORMAT_BC7_UNORM_SRGB:
        flags |= TEX_FILTER_SRGB_IN;
        break;

    case DXGI_FORMAT_A8_UNORM:
    case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
        flags &= ~TEX_FILTER_SRGB_IN;
        break;

    default:
        break;
    }

    switch (outFormat)
    {
    case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
    case DXGI_FORMAT_BC1_UNORM_SRGB:
    case DXGI_FORMAT_BC2_UNORM_SRGB:
    case DXGI_FORMAT_BC3_UNORM_SRGB:
    case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
    case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
    case DXGI_FORMAT_BC7_UNORM_SRGB:
        flags |= TEX_FILTER_SRGB_OUT;
        break;

    case DXGI_FORMAT_A8_UNORM:
    case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
        flags &= ~TEX_FILTER_SRGB_OUT;
        break;

    default:
        break;
    }

    if ((flags & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT))
    {
        flags &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT);
    }

    // sRGB input processing (sRGB -> Linear RGB)
    if (flags & TEX_FILTER_SRGB_IN)
    {
        if (!(in->flags & CONVF_DEPTH) && ((in->flags & CONVF_FLOAT) || (in->flags & CONVF_UNORM)))
        {
            XMVECTOR* ptr = pBuffer;
            for (size_t i = 0; i < count; ++i, ++ptr)
            {
                *ptr = XMColorSRGBToRGB(*ptr);
            }
        }
    }

    // Handle conversion special cases
    uint32_t diffFlags = in->flags ^ out->flags;
    if (diffFlags != 0)
    {
        if (diffFlags & CONVF_DEPTH)
        {
            //--- Depth conversions ---
            if (in->flags & CONVF_DEPTH)
            {
                // CONVF_DEPTH -> !CONVF_DEPTH
                if (in->flags & CONVF_STENCIL)
                {
                    // Stencil -> Alpha
                    static const XMVECTORF32 S = { { { 1.f, 1.f, 1.f, 255.f } } };

                    if (out->flags & CONVF_UNORM)
                    {
                        // UINT -> UNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorSplatY(v);
                            v1 = XMVectorClamp(v1, g_XMZero, S);
                            v1 = XMVectorDivide(v1, S);
                            *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110);
                        }
                    }
                    else if (out->flags & CONVF_SNORM)
                    {
                        // UINT -> SNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorSplatY(v);
                            v1 = XMVectorClamp(v1, g_XMZero, S);
                            v1 = XMVectorDivide(v1, S);
                            v1 = XMVectorMultiplyAdd(v1, g_XMTwo, g_XMNegativeOne);
                            *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110);
                        }
                    }
                    else
                    {
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorSplatY(v);
                            *ptr++ = XMVectorSelect(v1, v, g_XMSelect1110);
                        }
                    }
                }

                // Depth -> RGB
                if ((out->flags & CONVF_UNORM) && (in->flags & CONVF_FLOAT))
                {
                    // Depth FLOAT -> UNORM
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSaturate(v);
                        v1 = XMVectorSplatX(v1);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                    }
                }
                else if (out->flags & CONVF_SNORM)
                {
                    if (in->flags & CONVF_UNORM)
                    {
                        // Depth UNORM -> SNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                            v1 = XMVectorSplatX(v1);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                        }
                    }
                    else
                    {
                        // Depth FLOAT -> SNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorClamp(v, g_XMNegativeOne, g_XMOne);
                            v1 = XMVectorSplatX(v1);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                        }
                    }
                }
                else
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatX(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                    }
                }
            }
            else
            {
                // !CONVF_DEPTH -> CONVF_DEPTH

                // RGB -> Depth (red channel)
                switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE))
                {
                case TEX_FILTER_RGB_COPY_GREEN:
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatY(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                    }
                }
                break;

                case TEX_FILTER_RGB_COPY_BLUE:
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatZ(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                    }
                }
                break;

                default:
                    if ((in->flags & CONVF_UNORM) && ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B)))
                    {
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVector3Dot(v, g_Grayscale);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                        }
                        break;
                    }

#ifdef _MSC_VER
                    __fallthrough;
#endif
#ifdef __clang__
                    [[clang::fallthrough]];
#endif

                case TEX_FILTER_RGB_COPY_RED:
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatX(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                    }
                }
                break;
                }

                // Finialize type conversion for depth (red channel)
                if (out->flags & CONVF_UNORM)
                {
                    if (in->flags & CONVF_SNORM)
                    {
                        // SNORM -> UNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                        }
                    }
                    else if (in->flags & CONVF_FLOAT)
                    {
                        // FLOAT -> UNORM
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorSaturate(v);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                        }
                    }
                }

                if (out->flags & CONVF_STENCIL)
                {
                    // Alpha -> Stencil (green channel)
                    static const XMVECTORU32 select0100 = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 } } };
                    static const XMVECTORF32 S = { { { 255.f, 255.f, 255.f, 255.f } } };

                    if (in->flags & CONVF_UNORM)
                    {
                        // UNORM -> UINT
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorMultiply(v, S);
                            v1 = XMVectorSplatW(v1);
                            *ptr++ = XMVectorSelect(v, v1, select0100);
                        }
                    }
                    else if (in->flags & CONVF_SNORM)
                    {
                        // SNORM -> UINT
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                            v1 = XMVectorMultiply(v1, S);
                            v1 = XMVectorSplatW(v1);
                            *ptr++ = XMVectorSelect(v, v1, select0100);
                        }
                    }
                    else
                    {
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVectorSplatW(v);
                            *ptr++ = XMVectorSelect(v, v1, select0100);
                        }
                    }
                }
            }
        }
        else if (out->flags & CONVF_DEPTH)
        {
            // CONVF_DEPTH -> CONVF_DEPTH
            if (diffFlags & CONVF_FLOAT)
            {
                if (in->flags & CONVF_FLOAT)
                {
                    // FLOAT -> UNORM depth, preserve stencil
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSaturate(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1000);
                    }
                }
            }
        }
        else if (out->flags & CONVF_UNORM)
        {
            //--- Converting to a UNORM ---
            if (in->flags & CONVF_SNORM)
            {
                // SNORM -> UNORM
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                }
            }
            else if (in->flags & CONVF_FLOAT)
            {
                XMVECTOR* ptr = pBuffer;
                if (!(in->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS))
                {
                    // FLOAT -> UNORM (x2 bias)
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        v = XMVectorClamp(v, g_XMNegativeOne, g_XMOne);
                        *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                    }
                }
                else
                {
                    // FLOAT -> UNORM
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        *ptr++ = XMVectorSaturate(v);
                    }
                }
            }
        }
        else if (out->flags & CONVF_SNORM)
        {
            //--- Converting to a SNORM ---
            if (in->flags & CONVF_UNORM)
            {
                // UNORM -> SNORM
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                }
            }
            else if (in->flags & CONVF_FLOAT)
            {
                XMVECTOR* ptr = pBuffer;
                if ((in->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS))
                {
                    // FLOAT (positive only, x2 bias) -> SNORM
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        v = XMVectorSaturate(v);
                        *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                    }
                }
                else
                {
                    // FLOAT -> SNORM
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        *ptr++ = XMVectorClamp(v, g_XMNegativeOne, g_XMOne);
                    }
                }
            }
        }
        else if (diffFlags & CONVF_UNORM)
        {
            //--- Converting from a UNORM ---
            assert(in->flags & CONVF_UNORM);
            if (out->flags & CONVF_FLOAT)
            {
                if (!(out->flags & CONVF_POS_ONLY) && (flags & TEX_FILTER_FLOAT_X2BIAS))
                {
                    // UNORM (x2 bias) -> FLOAT
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                    }
                }
            }
        }
        else if (diffFlags & CONVF_POS_ONLY)
        {
            if (flags & TEX_FILTER_FLOAT_X2BIAS)
            {
                if (in->flags & CONVF_POS_ONLY)
                {
                    if (out->flags & CONVF_FLOAT)
                    {
                        // FLOAT (positive only, x2 bias) -> FLOAT
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            v = XMVectorSaturate(v);
                            *ptr++ = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                        }
                    }
                }
                else if (out->flags & CONVF_POS_ONLY)
                {
                    if (in->flags & CONVF_FLOAT)
                    {
                        // FLOAT -> FLOAT (positive only, x2 bias)
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            v = XMVectorClamp(v, g_XMNegativeOne, g_XMOne);
                            *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                        }
                    }
                    else if (in->flags & CONVF_SNORM)
                    {
                        // SNORM -> FLOAT (positive only, x2 bias)
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            *ptr++ = XMVectorMultiplyAdd(v, g_XMOneHalf, g_XMOneHalf);
                        }
                    }
                }
            }
        }

        // !CONVF_A -> CONVF_A is handled because LoadScanline ensures alpha defaults to 1.0 for no-alpha formats

        // CONVF_PACKED cases are handled because LoadScanline/StoreScanline handles packing/unpacking

        if (((out->flags & CONVF_RGBA_MASK) == CONVF_A) && !(in->flags & CONVF_A))
        {
            // !CONVF_A -> A format
            switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE))
            {
            case TEX_FILTER_RGB_COPY_GREEN:
            {
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    *ptr++ = XMVectorSplatY(v);
                }
            }
            break;

            case TEX_FILTER_RGB_COPY_BLUE:
            {
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    *ptr++ = XMVectorSplatZ(v);
                }
            }
            break;

            default:
                if ((in->flags & CONVF_UNORM) && ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B)))
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        *ptr++ = XMVector3Dot(v, g_Grayscale);
                    }
                    break;
                }

#ifdef _MSC_VER
                __fallthrough;
#endif
#ifdef __clang__
                [[clang::fallthrough]];
#endif

            case TEX_FILTER_RGB_COPY_RED:
            {
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    *ptr++ = XMVectorSplatX(v);
                }
            }
            break;
            }
        }
        else if (((in->flags & CONVF_RGBA_MASK) == CONVF_A) && !(out->flags & CONVF_A))
        {
            // A format -> !CONVF_A
            XMVECTOR* ptr = pBuffer;
            for (size_t i = 0; i < count; ++i)
            {
                XMVECTOR v = *ptr;
                *ptr++ = XMVectorSplatW(v);
            }
        }
        else if ((in->flags & CONVF_RGB_MASK) == CONVF_R)
        {
            if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B))
            {
                // R format -> RGB format
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    XMVECTOR v1 = XMVectorSplatX(v);
                    *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                }
            }
            else if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G))
            {
                // R format -> RG format
                XMVECTOR* ptr = pBuffer;
                for (size_t i = 0; i < count; ++i)
                {
                    XMVECTOR v = *ptr;
                    XMVECTOR v1 = XMVectorSplatX(v);
                    *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100);
                }
            }
        }
        else if ((in->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G | CONVF_B))
        {
            if ((out->flags & CONVF_RGB_MASK) == CONVF_R)
            {
                // RGB format -> R format
                switch (flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE))
                {
                case TEX_FILTER_RGB_COPY_GREEN:
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatY(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                    }
                }
                break;

                case TEX_FILTER_RGB_COPY_BLUE:
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSplatZ(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                    }
                }
                break;

                default:
                    if (in->flags & CONVF_UNORM)
                    {
                        XMVECTOR* ptr = pBuffer;
                        for (size_t i = 0; i < count; ++i)
                        {
                            XMVECTOR v = *ptr;
                            XMVECTOR v1 = XMVector3Dot(v, g_Grayscale);
                            *ptr++ = XMVectorSelect(v, v1, g_XMSelect1110);
                        }
                        break;
                    }

#ifdef _MSC_VER
                    __fallthrough;
#endif
#ifdef __clang__
                    [[clang::fallthrough]];
#endif

                case TEX_FILTER_RGB_COPY_RED:
                    // Leave data unchanged and the store will handle this...
                    break;
                }
            }
            else if ((out->flags & CONVF_RGB_MASK) == (CONVF_R | CONVF_G))
            {
                // RGB format -> RG format
                switch (static_cast<int>(flags & (TEX_FILTER_RGB_COPY_RED | TEX_FILTER_RGB_COPY_GREEN | TEX_FILTER_RGB_COPY_BLUE)))
                {
                case static_cast<int>(TEX_FILTER_RGB_COPY_RED) | static_cast<int>(TEX_FILTER_RGB_COPY_BLUE):
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSwizzle<0, 2, 0, 2>(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100);
                    }
                }
                break;

                case static_cast<int>(TEX_FILTER_RGB_COPY_GREEN) | static_cast<int>(TEX_FILTER_RGB_COPY_BLUE):
                {
                    XMVECTOR* ptr = pBuffer;
                    for (size_t i = 0; i < count; ++i)
                    {
                        XMVECTOR v = *ptr;
                        XMVECTOR v1 = XMVectorSwizzle<1, 2, 3, 0>(v);
                        *ptr++ = XMVectorSelect(v, v1, g_XMSelect1100);
                    }
                }
                break;

                case static_cast<int>(TEX_FILTER_RGB_COPY_RED) | static_cast<int>(TEX_FILTER_RGB_COPY_GREEN):
                default:
                    // Leave data unchanged and the store will handle this...
                    break;
                }
            }
        }
    }

    // sRGB output processing (Linear RGB -> sRGB)
    if (flags & TEX_FILTER_SRGB_OUT)
    {
        if (!(out->flags & CONVF_DEPTH) && ((out->flags & CONVF_FLOAT) || (out->flags & CONVF_UNORM)))
        {
            XMVECTOR* ptr = pBuffer;
            for (size_t i = 0; i < count; ++i, ++ptr)
            {
                *ptr = XMColorRGBToSRGB(*ptr);
            }
        }
    }
}