stride3d/stride · error · NotSupportedException

Unsupported StreamsKindSDSL for output parameter

Error message

Unsupported StreamsKindSDSL for output parameter: {t.Kind}

What it means

When generating the SPIR-V wrapper, entry-point parameters that are 'out' parameters (like 'out HS_OUTPUT output' or 'out HS_CONSTANTS constants') are mapped to a stream layout member via their StreamsKindSDSL kind. Only Output and Constants kinds are supported; any other kind in an output parameter position throws NotSupportedException.

Solutions

  1. Change the out parameter to use the proper output or constants structure type so its kind resolves to StreamsKindSDSL.Output or StreamsKindSDSL.Constants.
  2. Remove invalid out parameters that are neither the shader output nor the patch-constants struct from the entry-point signature.
  3. If a new kind legitimately needs support, add it to the switch in EntryPointWrapperGenerator.cs:237 mapping it to the correct struct type.
  4. Verify the SDSL parser's kind classification for your parameter type (debug why t.Kind got the unexpected value) before touching the signature.

Example fix

// before
void HSMain(InputPatch<VS_OUTPUT, 3> input, out Streams stream, out HS_CONSTANTS constants) // Streams kind unsupported for out

// after
void HSMain(InputPatch<VS_OUTPUT, 3> input, out HS_OUTPUT output, out HS_CONSTANTS constants)
Defensive patterns

Strategy: type-guard

Validate before calling

// Only Output and Constants kinds are valid as out parameters
static readonly HashSet<StreamsKindSDSL> AllowedOutKinds = new() { StreamsKindSDSL.Output, StreamsKindSDSL.Constants };
bool outKindsValid = entryPoint.Parameters.Where(p => p.IsOut).All(p => AllowedOutKinds.Contains(p.TypeKind));

Type guard

static bool IsSupportedOutKind(StreamsKindSDSL kind) =>
    kind == StreamsKindSDSL.Output || kind == StreamsKindSDSL.Constants;

Try / catch

try
{
    var wrapper = EntryPointWrapperGenerator.GenerateWrapper(...);
}
catch (NotSupportedException ex) when (ex.Message.StartsWith("Unsupported StreamsKindSDSL"))
{
    log.Error($"Entry point uses an out parameter with unsupported stream kind: {ex.Message}");
    throw new ShaderCompilationException("Unsupported out-parameter kind in entry point signature", ex);
}

Prevention

When it happens

Trigger: GenerateWrapper encounters an out parameter whose parsed SDSL type kind is neither StreamsKindSDSL.Output nor StreamsKindSDSL.Constants — e.g. an out parameter typed with a Streams kind, a stream composite, or an unrecognized custom kind in a hull/domain shader signature.

Common situations: Custom SDSL stream types passed as out parameters; mistyped signatures where a Streams struct was accidentally used as an out param; API changes in StreamsKindSDSL introducing kinds the wrapper generator does not yet handle; generator bugs in kind classification for hull-shader parameter structs.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs:237

                                    arguments[i] = constantVariable;
                                    // Copy back values from semantic/builtin variables to Constants struct
                                    foreach (var stream in streamLayout.PatchInputStreams)
                                    {
                                        var inputPtr = buffer.Add(new OpAccessChain(context.GetOrRegister(new PointerType(stream.Info.Type, Specification.StorageClass.Function)), context.Bound++, constantVariable, [context.CompileConstant(stream.Info.StreamStructFieldIndex).Id])).ResultId;
                                        var inputResult = buffer.Add(new OpLoad(context.GetOrRegister(stream.Info.Type), context.Bound++, stream.Id, null, [])).ResultId;
                                        inputResult = BuiltinProcessor.ConvertInterfaceVariable(buffer, context, stream.InterfaceType, stream.Info.Type, inputResult);
                                        buffer.Add(new OpStore(inputPtr, inputResult, null, []));
                                    }
                                    break;
                                }
                            case StreamsType t when t.Kind is StreamsKindSDSL.Output or StreamsKindSDSL.Constants && parameterModifiers == ParameterModifiers.Out:
                                {
                                    // Parameter is "out HS_OUTPUT output" or "out HS_CONSTANTS constants"
                                    var structType = t.Kind switch
                                    {
                                        StreamsKindSDSL.Output => streamLayout.OutputType,
                                        StreamsKindSDSL.Constants => streamLayout.ConstantsType!,
                                        _ => throw new NotSupportedException($"Unsupported StreamsKindSDSL for output parameter: {t.Kind}"),
                                    };
                                    var outVariable = buffer.Insert(variableInsertIndex++, new OpVariable(context.GetOrRegister(new PointerType(structType, Specification.StorageClass.Function)), context.Bound++, Specification.StorageClass.Function, null)).ResultId;
                                    arguments[i] = outVariable;
                                    break;
                                }
                            case var t when arguments[i] == 0:
                                throw new NotImplementedException($"Can't process argument {i + 1} of type {parameterType} in method {entryPoint.Id.Name}");
                        }
                    }
                }

                void ProcessTessellationArguments(Symbol function, Span<int> arguments)
                {
                    var functionType = (FunctionType)function.Type;
                    for (int i = 0; i < functionType.ParameterTypes.Count; i++)
                    {
                        var parameterType = ((PointerType)functionType.ParameterTypes[i].Type).BaseType;
                        var parameterModifiers = functionType.ParameterTypes[i].Modifiers;

View on GitHub (pinned to 96fad776d2)