{"record":{"id":"ac25d465152d9d94","repo":"stride3d/stride","slug":"unsupported-streamskindsdsl-for-output-parameter-t-kind","errorCode":null,"errorMessage":"Unsupported StreamsKindSDSL for output parameter: {t.Kind}","messagePattern":"Unsupported StreamsKindSDSL for output parameter: (.+?)","errorType":"validation","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs","lineNumber":237,"sourceCode":"                                    arguments[i] = constantVariable;\n                                    // Copy back values from semantic/builtin variables to Constants struct\n                                    foreach (var stream in streamLayout.PatchInputStreams)\n                                    {\n                                        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;\n                                        var inputResult = buffer.Add(new OpLoad(context.GetOrRegister(stream.Info.Type), context.Bound++, stream.Id, null, [])).ResultId;\n                                        inputResult = BuiltinProcessor.ConvertInterfaceVariable(buffer, context, stream.InterfaceType, stream.Info.Type, inputResult);\n                                        buffer.Add(new OpStore(inputPtr, inputResult, null, []));\n                                    }\n                                    break;\n                                }\n                            case StreamsType t when t.Kind is StreamsKindSDSL.Output or StreamsKindSDSL.Constants && parameterModifiers == ParameterModifiers.Out:\n                                {\n                                    // Parameter is \"out HS_OUTPUT output\" or \"out HS_CONSTANTS constants\"\n                                    var structType = t.Kind switch\n                                    {\n                                        StreamsKindSDSL.Output => streamLayout.OutputType,\n                                        StreamsKindSDSL.Constants => streamLayout.ConstantsType!,\n                                        _ => throw new NotSupportedException($\"Unsupported StreamsKindSDSL for output parameter: {t.Kind}\"),\n                                    };\n                                    var outVariable = buffer.Insert(variableInsertIndex++, new OpVariable(context.GetOrRegister(new PointerType(structType, Specification.StorageClass.Function)), context.Bound++, Specification.StorageClass.Function, null)).ResultId;\n                                    arguments[i] = outVariable;\n                                    break;\n                                }\n                            case var t when arguments[i] == 0:\n                                throw new NotImplementedException($\"Can't process argument {i + 1} of type {parameterType} in method {entryPoint.Id.Name}\");\n                        }\n                    }\n                }\n\n                void ProcessTessellationArguments(Symbol function, Span<int> arguments)\n                {\n                    var functionType = (FunctionType)function.Type;\n                    for (int i = 0; i < functionType.ParameterTypes.Count; i++)\n                    {\n                        var parameterType = ((PointerType)functionType.ParameterTypes[i].Type).BaseType;\n                        var parameterModifiers = functionType.ParameterTypes[i].Modifiers;","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs#L219-L255","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the out parameter to use the proper output or constants structure type so its kind resolves to StreamsKindSDSL.Output or StreamsKindSDSL.Constants.","Remove invalid out parameters that are neither the shader output nor the patch-constants struct from the entry-point signature.","If a new kind legitimately needs support, add it to the switch in EntryPointWrapperGenerator.cs:237 mapping it to the correct struct type.","Verify the SDSL parser's kind classification for your parameter type (debug why t.Kind got the unexpected value) before touching the signature."],"exampleFix":"// before\nvoid HSMain(InputPatch<VS_OUTPUT, 3> input, out Streams stream, out HS_CONSTANTS constants) // Streams kind unsupported for out\n\n// after\nvoid HSMain(InputPatch<VS_OUTPUT, 3> input, out HS_OUTPUT output, out HS_CONSTANTS constants)","handlingStrategy":"type-guard","validationCode":"// Only Output and Constants kinds are valid as out parameters\nstatic readonly HashSet<StreamsKindSDSL> AllowedOutKinds = new() { StreamsKindSDSL.Output, StreamsKindSDSL.Constants };\nbool outKindsValid = entryPoint.Parameters.Where(p => p.IsOut).All(p => AllowedOutKinds.Contains(p.TypeKind));","typeGuard":"static bool IsSupportedOutKind(StreamsKindSDSL kind) =>\n    kind == StreamsKindSDSL.Output || kind == StreamsKindSDSL.Constants;","tryCatchPattern":"try\n{\n    var wrapper = EntryPointWrapperGenerator.GenerateWrapper(...);\n}\ncatch (NotSupportedException ex) when (ex.Message.StartsWith(\"Unsupported StreamsKindSDSL\"))\n{\n    log.Error($\"Entry point uses an out parameter with unsupported stream kind: {ex.Message}\");\n    throw new ShaderCompilationException(\"Unsupported out-parameter kind in entry point signature\", ex);\n}","preventionTips":["Only pass the shader output struct or patch-constants struct as out parameters; never a Streams composite.","Validate entry-point signatures against allowed out kinds before wrapper generation.","Keep a whitelist mapping signature roles to StreamsKindSDSL values in your shader tooling.","When adding new StreamsKindSDSL members, extend the wrapper generator's switch and add a regression test in the same change."],"tags":["spirv","shader-compilation","unsupported-value","sdsl"],"backgroundTag":"unsupported-enum-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}