stride3d/stride · error · NotImplementedException

Unsupported format when converting vertex element ({srcDef.V

Error message

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

What it means

When converting vertex elements by semantic (e.g. POSITION), VertexBufferHelper dispatches on the source PixelFormat to pick a typed copy routine. Only a fixed set of formats (R32G32B32A32_Float, R16G16_Float, R16G16B16A16_Float, R16G16B16A16_UInt, R8G8B8A8_UInt, R8G8B8A8_UNorm) is implemented; anything else hits the default case and throws NotImplementedException. This signals the requested source format conversion is simply not implemented in this helper.

Solutions

  1. Re-export or convert the mesh so its vertex elements use one of the supported formats (R32G32B32A32_Float, R16G16_Float, R16G16B16A16_Float, R16G16B16A16_UInt, R8G8B8A8_UInt, R8G8B8A8_UNorm)
  2. Convert the buffer yourself to a supported format (e.g. expand R32G32_Float to R32G32B32A32_Float) before calling the helper
  3. Extend the switch in VertexBufferHelper with a SelectSrcType call for the missing format if you own the code
  4. Inspect srcDef.VertexElement.Format at runtime and log it to identify the exact unsupported format

Example fix

// before
var decl = VertexElement.Layout<PositionColorVertex>(); // uses R32G32_Float position
var helper = new VertexBufferHelper(...); // helper.Convert throws
// after
var decl = new VertexDeclaration(
    new VertexElement("POSITION", 0, PixelFormat.R32G32B32A32_Float, 0)); // supported format
Defensive patterns

Strategy: validation

Validate before calling

static readonly PixelFormat[] supported = { PixelFormat.R32G32B32A32_Float, PixelFormat.R16G16_Float, PixelFormat.R16G16B16A16_Float, PixelFormat.R16G16B16A16_UInt, PixelFormat.R8G8B8A8_UInt, PixelFormat.R8G8B8A8_UNorm };
bool ok = decl.VertexElements.All(e => supported.Contains(e.Format));

Try / catch

try { helper.Convert(...); }
catch (NotImplementedException ex) { logger.Error(ex, "Vertex format unsupported, re-export mesh with supported formats"); throw; }

Prevention

When it happens

Trigger: Calling Convert (semantic-based vertex conversion) with an input declaration whose element format is outside the supported list, e.g. R32G32_Float, R10G10B10A2_UNorm, R16G16B16A16_SNorm or any integer/normalized format not in the switch.

Common situations: Importing meshes saved with a different vertex compression format than the helper supports; switching platform/exporter settings that change vertex formats; assuming the helper supports arbitrary formats like it might for interop with other engines.

Related errors


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

Appendix: source

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

        {
            if (Binding.Declaration.TryGetElement(destDef.VertexElement.SemanticName, destDef.VertexElement.SemanticIndex, out var srcDef))
            {
                var srcOffset = srcDef.Offset;
                var destOffset = destDef.Offset;

                var srcFormat = srcDef.VertexElement.Format;
                switch (destDef.VertexElement.Format)
                {
                    // The particular semantic used doesn't matter too much here, we're just abusing the relaxed definition to fit any TDest
                    case PixelFormat.R32G32_Float: SelectSrcType<Relaxed<PositionSemantic>, Vector2>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R32G32B32_Float: SelectSrcType<Relaxed<PositionSemantic>, Vector3>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R32G32B32A32_Float: SelectSrcType<Relaxed<PositionSemantic>, Vector4>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R16G16_Float: SelectSrcType<Relaxed<PositionSemantic>, Half2>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R16G16B16A16_Float: SelectSrcType<Relaxed<PositionSemantic>, Half4>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R16G16B16A16_UInt: SelectSrcType<Relaxed<PositionSemantic>, UShort4>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R8G8B8A8_UInt: SelectSrcType<Relaxed<PositionSemantic>, Byte4>(parameters, srcOffset, destOffset, srcFormat); break;
                    case PixelFormat.R8G8B8A8_UNorm: SelectSrcType<Relaxed<PositionSemantic>, Color>(parameters, srcOffset, destOffset, srcFormat); break;
                    default: throw new NotImplementedException($"Unsupported format when converting vertex element ({srcDef.VertexElement.Format})");
                }
            }
            else
            {
                missing = true;
            }
        }

        return missing;

        static void SelectSrcType<TSemantic, TOutput>(InterleavedParameters param, int srcElemOffset, int destElemOffset, PixelFormat format) 
            where TSemantic : 
            IConverter<Vector2, TOutput>,
            IConverter<Vector3, TOutput>,
            IConverter<Vector4, TOutput>,
            IConverter<Half2, TOutput>,
            IConverter<Half4, TOutput>,
            IConverter<UShort4, TOutput>,

View on GitHub (pinned to 96fad776d2)