{"record":{"id":"7967b7d7331da0b8","repo":"stride3d/stride","slug":"second-parameter-of-geometry-shader-must-be-a","errorCode":null,"errorMessage":"Second parameter of geometry shader must be a GeometryStreamType","messagePattern":"Second parameter of geometry shader must be a GeometryStreamType","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs","lineNumber":358,"sourceCode":"\n                    // Merge block\n                    buffer.Add(new OpLabel(mergeLabel));\n                }\n            }\n            else if (executionModel == ExecutionModel.Geometry)\n            {\n                // Change signature of main() to not use the output Stream anymore\n                // TODO: Check it's really the 2nd parameter\n                SpirvBuilder.FunctionRemoveParameter(context, buffer, entryPoint, 1);\n\n                // Extract and remove execution mode (line, point, triangleadj, etc.)\n                var executionMode = entryPointFunctionType.ParameterTypes[0].Modifiers;\n                if (executionMode == ParameterModifiers.None)\n                    throw new InvalidOperationException(\"Execution mode primitive is missing for first parameter of geometry shader\");\n\n                // Extract output topology from the GeometryStreamType parameter before removing it\n                var outputStreamType = ((PointerType)entryPointFunctionType.ParameterTypes[1].Type).BaseType as GeometryStreamType\n                    ?? throw new InvalidOperationException(\"Second parameter of geometry shader must be a GeometryStreamType\");\n\n                entryPointFunctionType.ParameterTypes[0] = entryPointFunctionType.ParameterTypes[0] with { Modifiers = ParameterModifiers.None };\n                entryPointFunctionType.ParameterTypes.RemoveAt(1);\n\n                context.ReplaceType(entryPointFunctionType, entryPointTypeId);\n                context.Add(new OpExecutionMode(entryPoint.IdRef, executionMode switch\n                {\n                    ParameterModifiers.Point => ExecutionMode.InputPoints,\n                    ParameterModifiers.Line => ExecutionMode.InputLines,\n                    ParameterModifiers.LineAdjacency => ExecutionMode.InputLinesAdjacency,\n                    ParameterModifiers.Triangle => ExecutionMode.Triangles,\n                    ParameterModifiers.TriangleAdjacency => ExecutionMode.InputTrianglesAdjacency,\n                    _ => throw new NotSupportedException($\"Unsupported geometry input execution mode: {executionMode}\"),\n                }, []));\n                context.Add(new OpExecutionMode(entryPoint.IdRef, outputStreamType.Kind switch\n                {\n                    GeometryStreamOutputKindSDSL.Point => ExecutionMode.OutputPoints,\n                    GeometryStreamOutputKindSDSL.Line => ExecutionMode.OutputLineStrip,","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Generation/EntryPointWrapperGenerator.cs#L340-L376","documentation":"For geometry shaders the wrapper generator expects the second entry-point parameter to be a pointer to a GeometryStreamType, from which it extracts the output topology before removing the parameter from the signature. If the cast `... as GeometryStreamType` fails (the parameter's pointee is some other type), this InvalidOperationException is thrown. It is a signature-shape contract: GS entry points must be (primitive-modified input stream, GeometryStreamType output).","triggerScenarios":"Declaring a geometry shader entry point whose second parameter is not a GeometryStreamType — e.g. a plain streams struct, an OutputPatch, a scalar, or parameters reordered so the stream-type parameter is no longer at index 1. Note the generator blindly assumes index 1 (see the 'TODO: Check it's really the 2nd parameter' comment).","commonSituations":"Reordering GS parameters so the input stream comes second; writing a GS-like function in a stage where stream types differ; an SDSL type-resolution regression where GeometryStreamType resolution yields the base struct instead of the stream type.","solutions":["Ensure the second parameter of the geometry entry point is the geometry stream output type (GeometryStreamType) — restore the conventional (input stream, output stream) ordering","Check for parameter reordering in the SDSL source or a preprocessor pass that mutates the signature","If your GS legitimately has a different signature, fix or extend EntryPointWrapperGenerator.GenerateWrapper to locate the GeometryStreamType parameter instead of hardcoding index 1"],"exampleFix":"// before (wrong second parameter type)\nvoid GSMain(line StreamsInputStream inputs, OutputPatch<VertexOutput, 3> patch)\n// after\nvoid GSMain(line StreamsInputStream inputs, TriangleStream<GSOutput> outputStream)","handlingStrategy":"validation","validationCode":"bool secondIsGeometryStream = ((PointerType)entryPointFunctionType.ParameterTypes[1].Type).BaseType is GeometryStreamType;","typeGuard":"static bool IsGeometryStreamParameter(ParameterType p) =>\n    ((PointerType)p.Type).BaseType is GeometryStreamType;","tryCatchPattern":"try { wrapperGen.GenerateWrapper(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"must be a GeometryStreamType\"))\n{\n    // report: GS second parameter is not a GeometryStreamType; check signature ordering\n}","preventionTips":["Keep the conventional GS signature order: (primitive-modified input stream, geometry stream output)","Don't reorder GS parameters; the generator hardcodes parameter index 1","Validate with IsGeometryStreamParameter before running wrapper generation"],"tags":["shader-compilation","spirv","geometry-shader","type-mismatch","signature"],"backgroundTag":"incompatible-source-type","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"}