inline bool CreateInputLayoutFromFVF()

in Utilities/FlexibleVertexFormat.h [501:639]


        inline bool CreateInputLayoutFromFVF(uint32_t fvfCode, std::vector<D3D12_INPUT_ELEMENT_DESC>& il)
    {
        static constexpr DXGI_FORMAT s_blendFormats[] =
        {
            DXGI_FORMAT_R32_FLOAT,
            DXGI_FORMAT_R32G32_FLOAT,
            DXGI_FORMAT_R32G32B32_FLOAT,
            DXGI_FORMAT_R32G32B32A32_FLOAT,
        };

        static constexpr DXGI_FORMAT s_texCoordFormats[] =
        {
            DXGI_FORMAT_R32G32_FLOAT,
            DXGI_FORMAT_R32G32B32_FLOAT,
            DXGI_FORMAT_R32G32B32A32_FLOAT,
            DXGI_FORMAT_R32_FLOAT
        };

        il.clear();

        if ((fvfCode & ((D3DFVF_RESERVED0 | D3DFVF_RESERVED2) & ~D3DFVF_POSITION_MASK)) != 0)
            return false;

        uint32_t nTexCoords = (fvfCode & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
        if (nTexCoords > 8)
            return false;

        switch (fvfCode & D3DFVF_POSITION_MASK)
        {
        case 0:
            break;

        case D3DFVF_XYZRHW:
        case D3DFVF_XYZW:
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "SV_Position", 0, DXGI_FORMAT_R32G32B32A32_FLOAT,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
            break;

        default:
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "SV_Position", 0, DXGI_FORMAT_R32G32B32_FLOAT,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
            break;
        }

        size_t weights = 0;
        switch (fvfCode & D3DFVF_POSITION_MASK)
        {
        case D3DFVF_XYZB1: weights = 1; break;
        case D3DFVF_XYZB2: weights = 2; break;
        case D3DFVF_XYZB3: weights = 3; break;
        case D3DFVF_XYZB4: weights = 4; break;
        case D3DFVF_XYZB5: weights = 5; break;
        }

        if (weights > 0)
        {
            if (fvfCode & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR))
            {
                // subtract one for where the blendindices were
                if (weights > 1)
                {
                    il.emplace_back(
                        D3D12_INPUT_ELEMENT_DESC{ "BLENDWEIGHT", 0, s_blendFormats[weights - 2],
                        0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
                    );
                }

                il.emplace_back(
                    D3D12_INPUT_ELEMENT_DESC{ "BLENDINDICES", 0,
                    (fvfCode & D3DFVF_LASTBETA_UBYTE4) ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
                );
            }
            else if (weights == 5)
            {
                // D3DFVF_XYZB5 is only supported when the 5th beta is D3DFVF_LASTBETA_UBYTE4/D3DCOLOR
                il.clear();
                return false;
            }
            else
            {
                il.emplace_back(
                    D3D12_INPUT_ELEMENT_DESC{ "BLENDWEIGHT", 0, s_blendFormats[weights - 1],
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
                );
            }
        }

        if (fvfCode & D3DFVF_NORMAL)
        {
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
        }

        if (fvfCode & D3DFVF_PSIZE)
        {
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "PSIZE", 0, DXGI_FORMAT_R32_FLOAT,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
        }

        if (fvfCode & D3DFVF_DIFFUSE)
        {
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
        }

        if (fvfCode & D3DFVF_SPECULAR)
        {
            il.emplace_back(
                D3D12_INPUT_ELEMENT_DESC{ "COLOR", 1, DXGI_FORMAT_B8G8R8A8_UNORM,
                    0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
            );
        }

        if (nTexCoords > 0)
        {
            for (uint32_t t = 0; t < nTexCoords; ++t)
            {
                size_t index = (fvfCode >> (16 + t * 2)) & 0x3;
                il.emplace_back(
                    D3D12_INPUT_ELEMENT_DESC{ "TEXCOORD", static_cast<UINT>(t),
                        s_texCoordFormats[index],
                        0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
                );
            }
        }

        return true;
    }