diff --git a/packages/shader-lab/src/AstNodePool.ts b/packages/shader-lab/src/AstNodePool.ts new file mode 100644 index 0000000000..85e2435a8f --- /dev/null +++ b/packages/shader-lab/src/AstNodePool.ts @@ -0,0 +1,54 @@ +import { IPoolElement } from "@galacean/engine"; + +type Constructor = new (...args: any[]) => T; + +export interface IInitializedPoolElement> { + init(...args: ConstructorParameters): void; +} + +export const AstNodePoolSet: AstNodePool[] = []; +export function clearAllAstNodePool() { + for (let i = 0; i < AstNodePoolSet.length; i++) { + AstNodePoolSet[i].clear(); + } +} + +export class AstNodePool, T extends IPoolElement & IInitializedPoolElement> { + private _type: C; + private _elements: T[]; + private _usedElementCount: number = -1; + + constructor(type: C, initializeCount: number) { + this._type = type; + this._elements = new Array(initializeCount); + for (let i = 0; i < initializeCount; i++) { + this._elements[i] = new type(); + } + AstNodePoolSet.push(this); + } + + garbageCollection(): void { + const elements = this._elements; + for (let i = elements.length - 1; i >= 0; i--) { + elements[i]?.dispose(); + } + elements.length = 0; + } + + get(...args: ConstructorParameters): T { + this._usedElementCount++; + let element: T; + if (this._elements.length === this._usedElementCount) { + element = new this._type(...args); + this._elements.push(element); + } else { + element = this._elements[this._usedElementCount]; + } + element.init(...args); + return element; + } + + clear(): void { + this._usedElementCount = -1; + } +} diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index bb4bae7931..caf399b17c 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -7,6 +7,7 @@ import { ShaderContentParser } from "./contentParser"; // @ts-ignore import { ClearableObjectPool, Logger, ShaderLib, ShaderMacro, ShaderPlatformTarget } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; +import { clearAllAstNodePool } from "./AstNodePool"; export class ShaderLab implements IShaderLab { /** @@ -76,6 +77,7 @@ export class ShaderLab implements IShaderLab { const lexer = new Lexer(ppdContent); const tokens = lexer.tokenize(); + clearAllAstNodePool(); const program = ShaderLab._parser.parse(tokens); const codeGen = backend === ShaderPlatformTarget.GLES100 ? GLES100Visitor.getVisitor() : GLES300Visitor.getVisitor(); @@ -108,7 +110,7 @@ export class ShaderLab implements IShaderLab { const passResult = [] as any; for (const subShader of structInfo.subShaders) { for (const pass of subShader.passes) { - if (!pass.isUsePass) continue; + if (pass.isUsePass) continue; const passInfo = this._parseShaderPass( pass.contents, pass.vertexEntry, diff --git a/packages/shader-lab/src/codeGen/GLES100.ts b/packages/shader-lab/src/codeGen/GLES100.ts index 30841ddcc0..91a87020fb 100644 --- a/packages/shader-lab/src/codeGen/GLES100.ts +++ b/packages/shader-lab/src/codeGen/GLES100.ts @@ -16,7 +16,7 @@ export class GLES100Visitor extends GLESVisitor { override getAttributeDeclare(): ICodeSegment[] { const ret: ICodeSegment[] = []; - for (const [_, item] of VisitorContext.context._referencedAttributeList) { + for (const item of Object.values(VisitorContext.context._referencedAttributeList)) { ret.push({ text: `attribute ${item.typeInfo.typeLexeme} ${item.ident.lexeme};`, index: item.ident.location.start.index @@ -27,7 +27,7 @@ export class GLES100Visitor extends GLESVisitor { override getVaryingDeclare(): ICodeSegment[] { const ret: ICodeSegment[] = []; - for (const [_, item] of VisitorContext.context._referencedVaryingList) { + for (const item of Object.values(VisitorContext.context._referencedVaryingList)) { ret.push({ text: `varying ${item.typeInfo.typeLexeme} ${item.ident.lexeme};`, index: item.ident.location.start.index diff --git a/packages/shader-lab/src/codeGen/GLES300.ts b/packages/shader-lab/src/codeGen/GLES300.ts index 9d64cad7f5..32f8b88653 100644 --- a/packages/shader-lab/src/codeGen/GLES300.ts +++ b/packages/shader-lab/src/codeGen/GLES300.ts @@ -23,7 +23,7 @@ export class GLES300Visitor extends GLESVisitor { override getAttributeDeclare(): ICodeSegment[] { const ret: ICodeSegment[] = []; - for (const [_, item] of VisitorContext.context._referencedAttributeList) { + for (const item of Object.values(VisitorContext.context._referencedAttributeList)) { ret.push({ text: `in ${item.typeInfo.typeLexeme} ${item.ident.lexeme};`, index: item.ident.location.start.index @@ -35,7 +35,9 @@ export class GLES300Visitor extends GLESVisitor { override getVaryingDeclare(): ICodeSegment[] { const ret: ICodeSegment[] = []; const qualifier = VisitorContext.context.stage === EShaderStage.FRAGMENT ? "in" : "out"; - for (const [_, item] of VisitorContext.context._referencedVaryingList) { + const values = Object.values(VisitorContext.context._referencedVaryingList); + for (let i = 0; i < values.length; i++) { + const item = values[i]; ret.push({ text: `${item.qualifier ?? qualifier} ${item.typeInfo.typeLexeme} ${item.ident.lexeme};`, index: item.ident.location.start.index @@ -80,13 +82,13 @@ export class GLES300Visitor extends GLESVisitor { override visitVariableIdentifier(node: ASTNode.VariableIdentifier): string { if (VisitorContext.context.stage === EShaderStage.FRAGMENT && node.lexeme === "gl_FragColor") { - if (!VisitorContext.context._referencedVaryingList.has(V3_GL_FragColor)) { - VisitorContext.context._referencedVaryingList.set(V3_GL_FragColor, { + if (!VisitorContext.context._referencedVaryingList[V3_GL_FragColor]) { + VisitorContext.context._referencedVaryingList[V3_GL_FragColor] = { ident: new Token(ETokenType.ID, V3_GL_FragColor, ShaderLab.createPosition(0, 0, 0)), typeInfo: new SymbolType(EKeyword.VEC4, "vec4"), qualifier: "out", astNode: node - }); + }; } return V3_GL_FragColor; } diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index ce05b3cf02..53a6f1e203 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -109,15 +109,17 @@ export abstract class GLESVisitor extends CodeGenVisitor { ): ICodeSegment[] { const { _referencedGlobals } = VisitorContext.context; - if (lastLength === _referencedGlobals.size) { + if (lastLength === Object.keys(_referencedGlobals).length) { for (const precision of data.globalPrecisions) { textList.push({ text: precision.codeGen(this), index: precision.location.start.index }); } return textList; } - lastLength = _referencedGlobals.size; - for (const [ident, sm] of _referencedGlobals) { + lastLength = Object.keys(_referencedGlobals).length; + for (const ident in _referencedGlobals) { + const sm = _referencedGlobals[ident]; + if (_serialized.has(ident)) continue; _serialized.add(ident); diff --git a/packages/shader-lab/src/codeGen/VisitorContext.ts b/packages/shader-lab/src/codeGen/VisitorContext.ts index 20f78f7496..f537450227 100644 --- a/packages/shader-lab/src/codeGen/VisitorContext.ts +++ b/packages/shader-lab/src/codeGen/VisitorContext.ts @@ -23,9 +23,9 @@ export class VisitorContext { stage: EShaderStage; - _referencedAttributeList: Map = new Map(); - _referencedGlobals: Map = new Map(); - _referencedVaryingList: Map = new Map(); + _referencedAttributeList: Record = Object.create(null); + _referencedGlobals: Record = Object.create(null); + _referencedVaryingList: Record = Object.create(null); _curFn?: ASTNode.FunctionProtoType; @@ -39,9 +39,9 @@ export class VisitorContext { reset() { this.attributeList.length = 0; this.attributeStructs.length = 0; - this._referencedAttributeList.clear(); - this._referencedGlobals.clear(); - this._referencedVaryingList.clear(); + this._referencedAttributeList = Object.create(null); + this._referencedGlobals = Object.create(null); + this._referencedVaryingList = Object.create(null); } isAttributeStruct(type: string) { @@ -53,41 +53,41 @@ export class VisitorContext { } referenceAttribute(ident: string) { - if (this._referencedAttributeList.has(ident)) return; + if (this._referencedAttributeList[ident]) return; const prop = this.attributeList.find((item) => item.ident.lexeme === ident); if (!prop) { Logger.error("referenced attribute not found:", ident); return; } - this._referencedAttributeList.set(ident, prop); + this._referencedAttributeList[ident] = prop; } referenceVarying(ident: string) { - if (this._referencedVaryingList.has(ident)) return; + if (this._referencedVaryingList[ident]) return; const prop = this.varyingStruct?.propList.find((item) => item.ident.lexeme === ident); if (!prop) { Logger.error("referenced varying not found:", ident); return; } - this._referencedVaryingList.set(ident, prop); + this._referencedVaryingList[ident] = prop; } referenceGlobal(ident: string, type: ESymbolType) { - if (this._referencedGlobals.has(ident)) return; + if (this._referencedGlobals[ident]) return; if (type === ESymbolType.FN) { const fnEntries = this._passSymbolTable.getAllFnSymbols(ident); for (let i = 0; i < fnEntries.length; i++) { const key = i === 0 ? ident : ident + i; - this._referencedGlobals.set(key, fnEntries[i]); + this._referencedGlobals[key] = fnEntries[i]; } return; } const sm = this.passSymbolTable.lookup({ ident, symbolType: type }); if (sm) { - this._referencedGlobals.set(ident, sm); + this._referencedGlobals[ident] = sm; } } } diff --git a/packages/shader-lab/src/lalr/CFG.ts b/packages/shader-lab/src/lalr/CFG.ts index 6996ea4e9b..5be62df342 100644 --- a/packages/shader-lab/src/lalr/CFG.ts +++ b/packages/shader-lab/src/lalr/CFG.ts @@ -11,7 +11,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ...GrammarUtils.createProductionWithOptions( ENonTerminal.gs_shader_program, [[ENonTerminal.global_declaration], [ENonTerminal.gs_shader_program, ENonTerminal.global_declaration]], - ASTNode.GLShaderProgram + ASTNode.GLShaderProgram.pool ), ...GrammarUtils.createProductionWithOptions(ENonTerminal.global_declaration, [ @@ -28,7 +28,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.fully_specified_type, ETokenType.ID, ETokenType.SEMICOLON], [ENonTerminal.fully_specified_type, ETokenType.ID, ENonTerminal.array_specifier, ETokenType.SEMICOLON] ], - ASTNode.VariableDeclaration + ASTNode.VariableDeclaration.pool ), ...GrammarUtils.createProductionWithOptions( @@ -76,19 +76,19 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [EKeyword.U_SAMPLER_CUBE], [EKeyword.U_SAMPLER2D_ARRAY] ], - ASTNode.ExtBuiltinTypeSpecifierNonArray + ASTNode.ExtBuiltinTypeSpecifierNonArray.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.type_specifier_nonarray, [[ETokenType.ID], [ENonTerminal.ext_builtin_type_specifier_nonarray]], - ASTNode.TypeSpecifierNonArray + ASTNode.TypeSpecifierNonArray.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.fully_specified_type, [[ENonTerminal.type_specifier], [ENonTerminal.type_qualifier, ENonTerminal.type_specifier]], - ASTNode.FullySpecifiedType + ASTNode.FullySpecifiedType.pool ), ...GrammarUtils.createProductionWithOptions( @@ -97,13 +97,13 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.type_specifier_nonarray], [ENonTerminal.ext_builtin_type_specifier_nonarray, ENonTerminal.array_specifier] ], - ASTNode.TypeSpecifier + ASTNode.TypeSpecifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.type_qualifier, [[ENonTerminal.single_type_qualifier], [ENonTerminal.type_qualifier, ENonTerminal.single_type_qualifier]], - ASTNode.TypeQualifier + ASTNode.TypeQualifier.pool ), ...GrammarUtils.createProductionWithOptions( @@ -115,14 +115,14 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.invariant_qualifier], [EKeyword.PRECISE] ], - ASTNode.SingleTypeQualifier + ASTNode.SingleTypeQualifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.storage_qualifier, [[EKeyword.CONST], [EKeyword.IN], [EKeyword.INOUT], [EKeyword.OUT], [EKeyword.CENTROID]], // #if _EDITOR - ASTNode.StorageQualifier + ASTNode.StorageQualifier.pool // #endif ), @@ -130,7 +130,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.interpolation_qualifier, [[EKeyword.SMOOTH], [EKeyword.FLAT]], // #if _EDITOR - ASTNode.InterpolationQualifier + ASTNode.InterpolationQualifier.pool // #endif ), @@ -138,7 +138,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.invariant_qualifier, [[EKeyword.INVARIANT]], // #if _EDITOR - ASTNode.InvariantQualifier + ASTNode.InvariantQualifier.pool // #endif ), @@ -146,7 +146,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.precision_qualifier, [[EKeyword.HIGHP], [EKeyword.MEDIUMP], [EKeyword.LOWP]], // #if _EDITOR - ASTNode.PrecisionQualifier + ASTNode.PrecisionQualifier.pool // #endif ), @@ -169,13 +169,13 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ETokenType.SEMICOLON ] ], - ASTNode.StructSpecifier + ASTNode.StructSpecifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.struct_declaration_list, [[ENonTerminal.struct_declaration], [ENonTerminal.struct_declaration_list, ENonTerminal.struct_declaration]], - ASTNode.StructDeclarationList + ASTNode.StructDeclarationList.pool ), ...GrammarUtils.createProductionWithOptions( @@ -189,7 +189,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ETokenType.SEMICOLON ] ], - ASTNode.StructDeclaration + ASTNode.StructDeclaration.pool ), ...GrammarUtils.createProductionWithOptions( @@ -198,13 +198,13 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.struct_declarator], [ENonTerminal.struct_declarator_list, ETokenType.COMMA, ENonTerminal.struct_declarator] ], - ASTNode.StructDeclaratorList + ASTNode.StructDeclaratorList.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.struct_declarator, [[ETokenType.ID], [ETokenType.ID, ENonTerminal.array_specifier]], - ASTNode.StructDeclarator + ASTNode.StructDeclarator.pool ), ...GrammarUtils.createProductionWithOptions( @@ -213,13 +213,13 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ETokenType.LEFT_BRACKET, ETokenType.RIGHT_BRACKET], [ETokenType.LEFT_BRACKET, ENonTerminal.integer_constant_expression, ETokenType.RIGHT_BRACKET] ], - ASTNode.ArraySpecifier + ASTNode.ArraySpecifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.integer_constant_expression_operator, [[ETokenType.PLUS], [ETokenType.DASH], [ETokenType.STAR], [ETokenType.SLASH], [ETokenType.PERCENT]], - ASTNode.IntegerConstantExpressionOperator + ASTNode.IntegerConstantExpressionOperator.pool ), ...GrammarUtils.createProductionWithOptions( @@ -238,7 +238,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.variable_identifier ] ], - ASTNode.IntegerConstantExpression + ASTNode.IntegerConstantExpression.pool ), ...GrammarUtils.createProductionWithOptions( @@ -254,7 +254,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ] ], // #if _EDITOR - ASTNode.ConditionalExpression + ASTNode.ConditionalExpression.pool // #endif ), @@ -265,7 +265,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.logical_or_expression, ETokenType.OR_OP, ENonTerminal.logical_xor_expression] ], // #if _EDITOR - ASTNode.LogicalOrExpression + ASTNode.LogicalOrExpression.pool // #endif ), @@ -276,7 +276,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.logical_xor_expression, ETokenType.XOR_OP, ENonTerminal.logical_and_expression] ], // #if _EDITOR - ASTNode.LogicalXorExpression + ASTNode.LogicalXorExpression.pool // #endif ), @@ -287,7 +287,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.logical_and_expression, ETokenType.AND_OP, ENonTerminal.inclusive_or_expression] ], // #if _EDITOR - ASTNode.LogicalAndExpression + ASTNode.LogicalAndExpression.pool // #endif ), @@ -298,7 +298,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.inclusive_or_expression, ETokenType.VERTICAL_BAR, ENonTerminal.exclusive_or_expression] ], // #if _EDITOR - ASTNode.InclusiveOrExpression + ASTNode.InclusiveOrExpression.pool // #endif ), @@ -309,7 +309,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.exclusive_or_expression, ETokenType.CARET, ENonTerminal.and_expression] ], // #if _EDITOR - ASTNode.ExclusiveOrExpression + ASTNode.ExclusiveOrExpression.pool // #endif ), @@ -320,7 +320,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.and_expression, ETokenType.AMPERSAND, ENonTerminal.equality_expression] ], // #if _EDITOR - ASTNode.AndExpression + ASTNode.AndExpression.pool // #endif ), @@ -332,7 +332,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.equality_expression, ETokenType.NE_OP, ENonTerminal.relational_expression] ], // #if _EDITOR - ASTNode.EqualityExpression + ASTNode.EqualityExpression.pool // #endif ), @@ -346,7 +346,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.relational_expression, ETokenType.GE_OP, ENonTerminal.shift_expression] ], // #if _EDITOR - ASTNode.RelationalExpression + ASTNode.RelationalExpression.pool // #endif ), @@ -358,7 +358,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.shift_expression, ETokenType.RIGHT_OP, ENonTerminal.additive_expression] ], // #if _EDITOR - ASTNode.ShiftExpression + ASTNode.ShiftExpression.pool // #endif ), @@ -370,7 +370,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.additive_expression, ETokenType.DASH, ENonTerminal.multiplicative_expression] ], // #if _EDITOR - ASTNode.AdditiveExpression + ASTNode.AdditiveExpression.pool // #endif ), @@ -383,7 +383,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.multiplicative_expression, ETokenType.PERCENT, ENonTerminal.unary_expression] ], // #if _EDITOR - ASTNode.MultiplicativeExpression + ASTNode.MultiplicativeExpression.pool // #endif ), @@ -396,7 +396,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.unary_operator, ENonTerminal.unary_expression] ], // #if _EDITOR - ASTNode.UnaryExpression + ASTNode.UnaryExpression.pool // #endif ), @@ -404,7 +404,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.unary_operator, [[ETokenType.PLUS], [ETokenType.DASH], [ETokenType.BANG], [ETokenType.TILDE]], // #if _EDITOR - ASTNode.UnaryOperator + ASTNode.UnaryOperator.pool // #endif ), @@ -419,7 +419,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.postfix_expression, ETokenType.INC_OP], [ENonTerminal.postfix_expression, ETokenType.DEC_OP] ], - ASTNode.PostfixExpression + ASTNode.PostfixExpression.pool ), ...GrammarUtils.createProductionWithOptions( @@ -432,7 +432,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [EKeyword.FALSE], [ETokenType.LEFT_PAREN, ENonTerminal.expression, ETokenType.RIGHT_PAREN] ], - ASTNode.PrimaryExpression + ASTNode.PrimaryExpression.pool ), ...GrammarUtils.createProductionWithOptions( @@ -441,7 +441,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.assignment_expression], [ENonTerminal.expression, ETokenType.COMMA, ENonTerminal.assignment_expression] ], - ASTNode.Expression + ASTNode.Expression.pool ), ...GrammarUtils.createProductionWithOptions( @@ -450,7 +450,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.conditional_expression], [ENonTerminal.unary_expression, ENonTerminal.assignment_operator, ENonTerminal.assignment_expression] ], - ASTNode.AssignmentExpression + ASTNode.AssignmentExpression.pool ), ...GrammarUtils.createProductionWithOptions( @@ -469,14 +469,14 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ETokenType.OR_ASSIGN] ], // #if _EDITOR - ASTNode.AssignmentOperator + ASTNode.AssignmentOperator.pool // #endif ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_call, [[ENonTerminal.function_call_generic]], - ASTNode.FunctionCall + ASTNode.FunctionCall.pool ), ...GrammarUtils.createProductionWithOptions( @@ -491,7 +491,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.function_identifier, ETokenType.LEFT_PAREN, ETokenType.RIGHT_PAREN], [ENonTerminal.function_identifier, EKeyword.VOID, ETokenType.RIGHT_PAREN] ], - ASTNode.FunctionCallGeneric + ASTNode.FunctionCallGeneric.pool ), ...GrammarUtils.createProductionWithOptions( @@ -500,37 +500,37 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.assignment_expression], [ENonTerminal.function_call_parameter_list, ETokenType.COMMA, ENonTerminal.assignment_expression] ], - ASTNode.FunctionCallParameterList + ASTNode.FunctionCallParameterList.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_identifier, [[ENonTerminal.type_specifier]], - ASTNode.FunctionIdentifier + ASTNode.FunctionIdentifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_definition, [[ENonTerminal.function_prototype, ENonTerminal.compound_statement_no_scope]], - ASTNode.FunctionDefinition + ASTNode.FunctionDefinition.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_prototype, [[ENonTerminal.function_declarator, ETokenType.RIGHT_PAREN]], - ASTNode.FunctionProtoType + ASTNode.FunctionProtoType.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_declarator, [[ENonTerminal.function_header], [ENonTerminal.function_header, ENonTerminal.function_parameter_list]], - ASTNode.FunctionDeclarator + ASTNode.FunctionDeclarator.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.function_header, [[ENonTerminal.fully_specified_type, ETokenType.ID, ETokenType.LEFT_PAREN]], - ASTNode.FunctionHeader + ASTNode.FunctionHeader.pool ), ...GrammarUtils.createProductionWithOptions( @@ -539,13 +539,13 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.parameter_declaration], [ENonTerminal.function_parameter_list, ETokenType.COMMA, ENonTerminal.parameter_declaration] ], - ASTNode.FunctionParameterList + ASTNode.FunctionParameterList.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.parameter_declaration, [[ENonTerminal.type_qualifier, ENonTerminal.parameter_declarator], [ENonTerminal.parameter_declarator]], - ASTNode.ParameterDeclaration + ASTNode.ParameterDeclaration.pool ), ...GrammarUtils.createProductionWithOptions( @@ -554,20 +554,20 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.type_specifier, ETokenType.ID], [ENonTerminal.type_specifier, ETokenType.ID, ENonTerminal.array_specifier] ], - ASTNode.ParameterDeclarator + ASTNode.ParameterDeclarator.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.statement_list, [[ENonTerminal.statement], [ENonTerminal.statement_list, ENonTerminal.statement]], - ASTNode.StatementList + ASTNode.StatementList.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.statement, [[ENonTerminal.compound_statement], [ENonTerminal.simple_statement]], // #if _EDITOR - ASTNode.Statement + ASTNode.Statement.pool // #endif ), @@ -577,7 +577,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ETokenType.LEFT_BRACE, ETokenType.RIGHT_BRACE], [ETokenType.LEFT_BRACE, ENonTerminal.statement_list, ETokenType.RIGHT_BRACE] ], - ASTNode.CompoundStatementNoScope + ASTNode.CompoundStatementNoScope.pool ), ...GrammarUtils.createProductionWithOptions( @@ -587,7 +587,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.scope_brace, ENonTerminal.statement_list, ENonTerminal.scope_end_brace] ], // #if _EDITOR - ASTNode.CompoundStatement + ASTNode.CompoundStatement.pool // #endif ), @@ -601,7 +601,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.jump_statement] ], // #if _EDITOR - ASTNode.SimpleStatement + ASTNode.SimpleStatement.pool // #endif ), @@ -619,7 +619,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.type_qualifier, ETokenType.ID, ETokenType.SEMICOLON], [ENonTerminal.type_qualifier, ETokenType.ID, ENonTerminal.identifier_list, ETokenType.SEMICOLON] ], - ASTNode.Declaration + ASTNode.Declaration.pool ), ...GrammarUtils.createProductionWithOptions( @@ -628,7 +628,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ETokenType.COMMA, ETokenType.ID], [ENonTerminal.identifier_list, ETokenType.COMMA, ETokenType.ID] ], - ASTNode.IdentifierList + ASTNode.IdentifierList.pool ), ...GrammarUtils.createProductionWithOptions( @@ -647,7 +647,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ], [ENonTerminal.init_declarator_list, ETokenType.COMMA, ETokenType.ID, ETokenType.EQUAL, ENonTerminal.initializer] ], - ASTNode.InitDeclaratorList + ASTNode.InitDeclaratorList.pool ), ...GrammarUtils.createProductionWithOptions( @@ -664,7 +664,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ], [ENonTerminal.fully_specified_type, ETokenType.ID, ETokenType.EQUAL, ENonTerminal.initializer] ], - ASTNode.SingleDeclaration + ASTNode.SingleDeclaration.pool ), ...GrammarUtils.createProductionWithOptions( @@ -674,7 +674,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ETokenType.LEFT_BRACE, ENonTerminal.initializer_list, ETokenType.RIGHT_BRACE] ], // #if _EDITOR - ASTNode.Initializer + ASTNode.Initializer.pool // #endif ), @@ -682,7 +682,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.initializer_list, [[ENonTerminal.initializer], [ENonTerminal.initializer_list, ETokenType.COMMA, ENonTerminal.initializer]], // #if _EDITOR - ASTNode.InitializerList + ASTNode.InitializerList.pool // #endif ), @@ -690,7 +690,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.expression_statement, [[ETokenType.SEMICOLON], [ENonTerminal.expression, ETokenType.SEMICOLON]], // #if _EDITOR - ASTNode.ExpressionStatement + ASTNode.ExpressionStatement.pool // #endif ), @@ -710,7 +710,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ] ], // #if _EDITOR - ASTNode.SelectionStatement + ASTNode.SelectionStatement.pool // #endif ), @@ -728,7 +728,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ] ], // #if _EDITOR - ASTNode.IterationStatement + ASTNode.IterationStatement.pool // #endif ), @@ -742,14 +742,14 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ETokenType.SEMICOLON ] ], - ASTNode.PrecisionSpecifier + ASTNode.PrecisionSpecifier.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.for_init_statement, [[ENonTerminal.expression_statement], [ENonTerminal.declaration]], // #if _EDITOR - ASTNode.ForInitStatement + ASTNode.ForInitStatement.pool // #endif ), @@ -760,7 +760,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.fully_specified_type, ETokenType.ID, ETokenType.EQUAL, ENonTerminal.initializer] ], // #if _EDITOR - ASTNode.Condition + ASTNode.Condition.pool // #endif ), @@ -771,7 +771,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [ENonTerminal.conditionopt, ETokenType.SEMICOLON, ENonTerminal.expression] ], // #if _EDITOR - ASTNode.ForRestStatement + ASTNode.ForRestStatement.pool // #endif ), @@ -779,7 +779,7 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ ENonTerminal.conditionopt, [[ETokenType.EPSILON], [ENonTerminal.condition]], // #if _EDITOR - ASTNode.ConditionOpt + ASTNode.ConditionOpt.pool // #endif ), @@ -792,21 +792,25 @@ const productionAndRules: [GrammarSymbol[], TranslationRule | undefined][] = [ [EKeyword.RETURN, ENonTerminal.expression, ETokenType.SEMICOLON], [EKeyword.DISCARD, ETokenType.SEMICOLON] ], - ASTNode.JumpStatement + ASTNode.JumpStatement.pool ), - ...GrammarUtils.createProductionWithOptions(ENonTerminal.scope_brace, [[ETokenType.LEFT_BRACE]], ASTNode.ScopeBrace), + ...GrammarUtils.createProductionWithOptions( + ENonTerminal.scope_brace, + [[ETokenType.LEFT_BRACE]], + ASTNode.ScopeBrace.pool + ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.scope_end_brace, [[ETokenType.RIGHT_BRACE]], - ASTNode.ScopeEndBrace + ASTNode.ScopeEndBrace.pool ), ...GrammarUtils.createProductionWithOptions( ENonTerminal.variable_identifier, [[ETokenType.ID]], - ASTNode.VariableIdentifier + ASTNode.VariableIdentifier.pool ) ]; diff --git a/packages/shader-lab/src/lalr/Utils.ts b/packages/shader-lab/src/lalr/Utils.ts index 8c0ec62cde..ea7b956e48 100644 --- a/packages/shader-lab/src/lalr/Utils.ts +++ b/packages/shader-lab/src/lalr/Utils.ts @@ -1,11 +1,12 @@ import { EKeyword, ETokenType, ShaderRange } from "../common"; -import { ASTNode } from "../parser/AST"; +import { ASTNode, TreeNode } from "../parser/AST"; import { TranslationRule } from "../parser/SemanticAnalyzer"; import { ASTNodeConstructor } from "../parser/types"; import { ENonTerminal, GrammarSymbol } from "../parser/GrammarSymbol"; import Production from "./Production"; import { ActionInfo, EAction } from "./types"; import { ShaderLab } from "../ShaderLab"; +import { AstNodePool } from "../AstNodePool"; export default class GrammarUtils { static isTerminal(sm: GrammarSymbol) { @@ -23,18 +24,19 @@ export default class GrammarUtils { goal: ENonTerminal, options: GrammarSymbol[][], /** the ast node */ - astType?: ASTNodeConstructor + // astType?: ASTNodeConstructor + astTypePool?: AstNodePool ) { const ret: [GrammarSymbol[], TranslationRule | undefined][] = []; for (const opt of options) { ret.push([ [goal, ...opt], - (sa, ...children) => { + function (sa, ...children) { if (!children[0]) return; const start = children[0].location.start; const end = children[children.length - 1].location.end; const location = ShaderLab.createRange(start, end); - ASTNode.create(astType ?? ASTNode.TrivialNode, sa, location, children); + ASTNode.get(astTypePool ?? ASTNode.TrivialNode.pool, sa, location, children); } ]); } diff --git a/packages/shader-lab/src/parser/AST.ts b/packages/shader-lab/src/parser/AST.ts index 63917df91c..b3f0fd5d13 100644 --- a/packages/shader-lab/src/parser/AST.ts +++ b/packages/shader-lab/src/parser/AST.ts @@ -10,18 +10,38 @@ import { ShaderData } from "./ShaderInfo"; import { ESymbolType, FnSymbol, StructSymbol, VarSymbol } from "./symbolTable"; import { ParserUtils } from "../Utils"; import { ASTNodeConstructor, IParamInfo, NodeChild, StructProp, SymbolType } from "./types"; +import { AstNodePool, IInitializedPoolElement } from "../AstNodePool"; +import { IPoolElement } from "@galacean/engine"; -export class TreeNode { +export abstract class TreeNode + implements IPoolElement, IInitializedPoolElement TreeNode> +{ /** The non-terminal in grammar. */ readonly nt: ENonTerminal; - readonly children: NodeChild[]; - readonly location: ShaderRange; + private _children: NodeChild[]; + private _location: ShaderRange; + + get children() { + return this._children; + } + + get location() { + return this._location; + } + constructor(nt: ENonTerminal, loc: ShaderRange, children: NodeChild[]) { this.nt = nt; - this.location = loc; - this.children = children; + this._location = loc; + this._children = children; + } + + init(loc: ShaderRange, children: NodeChild[]) { + this._location = loc; + this._children = children; } + dispose(): void {} + // Visitor pattern interface for code generation codeGen(visitor: CodeGenVisitor) { return visitor.defaultCodeGen(this.children); @@ -38,20 +58,28 @@ export namespace ASTNode { throw "not token"; } - export function create(target: ASTNodeConstructor, sa: SematicAnalyzer, loc: ShaderRange, children: NodeChild[]) { - const node = Reflect.construct(target, [loc, children]); + export function get( + pool: AstNodePool, + sa: SematicAnalyzer, + loc: ShaderRange, + children: NodeChild[] + ) { + const node = pool.get(loc, children); node.semanticAnalyze(sa); sa.semanticStack.push(node); - return node; } export class TrivialNode extends TreeNode { + static pool = new AstNodePool(TrivialNode, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal._ignore, loc, children); } } export class ScopeBrace extends TreeNode { + static pool = new AstNodePool(ScopeBrace, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.scope_brace, loc, children); } @@ -62,6 +90,8 @@ export namespace ASTNode { } export class ScopeEndBrace extends TreeNode { + static pool = new AstNodePool(ScopeEndBrace, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.scope_end_brace, loc, children); } @@ -72,6 +102,8 @@ export namespace ASTNode { } export class JumpStatement extends TreeNode { + static pool = new AstNodePool(JumpStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.jump_statement, loc, children); } @@ -91,42 +123,56 @@ export namespace ASTNode { // #if _EDITOR export class ConditionOpt extends TreeNode { + static pool = new AstNodePool(ConditionOpt, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.conditionopt, loc, children); } } export class ForRestStatement extends TreeNode { + static pool = new AstNodePool(ForRestStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.for_rest_statement, loc, children); } } export class Condition extends TreeNode { + static pool = new AstNodePool(Condition, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.condition, loc, children); } } export class ForInitStatement extends TreeNode { + static pool = new AstNodePool(ForInitStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.for_init_statement, loc, children); } } export class IterationStatement extends TreeNode { + static pool = new AstNodePool(IterationStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.iteration_statement, loc, children); } } export class SelectionStatement extends TreeNode { + static pool = new AstNodePool(SelectionStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.selection_statement, loc, children); } } export class ExpressionStatement extends TreeNode { + static pool = new AstNodePool(ExpressionStatement, 10); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.expression_statement, loc, children); } @@ -145,10 +191,17 @@ export namespace ASTNode { constructor(nt: ENonTerminal, loc: ShaderRange, children: NodeChild[]) { super(nt, loc, children); } + + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); + this._type = undefined; + } } // #if _EDITOR export class InitializerList extends ExpressionAstNode { + static pool = new AstNodePool(InitializerList, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.initializer_list, loc, children); } @@ -160,6 +213,8 @@ export namespace ASTNode { } export class Initializer extends ExpressionAstNode { + static pool = new AstNodePool(Initializer, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.initializer, loc, children); } @@ -175,6 +230,8 @@ export namespace ASTNode { // #endif export class SingleDeclaration extends TreeNode { + static pool = new AstNodePool(SingleDeclaration, 5); + typeSpecifier: TypeSpecifier; arraySpecifier?: ArraySpecifier; @@ -182,6 +239,12 @@ export namespace ASTNode { super(ENonTerminal.single_declaration, loc, children); } + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); + this.typeSpecifier = undefined; + this.arraySpecifier = undefined; + } + override semanticAnalyze(sa: SematicAnalyzer): void { const fullyType = this.children[0] as FullySpecifiedType; const id = this.children[1] as Token; @@ -210,6 +273,8 @@ export namespace ASTNode { } export class FullySpecifiedType extends TreeNode { + static pool = new AstNodePool(FullySpecifiedType, 5); + get qualifierList() { if (this.children.length > 1) { return (this.children[0]).qualifierList; @@ -230,6 +295,8 @@ export namespace ASTNode { } export class TypeQualifier extends TreeNode { + static pool = new AstNodePool(TypeQualifier, 5); + qualifierList: EKeyword[]; constructor(loc: ShaderRange, children: NodeChild[]) { @@ -249,6 +316,8 @@ export namespace ASTNode { } export class SingleTypeQualifier extends TreeNode { + static pool = new AstNodePool(SingleTypeQualifier, 5); + qualifier: EKeyword; lexeme: string; @@ -269,7 +338,9 @@ export namespace ASTNode { } abstract class BasicTypeQualifier extends TreeNode { - qualifier: EKeyword; + get qualifier(): EKeyword { + return (this.children[0]).type as EKeyword; + } get lexeme(): string { return (this.children[0]).lexeme; } @@ -277,32 +348,36 @@ export namespace ASTNode { constructor(loc: ShaderRange, nt: ENonTerminal, children: NodeChild[]) { super(nt, loc, children); } - - override semanticAnalyze(sa: SematicAnalyzer): void { - this.qualifier = (this.children[0]).type as EKeyword; - } } // #if _EDITOR export class StorageQualifier extends BasicTypeQualifier { + static pool = new AstNodePool(StorageQualifier, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(loc, ENonTerminal.storage_qualifier, children); } } export class PrecisionQualifier extends BasicTypeQualifier { + static pool = new AstNodePool(PrecisionQualifier, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(loc, ENonTerminal.precision_qualifier, children); } } export class InterpolationQualifier extends BasicTypeQualifier { + static pool = new AstNodePool(InterpolationQualifier, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(loc, ENonTerminal.interpolation_qualifier, children); } } export class InvariantQualifier extends BasicTypeQualifier { + static pool = new AstNodePool(InvariantQualifier, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(loc, ENonTerminal.invariant_qualifier, children); } @@ -310,9 +385,17 @@ export namespace ASTNode { // #endif export class TypeSpecifier extends TreeNode { - type: GalaceanDataType; - lexeme: string; - arraySize?: number; + static pool = new AstNodePool(TypeSpecifier, 10); + + get type(): GalaceanDataType { + return (this.children![0] as TypeSpecifierNonArray).type; + } + get lexeme(): string { + return (this.children![0] as TypeSpecifierNonArray).lexeme; + } + get arraySize(): number { + return (this.children?.[1] as ArraySpecifier)?.size; + } get isCustom() { return typeof this.type === "string"; @@ -321,28 +404,24 @@ export namespace ASTNode { constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.type_specifier, loc, children); } - - override semanticAnalyze(sa: SematicAnalyzer): void { - this.type = (this.children![0] as TypeSpecifierNonArray).type; - this.arraySize = (this.children?.[1] as ArraySpecifier)?.size; - this.lexeme = (this.children![0] as TypeSpecifierNonArray).lexeme; - } } export class ArraySpecifier extends TreeNode { - size?: number; + static pool = new AstNodePool(ArraySpecifier, 5); - constructor(loc: ShaderRange, children: NodeChild[]) { - super(ENonTerminal.array_specifier, loc, children); + get size(): number | undefined { + const integerConstantExpr = this.children[1] as IntegerConstantExpression; + return integerConstantExpr.value; } - override semanticAnalyze(sa: SematicAnalyzer): void { - const integerConstantExpr = this.children[1] as IntegerConstantExpression; - this.size = integerConstantExpr.value; + constructor(loc: ShaderRange, children: NodeChild[]) { + super(ENonTerminal.array_specifier, loc, children); } } export class IntegerConstantExpressionOperator extends TreeNode { + static pool = new AstNodePool(IntegerConstantExpressionOperator, 10); + compute: (a: number, b: number) => number; get lexeme(): string { return (this.children[0] as Token).lexeme; @@ -377,11 +456,18 @@ export namespace ASTNode { } export class IntegerConstantExpression extends TreeNode { + static pool = new AstNodePool(IntegerConstantExpression, 5); + value?: number; constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.integer_constant_expression, loc, children); } + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); + this.value = undefined; + } + override semanticAnalyze(sa: SematicAnalyzer): void { if (this.children.length === 1) { const child = this.children[0]; @@ -405,14 +491,17 @@ export namespace ASTNode { } export class TypeSpecifierNonArray extends TreeNode { + static pool = new AstNodePool(TypeSpecifierNonArray, 5); + type: GalaceanDataType; lexeme: string; constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.type_specifier_nonarray, loc, children); } - override semanticAnalyze(sa: SematicAnalyzer): void { - const tt = this.children[0]; + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); + const tt = children[0]; if (tt instanceof Token) { this.type = tt.lexeme; this.lexeme = tt.lexeme; @@ -424,11 +513,17 @@ export namespace ASTNode { } export class ExtBuiltinTypeSpecifierNonArray extends TreeNode { + static pool = new AstNodePool(ExtBuiltinTypeSpecifierNonArray, 5); + type: TokenType; lexeme: string; constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.ext_builtin_type_specifier_nonarray, loc, children); + } + + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); const token = this.children[0] as Token; this.type = token.type; this.lexeme = token.lexeme; @@ -436,6 +531,8 @@ export namespace ASTNode { } export class InitDeclaratorList extends TreeNode { + static pool = new AstNodePool(InitDeclaratorList, 5); + get typeInfo(): SymbolType { if (this.children.length === 1) { const singleDecl = this.children[0] as SingleDeclaration; @@ -477,6 +574,8 @@ export namespace ASTNode { } export class IdentifierList extends TreeNode { + static pool = new AstNodePool(IdentifierList, 5); + get idList(): Token[] { if (this.children.length === 2) { return [this.children[1] as Token]; @@ -490,6 +589,8 @@ export namespace ASTNode { } export class Declaration extends TreeNode { + static pool = new AstNodePool(Declaration, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.declaration, loc, children); } @@ -500,6 +601,8 @@ export namespace ASTNode { } export class FunctionProtoType extends TreeNode { + static pool = new AstNodePool(FunctionProtoType, 5); + private get declarator() { return this.children[0] as FunctionDeclarator; } @@ -530,6 +633,8 @@ export namespace ASTNode { } export class FunctionDeclarator extends TreeNode { + static pool = new AstNodePool(FunctionDeclarator, 5); + private get header() { return this.children[0] as FunctionHeader; } @@ -560,6 +665,8 @@ export namespace ASTNode { } export class FunctionHeader extends TreeNode { + static pool = new AstNodePool(FunctionHeader, 5); + get ident() { return this.children[1] as Token; } @@ -581,6 +688,8 @@ export namespace ASTNode { } export class FunctionParameterList extends TreeNode { + static pool = new AstNodePool(FunctionParameterList, 5); + get parameterInfoList(): IParamInfo[] { if (this.children.length === 1) { const decl = this.children[0] as ParameterDeclaration; @@ -612,6 +721,8 @@ export namespace ASTNode { } export class ParameterDeclaration extends TreeNode { + static pool = new AstNodePool(ParameterDeclaration, 5); + get typeQualifier() { if (this.children.length === 2) return this.children[0] as TypeQualifier; } @@ -646,6 +757,8 @@ export namespace ASTNode { } export class ParameterDeclarator extends TreeNode { + static pool = new AstNodePool(ParameterDeclarator, 5); + get ident() { return this.children[1] as Token; } @@ -663,12 +776,16 @@ export namespace ASTNode { // #if _EDITOR export class SimpleStatement extends TreeNode { + static pool = new AstNodePool(SimpleStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.simple_statement, loc, children); } } export class CompoundStatement extends TreeNode { + static pool = new AstNodePool(CompoundStatement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.compound_statement, loc, children); } @@ -676,6 +793,8 @@ export namespace ASTNode { // #endif export class CompoundStatementNoScope extends TreeNode { + static pool = new AstNodePool(CompoundStatementNoScope, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.compound_statement_no_scope, loc, children); } @@ -683,6 +802,8 @@ export namespace ASTNode { // #if _EDITOR export class Statement extends TreeNode { + static pool = new AstNodePool(Statement, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.statement, loc, children); } @@ -690,6 +811,8 @@ export namespace ASTNode { // #endif export class StatementList extends TreeNode { + static pool = new AstNodePool(StatementList, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.statement_list, loc, children); } @@ -700,6 +823,8 @@ export namespace ASTNode { } export class FunctionDefinition extends TreeNode { + static pool = new AstNodePool(FunctionDefinition, 5); + get protoType() { return this.children[0] as FunctionProtoType; } @@ -724,6 +849,8 @@ export namespace ASTNode { } export class FunctionCall extends ExpressionAstNode { + static pool = new AstNodePool(FunctionCall, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.function_call, loc, children); } @@ -738,12 +865,19 @@ export namespace ASTNode { } export class FunctionCallGeneric extends ExpressionAstNode { + static pool = new AstNodePool(FunctionCallGeneric, 5); + fnSymbol: FnSymbol | StructSymbol | undefined; constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.function_call_generic, loc, children); } + override init(loc: ShaderRange, children: NodeChild[]): void { + super.init(loc, children); + this.fnSymbol = undefined; + } + override semanticAnalyze(sa: SematicAnalyzer): void { const functionIdentifier = this.children[0] as FunctionIdentifier; if (functionIdentifier.isBuiltin) { @@ -780,6 +914,8 @@ export namespace ASTNode { } export class FunctionCallParameterList extends TreeNode { + static pool = new AstNodePool(FunctionCallParameterList, 5); + get paramSig(): GalaceanDataType[] | undefined { if (this.children.length === 1) { const expr = this.children[0] as AssignmentExpression; @@ -813,6 +949,8 @@ export namespace ASTNode { } export class PrecisionSpecifier extends TreeNode { + static pool = new AstNodePool(PrecisionSpecifier, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.precision_specifier, loc, children); } @@ -823,6 +961,8 @@ export namespace ASTNode { } export class FunctionIdentifier extends TreeNode { + static pool = new AstNodePool(FunctionIdentifier, 5); + get ident() { const ty = this.children[0] as TypeSpecifier; return ty.type; @@ -849,6 +989,8 @@ export namespace ASTNode { } export class AssignmentExpression extends ExpressionAstNode { + static pool = new AstNodePool(AssignmentExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.assignment_expression, loc, children); } @@ -868,6 +1010,8 @@ export namespace ASTNode { // #if _EDITOR export class AssignmentOperator extends TreeNode { + static pool = new AstNodePool(AssignmentOperator, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.assignment_operator, loc, children); } @@ -875,6 +1019,8 @@ export namespace ASTNode { // #endif export class Expression extends ExpressionAstNode { + static pool = new AstNodePool(Expression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.expression, loc, children); } @@ -893,6 +1039,8 @@ export namespace ASTNode { } export class PrimaryExpression extends ExpressionAstNode { + static pool = new AstNodePool(PrimaryExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.primary_expression, loc, children); } @@ -924,6 +1072,8 @@ export namespace ASTNode { } export class PostfixExpression extends ExpressionAstNode { + static pool = new AstNodePool(PostfixExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.postfix_expression, loc, children); } @@ -942,6 +1092,8 @@ export namespace ASTNode { // #if _EDITOR export class UnaryOperator extends TreeNode { + static pool = new AstNodePool(UnaryOperator, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.unary_operator, loc, children); } @@ -950,6 +1102,8 @@ export namespace ASTNode { // #if _EDITOR export class UnaryExpression extends ExpressionAstNode { + static pool = new AstNodePool(UnaryExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.unary_expression, loc, children); } @@ -962,6 +1116,8 @@ export namespace ASTNode { // #if _EDITOR export class MultiplicativeExpression extends ExpressionAstNode { + static pool = new AstNodePool(MultiplicativeExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.multiplicative_expression, loc, children); } @@ -982,6 +1138,8 @@ export namespace ASTNode { // #if _EDITOR export class AdditiveExpression extends ExpressionAstNode { + static pool = new AstNodePool(AdditiveExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.additive_expression, loc, children); } @@ -1002,6 +1160,8 @@ export namespace ASTNode { // #if _EDITOR export class ShiftExpression extends ExpressionAstNode { + static pool = new AstNodePool(ShiftExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.shift_expression, loc, children); } @@ -1015,6 +1175,8 @@ export namespace ASTNode { // #if _EDITOR export class RelationalExpression extends ExpressionAstNode { + static pool = new AstNodePool(RelationalExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.relational_expression, loc, children); } @@ -1031,6 +1193,8 @@ export namespace ASTNode { // #if _EDITOR export class EqualityExpression extends ExpressionAstNode { + static pool = new AstNodePool(EqualityExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.equality_expression, loc, children); } @@ -1047,6 +1211,8 @@ export namespace ASTNode { // #if _EDITOR export class AndExpression extends ExpressionAstNode { + static pool = new AstNodePool(AndExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.and_expression, loc, children); } @@ -1063,6 +1229,8 @@ export namespace ASTNode { // #if _EDITOR export class ExclusiveOrExpression extends ExpressionAstNode { + static pool = new AstNodePool(ExclusiveOrExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.exclusive_or_expression, loc, children); } @@ -1079,6 +1247,8 @@ export namespace ASTNode { // #if _EDITOR export class InclusiveOrExpression extends ExpressionAstNode { + static pool = new AstNodePool(InclusiveOrExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.inclusive_or_expression, loc, children); } @@ -1095,6 +1265,8 @@ export namespace ASTNode { // #if _EDITOR export class LogicalAndExpression extends ExpressionAstNode { + static pool = new AstNodePool(LogicalAndExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.logical_and_expression, loc, children); } @@ -1111,6 +1283,8 @@ export namespace ASTNode { // #if _EDITOR export class LogicalXorExpression extends ExpressionAstNode { + static pool = new AstNodePool(LogicalXorExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.logical_xor_expression, loc, children); } @@ -1127,6 +1301,8 @@ export namespace ASTNode { // #if _EDITOR export class LogicalOrExpression extends ExpressionAstNode { + static pool = new AstNodePool(LogicalOrExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.logical_or_expression, loc, children); } @@ -1143,6 +1319,8 @@ export namespace ASTNode { // #if _EDITOR export class ConditionalExpression extends ExpressionAstNode { + static pool = new AstNodePool(ConditionalExpression, 5); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.conditional_expression, loc, children); } @@ -1156,6 +1334,8 @@ export namespace ASTNode { // #endif export class StructSpecifier extends TreeNode { + static pool = new AstNodePool(StructSpecifier, 5); + ident?: Token; get propList(): StructProp[] { @@ -1176,6 +1356,8 @@ export namespace ASTNode { } export class StructDeclarationList extends TreeNode { + static pool = new AstNodePool(StructDeclarationList, 5); + get propList(): StructProp[] { if (this.children.length === 1) { return (this.children[0]).propList; @@ -1191,6 +1373,8 @@ export namespace ASTNode { } export class StructDeclaration extends TreeNode { + static pool = new AstNodePool(StructDeclaration, 5); + get typeSpecifier() { if (this.children.length === 3) { return this.children[0] as TypeSpecifier; @@ -1207,7 +1391,8 @@ export namespace ASTNode { get propList(): StructProp[] { const ret: StructProp[] = []; - for (const declarator of this.declaratorList.declaratorList) { + for (let i = 0; i < this.declaratorList.declaratorList.length; i++) { + const declarator = this.declaratorList.declaratorList[i]; const typeInfo = new SymbolType(this.typeSpecifier.type, this.typeSpecifier.lexeme, declarator.arraySpecifier); const prop = new StructProp(typeInfo, declarator.ident); ret.push(prop); @@ -1221,6 +1406,8 @@ export namespace ASTNode { } export class StructDeclaratorList extends TreeNode { + static pool = new AstNodePool(StructDeclaratorList, 5); + get declaratorList(): StructDeclarator[] { if (this.children.length === 1) { return [this.children[0] as StructDeclarator]; @@ -1236,6 +1423,8 @@ export namespace ASTNode { } export class StructDeclarator extends TreeNode { + static pool = new AstNodePool(StructDeclarator, 5); + get ident() { return this.children[0] as Token; } @@ -1250,6 +1439,8 @@ export namespace ASTNode { } export class VariableDeclaration extends TreeNode { + static pool = new AstNodePool(VariableDeclaration, 20); + constructor(loc: ShaderRange, children: NodeChild[]) { super(ENonTerminal.variable_declaration, loc, children); } @@ -1269,12 +1460,15 @@ export namespace ASTNode { } export class VariableIdentifier extends TreeNode { + static pool = new AstNodePool(VariableIdentifier, 20); + symbolInfo: | VarSymbol // #if _EDITOR | BuiltinVariable // #endif | null; + get lexeme(): string { return (this.children[0]).lexeme; } @@ -1313,6 +1507,8 @@ export namespace ASTNode { } export class GLShaderProgram extends TreeNode { + static pool = new AstNodePool(GLShaderProgram, 1); + shaderData: ShaderData; constructor(loc: ShaderRange, children: NodeChild[]) { diff --git a/tests/src/shader-lab/shaders/syntax.shader b/tests/src/shader-lab/shaders/syntax.shader deleted file mode 100644 index 8b7145792b..0000000000 --- a/tests/src/shader-lab/shaders/syntax.shader +++ /dev/null @@ -1,121 +0,0 @@ -Shader "Water" { - - SubShader "subname" { - - Pass "default" { - - struct a2v { - vec4 POSITION; - vec2 TEXCOORD_0; - } - - struct v2f { - vec2 v_uv; - vec3 v_position; - } - - #define SCENE_SHADOW_TYPE 3 - #define RENDERER_BLENDSHAPE_COUNT 10 - - lowp mat4 renderer_MVPMat; - highp mat4 renderer_MVMat; - - mediump vec4 u_color; - lowp vec4 u_fogColor; - highp float u_fogDensity; - vec4 material_BaseColor; - float material_AlphaCutoff; - vec4 material_BaseColor; - float material_AlphaCutoff; - ivec3 renderer_BlendShapeTextureInfo; - vec2 renderer_BlendShapeWeights[RENDERER_BLENDSHAPE_COUNT]; - - VertexShader = vert; - FragmentShader = frag; - - vec4 linearToGamma(vec4 linearIn) { - return vec4(pow(linearIn.rgb, vec3(1.0 / 2.2)), linearIn.a); - } - - BlendState = blendState; - - StencilState { - Enabled = true; - ReferenceValue = 2; - Mask = 1.3; // 0xffffffff - WriteMask = 0.32; // 0xffffffff - CompareFunctionFront = CompareFunction.Less; - PassOperationBack = StencilOperation.Zero; - } - - DepthState = depthState; - RasterState = rasterState; - - vec3 getBlendShapeVertexElement(int blendShapeIndex, int vertexElementIndex) - { - int y = vertexElementIndex / renderer_BlendShapeTextureInfo.y; - int x = vertexElementIndex - y * renderer_BlendShapeTextureInfo.y; - ivec3 uv = ivec3(x, y , blendShapeIndex); - vec4 tmp = texture2D(u_textures[1], vec2(uv.xy)); - return tmp.xyz; - } - - v2f vert(a2v v) { - v2f o; - - o.v_uv = v.TEXCOORD_0; - vec4 tmp = renderer_MVMat * POSITION; - o.v_position = tmp.xyz; - gl_Position = renderer_MVPMat * v.POSITION; - - for(int i = 0; i < RENDERER_BLENDSHAPE_COUNT; i++){ - int vertexElementOffset = 2; - float weight = renderer_BlendShapeWeights[i].x; - o.v_position.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight; - - #ifndef MATERIAL_OMIT_NORMAL - #if defined( RENDERER_HAS_NORMAL ) && defined( RENDERER_BLENDSHAPE_HAS_NORMAL ) - vertexElementOffset += 1; - normal += getBlendShapeVertexElement(i, vertexElementOffset) * weight; - #endif - - #if defined( RENDERER_HAS_TANGENT ) && defined(RENDERER_BLENDSHAPE_HAS_TANGENT) && ( defined(MATERIAL_HAS_NORMALTEXTURE) || defined(MATERIAL_HAS_CLEAR_COAT_NORMAL_TEXTURE) ) - vertexElementOffset += 1; - tangent.xyz += getBlendShapeVertexElement(i, vertexElementOffset) * weight; - #endif - #endif - } - - return o; - } - - void frag(v2f i) { - vec4 baseColor = material_BaseColor; - - #ifdef MATERIAL_HAS_BASETEXTURE - vec4 textureColor = texture2D(u_textures[2], v_uv); - #ifndef ENGINE_IS_COLORSPACE_GAMMA - textureColor = gammaToLinear(textureColor); - #endif - baseColor *= textureColor; - #endif - - #ifdef MATERIAL_IS_ALPHA_CUTOFF - if( baseColor.a < material_AlphaCutoff ) { - discard; - } - #endif - - gl_FragColor = baseColor; - - #ifndef MATERIAL_IS_TRANSPARENT - gl_FragColor.a = 1.0; - #endif - - #ifndef ENGINE_IS_COLORSPACE_GAMMA - gl_FragColor = linearToGamma(gl_FragColor); - #endif - } - } - } -} \ No newline at end of file