stride3d/stride · error · NotImplementedException

Unsupported format when converting vertex element

Error message

Unsupported format when converting vertex element ({elementData.VertexElement.Format})

What it means

The typed Read path of VertexBufferHelper converts each vertex element by dispatching on its PixelFormat to an InnerRead<...,TSource,...> instantiation. The supported set is R32G32B32A32_Float, R16G16_Float, R16G16B16A16_Float, R16G16B16A16_UInt, R8G8B8A8_UInt, R8G8B8A8_UNorm; any other format throws NotImplementedException. This is a deliberate guard so element reads never misinterpret raw bytes.

Solutions

  1. Use one of the supported PixelFormats in the vertex declaration
  2. Decode the unsupported element manually from the raw byte data and feed supported data to the helper
  3. Add a new case to the switch mapping the format to an InnerRead instantiation with the matching unmanaged type
  4. Check the format string in the exception message to identify exactly which element/format to fix

Example fix

// before
colorElement = new VertexElement("COLOR", 0, PixelFormat.R8G8B8A8_SNorm, 0); // throws
// after
colorElement = new VertexElement("COLOR", 0, PixelFormat.R8G8B8A8_UNorm, 0); // supported
Defensive patterns

Strategy: validation

Validate before calling

if (!supportedFormats.Contains(elementData.VertexElement.Format)) return false; // skip or pre-convert

Try / catch

try { read = reader.Read<...>(destination); }
catch (NotImplementedException ex) { logger.Error(ex, $"Cannot read element format"); throw; }

Prevention

When it happens

Trigger: Calling Read on a vertex buffer whose element format (elementData.VertexElement.Format) is not among the supported formats, e.g. reading positions stored as R32G32B32_Float or SNorm colors.

Common situations: Reading buffers produced by exporters that use compact formats; platform-specific vertex compression; custom vertex declarations using formats the helper never learned to decode.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/ddb5a4c4be15e1fd. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/VertexBufferHelper.cs:258

        IConverter<Byte4, TDest>,
        IConverter<Color, TDest>,
        ISemantic 
        where TDest : unmanaged
        where TReader : IReader<TDest>, allows ref struct
    {
        if (Binding.Declaration.TryGetElement(TSemantic.Name, semanticIndex, out var elementData))
        {
            switch (elementData.VertexElement.Format)
            {
                case PixelFormat.R32G32_Float: InnerRead<TSemantic, TReader, Vector2, TDest>(destination, reader, elementData); break;
                case PixelFormat.R32G32B32_Float: InnerRead<TSemantic, TReader, Vector3, TDest>(destination, reader, elementData); break;
                case PixelFormat.R32G32B32A32_Float: InnerRead<TSemantic, TReader, Vector4, TDest>(destination, reader, elementData); break;
                case PixelFormat.R16G16_Float: InnerRead<TSemantic, TReader, Half2, TDest>(destination, reader, elementData); break;
                case PixelFormat.R16G16B16A16_Float: InnerRead<TSemantic, TReader, Half4, TDest>(destination, reader, elementData); break;
                case PixelFormat.R16G16B16A16_UInt: InnerRead<TSemantic, TReader, UShort4, TDest>(destination, reader, elementData); break;
                case PixelFormat.R8G8B8A8_UInt: InnerRead<TSemantic, TReader, Byte4, TDest>(destination, reader, elementData); break;
                case PixelFormat.R8G8B8A8_UNorm: InnerRead<TSemantic, TReader, Color, TDest>(destination, reader, elementData); break;
                default: throw new NotImplementedException($"Unsupported format when converting vertex element ({elementData.VertexElement.Format})");
            }

            return true;
        }

        return false;
    }

    private unsafe void InnerRead<TConverter, TReader, TSource, TDest>(Span<TDest> destination, TReader reader, VertexElementWithOffset element) 
        where TConverter : IConverter<TSource, TDest> 
        where TSource : unmanaged
        where TReader : IReader<TDest>, allows ref struct
    {
        if (sizeof(TSource) != element.Size)
            throw new ArgumentException($"{typeof(TSource)} does not match element size ({sizeof(TSource)} != {element.Size})");

        var stride = Binding.Declaration.VertexStride;
        var offset = element.Offset;

View on GitHub (pinned to 96fad776d2)