stride3d/stride · error · InvalidOperationException
InterfaceProcessor: At least a pixel or compute shader is…
Error message
InterfaceProcessor: At least a pixel or compute shader is expected
What it means
During SPIR-V interface processing for a merged shader, InterfaceProcessor.Process resolves entry points (VS/HS/DS/GS/PS/CS) and requires at least one pixel or compute shader entry point. If neither PSMain nor CSMain exists in the symbol table it throws this InvalidOperationException because the stream/interface analysis pipeline is designed around a fragment- or compute-stage terminal shader.
Solutions
- Add a pixel or compute shader mixin (one exposing PSMain or CSMain) to the composed ShaderSource before merging
- Check the effect composition so the terminal fragment/compute class is actually included in the shader chain
- If the stage truly has no PS/CS, bypass InterfaceProcessor.Process or split the merge so stage-only modules are handled separately
Example fix
// before var mixer = new ShaderMixer(); mixer.MergeSDSL(new ShaderSource(typeof(MyVertexOnlyShader)), options, log, out var bytecode, out _, out _, out _); // after var mixer = new ShaderMixer(); mixer.MergeSDSL(new ShaderSource(typeof(MyVertexOnlyShader)).Compose(typeof(MyPixelShader)), options, log, out var bytecode, out _, out _, out _);
Defensive patterns
Strategy: validation
Validate before calling
// before MergeSDSL, ensure a terminal pixel or compute stage exists in the composition
bool hasPixelOrCompute = composition.Classes.Any(c =>
c.GetMethods().Any(m => m.Name is "PSMain" or "CSMain"));
if (!hasPixelOrCompute)
throw new InvalidOperationException("Shader composition must include a pixel (PSMain) or compute (CSMain) stage."); Try / catch
try
{
mixer.MergeSDSL(shaderSource, options, log, out var bytecode, out _, out _, out _);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("At least a pixel or compute shader"))
{
log.Error("Composition lacks a terminal pixel/compute stage: " + ex.Message);
} Prevention
- Always compose effects around a base class that provides PSMain or CSMain
- Write a unit test that compiles each effect composition end-to-end
- Review mixin lists when refactoring shader inheritance chains
When it happens
Trigger: Calling ShaderMixer.MergeSDSL on a composed ShaderSource whose merged SPIR-V contains only vertex/hull/domain/geometry entry points (no PSMain and no CSMain), so ResolveEntryPoint returns null for both.
Common situations: Compiling a shader class chain that ends in a vertex-only or geometry-only stage; forgetting to include the pixel shader mixin in a composition; composing effect shaders where the pixel stage is provided at a later pipeline stage so the merged module legitimately lacks PSMain.
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
- InterfaceProcessor: If a
- Can't cast from to (larger matrix)
- Can't cast from to
- Can't cast from to
- Can't figure array output size for tessellation shader
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/cead8179912abe9c.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/InterfaceProcessor.cs:150
return chain;
}
public Result Process(SymbolTable table, SpirvBuffer buffer, SpirvContext context)
{
// OpEntryPoint emission is deferred to allow fixups (e.g. adding dummy DS inputs for HS-internal outputs)
var entryPoints = new List<EntryPointInfo>();
compositionFunctions = CollectCompositionFunctions(buffer);
var entryPointVS = ResolveEntryPoint(table, "VSMain");
var entryPointHS = ResolveEntryPoint(table, "HSMain");
var entryPointDS = ResolveEntryPoint(table, "DSMain");
var entryPointGS = ResolveEntryPoint(table, "GSMain");
var entryPointPS = ResolveEntryPoint(table, "PSMain");
var entryPointCS = ResolveEntryPoint(table, "CSMain");
var entryPointPSOrCS = entryPointCS ?? entryPointPS ?? throw new InvalidOperationException($"{nameof(InterfaceProcessor)}: At least a pixel or compute shader is expected");
if (entryPointPS == null && entryPointCS == null)
throw new InvalidOperationException($"{nameof(InterfaceProcessor)}: Found both a pixel and a compute shader");
var analysisResult = StreamAnalyzer.Analyze(buffer, context);
VariableMerger.MergeSameSemanticVariables(table, context, buffer, analysisResult);
var streams = analysisResult.Streams;
var liveAnalysis = new LiveAnalysis();
ReadWriteAnalyzer.AnalyzeStreamReadWrites(buffer, context, entryPointPSOrCS.IdRef, analysisResult, liveAnalysis);
if (entryPointCS != null)
{
entryPoints.Add(GenerateStreamWrapper(table, buffer, context, ExecutionModel.GLCompute, entryPointCS, analysisResult, liveAnalysis, false));
}
if (entryPointHS != null || entryPointDS != null)
context.Add(new OpCapability(Capability.Tessellation));
else if (entryPointGS != null)View on GitHub (pinned to 96fad776d2)