HRESULT VBReader::Impl::Read()

in DirectXMesh/DirectXMeshVBReader.cpp [283:644]


HRESULT VBReader::Impl::Read(XMVECTOR* buffer, const char* semanticName, unsigned int semanticIndex, size_t count, bool x2bias) const
{
    if (!buffer || !semanticName || !count)
        return E_INVALIDARG;

    auto range = mSemantics.equal_range(semanticName);

    auto it = range.first;
    for (; it != range.second; ++it)
    {
        if (mInputDesc[it->second].SemanticIndex == semanticIndex)
            break;
    }

    if (it == range.second)
        return HRESULT_E_INVALID_NAME;

    uint32_t inputSlot = mInputDesc[it->second].InputSlot;

    auto vb = static_cast<const uint8_t*>(mBuffers[inputSlot]);
    if (!vb)
        return E_FAIL;

    if (count > mVerts[inputSlot])
        return E_BOUNDS;

    uint32_t stride = mStrides[inputSlot];
    if (!stride)
        return E_UNEXPECTED;

    const uint8_t* eptr = vb + stride * mVerts[inputSlot];
    const uint8_t* ptr = vb + mInputDesc[it->second].AlignedByteOffset;

    switch (static_cast<int>(mInputDesc[it->second].Format))
    {
    case DXGI_FORMAT_R32G32B32A32_FLOAT:
        LOAD_VERTS(XMFLOAT4, XMLoadFloat4)

    case DXGI_FORMAT_R32G32B32A32_UINT:
        LOAD_VERTS(XMUINT4, XMLoadUInt4)

    case DXGI_FORMAT_R32G32B32A32_SINT:
        LOAD_VERTS(XMINT4, XMLoadSInt4)

    case DXGI_FORMAT_R32G32B32_FLOAT:
        LOAD_VERTS(XMFLOAT3, XMLoadFloat3)

    case DXGI_FORMAT_R32G32B32_UINT:
        LOAD_VERTS(XMUINT3, XMLoadUInt3)

    case DXGI_FORMAT_R32G32B32_SINT:
        LOAD_VERTS(XMINT3, XMLoadSInt3)

    case DXGI_FORMAT_R16G16B16A16_FLOAT:
        LOAD_VERTS(XMHALF4, XMLoadHalf4)

    case DXGI_FORMAT_R16G16B16A16_UNORM:
        LOAD_VERTS4_X2(XMUSHORTN4, XMLoadUShortN4, x2bias)

    case DXGI_FORMAT_R16G16B16A16_UINT:
        LOAD_VERTS(XMUSHORT4, XMLoadUShort4)

    case DXGI_FORMAT_R16G16B16A16_SNORM:
        LOAD_VERTS(XMSHORTN4, XMLoadShortN4)

    case DXGI_FORMAT_R16G16B16A16_SINT:
        LOAD_VERTS(XMSHORT4, XMLoadShort4)

    case DXGI_FORMAT_R32G32_FLOAT:
        LOAD_VERTS(XMFLOAT2, XMLoadFloat2)

    case DXGI_FORMAT_R32G32_UINT:
        LOAD_VERTS(XMUINT2, XMLoadUInt2)

    case DXGI_FORMAT_R32G32_SINT:
        LOAD_VERTS(XMINT2, XMLoadSInt2)

    case DXGI_FORMAT_R10G10B10A2_UNORM:
        LOAD_VERTS3_X2(XMUDECN4, XMLoadUDecN4, x2bias)

    case DXGI_FORMAT_R10G10B10A2_UINT:
        LOAD_VERTS(XMUDEC4, XMLoadUDec4)

    case DXGI_FORMAT_R11G11B10_FLOAT:
        LOAD_VERTS3_X2(XMFLOAT3PK, XMLoadFloat3PK, x2bias)

    case DXGI_FORMAT_R8G8B8A8_UNORM:
        LOAD_VERTS4_X2(XMUBYTEN4, XMLoadUByteN4, x2bias)

    case DXGI_FORMAT_R8G8B8A8_UINT:
        LOAD_VERTS(XMUBYTE4, XMLoadUByte4)

    case DXGI_FORMAT_R8G8B8A8_SNORM:
        LOAD_VERTS(XMBYTEN4, XMLoadByteN4)

    case DXGI_FORMAT_R8G8B8A8_SINT:
        LOAD_VERTS(XMBYTE4, XMLoadByte4)

    case DXGI_FORMAT_R16G16_FLOAT:
        LOAD_VERTS(XMHALF2, XMLoadHalf2)

    case DXGI_FORMAT_R16G16_UNORM:
        LOAD_VERTS2_X2(XMUSHORTN2, XMLoadUShortN2, x2bias)

    case DXGI_FORMAT_R16G16_UINT:
        LOAD_VERTS(XMUSHORT2, XMLoadUShort2)

    case DXGI_FORMAT_R16G16_SNORM:
        LOAD_VERTS(XMSHORTN2, XMLoadShortN2)

    case DXGI_FORMAT_R16G16_SINT:
        LOAD_VERTS(XMSHORT2, XMLoadShort2)

    case DXGI_FORMAT_R32_FLOAT:
        LOAD_VERTS(float, XMLoadFloat)

    case DXGI_FORMAT_R32_UINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(uint32_t)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadInt(reinterpret_cast<const uint32_t*>(ptr));
            *buffer++ = XMConvertVectorUIntToFloat(v, 0);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R32_SINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(int32_t)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadInt(reinterpret_cast<const uint32_t*>(ptr));
            *buffer++ = XMConvertVectorIntToFloat(v, 0);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R8G8_UNORM:
        LOAD_VERTS2_X2(XMUBYTEN2, XMLoadUByteN2, x2bias)

    case DXGI_FORMAT_R8G8_UINT:
        LOAD_VERTS(XMUBYTE2, XMLoadUByte2)

    case DXGI_FORMAT_R8G8_SNORM:
        LOAD_VERTS(XMBYTEN2, XMLoadByteN2)

    case DXGI_FORMAT_R8G8_SINT:
        LOAD_VERTS(XMBYTE2, XMLoadByte2)

    case DXGI_FORMAT_R16_FLOAT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(HALF)) > eptr)
                return E_UNEXPECTED;
            float v = XMConvertHalfToFloat(*reinterpret_cast<const HALF*>(ptr));
            *buffer++ = XMVectorSet(v, 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R16_UNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(uint16_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const uint16_t*>(ptr);
            float f = static_cast<float>(i) / 65535.f;
            if (x2bias)
            {
                f = f*2.f - 1.f;
            }
            XMVECTOR v = XMVectorSet(f, 0.f, 0.f, 0.f);
            *buffer++ = v;
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R16_UINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(uint16_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const uint16_t*>(ptr);
            *buffer++ = XMVectorSet(static_cast<float>(i), 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R16_SNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(int16_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const int16_t*>(ptr);
            *buffer++ = XMVectorSet(static_cast<float>(i) / 32767.f, 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R16_SINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(int16_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const int16_t*>(ptr);
            *buffer++ = XMVectorSet(static_cast<float>(i), 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R8_UNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(uint8_t)) > eptr)
                return E_UNEXPECTED;
            const uint8_t i = *ptr;
            float f = static_cast<float>(i) / 255.f;
            if (x2bias)
            {
                f = f*2.f - 1.f;
            }
            XMVECTOR v = XMVectorSet(f, 0.f, 0.f, 0.f);
            *buffer++ = v;
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R8_UINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(uint8_t)) > eptr)
                return E_UNEXPECTED;
            const uint8_t i = *ptr;
            *buffer++ = XMVectorSet(static_cast<float>(i), 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R8_SNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(int8_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const int8_t*>(ptr);
            *buffer++ = XMVectorSet(static_cast<float>(i) / 127.f, 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_R8_SINT:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(int8_t)) > eptr)
                return E_UNEXPECTED;
            auto i = *reinterpret_cast<const int8_t*>(ptr);
            *buffer++ = XMVectorSet(static_cast<float>(i), 0.f, 0.f, 0.f);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_B5G6R5_UNORM:
    {
        static const XMVECTORF32 s_Scale = { { { 1.f / 31.f, 1.f / 63.f, 1.f / 31.f, 1.f } } };
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(XMU565)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadU565(reinterpret_cast<const XMU565*>(ptr));
            v = XMVectorMultiply(v, s_Scale);
            if (x2bias)
            {
                XMVECTOR v2 = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                v = XMVectorSelect(v, v2, g_XMSelect1110);
            }
            *buffer++ = XMVectorSwizzle<2, 1, 0, 3>(v);
            ptr += stride;
        }
    }
    break;

    case DXGI_FORMAT_B5G5R5A1_UNORM:
    {
        static const XMVECTORF32 s_Scale = { { { 1.f / 31.f, 1.f / 31.f, 1.f / 31.f, 1.f } } };
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(XMU555)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadU555(reinterpret_cast<const XMU555*>(ptr));
            v = XMVectorMultiply(v, s_Scale);
            if (x2bias)
            {
                XMVECTOR v2 = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                v = XMVectorSelect(v, v2, g_XMSelect1110);
            }
            *buffer++ = XMVectorSwizzle<2, 1, 0, 3>(v);
            ptr += stride;
        }
    }
    break;

    case DXGI_FORMAT_B8G8R8A8_UNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(XMUBYTEN4)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadUByteN4(reinterpret_cast<const XMUBYTEN4*>(ptr));
            if (x2bias)
            {
                v = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
            }
            *buffer++ = XMVectorSwizzle<2, 1, 0, 3>(v);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_B8G8R8X8_UNORM:
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(XMUBYTEN4)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadUByteN4(reinterpret_cast<const XMUBYTEN4*>(ptr));
            if (x2bias)
            {
                XMVECTOR v2 = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
                v = XMVectorSelect(v, v2, g_XMSelect1110);
            }
            v = XMVectorSwizzle<2, 1, 0, 3>(v);
            *buffer++ = XMVectorSelect(g_XMZero, v, g_XMSelect1110);
            ptr += stride;
        }
        break;

    case DXGI_FORMAT_B4G4R4A4_UNORM:
    {
        static const XMVECTORF32 s_Scale = { { { 1.f / 15.f, 1.f / 15.f, 1.f / 15.f, 1.f / 15.f } } };
        for (size_t icount = 0; icount < count; ++icount)
        {
            if ((ptr + sizeof(XMUNIBBLE4)) > eptr)
                return E_UNEXPECTED;
            XMVECTOR v = XMLoadUNibble4(reinterpret_cast<const XMUNIBBLE4*>(ptr));
            v = XMVectorMultiply(v, s_Scale);
            if (x2bias)
            {
                v = XMVectorMultiplyAdd(v, g_XMTwo, g_XMNegativeOne);
            }
            *buffer++ = XMVectorSwizzle<2, 1, 0, 3>(v);
            ptr += stride;
        }
    }
    break;

    case XBOX_DXGI_FORMAT_R10G10B10_SNORM_A2_UNORM:
        // Xbox One specific format
        LOAD_VERTS(XMXDECN4, XMLoadXDecN4)

    default:
        return E_FAIL;
    }

    return S_OK;
}