stride3d/stride · error · NotImplementedException

Not enough generic parameters specified when instantiating

Error message

Not enough generic parameters specified when instantiating {classSource.ToClassNameWithGenerics()}

What it means

While walking the declaring context, an OpGenericParameterSDSL instruction refers to a generic parameter index that is not covered by the generic arguments supplied on the shader instantiation (classSource.GenericArguments). BuildInheritanceListWithoutSelf throws NotImplementedException because the shader class expects more generic parameters than the caller provided.

Solutions

  1. Supply all required generic arguments at the instantiation site, e.g. `MyShader<float, float2>` matching the shader's declared generic parameter count.
  2. Check the shader (and every shader it inherits/mixes) for OpGenericParameterSDSL declarations and count them against your argument list.
  3. Give the generic parameter a default value in the shader source if it should be optional.

Example fix

// before (SDSL)
var x = new MyShader<float>();
// after
var x = new MyShader<float, float2>();
Defensive patterns

Strategy: validation

Validate before calling

int declaredGenericCount = /* count OpGenericParameterSDSL in declaring context */;
if (classSource.GenericArguments.Length < declaredGenericCount)
    throw new ArgumentException($"{classSource.ClassName} needs {declaredGenericCount} generic args, got {classSource.GenericArguments.Length}");

Try / catch

try { builder.BuildInheritanceList(...); }
catch (NotImplementedException ex) { throw new ShaderCompilationException($"Fix generics at instantiation: {ex.Message}", ex); }

Prevention

When it happens

Trigger: Instantiating (e.g. via ShaderClassSource with generics, or a mixin import) a shader whose body declares OpGenericParameterSDSL with Index >= number of supplied generic arguments.

Common situations: Writing `MyShader<>` or `MyShader<float>` in SDSL while the shader (or a parent it inherits) declares two or more generic parameters; copying an instantiation that omitted arguments after a shader gained an extra generic parameter.

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/76e549c4858ae42f. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs:152

public partial class SpirvBuilder
{
    public static void BuildInheritanceListWithoutSelf(IExternalShaderLoader shaderLoader, SpirvContext topLevelContext, ShaderClassInstantiation classSource, ReadOnlySpan<ShaderMacro> macros, SpirvContext declaringContext, List<ShaderClassInstantiation> inheritanceList, ResolveStep resolveStep)
    {
        // Build shader name mapping and collect generic parameter expressions
        var shaderMapping = new Dictionary<int, ShaderClassInstantiation>();
        // Map generic parameter index → resolved expression from classSource
        ConstantExpression[]? resolvedGenericArgs = null;
        string? declaringClassName = null;
        // Also build import-level resolution: map shader name → its import's generic args (as expressions)
        // Used to resolve GenericParamExpr that reference parent shaders' generics
        var importArgsByName = new Dictionary<string, ConstantExpression[]>();

        foreach (var i in declaringContext)
        {
            if (i.Op == Op.OpGenericParameterSDSL && (OpGenericParameterSDSL)i is { } genericParameter)
            {
                if (genericParameter.Index >= classSource.GenericArguments.Length)
                    throw new NotImplementedException($"Not enough generic parameters specified when instantiating {classSource.ToClassNameWithGenerics()}");
                resolvedGenericArgs ??= classSource.GenericArguments;
                declaringClassName ??= genericParameter.DeclaringClass;
            }
            if (i.Op == Op.OpImportShaderSDSL && (OpImportShaderSDSL)i is { } importShader)
            {
                var shaderClassSource = ConvertToShaderClassSource(declaringContext, importShader);
                shaderMapping[importShader.ResultId] = shaderClassSource;
                if (shaderClassSource.GenericArguments.Length > 0)
                    importArgsByName[importShader.ShaderName] = shaderClassSource.GenericArguments;
            }
        }

        ConstantExpression ResolveGenericArg(ConstantExpression arg)
        {
            // First substitute the current shader's own generics
            if (resolvedGenericArgs != null && declaringClassName != null)
                arg = arg.Substitute(declaringClassName, resolvedGenericArgs);
            // Then resolve any remaining GenericParamExpr by looking up parent imports

View on GitHub (pinned to 96fad776d2)