stride3d/stride · error · InvalidOperationException

No vertex entry point and no fallback vertex shader

Error message

No vertex entry point and no fallback vertex shader

What it means

Thrown when preparing graphics pipelines: the test's SPIR-V bytecode has no vertex-stage entry point and no fallback vertex shader (fallbackVertexProbe) was supplied. The renderer always needs a vertex stage, either the bytecode's own or the built-in quad passthrough.

Solutions

  1. Pass a fallbackVertexProbe (and fallbackVertexModule) constructed from the built-in quad passthrough SPIR-V when constructing VulkanFrameRenderer.
  2. Check the bytecode actually contains an OpEntryPoint with ExecutionModel Vertex; re-export/recompile the shader with a vertex entry if not.
  3. Route compute-only shaders through Compute() instead of RenderFrame().

Example fix

// before
var renderer = new VulkanFrameRenderer(probe, shaderModule, fragmentFallback: null);
// after
var renderer = new VulkanFrameRenderer(probe, shaderModule, fallbackVertexProbe: quadProbe, fallbackVertexModule: quadModule);
Defensive patterns

Strategy: fallback

Validate before calling

var hasVertex = probe.FindEntryPoint(SpirvProbe.ExecutionModelVertex) != null;
var hasFragment = probe.FindEntryPoint(SpirvProbe.ExecutionModelFragment) != null;
if (!hasFragment || (!hasVertex && fallbackVertexProbe == null))
    throw new InvalidOperationException("RenderFrame requires a fragment entry point and a vertex entry point or fallback");

Try / catch

try { renderer.RenderFrame(output); }
catch (InvalidOperationException ex) when (ex.Message.Contains("entry point"))
{
    // switch to the compute path or supply fallback vertex shader and retry
}

Prevention

When it happens

Trigger: Calling RenderFrame with a probe whose bytecode contains only fragment (or compute) entry points while fallbackVertexProbe is null, so the ?? throw fires before pipeline creation.

Common situations: Testing a fragment-only or compute-only shader through the graphics RenderFrame path; forgetting to pass fallbackVertexProbe/fallbackVertexModule to the renderer constructor; an entry point name mismatch so FindEntryPoint(ExecutionModelVertex) misses a vertex function that exists.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Tests/FrameRenderer.Vulkan.cs:600

        // Quad geometry, same as the D3D11 renderer
        ReadOnlySpan<float> vertices =
        [
            1f,  1f, 0f,  1.0f, 1.0f,
            1f, -1f, 0f,  1.0f, 0.0f,
            -1f,-1f, 0f,  0.0f, 0.0f,
            -1f, 1f, 1f,  0.0f, 1.0f,
        ];
        ReadOnlySpan<uint> indices = [0, 1, 3, 1, 2, 3];
        var (vertexBuffer, _) = CreateHostBuffer((ulong)(vertices.Length * sizeof(float)), VkBufferUsageFlags.VertexBuffer, MemoryMarshal.AsBytes(vertices));
        var (indexBuffer, _) = CreateHostBuffer((ulong)(indices.Length * sizeof(uint)), VkBufferUsageFlags.IndexBuffer, MemoryMarshal.AsBytes(indices));

        // Vertex shader: from the test's bytecode when present, else the quad passthrough
        var vertexProbe = probe;
        var vertexModule = shaderModule;
        var vertexEntryPoint = probe.FindEntryPoint(SpirvProbe.ExecutionModelVertex);
        if (vertexEntryPoint == null)
        {
            vertexProbe = fallbackVertexProbe ?? throw new InvalidOperationException("No vertex entry point and no fallback vertex shader");
            vertexModule = fallbackVertexModule;
            vertexEntryPoint = vertexProbe.FindEntryPoint(SpirvProbe.ExecutionModelVertex);
        }
        var fragmentEntryPoint = probe.FindEntryPoint(SpirvProbe.ExecutionModelFragment)
            ?? throw new InvalidOperationException("No fragment entry point");

        // Vertex attributes: POSITION/TEXCOORD from the quad buffer, other semantics from
        // per-instance single-element buffers built from "stream.SEMANTIC" test parameters
        var bindingDescriptions = new List<VkVertexInputBindingDescription>
        {
            new() { binding = 0, stride = 5 * sizeof(float), inputRate = VkVertexInputRate.Vertex },
        };
        var attributeDescriptions = new List<VkVertexInputAttributeDescription>();
        var vertexBufferHandles = new List<VkBuffer> { vertexBuffer };
        foreach (var (location, semantic) in vertexProbe.GetStageInputs(vertexEntryPoint))
        {
            if (semantic.StartsWith("POSITION", StringComparison.OrdinalIgnoreCase))
            {

View on GitHub (pinned to 96fad776d2)