From 5a26f3d8ccd113853e2595cd4d5176eed9d2b971 Mon Sep 17 00:00:00 2001 From: SwayYan Date: Wed, 20 Sep 2023 12:06:40 +0800 Subject: [PATCH 01/60] fix(shader-lab): compatible with empty macro --- packages/shader-lab/src/RuntimeContext.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shader-lab/src/RuntimeContext.ts b/packages/shader-lab/src/RuntimeContext.ts index 8624faf161..5b70213a89 100644 --- a/packages/shader-lab/src/RuntimeContext.ts +++ b/packages/shader-lab/src/RuntimeContext.ts @@ -270,7 +270,7 @@ export default class RuntimeContext { getMacroText(macros: (FnMacroAstNode | FnMacroConditionAstNode)[], needSort = false): string { const list = needSort ? macros.sort(AstNodeUtils.astSortAsc) : macros; - return list.map((item) => item.serialize(this)).join("\n"); + return list?.map((item) => item.serialize(this)).join("\n"); } getGlobalText(): string { From 0d45d9c77f9803f5d69d7f5e058289ff2821ae5b Mon Sep 17 00:00:00 2001 From: SwayYan Date: Thu, 21 Sep 2023 16:02:36 +0800 Subject: [PATCH 02/60] fix(shader-lab): add break and continue syntax --- packages/shader-lab/src/ShaderVisitor.ts | 20 ++++++++++++++++ packages/shader-lab/src/ast-node/AstNode.ts | 12 ++++++++++ .../shader-lab/src/parser/ShaderParser.ts | 12 ++++++++++ .../src/parser/tokens/GLSLKeywords.ts | 4 +++- packages/shader-lab/src/types.ts | 24 +++++++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/shader-lab/src/ShaderVisitor.ts b/packages/shader-lab/src/ShaderVisitor.ts index c7ffa899e1..812e400f2e 100644 --- a/packages/shader-lab/src/ShaderVisitor.ts +++ b/packages/shader-lab/src/ShaderVisitor.ts @@ -9,8 +9,10 @@ import { BlendFactorAstNode, BlendOperationAstNode, BooleanAstNode, + BreakStatementAstNode, CompareFunctionAstNode, ConditionExprAstNode, + ContinueStatementAstNode, CullModeAstNode, DeclarationWithoutAssignAstNode, DiscardStatementAstNode, @@ -80,8 +82,10 @@ import { _ruleBlendStatePropertyDeclarationCstChildren, _ruleBlendStateValueCstChildren, _ruleBooleanCstChildren, + _ruleBreakStatementCstChildren, _ruleCompareFunctionCstChildren, _ruleConditionExprCstChildren, + _ruleContinueStatementCstChildren, _ruleCullModeCstChildren, _ruleDeclarationWithoutAssignCstChildren, _ruleDepthSatePropertyDeclarationCstChildren, @@ -417,6 +421,22 @@ export class ShaderVisitor extends ShaderVisitorConstructor implements Partial { diff --git a/packages/shader-lab/src/ast-node/AstNode.ts b/packages/shader-lab/src/ast-node/AstNode.ts index 0fe5a1aa92..75578f0044 100644 --- a/packages/shader-lab/src/ast-node/AstNode.ts +++ b/packages/shader-lab/src/ast-node/AstNode.ts @@ -272,6 +272,18 @@ export class DiscardStatementAstNode extends AstNode { } } +export class BreakStatementAstNode extends AstNode { + override _doSerialization(context?: RuntimeContext, args?: any): string { + return "break;"; + } +} + +export class ContinueStatementAstNode extends AstNode { + override _doSerialization(context?: RuntimeContext, args?: any): string { + return "continue;"; + } +} + export class FnParenthesisAtomicAstNode extends AstNode { override _doSerialization(context?: RuntimeContext, args?: any): string { let ret = `(${this.content.parenthesisNode.serialize(context)})`; diff --git a/packages/shader-lab/src/parser/ShaderParser.ts b/packages/shader-lab/src/parser/ShaderParser.ts index e1068c01c9..7540e501f9 100644 --- a/packages/shader-lab/src/parser/ShaderParser.ts +++ b/packages/shader-lab/src/parser/ShaderParser.ts @@ -334,6 +334,16 @@ export class ShaderParser extends CstParser { this.CONSUME(Symbols.Semicolon); }); + private _ruleBreakStatement = this.RULE("_ruleBreakStatement", () => { + this.CONSUME(GLKeywords.Break); + this.CONSUME(Symbols.Semicolon); + }); + + private _ruleContinueStatement = this.RULE("_ruleContinueStatement", () => { + this.CONSUME(GLKeywords.Continue); + this.CONSUME(Symbols.Semicolon); + }); + private _ruleFnStatement = this.RULE("_ruleFnStatement", () => { this.OR([ { ALT: () => this.SUBRULE(this._ruleFnCall) }, @@ -342,6 +352,8 @@ export class ShaderParser extends CstParser { { ALT: () => this.SUBRULE(this._ruleFnVariableDeclaration) }, { ALT: () => this.SUBRULE(this._ruleFnConditionStatement) }, { ALT: () => this.SUBRULE(this._ruleDiscardStatement) }, + { ALT: () => this.SUBRULE(this._ruleBreakStatement) }, + { ALT: () => this.SUBRULE(this._ruleContinueStatement) }, { ALT: () => this.SUBRULE(this._ruleForLoopStatement) }, { ALT: () => this.SUBRULE(this._ruleFn) } ]); diff --git a/packages/shader-lab/src/parser/tokens/GLSLKeywords.ts b/packages/shader-lab/src/parser/tokens/GLSLKeywords.ts index fdaffe3f6a..b05eab0913 100644 --- a/packages/shader-lab/src/parser/tokens/GLSLKeywords.ts +++ b/packages/shader-lab/src/parser/tokens/GLSLKeywords.ts @@ -23,6 +23,8 @@ export const Struct = TokenUtils.createKeywordToken("struct"); export const If = TokenUtils.createKeywordToken("if"); export const Else = TokenUtils.createKeywordToken("else"); export const Discard = TokenUtils.createKeywordToken("discard"); +export const Break = TokenUtils.createKeywordToken("break"); +export const Continue = TokenUtils.createKeywordToken("continue"); export const Void = TokenUtils.createKeywordToken("void"); export const Return = TokenUtils.createKeywordToken("return"); export const For = TokenUtils.createKeywordToken("for"); @@ -30,4 +32,4 @@ export const For = TokenUtils.createKeywordToken("for"); // export const variableTokenList = [GLPosition, GLFragColor]; export const funcTokenList = [Texture2D]; export const macroTokenList = [M_DEFINE, M_IFDEF, M_IFNDEF, M_IF, M_ELSE, M_ELIF, M_ENDIF, M_UNDEFINE, M_INCLUDE]; -export const otherTokenList = [Struct, If, Else, Discard, Void, Return, For]; +export const otherTokenList = [Struct, If, Else, Discard, Void, Return, For, Break, Continue]; diff --git a/packages/shader-lab/src/types.ts b/packages/shader-lab/src/types.ts index dd59e24365..afdfae48b3 100644 --- a/packages/shader-lab/src/types.ts +++ b/packages/shader-lab/src/types.ts @@ -481,6 +481,26 @@ export type _ruleDiscardStatementCstChildren = { Semicolon: IToken[]; }; +export interface _ruleBreakStatementCstNode extends CstNode { + name: "_ruleBreakStatement"; + children: _ruleBreakStatementCstChildren; +} + +export type _ruleBreakStatementCstChildren = { + break: IToken[]; + Semicolon: IToken[]; +}; + +export interface _ruleContinueStatementCstNode extends CstNode { + name: "_ruleContinueStatement"; + children: _ruleContinueStatementCstChildren; +} + +export type _ruleContinueStatementCstChildren = { + continue: IToken[]; + Semicolon: IToken[]; +}; + export interface _ruleFnStatementCstNode extends CstNode { name: "_ruleFnStatement"; children: _ruleFnStatementCstChildren; @@ -493,6 +513,8 @@ export type _ruleFnStatementCstChildren = { _ruleFnVariableDeclaration?: _ruleFnVariableDeclarationCstNode[]; _ruleFnConditionStatement?: _ruleFnConditionStatementCstNode[]; _ruleDiscardStatement?: _ruleDiscardStatementCstNode[]; + _ruleBreakStatement?: _ruleBreakStatementCstNode[]; + _ruleContinueStatement?: _ruleContinueStatementCstNode[]; _ruleForLoopStatement?: _ruleForLoopStatementCstNode[]; _ruleFn?: _ruleFnCstNode[]; }; @@ -1241,6 +1263,8 @@ export interface ICstNodeVisitor extends ICstVisitor { _ruleArrayIndex(children: _ruleArrayIndexCstChildren, param?: IN): OUT; _ruleMultiplicationOperator(children: _ruleMultiplicationOperatorCstChildren, param?: IN): OUT; _ruleDiscardStatement(children: _ruleDiscardStatementCstChildren, param?: IN): OUT; + _ruleBreakStatement(children: _ruleBreakStatementCstChildren, param?: IN): OUT; + _ruleContinueStatement(children: _ruleContinueStatementCstChildren, param?: IN): OUT; _ruleFnStatement(children: _ruleFnStatementCstChildren, param?: IN): OUT; _ruleFnAssignStatement(children: _ruleFnAssignStatementCstChildren, param?: IN): OUT; _ruleForLoopStatement(children: _ruleForLoopStatementCstChildren, param?: IN): OUT; From 8871d9b06712665c786b25c0423e8b8fac15fdc9 Mon Sep 17 00:00:00 2001 From: SwayYan Date: Wed, 11 Oct 2023 16:15:11 +0800 Subject: [PATCH 03/60] fix: typo --- packages/core/src/shader/Shader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index a922c528c4..d0eb131856 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -38,7 +38,7 @@ export class Shader { * // Import shaderLab * import { ShaderLab } from "@galacean/engine-shader-lab"; * // Create engine with shaderLab - * const engine = await WebGLEngine.create({ canvas: "canvas", new ShaderLab() }); + * const engine = await WebGLEngine.create({ canvas: "canvas", shader: new ShaderLab() }); * ... * ``` * From f649a58c681862c5707e4602bb3d49e176bd0b19 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 1 Nov 2023 12:04:29 +0800 Subject: [PATCH 04/60] fix(shader-lab): Make usepass compatible with buitin shader --- packages/shader-lab/package.json | 1 + packages/shader-lab/src/parser/tokens/Value.ts | 2 +- tests/src/shader-lab/shaders/demo.shader | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index 089fbb7e83..1bc62d74c6 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -8,6 +8,7 @@ "license": "MIT", "main": "dist/main.js", "module": "dist/module.js", + "browser": "dist/browser.js", "debug": "src/index.ts", "types": "types/index.d.ts", "scripts": { diff --git a/packages/shader-lab/src/parser/tokens/Value.ts b/packages/shader-lab/src/parser/tokens/Value.ts index 88f689a030..9505758125 100644 --- a/packages/shader-lab/src/parser/tokens/Value.ts +++ b/packages/shader-lab/src/parser/tokens/Value.ts @@ -4,7 +4,7 @@ export const ValueInt = createToken({ name: "ValueInt", pattern: /-?\d+/ }); export const ValueFloat = createToken({ name: "ValueFloat", pattern: /-?\d+\.\d+/ }); export const ValueString = createToken({ name: "ValueString", - pattern: /"[\w\s/\.]*"/ + pattern: /"[\w-\s/\.]*"/ }); export const ValueTrue = createToken({ name: "ValueTrue", pattern: /true/ }); export const ValueFalse = createToken({ name: "ValueFalse", pattern: /false/ }); diff --git a/tests/src/shader-lab/shaders/demo.shader b/tests/src/shader-lab/shaders/demo.shader index ccf3984092..ca29fe4be0 100644 --- a/tests/src/shader-lab/shaders/demo.shader +++ b/tests/src/shader-lab/shaders/demo.shader @@ -114,5 +114,6 @@ Shader "Water" { #endif } } + UsePass "blinn-phong/Default/Forward" } } \ No newline at end of file From e33a66f7ba008562fa9498a0db02b8f19facc5ef Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 2 Nov 2023 15:51:25 +0800 Subject: [PATCH 05/60] fix(shader-lab): compatible with no varying variable --- packages/shader-lab/src/Ast2GLSLUtils.ts | 22 +++++--------- tests/src/shader-lab/ShaderLab.test.ts | 5 ++++ .../src/shader-lab/shaders/noFragArgs.shader | 30 +++++++++++++++++++ 3 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 tests/src/shader-lab/shaders/noFragArgs.shader diff --git a/packages/shader-lab/src/Ast2GLSLUtils.ts b/packages/shader-lab/src/Ast2GLSLUtils.ts index b3bf252e47..5d3c074676 100644 --- a/packages/shader-lab/src/Ast2GLSLUtils.ts +++ b/packages/shader-lab/src/Ast2GLSLUtils.ts @@ -24,20 +24,14 @@ export class Ast2GLSLUtils { // parse varying variables const varyingStructAstNode = context.findGlobal(vertFnAst.content.returnType.content.text)?.ast as StructAstNode; - if (!varyingStructAstNode) { - context.diagnostics.push({ - severity: DiagnosticSeverity.Error, - message: "no varying struct definition", - token: vertFnAst.content.returnType.position - }); - return ""; + if (varyingStructAstNode) { + context.varyingStructInfo.structAstNode = varyingStructAstNode; + context.varyingStructInfo.reference = varyingStructAstNode.content.variables.map((v) => ({ + referenced: false, + property: v, + text: `varying ${v.content.type.serialize(context)} ${v.content.variableNode.serialize(context)}` + })); } - context.varyingStructInfo.structAstNode = varyingStructAstNode; - context.varyingStructInfo.reference = varyingStructAstNode.content.variables.map((v) => ({ - referenced: false, - property: v, - text: `varying ${v.content.type.serialize(context)} ${v.content.variableNode.serialize(context)}` - })); // parsing attribute variables vertFnAst.content.args.forEach((arg) => { @@ -101,7 +95,7 @@ export class Ast2GLSLUtils { } context.setMainFnAst(fragFnAst); - context.varyingStructInfo.objectName = fragFnAst.content.args[0].content.name; + context.varyingStructInfo.objectName = fragFnAst.content.args?.[0].content.name; const fragmentFnStr = fragFnAst.serialize(context); // There may be global variable references in conditional macro statement, so it needs to be serialized first. diff --git a/tests/src/shader-lab/ShaderLab.test.ts b/tests/src/shader-lab/ShaderLab.test.ts index eaa6f66838..bc3baa55f3 100644 --- a/tests/src/shader-lab/ShaderLab.test.ts +++ b/tests/src/shader-lab/ShaderLab.test.ts @@ -200,4 +200,9 @@ describe("ShaderLab", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/triangle.shader")).toString(); glslValidate(demoShader, shaderLab); }); + + it("No frag shader args", () => { + const demoShader = fs.readFileSync(path.join(__dirname, "shaders/noFragArgs.shader")).toString(); + glslValidate(demoShader, shaderLab); + }); }); diff --git a/tests/src/shader-lab/shaders/noFragArgs.shader b/tests/src/shader-lab/shaders/noFragArgs.shader new file mode 100644 index 0000000000..f99b87871f --- /dev/null +++ b/tests/src/shader-lab/shaders/noFragArgs.shader @@ -0,0 +1,30 @@ +Shader "Test-Default" { + Tags { ReplaceTag = "transparent" } + SubShader "Default" { + Pass "test" { + Tags { ReplaceTag = "opaque" } + mat4 renderer_MVPMat; + + struct a2v { + vec4 POSITION; + } + + // struct v2f { + // vec2 uv; + // } + + VertexShader = vert; + FragmentShader = frag; + + v2f vert(a2v v) { + gl_Position = renderer_MVPMat * v.POSITION; + } + + void frag() { + vec3 grayColor = vec3(0.299, 0.587, 0.114); + float gray = dot(grayColor, gl_FragColor.rgb); + gl_FragColor = vec4(gray, gray, gray, gl_FragColor.a); + } + } + } +} \ No newline at end of file From 41ef06fc71c57a40a3976d4b479583eec8d285dc Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 6 Nov 2023 11:01:22 +0800 Subject: [PATCH 06/60] feat(shader-lab): detect mismatch return type --- packages/shader-lab/src/ast-node/AstNode.ts | 13 +++++++++++++ packages/shader-lab/src/ast-node/AstNodeContent.ts | 4 +++- tests/src/shader-lab/shaders/noFragArgs.shader | 2 +- tests/src/shader-lab/shaders/planarShadow.shader | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/shader-lab/src/ast-node/AstNode.ts b/packages/shader-lab/src/ast-node/AstNode.ts index 2e7da08a96..fd26a17b25 100644 --- a/packages/shader-lab/src/ast-node/AstNode.ts +++ b/packages/shader-lab/src/ast-node/AstNode.ts @@ -202,6 +202,18 @@ export class FnAstNode extends AstNode { } const body = this.content.body.serialize(context); + if ( + (this.content.returnType.content.text === "void" && this.content.returnStatement) || + (this.content.returnType.content.text !== "void" && !this.content.returnStatement) + ) { + context.diagnostics.push({ + severity: DiagnosticSeverity.Error, + message: "Mismatched return type", + token: this.position + }); + throw "Mismatched return type"; + } + context.functionAstStack.pop(); return `${returnType} ${fnName} (${args}) {\n${body}\n}`; } @@ -493,6 +505,7 @@ export class FnArrayVariableAstNode extends AstNode export class FnReturnStatementAstNode extends AstNode { override _doSerialization(context: RuntimeContext): string { + context.currentFunctionInfo.fnAst.content.returnStatement = this; if (context.currentFunctionInfo.fnAst === context.currentMainFnAst) { return ""; } diff --git a/packages/shader-lab/src/ast-node/AstNodeContent.ts b/packages/shader-lab/src/ast-node/AstNodeContent.ts index 39606d5ce8..3f837ff48c 100644 --- a/packages/shader-lab/src/ast-node/AstNodeContent.ts +++ b/packages/shader-lab/src/ast-node/AstNodeContent.ts @@ -42,7 +42,8 @@ import { FnVariableDeclareUnitAstNode, FnMacroUndefineAstNode, FnMacroConditionAstNode, - RenderQueueValueAstNode + RenderQueueValueAstNode, + FnReturnStatementAstNode } from "./AstNode"; export interface IShaderAstContent { @@ -111,6 +112,7 @@ export interface IFnAstContent { name: string; args: FnArgAstNode[]; body: AstNode; + returnStatement?: FnReturnStatementAstNode; } export interface IFnBodyAstContent { diff --git a/tests/src/shader-lab/shaders/noFragArgs.shader b/tests/src/shader-lab/shaders/noFragArgs.shader index f99b87871f..438888ced9 100644 --- a/tests/src/shader-lab/shaders/noFragArgs.shader +++ b/tests/src/shader-lab/shaders/noFragArgs.shader @@ -16,7 +16,7 @@ Shader "Test-Default" { VertexShader = vert; FragmentShader = frag; - v2f vert(a2v v) { + void vert(a2v v) { gl_Position = renderer_MVPMat * v.POSITION; } diff --git a/tests/src/shader-lab/shaders/planarShadow.shader b/tests/src/shader-lab/shaders/planarShadow.shader index 954033c5fe..eb0d494de3 100644 --- a/tests/src/shader-lab/shaders/planarShadow.shader +++ b/tests/src/shader-lab/shaders/planarShadow.shader @@ -123,6 +123,7 @@ Shader "PlanarShadow" { // shadow color o.color = u_planarShadowColor; o.color.a *= falloff; + return o; } VertexShader = vert; From b5214fc9c4167448195a966668aa7f9c9af013d8 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 7 Nov 2023 16:13:35 +0800 Subject: [PATCH 07/60] fix(shader-lab): renderState assignment --- packages/shader-lab/src/RuntimeContext.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/shader-lab/src/RuntimeContext.ts b/packages/shader-lab/src/RuntimeContext.ts index 5b70213a89..1dd6083b45 100644 --- a/packages/shader-lab/src/RuntimeContext.ts +++ b/packages/shader-lab/src/RuntimeContext.ts @@ -205,17 +205,16 @@ export default class RuntimeContext { const [constantProps, variableProps] = ret.renderStates; this.payload = { parsingRenderState: true }; - const tmpRenderStates = ast.content.renderStates; + const tmpRenderStates = ast.content.renderStates ?? []; ast.content.properties.forEach((prop) => this._parsePassProperty(>ast, prop, ret, tmpRenderStates) ); - if (tmpRenderStates) { - for (const rs of tmpRenderStates) { - const [constP, variableP] = rs.getContentValue(this).properties; - Object.assign(constantProps, constP); - Object.assign(variableProps, variableP); - } + for (const rs of tmpRenderStates) { + const [constP, variableP] = rs.getContentValue(this).properties; + Object.assign(constantProps, constP); + Object.assign(variableProps, variableP); } + this.payload = undefined; const renderQueueNode = ast.content.renderQueue; From f36ce020b558f0b0f792565396c1c91cbff47b32 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 13 Nov 2023 10:01:57 +0800 Subject: [PATCH 08/60] feat: extend material loader data type --- packages/loader/src/MaterialLoader.ts | 4 ++++ .../resource-deserialize/resources/schema/MaterialSchema.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/loader/src/MaterialLoader.ts b/packages/loader/src/MaterialLoader.ts index 145f5c8780..a8bfd96884 100644 --- a/packages/loader/src/MaterialLoader.ts +++ b/packages/loader/src/MaterialLoader.ts @@ -74,6 +74,10 @@ class MaterialLoader extends Loader { }) ); break; + case "Boolean": + materialShaderData.setInt(key, value ? 1 : 0); + case "Integer": + materialShaderData.setInt(key, Number(value)); } } diff --git a/packages/loader/src/resource-deserialize/resources/schema/MaterialSchema.ts b/packages/loader/src/resource-deserialize/resources/schema/MaterialSchema.ts index 07410cec8e..377ea86126 100644 --- a/packages/loader/src/resource-deserialize/resources/schema/MaterialSchema.ts +++ b/packages/loader/src/resource-deserialize/resources/schema/MaterialSchema.ts @@ -90,7 +90,7 @@ export interface IMaterialSchema { shader: string; shaderData: { [key: string]: { - type: "Vector2" | "Vector3" | "Vector4" | "Color" | "Float" | "Texture"; + type: "Vector2" | "Vector3" | "Vector4" | "Color" | "Float" | "Texture" | "Boolean" | "Integer"; value: IVector3 | IVector2 | IColor | number | IAssetRef; }; }; From 634236f90337ca8e0a1643c933e7cb2caf54506d Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 13 Nov 2023 14:19:40 +0800 Subject: [PATCH 09/60] fix(shader-lab): glsl type pattern --- .../shader-lab/src/parser/tokens/GLSLTypes.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/shader-lab/src/parser/tokens/GLSLTypes.ts b/packages/shader-lab/src/parser/tokens/GLSLTypes.ts index 8f767dff0c..fda23bde90 100644 --- a/packages/shader-lab/src/parser/tokens/GLSLTypes.ts +++ b/packages/shader-lab/src/parser/tokens/GLSLTypes.ts @@ -1,26 +1,26 @@ import { createToken } from "chevrotain"; -export const glsl_mat2 = createToken({ name: "glsl_mat2", pattern: /mat2/ }); -export const glsl_mat3 = createToken({ name: "glsl_mat3", pattern: /mat3/ }); -export const glsl_mat4 = createToken({ name: "glsl_mat4", pattern: /mat4/ }); +export const glsl_mat2 = createToken({ name: "glsl_mat2", pattern: /mat2\s/ }); +export const glsl_mat3 = createToken({ name: "glsl_mat3", pattern: /mat3\s/ }); +export const glsl_mat4 = createToken({ name: "glsl_mat4", pattern: /mat4\s/ }); -export const glsl_vec2 = createToken({ name: "glsl_vec2", pattern: /vec2/ }); -export const glsl_vec3 = createToken({ name: "glsl_vec3", pattern: /vec3/ }); -export const glsl_vec4 = createToken({ name: "glsl_vec4", pattern: /vec4/ }); +export const glsl_vec2 = createToken({ name: "glsl_vec2", pattern: /vec2\s/ }); +export const glsl_vec3 = createToken({ name: "glsl_vec3", pattern: /vec3\s/ }); +export const glsl_vec4 = createToken({ name: "glsl_vec4", pattern: /vec4\s/ }); -export const glsl_ivec2 = createToken({ name: "glsl_ivec2", pattern: /ivec2/ }); -export const glsl_ivec3 = createToken({ name: "glsl_ivec3", pattern: /ivec3/ }); -export const glsl_ivec4 = createToken({ name: "glsl_ivec4", pattern: /ivec4/ }); +export const glsl_ivec2 = createToken({ name: "glsl_ivec2", pattern: /ivec2\s/ }); +export const glsl_ivec3 = createToken({ name: "glsl_ivec3", pattern: /ivec3\s/ }); +export const glsl_ivec4 = createToken({ name: "glsl_ivec4", pattern: /ivec4\s/ }); -export const glsl_float = createToken({ name: "glsl_float", pattern: /float/ }); -export const glsl_int = createToken({ name: "glsl_int", pattern: /int/ }); +export const glsl_float = createToken({ name: "glsl_float", pattern: /float\s/ }); +export const glsl_int = createToken({ name: "glsl_int", pattern: /int\s/ }); export const glsl_sampler2D = createToken({ name: "glsl_sampler2D", - pattern: /sampler2D/ + pattern: /sampler2D\s/ }); -export const glsl_sampler2DArray = createToken({ name: "sampler2DArray", pattern: /sampler2DArray/ }); +export const glsl_sampler2DArray = createToken({ name: "sampler2DArray", pattern: /sampler2DArray / }); export const tokenList = [ glsl_ivec2, From 91e6fa4aab6df2da732a7b53227cd61714505fab Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 13 Nov 2023 14:39:27 +0800 Subject: [PATCH 10/60] fix(shader-lab): glsl type pattern --- packages/shader-lab/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index d79611f7e6..5bf22de905 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -8,7 +8,6 @@ "license": "MIT", "main": "dist/main.js", "module": "dist/module.js", - "browser": "dist/browser.js", "debug": "src/index.ts", "types": "types/index.d.ts", "scripts": { From 3932448c79d48428521e6c172c6352702a7cb838 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 15 Nov 2023 14:27:54 +0800 Subject: [PATCH 11/60] fix: switch case break --- packages/loader/src/MaterialLoader.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/loader/src/MaterialLoader.ts b/packages/loader/src/MaterialLoader.ts index a8bfd96884..6048f24301 100644 --- a/packages/loader/src/MaterialLoader.ts +++ b/packages/loader/src/MaterialLoader.ts @@ -76,8 +76,10 @@ class MaterialLoader extends Loader { break; case "Boolean": materialShaderData.setInt(key, value ? 1 : 0); + break; case "Integer": materialShaderData.setInt(key, Number(value)); + break; } } From 671cace03db15504f45adad8614105a45a12fa1d Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 11 Jun 2024 11:20:20 +0800 Subject: [PATCH 12/60] fix: array index loss --- packages/shader-lab/src/ast-node/AstNode.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/shader-lab/src/ast-node/AstNode.ts b/packages/shader-lab/src/ast-node/AstNode.ts index 2dd987174f..f889655f4b 100644 --- a/packages/shader-lab/src/ast-node/AstNode.ts +++ b/packages/shader-lab/src/ast-node/AstNode.ts @@ -627,13 +627,19 @@ export class FnVariableAstNode extends AstNode { override _doSerialization(context: RuntimeContext): string { const objName = this.content.variable; const propName = this.content.properties?.[0].content; + + const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])] + .sort((a, b) => AstNodeUtils.astSortAsc(a.position, b.position)) + .map((item) => item.serialize(context)) + .join(""); + if (propName) { if (objName === context.varyingStructInfo.objectName) { const ref = context.varyingStructInfo.reference?.find( (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return this.content.properties.map((item) => item.content).join("."); + return propList; } else { const attribStruct = context.attributeStructListInfo.find((struct) => struct.objectName === objName); if (attribStruct) { @@ -641,7 +647,7 @@ export class FnVariableAstNode extends AstNode { (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return this.content.properties.map((item) => item.content).join("."); + return propList; } } } @@ -654,10 +660,7 @@ export class FnVariableAstNode extends AstNode { }); } } - const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])] - .sort((a, b) => AstNodeUtils.astSortAsc(a.position, b.position)) - .map((item) => item.serialize(context)) - .join(""); + return objName + propList; } } From 9226d388d701046813775ea0ba38efd691b9630e Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 11 Jun 2024 22:05:25 +0800 Subject: [PATCH 13/60] fix: test-case --- packages/shader-lab/src/ast-node/AstNode.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/shader-lab/src/ast-node/AstNode.ts b/packages/shader-lab/src/ast-node/AstNode.ts index f889655f4b..86285640cc 100644 --- a/packages/shader-lab/src/ast-node/AstNode.ts +++ b/packages/shader-lab/src/ast-node/AstNode.ts @@ -628,10 +628,9 @@ export class FnVariableAstNode extends AstNode { const objName = this.content.variable; const propName = this.content.properties?.[0].content; - const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])] - .sort((a, b) => AstNodeUtils.astSortAsc(a.position, b.position)) - .map((item) => item.serialize(context)) - .join(""); + const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])].sort((a, b) => + AstNodeUtils.astSortAsc(a.position, b.position) + ); if (propName) { if (objName === context.varyingStructInfo.objectName) { @@ -639,7 +638,7 @@ export class FnVariableAstNode extends AstNode { (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return propList; + return propList.map((item) => item.content).join("."); } else { const attribStruct = context.attributeStructListInfo.find((struct) => struct.objectName === objName); if (attribStruct) { @@ -647,7 +646,7 @@ export class FnVariableAstNode extends AstNode { (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return propList; + return propList.map((item) => item.content).join("."); } } } @@ -661,7 +660,7 @@ export class FnVariableAstNode extends AstNode { } } - return objName + propList; + return objName + propList.map((item) => item.serialize(context)).join(""); } } From ff6a69a3f69ddacc82f409bf55e8fb72cf322ceb Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 12 Jun 2024 10:09:07 +0800 Subject: [PATCH 14/60] fix: test-case --- packages/shader-lab/src/ast-node/AstNode.ts | 15 +++++++++------ tests/src/shader-lab/shaders/demo.shader | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/shader-lab/src/ast-node/AstNode.ts b/packages/shader-lab/src/ast-node/AstNode.ts index 86285640cc..e18ee3662b 100644 --- a/packages/shader-lab/src/ast-node/AstNode.ts +++ b/packages/shader-lab/src/ast-node/AstNode.ts @@ -628,9 +628,10 @@ export class FnVariableAstNode extends AstNode { const objName = this.content.variable; const propName = this.content.properties?.[0].content; - const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])].sort((a, b) => - AstNodeUtils.astSortAsc(a.position, b.position) - ); + const propList = [...(this.content.properties ?? []), ...(this.content.indexes ?? [])] + .sort((a, b) => AstNodeUtils.astSortAsc(a.position, b.position)) + .map((item) => item.serialize(context)) + .join(""); if (propName) { if (objName === context.varyingStructInfo.objectName) { @@ -638,7 +639,8 @@ export class FnVariableAstNode extends AstNode { (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return propList.map((item) => item.content).join("."); + if (propList.startsWith(".")) return propList.slice(1); + return propList; } else { const attribStruct = context.attributeStructListInfo.find((struct) => struct.objectName === objName); if (attribStruct) { @@ -646,7 +648,8 @@ export class FnVariableAstNode extends AstNode { (ref) => ref.property.content.variableNode.content.variable === propName ); ref && (ref.referenced = true); - return propList.map((item) => item.content).join("."); + if (propList.startsWith(".")) return propList.slice(1); + return propList; } } } @@ -660,7 +663,7 @@ export class FnVariableAstNode extends AstNode { } } - return objName + propList.map((item) => item.serialize(context)).join(""); + return objName + propList; } } diff --git a/tests/src/shader-lab/shaders/demo.shader b/tests/src/shader-lab/shaders/demo.shader index a529185d3e..1148d96683 100644 --- a/tests/src/shader-lab/shaders/demo.shader +++ b/tests/src/shader-lab/shaders/demo.shader @@ -43,6 +43,7 @@ Shader "Water" { struct a2v { vec4 POSITION; vec2 TEXCOORD_0; + mat3 TBN; } struct v2f { @@ -88,6 +89,7 @@ Shader "Water" { vec4 tmp = renderer_MVMat * POSITION; o.v_position = tmp.xyz; gl_Position = renderer_MVPMat * v.POSITION; + vec3 tangentW = v.TBN[0]; return o; } From 94e30f52b65593a853c2afc03cc62e7456e96825 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 16 Jul 2024 14:03:29 +0800 Subject: [PATCH 15/60] fix: conditional compilation --- packages/shader-lab/package.json | 7 +------ packages/shader-lab/src/Utils.ts | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index ceb5d162f1..5490505c02 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -12,9 +12,7 @@ "debug": "src/index.ts", "types": "types/index.d.ts", "scripts": { - "b:types": "tsc", - "gen_diagram": "ts-node ./scripts/genDiagram.ts", - "gen_dts": "ts-node ./scripts/genDts.ts" + "b:types": "tsc" }, "umd": { "name": "Galacean.ShaderLab", @@ -26,9 +24,6 @@ "dist/**/*", "types/**/*" ], - "dependencies": { - "chevrotain": "^10.5.0" - }, "devDependencies": { "@galacean/engine-design": "workspace:*", "@galacean/engine": "workspace:*" diff --git a/packages/shader-lab/src/Utils.ts b/packages/shader-lab/src/Utils.ts index a7d65617e8..38614c1e0e 100644 --- a/packages/shader-lab/src/Utils.ts +++ b/packages/shader-lab/src/Utils.ts @@ -4,8 +4,8 @@ import { EKeyword, ETokenType, GalaceanDataType, ShaderRange, ShaderPosition } f import { TreeNode } from "./parser/AST"; // #if _EDITOR import State from "./lalr/State"; -import { Logger } from "@galacean/engine"; // #endif +import { Logger } from "@galacean/engine"; export class ParserUtils { static unwrapNodeByType(node: TreeNode, type: ENonTerminal): T | undefined { From e3c7aa5b90c15e139174a7f320bf6d3be3447eb5 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 16 Jul 2024 15:35:24 +0800 Subject: [PATCH 16/60] fix: expand token --- packages/shader-lab/src/index.ts | 3 +-- packages/shader-lab/src/preprocessor/PpParser.ts | 2 -- packages/shader-lab/src/preprocessor/PpScanner.ts | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/shader-lab/src/index.ts b/packages/shader-lab/src/index.ts index bb84aed6cd..7e733a06cc 100644 --- a/packages/shader-lab/src/index.ts +++ b/packages/shader-lab/src/index.ts @@ -1,8 +1,7 @@ export { ShaderLab } from "./ShaderLab"; // #if _EDITOR -import { Preprocessor } from "./preprocessor"; -export { Preprocessor }; +export { Preprocessor } from "./preprocessor"; // #endif //@ts-ignore diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 8d59d2e403..f269c1fa63 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -605,9 +605,7 @@ export default class PpParser { } private static _onToken(token: BaseToken, scanner: PpScanner) { - // #if !_EDITOR this._skipEditorBlock(token, scanner); - // #endif this._expandToken(token, scanner); } diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index 33422d7d5f..2eb39a9de1 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -84,7 +84,7 @@ export default class PpScanner extends BaseScanner { if (this.isEnd()) return EOF; const start = this._currentIndex; - while (LexerUtils.isLetter(this.getCurChar())) { + while (LexerUtils.isLetter(this.getCurChar()) && !this.isEnd()) { this.advance(); } const end = this._currentIndex; From 36b77e081bdddbd6754dc454df4ec3b28cf41ad1 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 16 Jul 2024 15:40:17 +0800 Subject: [PATCH 17/60] fix: expand token --- packages/shader-lab/src/preprocessor/PpScanner.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index 2eb39a9de1..7544558c74 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -189,7 +189,6 @@ export default class PpScanner extends BaseScanner { return { token, nextDirective: directive }; } - // #if !_EDITOR scanPairedBlock(lc = "{", rc = "}") { this.scanToChar(lc); let lvl = 0; @@ -199,7 +198,6 @@ export default class PpScanner extends BaseScanner { this._advance(); } while (lvl > 0); } - // #endif /** * @returns end ShaderPosition From b2e07fc8a6a25ddef75f193f00cf54d71723a72c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 16 Jul 2024 17:40:18 +0800 Subject: [PATCH 18/60] feat: code opt --- .../shader-lab/src/preprocessor/PpParser.ts | 2 +- .../shader-lab/src/preprocessor/PpScanner.ts | 20 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index f269c1fa63..98a1d5c639 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -612,7 +612,7 @@ export default class PpParser { private static _skipEditorBlock(token: BaseToken, scanner: PpScanner) { if (token.lexeme === "EditorProperties" || token.lexeme === "EditorMacros") { const start = scanner.current - token.lexeme.length; - scanner.scanPairedBlock(); + scanner.scanPairedBlock("{", "}"); const end = scanner.current; const startPosition = ShaderLab.createPosition(start); const endPosition = ShaderLab.createPosition(end); diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index 7544558c74..892f8b87d3 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -161,7 +161,8 @@ export default class PpScanner extends BaseScanner { } scanToChar(char: string) { - while (this.getCurChar() !== char && !this.isEnd()) { + const source = this._source; + while (source[this._currentIndex] !== char && !this.isEnd()) { this.advance(); } } @@ -189,14 +190,21 @@ export default class PpScanner extends BaseScanner { return { token, nextDirective: directive }; } - scanPairedBlock(lc = "{", rc = "}") { + scanPairedBlock(lc: string, rc: string): void { this.scanToChar(lc); - let lvl = 0; + let level = 0; + const source = this._source; + do { - if (this.getCurChar() === lc) lvl += 1; - else if (this.getCurChar() === rc) lvl -= 1; + const curChar = source[this._currentIndex]; + + if (curChar === lc) { + level++; + } else if (curChar === rc) { + level--; + } this._advance(); - } while (lvl > 0); + } while (level > 0); } /** From 93df92e2e442a6b79a5f380323571b926b11b4a3 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 16 Jul 2024 17:43:24 +0800 Subject: [PATCH 19/60] fix: ci --- pnpm-lock.yaml | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc827d5d7d..d76a98b9c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -245,10 +245,6 @@ importers: version: link:../design packages/shader-lab: - dependencies: - chevrotain: - specifier: ^10.5.0 - version: 10.5.0 devDependencies: '@galacean/engine': specifier: workspace:* @@ -521,29 +517,6 @@ packages: to-fast-properties: 2.0.0 dev: true - /@chevrotain/cst-dts-gen@10.5.0: - resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} - dependencies: - '@chevrotain/gast': 10.5.0 - '@chevrotain/types': 10.5.0 - lodash: 4.17.21 - dev: false - - /@chevrotain/gast@10.5.0: - resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} - dependencies: - '@chevrotain/types': 10.5.0 - lodash: 4.17.21 - dev: false - - /@chevrotain/types@10.5.0: - resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} - dev: false - - /@chevrotain/utils@10.5.0: - resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} - dev: false - /@choojs/findup@0.2.1: resolution: {integrity: sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==} hasBin: true @@ -2040,17 +2013,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /chevrotain@10.5.0: - resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} - dependencies: - '@chevrotain/cst-dts-gen': 10.5.0 - '@chevrotain/gast': 10.5.0 - '@chevrotain/types': 10.5.0 - '@chevrotain/utils': 10.5.0 - lodash: 4.17.21 - regexp-to-ast: 0.5.0 - dev: false - /chokidar@3.5.1: resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} engines: {node: '>= 8.10.0'} @@ -4267,6 +4229,7 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true /log-symbols@4.0.0: resolution: {integrity: sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==} @@ -5081,10 +5044,6 @@ packages: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} dev: true - /regexp-to-ast@0.5.0: - resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} - dev: false - /release-zalgo@1.0.0: resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} engines: {node: '>=4'} From 8e0cc2856dd5a13acfdbc93e7d509f399b7b2978 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 17 Jul 2024 11:25:25 +0800 Subject: [PATCH 20/60] feat: cache error shader --- packages/shader-lab/src/ShaderLab.ts | 3 +++ packages/shader-lab/src/parser/ShaderTargetParser.ts | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index c687e7fad7..c14ac06e31 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -80,6 +80,9 @@ export class ShaderLab implements IShaderLab { const lexer = new Lexer(ppdContent); const tokens = lexer.tokenize(); const program = ShaderLab._parser.parse(tokens); + if (!program) { + return { vertex: "", fragment: "" }; + } const codeGen = backend === ShaderPlatformTarget.GLES100 ? GLES100Visitor.getVisitor() : GLES300Visitor.getVisitor(); diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index 3248f92da4..56250740b7 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -52,7 +52,7 @@ export class ShaderTargetParser { this.sematicAnalyzer = new SematicAnalyzer(); } - parse(tokens: Generator) { + parse(tokens: Generator): ASTNode.GLShaderProgram | null { this.sematicAnalyzer.reset(); const start = performance.now(); const { _traceBackStack: traceBackStack, sematicAnalyzer } = this; @@ -104,9 +104,7 @@ export class ShaderTargetParser { continue; } else { Logger.error(token.location, `parse error token ${token.lexeme}`); - // #if _EDITOR - throw `invalid action table by token ${token.lexeme}, ${token.location.start.line}, ${token.location.start.column}`; - // #endif + return null; } } } From c92e674e13314d307ffc4c147545a0968b510c18 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 17 Jul 2024 16:09:18 +0800 Subject: [PATCH 21/60] fix: preprocessor parse expression --- packages/shader-lab/src/preprocessor/PpParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 98a1d5c639..6eeba54e60 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -382,7 +382,7 @@ export default class PpParser { if (scanner.getCurChar() === "(") { scanner.advance(); scanner.skipSpace(false); - const ret = this._parseConstant(scanner); + const ret = this._parseConstantExpression(scanner); scanner.scanToChar(")"); scanner.advance(); return ret; From 9eb7398d5d2a924a37529bfa54568549b83a6f3f Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 17 Jul 2024 18:15:14 +0800 Subject: [PATCH 22/60] fix: gles 100 code gen --- packages/shader-lab/src/codeGen/GLES100.ts | 10 +++++++++- packages/shader-lab/src/codeGen/GLES300.ts | 2 +- packages/shader-lab/src/codeGen/GLESVisitor.ts | 7 ++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/shader-lab/src/codeGen/GLES100.ts b/packages/shader-lab/src/codeGen/GLES100.ts index 91a87020fb..e590e63c9f 100644 --- a/packages/shader-lab/src/codeGen/GLES100.ts +++ b/packages/shader-lab/src/codeGen/GLES100.ts @@ -4,7 +4,15 @@ import { VisitorContext } from "./VisitorContext"; import { ICodeSegment } from "./types"; export class GLES100Visitor extends GLESVisitor { - versionText: string = "#version 100 es"; + override _versionText: string = `#version 100`; + override _extensions: string = [ + "GL_EXT_shader_texture_lod", + "GL_OES_standard_derivatives", + "GL_EXT_draw_buffers", + "GL_EXT_frag_depth" + ] + .map((e) => `#extension ${e} : enable\n`) + .join(""); private static _singleton: GLES100Visitor; static getVisitor(): GLES100Visitor { diff --git a/packages/shader-lab/src/codeGen/GLES300.ts b/packages/shader-lab/src/codeGen/GLES300.ts index 650a693eab..31576ab866 100644 --- a/packages/shader-lab/src/codeGen/GLES300.ts +++ b/packages/shader-lab/src/codeGen/GLES300.ts @@ -11,7 +11,7 @@ import { ShaderLab } from "../ShaderLab"; const V3_GL_FragColor = "GS_glFragColor"; export class GLES300Visitor extends GLESVisitor { - versionText: string = "#version 300 es"; + override _versionText: string = "#version 300 es"; private static _singleton: GLES300Visitor; static getVisitor(): GLES300Visitor { diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index 7db94d83be..9f16c22d20 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -11,7 +11,8 @@ import { VisitorContext } from "./VisitorContext"; const defaultPrecision = `precision mediump float;`; export abstract class GLESVisitor extends CodeGenVisitor { - abstract versionText: string; + protected _versionText: string = ""; + protected _extensions: string = ""; abstract getAttributeDeclare(): ICodeSegment[]; abstract getVaryingDeclare(): ICodeSegment[]; @@ -81,7 +82,7 @@ export abstract class GLESVisitor extends CodeGenVisitor { VisitorContext.context.reset(); - return `${this.versionText}\n${defaultPrecision}\n${globalCode}\n\nvoid main() ${statements}`; + return `${this._versionText}\n${defaultPrecision}\n${globalCode}\n\nvoid main() ${statements}`; } private _fragmentMain(entry: string, data: ShaderData): string { @@ -101,7 +102,7 @@ export abstract class GLESVisitor extends CodeGenVisitor { .join("\n"); VisitorContext.context.reset(); - return `${this.versionText}\n${defaultPrecision}\n${globalCode}\n\nvoid main() ${statements}`; + return `${this._versionText}\n${this._extensions}\n${defaultPrecision}\n${globalCode}\n\nvoid main() ${statements}`; } private _getGlobalText( From 9f5b5bc515dd8546005906d5fc7bf2e036b8d73d Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 10:34:35 +0800 Subject: [PATCH 23/60] feat: support relative path include --- packages/core/src/shader/Shader.ts | 24 ++++++++++++------- packages/core/src/shader/ShaderPass.ts | 21 +++++++++++----- packages/design/src/shader-lab/IShaderLab.ts | 6 ++++- packages/shader-lab/src/ShaderLab.ts | 11 +++++---- .../shader-lab/src/preprocessor/PpParser.ts | 12 +++++++--- .../src/preprocessor/Preprocessor.ts | 9 +++++-- tests/src/shader-lab/ShaderValidate.ts | 5 ++-- 7 files changed, 61 insertions(+), 27 deletions(-) diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index 5b5cda10e6..270333c4e8 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -44,12 +44,13 @@ export class Shader implements IReferable { * ``` * * @param shaderSource - shader code + * @param path - used by the preprocessor in `ShaderLab` to resolve the relative path of `#include` directive * @returns Shader * * @throws * Throw string exception if shaderLab has not been enabled properly. */ - static create(shaderSource: string): Shader; + static create(shaderSource: string, path?: string): Shader; /** * Create a shader. @@ -78,13 +79,17 @@ export class Shader implements IReferable { static create( nameOrShaderSource: string, - vertexSourceOrShaderPassesOrSubShaders?: SubShader[] | ShaderPass[] | string, + vertexSourceOrShaderPassesOrSubShadersOrPath?: SubShader[] | ShaderPass[] | string, fragmentSource?: string ): Shader { let shader: Shader; const shaderMap = Shader._shaderMap; - if (!vertexSourceOrShaderPassesOrSubShaders) { + if ( + !fragmentSource && + (vertexSourceOrShaderPassesOrSubShadersOrPath === undefined || + typeof vertexSourceOrShaderPassesOrSubShadersOrPath === "string") + ) { if (!Shader._shaderLab) { throw "ShaderLab has not been set up yet."; } @@ -109,6 +114,7 @@ export class Shader implements IReferable { passInfo.contents, passInfo.vertexEntry, passInfo.fragmentEntry, + vertexSourceOrShaderPassesOrSubShadersOrPath ?? "", passInfo.tags ); @@ -143,17 +149,17 @@ export class Shader implements IReferable { console.error(`Shader named "${nameOrShaderSource}" already exists.`); return; } - if (typeof vertexSourceOrShaderPassesOrSubShaders === "string") { - const shaderPass = new ShaderPass(vertexSourceOrShaderPassesOrSubShaders, fragmentSource); + if (typeof vertexSourceOrShaderPassesOrSubShadersOrPath === "string") { + const shaderPass = new ShaderPass(vertexSourceOrShaderPassesOrSubShadersOrPath, fragmentSource); shader = new Shader(nameOrShaderSource, [new SubShader("Default", [shaderPass])]); } else { - if (vertexSourceOrShaderPassesOrSubShaders.length > 0) { - if (vertexSourceOrShaderPassesOrSubShaders[0].constructor === ShaderPass) { + if (vertexSourceOrShaderPassesOrSubShadersOrPath.length > 0) { + if (vertexSourceOrShaderPassesOrSubShadersOrPath[0].constructor === ShaderPass) { shader = new Shader(nameOrShaderSource, [ - new SubShader("Default", vertexSourceOrShaderPassesOrSubShaders) + new SubShader("Default", vertexSourceOrShaderPassesOrSubShadersOrPath) ]); } else { - shader = new Shader(nameOrShaderSource, vertexSourceOrShaderPassesOrSubShaders.slice()); + shader = new Shader(nameOrShaderSource, vertexSourceOrShaderPassesOrSubShadersOrPath.slice()); } } else { throw "SubShader or ShaderPass count must large than 0."; diff --git a/packages/core/src/shader/ShaderPass.ts b/packages/core/src/shader/ShaderPass.ts index a33e8e304e..5ce8be5a10 100644 --- a/packages/core/src/shader/ShaderPass.ts +++ b/packages/core/src/shader/ShaderPass.ts @@ -18,6 +18,7 @@ import { RenderState } from "./state/RenderState"; */ export class ShaderPass extends ShaderPart { private static _shaderPassCounter: number = 0; + private static _shaderRootPath = "shaders://root/"; /** @internal */ _shaderPassId: number = 0; @@ -39,6 +40,7 @@ export class ShaderPass extends ShaderPart { private readonly _shaderLabSource: string; private readonly _vertexEntry: string; private readonly _fragmentEntry: string; + private readonly _path: string; private _platformMacros: string[] = []; @@ -50,6 +52,7 @@ export class ShaderPass extends ShaderPart { shaderLabSource: string, vertexEntry: string, fragmentEntry: string, + path: string, tags?: Record ); @@ -80,6 +83,7 @@ export class ShaderPass extends ShaderPart { vertexSourceOrFragmentSourceOrCode?: string | Record, fragmentSourceOrTagsOrVertexEntry?: string | Record, fragmentEntryOrTags?: string | Record, + tagsOrPath?: Record | string, tags?: Record ) { super(); @@ -88,6 +92,7 @@ export class ShaderPass extends ShaderPart { if (typeof fragmentEntryOrTags === "string") { this._name = nameOrVertexSource; + this._path = tagsOrPath as string; this._shaderLabSource = vertexSourceOrFragmentSourceOrCode as string; this._vertexEntry = fragmentSourceOrTagsOrVertexEntry as string; this._fragmentEntry = fragmentEntryOrTags; @@ -156,21 +161,23 @@ export class ShaderPass extends ShaderPart { vertexEntry: string, fragmentEntry: string ) { + const { _path, _platformMacros } = this; + const isWebGL2 = engine._hardwareRenderer.isWebGL2; const macros = new Array(); ShaderMacro._getMacrosElements(macroCollection, macros); - this._platformMacros.length = 0; + _platformMacros.length = 0; if (engine._hardwareRenderer.canIUse(GLCapabilityType.shaderTextureLod)) { - this._platformMacros.push("HAS_TEX_LOD"); + _platformMacros.push("HAS_TEX_LOD"); } if (engine._hardwareRenderer.canIUse(GLCapabilityType.standardDerivatives)) { - this._platformMacros.push("HAS_DERIVATIVES"); + _platformMacros.push("HAS_DERIVATIVES"); } if (isWebGL2) { - this._platformMacros.push("GRAPHICS_API_WEBGL2"); + _platformMacros.push("GRAPHICS_API_WEBGL2"); } else { - this._platformMacros.push("GRAPHICS_API_WEBGL1"); + _platformMacros.push("GRAPHICS_API_WEBGL1"); } const start = performance.now(); @@ -180,7 +187,9 @@ export class ShaderPass extends ShaderPart { fragmentEntry, macros, isWebGL2 ? ShaderPlatformTarget.GLES300 : ShaderPlatformTarget.GLES100, - this._platformMacros + _platformMacros, + ShaderPass._shaderRootPath, + new URL(_path, ShaderPass._shaderRootPath).href ); Logger.info(`[ShaderLab compilation] cost time: ${performance.now() - start}ms`); diff --git a/packages/design/src/shader-lab/IShaderLab.ts b/packages/design/src/shader-lab/IShaderLab.ts index 0ed9c83dd4..22f9012a9d 100644 --- a/packages/design/src/shader-lab/IShaderLab.ts +++ b/packages/design/src/shader-lab/IShaderLab.ts @@ -14,6 +14,8 @@ export interface IShaderLab { /** * @internal * Parse shader pass source code. + * @param pathOrigin follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` + * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must be prefixed by `pathOrigin` */ _parseShaderPass( shaderPassSource: string, @@ -21,6 +23,8 @@ export interface IShaderLab { fragmentEntry: string, macros: any[], backend: number, - platformMacros: string[] + platformMacros: string[], + pathOrigin: string, + basePathForIncludeKey: string ): IShaderProgramSource; } diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index c14ac06e31..4be32fce0c 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -53,11 +53,12 @@ export class ShaderLab implements IShaderLab { fragmentEntry: string, macros: ShaderMacro[], backend: ShaderPlatformTarget, - platformMacros: string[] + platformMacros: string[], + pathOrigin: string, + basePathForIncludeKey: string ) { ShaderLabObjectPool.clearAllShaderLabObjectPool(); - - Preprocessor.reset(ShaderLib); + Preprocessor.reset(ShaderLib, pathOrigin, basePathForIncludeKey); for (const macro of macros) { Preprocessor.addPredefinedMacro(macro.name, macro.value); } @@ -119,7 +120,9 @@ export class ShaderLab implements IShaderLab { pass.fragmentEntry, macros, backend, - [] + [], + "shaders://root/", + new URL(pass.name, "shaders://root/").href ) as any; passInfo.name = pass.name; passResult.push(passInfo); diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 6eeba54e60..0e0145ce04 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -28,14 +28,18 @@ export default class PpParser { private static _branchMacros: Set = new Set(); private static _includeMap: Record; + private static _basePathForIncludeKey: string; + private static _pathOrigin: string; - static reset(includeMap: Record) { + static reset(includeMap: Record, pathOrigin: string, basePathForIncludeKey: string) { this._definedMacros.clear(); this._expandSegmentsStack.length = 0; this._expandSegmentsStack.push([]); this._branchMacros.clear(); this.addPredefinedMacro("GL_ES"); this._includeMap = includeMap; + this._basePathForIncludeKey = basePathForIncludeKey; + this._pathOrigin = pathOrigin; } static addPredefinedMacro(macro: string, value?: string) { @@ -94,12 +98,14 @@ export default class PpParser { scanner.skipSpace(true); const id = scanner.scanQuotedString(); + const includedPath = new URL(id.lexeme, this._basePathForIncludeKey).href.substring(this._pathOrigin.length); + scanner.scanToChar("\n"); const end = scanner.getShaderPosition(); - const chunk = this._includeMap[id.lexeme]; + const chunk = this._includeMap[includedPath]; if (!chunk) { - ParserUtils.throw(id.location, `Shader slice "${id.lexeme}" not founded.`); + ParserUtils.throw(id.location, `Shader slice "${includedPath}" not founded.`); } const range = ShaderLab.createRange(start, end); diff --git a/packages/shader-lab/src/preprocessor/Preprocessor.ts b/packages/shader-lab/src/preprocessor/Preprocessor.ts index a95cd6efdb..c14a3e4e09 100644 --- a/packages/shader-lab/src/preprocessor/Preprocessor.ts +++ b/packages/shader-lab/src/preprocessor/Preprocessor.ts @@ -5,8 +5,13 @@ import PpScanner from "./PpScanner"; export class Preprocessor { static baseScanner: PpScanner; - static reset(includeMap: Record): void { - PpParser.reset(includeMap); + /** + * Reset the parser of `Preprocessor` + * @param pathOrigin follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` + * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must be prefixed by `pathOrigin` + */ + static reset(includeMap: Record, pathOrigin: string, basePathForIncludeKey: string): void { + PpParser.reset(includeMap, pathOrigin, basePathForIncludeKey); } /** diff --git a/tests/src/shader-lab/ShaderValidate.ts b/tests/src/shader-lab/ShaderValidate.ts index e6be8e3553..016ca86112 100644 --- a/tests/src/shader-lab/ShaderValidate.ts +++ b/tests/src/shader-lab/ShaderValidate.ts @@ -80,14 +80,15 @@ export function glslValidate(shaderSource, _shaderLab?: ShaderLab, includeMap = shader.subShaders.forEach((subShader) => { subShader.passes.forEach((pass) => { if (pass.isUsePass) return; - // @ts-ignore const compiledPass = shaderLab._parseShaderPass( pass.contents, pass.vertexEntry, pass.fragmentEntry, [], ShaderPlatformTarget.GLES300, - [] + [], + "shaders://root/", + "shaders://root/" ); validateShaderPass(pass, compiledPass.vertex, compiledPass.fragment); }); From 964b84611b9037a034278953353bf4036526526b Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 10:42:22 +0800 Subject: [PATCH 24/60] feat: test case --- tests/src/shader-lab/shaders/unlit.shader | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/shader-lab/shaders/unlit.shader b/tests/src/shader-lab/shaders/unlit.shader index 7065358f19..061edabd66 100644 --- a/tests/src/shader-lab/shaders/unlit.shader +++ b/tests/src/shader-lab/shaders/unlit.shader @@ -54,7 +54,7 @@ Shader "Water" { ivec3 renderer_BlendShapeTextureInfo; vec2 renderer_BlendShapeWeights[RENDERER_BLENDSHAPE_COUNT]; - #include "test_common" + #include "./test_common" #include "brdf" BlendState = blendState; From f6fed8b5b4014c5e523c0a10b2230387af40fded Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 11:22:28 +0800 Subject: [PATCH 25/60] feat: compatible with builtin shader chunk import --- packages/shader-lab/src/preprocessor/PpParser.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 0e0145ce04..02ee847c41 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -98,11 +98,17 @@ export default class PpParser { scanner.skipSpace(true); const id = scanner.scanQuotedString(); - const includedPath = new URL(id.lexeme, this._basePathForIncludeKey).href.substring(this._pathOrigin.length); + let includedPath: string; + // builtin path + if (id.lexeme[0] !== "." && id.lexeme[0] !== "/") { + includedPath = id.lexeme; + } else { + // relative path + includedPath = new URL(id.lexeme, this._basePathForIncludeKey).href.substring(this._pathOrigin.length); + } scanner.scanToChar("\n"); const end = scanner.getShaderPosition(); - const chunk = this._includeMap[includedPath]; if (!chunk) { ParserUtils.throw(id.location, `Shader slice "${includedPath}" not founded.`); From 519ab4051e2c1c2581b27e481c5b881363123ab1 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 14:14:35 +0800 Subject: [PATCH 26/60] feat: code opt --- packages/core/src/shader/ShaderPass.ts | 20 +++++++++---------- packages/design/src/shader-lab/IShaderLab.ts | 4 +--- packages/shader-lab/src/ShaderLab.ts | 9 ++++----- .../shader-lab/src/preprocessor/PpParser.ts | 8 ++++---- .../src/preprocessor/Preprocessor.ts | 4 ++-- tests/src/shader-lab/ShaderValidate.ts | 6 +++--- 6 files changed, 24 insertions(+), 27 deletions(-) diff --git a/packages/core/src/shader/ShaderPass.ts b/packages/core/src/shader/ShaderPass.ts index 5ce8be5a10..9c0e13f66e 100644 --- a/packages/core/src/shader/ShaderPass.ts +++ b/packages/core/src/shader/ShaderPass.ts @@ -18,7 +18,8 @@ import { RenderState } from "./state/RenderState"; */ export class ShaderPass extends ShaderPart { private static _shaderPassCounter: number = 0; - private static _shaderRootPath = "shaders://root/"; + /** @internal */ + static _shaderRootPath = "shaders://root/"; /** @internal */ _shaderPassId: number = 0; @@ -161,23 +162,23 @@ export class ShaderPass extends ShaderPart { vertexEntry: string, fragmentEntry: string ) { - const { _path, _platformMacros } = this; + const { _path: path, _platformMacros: platformMacros } = this; const isWebGL2 = engine._hardwareRenderer.isWebGL2; const macros = new Array(); ShaderMacro._getMacrosElements(macroCollection, macros); - _platformMacros.length = 0; + platformMacros.length = 0; if (engine._hardwareRenderer.canIUse(GLCapabilityType.shaderTextureLod)) { - _platformMacros.push("HAS_TEX_LOD"); + platformMacros.push("HAS_TEX_LOD"); } if (engine._hardwareRenderer.canIUse(GLCapabilityType.standardDerivatives)) { - _platformMacros.push("HAS_DERIVATIVES"); + platformMacros.push("HAS_DERIVATIVES"); } if (isWebGL2) { - _platformMacros.push("GRAPHICS_API_WEBGL2"); + platformMacros.push("GRAPHICS_API_WEBGL2"); } else { - _platformMacros.push("GRAPHICS_API_WEBGL1"); + platformMacros.push("GRAPHICS_API_WEBGL1"); } const start = performance.now(); @@ -187,9 +188,8 @@ export class ShaderPass extends ShaderPart { fragmentEntry, macros, isWebGL2 ? ShaderPlatformTarget.GLES300 : ShaderPlatformTarget.GLES100, - _platformMacros, - ShaderPass._shaderRootPath, - new URL(_path, ShaderPass._shaderRootPath).href + platformMacros, + new URL(path, ShaderPass._shaderRootPath).href ); Logger.info(`[ShaderLab compilation] cost time: ${performance.now() - start}ms`); diff --git a/packages/design/src/shader-lab/IShaderLab.ts b/packages/design/src/shader-lab/IShaderLab.ts index 22f9012a9d..fec2d72571 100644 --- a/packages/design/src/shader-lab/IShaderLab.ts +++ b/packages/design/src/shader-lab/IShaderLab.ts @@ -14,8 +14,7 @@ export interface IShaderLab { /** * @internal * Parse shader pass source code. - * @param pathOrigin follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` - * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must be prefixed by `pathOrigin` + * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` */ _parseShaderPass( shaderPassSource: string, @@ -24,7 +23,6 @@ export interface IShaderLab { macros: any[], backend: number, platformMacros: string[], - pathOrigin: string, basePathForIncludeKey: string ): IShaderProgramSource; } diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 4be32fce0c..335d64c47e 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -5,7 +5,7 @@ import { GLES100Visitor, GLES300Visitor } from "./codeGen"; import { IShaderContent, IShaderLab } from "@galacean/engine-design/src/shader-lab"; import { ShaderContentParser } from "./contentParser"; // @ts-ignore -import { Logger, ShaderLib, ShaderMacro, ShaderPlatformTarget } from "@galacean/engine"; +import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; @@ -54,11 +54,10 @@ export class ShaderLab implements IShaderLab { macros: ShaderMacro[], backend: ShaderPlatformTarget, platformMacros: string[], - pathOrigin: string, basePathForIncludeKey: string ) { ShaderLabObjectPool.clearAllShaderLabObjectPool(); - Preprocessor.reset(ShaderLib, pathOrigin, basePathForIncludeKey); + Preprocessor.reset(ShaderLib, basePathForIncludeKey); for (const macro of macros) { Preprocessor.addPredefinedMacro(macro.name, macro.value); } @@ -121,8 +120,8 @@ export class ShaderLab implements IShaderLab { macros, backend, [], - "shaders://root/", - new URL(pass.name, "shaders://root/").href + // @ts-ignore + new URL(pass.name, ShaderPass._shaderRootPath).href ) as any; passInfo.name = pass.name; passResult.push(passInfo); diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 02ee847c41..8b8b627b16 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -10,6 +10,7 @@ import { EPpKeyword, EPpToken, PpConstant } from "./constants"; import PpScanner from "./PpScanner"; import { PpUtils } from "./Utils"; import { ShaderLab } from "../ShaderLab"; +import { ShaderPass } from "@galacean/engine"; export interface ExpandSegment { // #if _EDITOR @@ -29,9 +30,8 @@ export default class PpParser { private static _includeMap: Record; private static _basePathForIncludeKey: string; - private static _pathOrigin: string; - static reset(includeMap: Record, pathOrigin: string, basePathForIncludeKey: string) { + static reset(includeMap: Record, basePathForIncludeKey: string) { this._definedMacros.clear(); this._expandSegmentsStack.length = 0; this._expandSegmentsStack.push([]); @@ -39,7 +39,6 @@ export default class PpParser { this.addPredefinedMacro("GL_ES"); this._includeMap = includeMap; this._basePathForIncludeKey = basePathForIncludeKey; - this._pathOrigin = pathOrigin; } static addPredefinedMacro(macro: string, value?: string) { @@ -104,7 +103,8 @@ export default class PpParser { includedPath = id.lexeme; } else { // relative path - includedPath = new URL(id.lexeme, this._basePathForIncludeKey).href.substring(this._pathOrigin.length); + // @ts-ignore + includedPath = new URL(id.lexeme, this._basePathForIncludeKey).href.substring(ShaderPass._shaderRootPath.length); } scanner.scanToChar("\n"); diff --git a/packages/shader-lab/src/preprocessor/Preprocessor.ts b/packages/shader-lab/src/preprocessor/Preprocessor.ts index c14a3e4e09..1f37c0caec 100644 --- a/packages/shader-lab/src/preprocessor/Preprocessor.ts +++ b/packages/shader-lab/src/preprocessor/Preprocessor.ts @@ -10,8 +10,8 @@ export class Preprocessor { * @param pathOrigin follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must be prefixed by `pathOrigin` */ - static reset(includeMap: Record, pathOrigin: string, basePathForIncludeKey: string): void { - PpParser.reset(includeMap, pathOrigin, basePathForIncludeKey); + static reset(includeMap: Record, basePathForIncludeKey: string): void { + PpParser.reset(includeMap, basePathForIncludeKey); } /** diff --git a/tests/src/shader-lab/ShaderValidate.ts b/tests/src/shader-lab/ShaderValidate.ts index 016ca86112..adf297ed42 100644 --- a/tests/src/shader-lab/ShaderValidate.ts +++ b/tests/src/shader-lab/ShaderValidate.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; import { ShaderLab } from "@galacean/engine-shader-lab"; -import { Shader, ShaderFactory, ShaderPlatformTarget } from "@galacean/engine-core"; +import { Shader, ShaderFactory, ShaderPass, ShaderPlatformTarget } from "@galacean/engine-core"; import { IShaderContent } from "@galacean/engine-design/src/shader-lab"; function addLineNum(str: string) { @@ -87,8 +87,8 @@ export function glslValidate(shaderSource, _shaderLab?: ShaderLab, includeMap = [], ShaderPlatformTarget.GLES300, [], - "shaders://root/", - "shaders://root/" + // @ts-ignore + ShaderPass._shaderRootPath ); validateShaderPass(pass, compiledPass.vertex, compiledPass.fragment); }); From ee6a8139fca739937df18570573f8e5873a47949 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 14:45:45 +0800 Subject: [PATCH 27/60] feat: code opt --- packages/core/src/shader/Shader.ts | 36 +++++++++++++++----------- packages/core/src/shader/ShaderPass.ts | 10 ++++--- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index 270333c4e8..799dc6cd8c 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -44,13 +44,12 @@ export class Shader implements IReferable { * ``` * * @param shaderSource - shader code - * @param path - used by the preprocessor in `ShaderLab` to resolve the relative path of `#include` directive * @returns Shader * * @throws * Throw string exception if shaderLab has not been enabled properly. */ - static create(shaderSource: string, path?: string): Shader; + static create(shaderSource: string): Shader; /** * Create a shader. @@ -79,17 +78,13 @@ export class Shader implements IReferable { static create( nameOrShaderSource: string, - vertexSourceOrShaderPassesOrSubShadersOrPath?: SubShader[] | ShaderPass[] | string, + vertexSourceOrShaderPassesOrSubShaders?: SubShader[] | ShaderPass[] | string, fragmentSource?: string ): Shader { let shader: Shader; const shaderMap = Shader._shaderMap; - if ( - !fragmentSource && - (vertexSourceOrShaderPassesOrSubShadersOrPath === undefined || - typeof vertexSourceOrShaderPassesOrSubShadersOrPath === "string") - ) { + if (!vertexSourceOrShaderPassesOrSubShaders) { if (!Shader._shaderLab) { throw "ShaderLab has not been set up yet."; } @@ -114,7 +109,6 @@ export class Shader implements IReferable { passInfo.contents, passInfo.vertexEntry, passInfo.fragmentEntry, - vertexSourceOrShaderPassesOrSubShadersOrPath ?? "", passInfo.tags ); @@ -149,17 +143,17 @@ export class Shader implements IReferable { console.error(`Shader named "${nameOrShaderSource}" already exists.`); return; } - if (typeof vertexSourceOrShaderPassesOrSubShadersOrPath === "string") { - const shaderPass = new ShaderPass(vertexSourceOrShaderPassesOrSubShadersOrPath, fragmentSource); + if (typeof vertexSourceOrShaderPassesOrSubShaders === "string") { + const shaderPass = new ShaderPass(vertexSourceOrShaderPassesOrSubShaders, fragmentSource); shader = new Shader(nameOrShaderSource, [new SubShader("Default", [shaderPass])]); } else { - if (vertexSourceOrShaderPassesOrSubShadersOrPath.length > 0) { - if (vertexSourceOrShaderPassesOrSubShadersOrPath[0].constructor === ShaderPass) { + if (vertexSourceOrShaderPassesOrSubShaders.length > 0) { + if (vertexSourceOrShaderPassesOrSubShaders[0].constructor === ShaderPass) { shader = new Shader(nameOrShaderSource, [ - new SubShader("Default", vertexSourceOrShaderPassesOrSubShadersOrPath) + new SubShader("Default", vertexSourceOrShaderPassesOrSubShaders) ]); } else { - shader = new Shader(nameOrShaderSource, vertexSourceOrShaderPassesOrSubShadersOrPath.slice()); + shader = new Shader(nameOrShaderSource, vertexSourceOrShaderPassesOrSubShaders.slice()); } } else { throw "SubShader or ShaderPass count must large than 0."; @@ -287,6 +281,18 @@ export class Shader implements IReferable { return this._destroyed; } + /** + * @internal + * path should follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` + */ + _registerPath(path: string) { + for (const subShader of this._subShaders) { + for (const shaderPass of subShader.passes) { + shaderPass.path = path; + } + } + } + private constructor( public readonly name: string, subShaders: SubShader[] diff --git a/packages/core/src/shader/ShaderPass.ts b/packages/core/src/shader/ShaderPass.ts index 9c0e13f66e..c8ecf4040b 100644 --- a/packages/core/src/shader/ShaderPass.ts +++ b/packages/core/src/shader/ShaderPass.ts @@ -41,10 +41,15 @@ export class ShaderPass extends ShaderPart { private readonly _shaderLabSource: string; private readonly _vertexEntry: string; private readonly _fragmentEntry: string; - private readonly _path: string; + private _path = ""; private _platformMacros: string[] = []; + /** @internal */ + set path(val: string) { + this._path = val; + } + /** * @internal */ @@ -53,7 +58,6 @@ export class ShaderPass extends ShaderPart { shaderLabSource: string, vertexEntry: string, fragmentEntry: string, - path: string, tags?: Record ); @@ -84,7 +88,6 @@ export class ShaderPass extends ShaderPart { vertexSourceOrFragmentSourceOrCode?: string | Record, fragmentSourceOrTagsOrVertexEntry?: string | Record, fragmentEntryOrTags?: string | Record, - tagsOrPath?: Record | string, tags?: Record ) { super(); @@ -93,7 +96,6 @@ export class ShaderPass extends ShaderPart { if (typeof fragmentEntryOrTags === "string") { this._name = nameOrVertexSource; - this._path = tagsOrPath as string; this._shaderLabSource = vertexSourceOrFragmentSourceOrCode as string; this._vertexEntry = fragmentSourceOrTagsOrVertexEntry as string; this._fragmentEntry = fragmentEntryOrTags; From d7e0ac87e177b0409e2a5a1169cea1e89d928bc8 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 15:11:03 +0800 Subject: [PATCH 28/60] feat: code opt --- packages/shader-lab/src/preprocessor/PpParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 8b8b627b16..025d311cc0 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -99,7 +99,7 @@ export default class PpParser { const id = scanner.scanQuotedString(); let includedPath: string; // builtin path - if (id.lexeme[0] !== "." && id.lexeme[0] !== "/") { + if (id.lexeme[0] !== ".") { includedPath = id.lexeme; } else { // relative path From 8f75c28312314eff486a71449a3df13f5b59f078 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 15:28:37 +0800 Subject: [PATCH 29/60] feat: code opt --- packages/core/src/shader/Shader.ts | 2 +- packages/core/src/shader/ShaderPass.ts | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/core/src/shader/Shader.ts b/packages/core/src/shader/Shader.ts index 799dc6cd8c..8b216200ef 100644 --- a/packages/core/src/shader/Shader.ts +++ b/packages/core/src/shader/Shader.ts @@ -288,7 +288,7 @@ export class Shader implements IReferable { _registerPath(path: string) { for (const subShader of this._subShaders) { for (const shaderPass of subShader.passes) { - shaderPass.path = path; + shaderPass._path = path; } } } diff --git a/packages/core/src/shader/ShaderPass.ts b/packages/core/src/shader/ShaderPass.ts index c8ecf4040b..934b8030a0 100644 --- a/packages/core/src/shader/ShaderPass.ts +++ b/packages/core/src/shader/ShaderPass.ts @@ -41,15 +41,11 @@ export class ShaderPass extends ShaderPart { private readonly _shaderLabSource: string; private readonly _vertexEntry: string; private readonly _fragmentEntry: string; - private _path = ""; + /** @internal */ + _path = ""; private _platformMacros: string[] = []; - /** @internal */ - set path(val: string) { - this._path = val; - } - /** * @internal */ From 00447fb46a3b228bf29a9ccfd0d1acf0839a40aa Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 18 Jul 2024 15:30:28 +0800 Subject: [PATCH 30/60] feat: code opt --- packages/shader-lab/src/preprocessor/Preprocessor.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/shader-lab/src/preprocessor/Preprocessor.ts b/packages/shader-lab/src/preprocessor/Preprocessor.ts index 1f37c0caec..35021f393e 100644 --- a/packages/shader-lab/src/preprocessor/Preprocessor.ts +++ b/packages/shader-lab/src/preprocessor/Preprocessor.ts @@ -7,8 +7,7 @@ export class Preprocessor { /** * Reset the parser of `Preprocessor` - * @param pathOrigin follow the specifications of [URL.origin](https://developer.mozilla.org/en-US/docs/Web/API/URL/origin), like: `shaders://root/` - * @param basePathForIncludeKey the base path to resolve the relative path of `#include` directive. Must be prefixed by `pathOrigin` + * @param basePathForIncludeKey - the base path to resolve the relative path of `#include` directive */ static reset(includeMap: Record, basePathForIncludeKey: string): void { PpParser.reset(includeMap, basePathForIncludeKey); From d5a3c0cb9169e6b122dd8370c0d799306a077d32 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Fri, 19 Jul 2024 18:05:33 +0800 Subject: [PATCH 31/60] feat: add log --- packages/core/src/index.ts | 2 + packages/shader-lab/src/Error.ts | 17 +++++-- packages/shader-lab/src/ShaderLab.ts | 19 +++++++- .../shader-lab/src/common/ShaderPosition.ts | 4 ++ packages/shader-lab/src/common/ShaderRange.ts | 4 ++ .../shader-lab/src/preprocessor/PpParser.ts | 45 ++++++++++++------- .../src/preprocessor/Preprocessor.ts | 8 +++- 7 files changed, 79 insertions(+), 20 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 01952de4e2..df404a7cf9 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -66,3 +66,5 @@ export * from "./Utils"; export { ShaderMacroCollection } from "./shader/ShaderMacroCollection"; export * from "./postProcess"; +/** @internal */ +export { ShaderProgram } from "./shader/ShaderProgram"; diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 6649f64157..06163f21a7 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -1,13 +1,24 @@ // #if _EDITOR -import { ShaderRange } from "./common"; +import { ShaderPosition, ShaderRange } from "./common"; export abstract class GSError extends Error { - readonly loc: ShaderRange; + readonly loc: ShaderRange | ShaderPosition; - constructor(message: string, loc: ShaderRange, cause?: Error) { + constructor(message: string, loc: ShaderRange | ShaderPosition, cause?: Error) { super(message, { cause }); this.loc = loc; } + + override toString(): string { + return `${this.loc.toString()}: ${this.message}`; + } +} + +export class PreprocessorError extends GSError { + constructor(message: string, loc: ShaderRange | ShaderPosition, cause?: Error) { + super(message, loc, cause); + this.name = "PreprocessorError"; + } } export class SemanticError extends GSError { diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 335d64c47e..a19981711a 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -5,9 +5,10 @@ import { GLES100Visitor, GLES300Visitor } from "./codeGen"; import { IShaderContent, IShaderLab } from "@galacean/engine-design/src/shader-lab"; import { ShaderContentParser } from "./contentParser"; // @ts-ignore -import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget } from "@galacean/engine"; +import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget, ShaderProgram } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; +import { GSError, PreprocessorError } from "./Error"; export class ShaderLab implements IShaderLab { /** @@ -74,6 +75,10 @@ export class ShaderLab implements IShaderLab { const preprocessorStart = performance.now(); const ppdContent = Preprocessor.process(source); + if (Preprocessor.errors.length > 0) { + this._reportPreprocessError(Preprocessor.errors, source); + return { vertex: "", fragment: "" }; + } Logger.info(`[pass compilation - preprocessor] cost time ${performance.now() - preprocessorStart}ms`); @@ -130,4 +135,16 @@ export class ShaderLab implements IShaderLab { return passResult; } // #endif + + private _reportPreprocessError(errors: PreprocessorError[], source: string) { + const errorsMsg = errors.map((item) => item.toString()).join("\n"); + console.error( + "Error occur when expansion ShaderLab code:\n\n" + + errorsMsg + + "ShaderLab source:\n\n" + + ShaderProgram._addLineNum(source) + ); + } + + // private _reportParserError() } diff --git a/packages/shader-lab/src/common/ShaderPosition.ts b/packages/shader-lab/src/common/ShaderPosition.ts index 3b5ee0fc24..5b173ba834 100644 --- a/packages/shader-lab/src/common/ShaderPosition.ts +++ b/packages/shader-lab/src/common/ShaderPosition.ts @@ -26,4 +26,8 @@ export class ShaderPosition implements IPoolElement { this.line = 0; this.column = 0; } + + toString() { + return ``; + } } diff --git a/packages/shader-lab/src/common/ShaderRange.ts b/packages/shader-lab/src/common/ShaderRange.ts index e79d4143e0..41a6e436bc 100644 --- a/packages/shader-lab/src/common/ShaderRange.ts +++ b/packages/shader-lab/src/common/ShaderRange.ts @@ -14,4 +14,8 @@ export class ShaderRange implements IPoolElement { this.start.dispose(); this.end.dispose(); } + + toString() { + return `[Start: ${this.start.toString()}; End: ${this.end.toString()}]`; + } } diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 025d311cc0..8af73fb6ca 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -1,4 +1,4 @@ -import { ShaderRange } from "../common"; +import { ShaderPosition, ShaderRange } from "../common"; import LexerUtils from "../lexer/Utils"; import { MacroDefine } from "./MacroDefine"; // #if _EDITOR @@ -10,7 +10,8 @@ import { EPpKeyword, EPpToken, PpConstant } from "./constants"; import PpScanner from "./PpScanner"; import { PpUtils } from "./Utils"; import { ShaderLab } from "../ShaderLab"; -import { ShaderPass } from "@galacean/engine"; +import { Logger, ShaderPass } from "@galacean/engine"; +import { PreprocessorError } from "../Error"; export interface ExpandSegment { // #if _EDITOR @@ -31,6 +32,9 @@ export default class PpParser { private static _includeMap: Record; private static _basePathForIncludeKey: string; + /** @internal */ + static _errors: PreprocessorError[] = []; + static reset(includeMap: Record, basePathForIncludeKey: string) { this._definedMacros.clear(); this._expandSegmentsStack.length = 0; @@ -39,6 +43,7 @@ export default class PpParser { this.addPredefinedMacro("GL_ES"); this._includeMap = includeMap; this._basePathForIncludeKey = basePathForIncludeKey; + this._errors.length = 0; } static addPredefinedMacro(macro: string, value?: string) { @@ -54,8 +59,8 @@ export default class PpParser { this._definedMacros.set(macro, new MacroDefine(tk, macroBody)); } - static parse(scanner: PpScanner): string { - while (!scanner.isEnd()) { + static parse(scanner: PpScanner): string | null { + while (!scanner.isEnd() && this._errors.length === 0) { const directive = scanner.scanDirective(this._onToken.bind(this))!; if (scanner.isEnd()) break; switch (directive.type) { @@ -84,6 +89,7 @@ export default class PpParser { break; } } + if (this._errors.length > 0) return null; return PpUtils.expand(this.expandSegments, scanner.source, scanner.sourceMap); } @@ -92,6 +98,10 @@ export default class PpParser { return this._expandSegmentsStack[this._expandSegmentsStack.length - 1]; } + private static reportError(loc: ShaderRange | ShaderPosition, message: string) { + this._errors.push(new PreprocessorError(message, loc)); + } + private static _parseInclude(scanner: PpScanner) { const start = scanner.getShaderPosition(8); @@ -111,7 +121,9 @@ export default class PpParser { const end = scanner.getShaderPosition(); const chunk = this._includeMap[includedPath]; if (!chunk) { - ParserUtils.throw(id.location, `Shader slice "${includedPath}" not founded.`); + this.reportError(id.location, `Shader slice "${includedPath}" not founded.`); + + return; } const range = ShaderLab.createRange(start, end); @@ -285,7 +297,8 @@ export default class PpParser { scanner.skipSpace(false); const operand2 = this._parseRelationalExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - ParserUtils.throw(opPos, "invalid operator in relation expression."); + this.reportError(opPos, "invalid operator in relation expression."); + return; } switch (operator) { case ">": @@ -310,7 +323,8 @@ export default class PpParser { scanner.skipSpace(false); const operand2 = this._parseShiftExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - ParserUtils.throw(opPos, "invalid operator in shift expression."); + this.reportError(opPos, "invalid operator in shift expression."); + return; } switch (operator) { case ">>": @@ -333,7 +347,8 @@ export default class PpParser { scanner.skipSpace(false); const operand2 = this._parseAdditiveExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - ParserUtils.throw(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator."); + return false; } switch (operator) { case "+": @@ -354,7 +369,8 @@ export default class PpParser { scanner.skipSpace(false); const operand2 = this._parseMulticativeExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - ParserUtils.throw(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator."); + return; } switch (operator) { case "*": @@ -375,7 +391,7 @@ export default class PpParser { const opPos = scanner.getShaderPosition(); const parenExpr = this._parseParenthesisExpression(scanner); if ((operator === "!" && typeof parenExpr !== "boolean") || (operator !== "!" && typeof parenExpr !== "number")) { - ParserUtils.throw(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator."); } switch (operator) { @@ -417,15 +433,14 @@ export default class PpParser { } else { const macro = this._definedMacros.get(id.lexeme); if (!macro) { - // ParserUtils.throw(id.location, 'undefined macro:', id.lexeme); return false; } if (macro.isFunction) { - ParserUtils.throw(id.location, "invalid function macro usage"); + this.reportError(id.location, "invalid function macro usage"); } const value = Number(macro.body.lexeme); if (!Number.isInteger(value)) { - ParserUtils.throw(id.location, "invalid const macro:", id.lexeme); + this.reportError(id.location, `invalid const macro: ${id.lexeme}`); } this._branchMacros.add(id.lexeme); return value; @@ -434,7 +449,7 @@ export default class PpParser { const integer = scanner.scanInteger(); return Number(integer.lexeme); } else { - ParserUtils.throw(scanner.getShaderPosition(), "invalid token", scanner.getCurChar()); + this.reportError(scanner.getShaderPosition(), `invalid token: ${scanner.getCurChar()}`); } } @@ -571,7 +586,7 @@ export default class PpParser { let end = macro.location.end; if (this._definedMacros.get(macro.lexeme) && macro.lexeme.startsWith("GL_")) { - ParserUtils.throw(macro.location, "redefined macro:", macro.lexeme); + this.reportError(macro.location, `redefined macro: ${macro.lexeme}`); } let macroArgs: BaseToken[] | undefined; diff --git a/packages/shader-lab/src/preprocessor/Preprocessor.ts b/packages/shader-lab/src/preprocessor/Preprocessor.ts index 35021f393e..1e06f346db 100644 --- a/packages/shader-lab/src/preprocessor/Preprocessor.ts +++ b/packages/shader-lab/src/preprocessor/Preprocessor.ts @@ -1,8 +1,14 @@ +import { PreprocessorError } from "../Error"; import PpParser from "./PpParser"; import PpScanner from "./PpScanner"; /** @internal */ export class Preprocessor { + /** @internal */ + static get errors(): PreprocessorError[] { + return PpParser._errors; + } + static baseScanner: PpScanner; /** @@ -16,7 +22,7 @@ export class Preprocessor { /** * Should call it after reset. */ - static process(source: string): string { + static process(source: string): string | null { this.baseScanner = new PpScanner(source); return PpParser.parse(this.baseScanner); } From c1762262d15cbf7f88c4b85a67acbc168cc4ab2e Mon Sep 17 00:00:00 2001 From: Sway007 Date: Fri, 19 Jul 2024 20:03:34 +0800 Subject: [PATCH 32/60] feat: add log --- packages/shader-lab/src/Error.ts | 4 +--- packages/shader-lab/src/ShaderLab.ts | 23 +++++++++++-------- packages/shader-lab/src/common/BaseScanner.ts | 13 +++++++++-- .../shader-lab/src/common/ShaderPosition.ts | 2 +- packages/shader-lab/src/common/ShaderRange.ts | 2 +- .../shader-lab/src/preprocessor/PpParser.ts | 8 ++++++- .../shader-lab/src/preprocessor/PpScanner.ts | 3 --- .../src/preprocessor/Preprocessor.ts | 8 +------ 8 files changed, 35 insertions(+), 28 deletions(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 06163f21a7..669ab2655a 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -1,4 +1,3 @@ -// #if _EDITOR import { ShaderPosition, ShaderRange } from "./common"; export abstract class GSError extends Error { @@ -10,7 +9,7 @@ export abstract class GSError extends Error { } override toString(): string { - return `${this.loc.toString()}: ${this.message}`; + return `${this.loc.toString()}\nReason: ${this.message}`; } } @@ -27,4 +26,3 @@ export class SemanticError extends GSError { this.name = "SemanticError"; } } -// #endif diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index a19981711a..34db4640c5 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -8,7 +8,8 @@ import { ShaderContentParser } from "./contentParser"; import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget, ShaderProgram } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; -import { GSError, PreprocessorError } from "./Error"; +import { PreprocessorError } from "./Error"; +import { PpParser } from "./preprocessor/PpParser"; export class ShaderLab implements IShaderLab { /** @@ -75,8 +76,8 @@ export class ShaderLab implements IShaderLab { const preprocessorStart = performance.now(); const ppdContent = Preprocessor.process(source); - if (Preprocessor.errors.length > 0) { - this._reportPreprocessError(Preprocessor.errors, source); + if (PpParser._errors.length > 0) { + this._reportPreprocessError(PpParser._errors); return { vertex: "", fragment: "" }; } @@ -136,14 +137,16 @@ export class ShaderLab implements IShaderLab { } // #endif - private _reportPreprocessError(errors: PreprocessorError[], source: string) { + private _reportPreprocessError(errors: PreprocessorError[]) { const errorsMsg = errors.map((item) => item.toString()).join("\n"); - console.error( - "Error occur when expansion ShaderLab code:\n\n" + - errorsMsg + - "ShaderLab source:\n\n" + - ShaderProgram._addLineNum(source) - ); + if (Logger.isEnabled) { + Logger.error( + `\nPreprocessor error occur in file ${PpParser._scanningFile}:\n\n` + + errorsMsg + + "ShaderLab source:\n\n" + + ShaderProgram._addLineNum(PpParser._scanningText) + ); + } } // private _reportParserError() diff --git a/packages/shader-lab/src/common/BaseScanner.ts b/packages/shader-lab/src/common/BaseScanner.ts index 87ca8f80a5..2b28672093 100644 --- a/packages/shader-lab/src/common/BaseScanner.ts +++ b/packages/shader-lab/src/common/BaseScanner.ts @@ -44,6 +44,16 @@ export default class BaseScanner { ); } + // #if _EDITOR + get line() { + return this._line; + } + + get column() { + return this._column; + } + // #endif + protected readonly _keywordsMap: Map; constructor(source: string, kws: Map = new Map()) { @@ -73,8 +83,6 @@ export default class BaseScanner { return; } - this._currentIndex++; - // #if _EDITOR if (this.getCurChar() === "\n") { this._line += 1; @@ -83,6 +91,7 @@ export default class BaseScanner { this._column += 1; } // #endif + this._currentIndex++; } skipSpace(includeLineBreak: boolean): void { diff --git a/packages/shader-lab/src/common/ShaderPosition.ts b/packages/shader-lab/src/common/ShaderPosition.ts index 5b173ba834..308e02b58d 100644 --- a/packages/shader-lab/src/common/ShaderPosition.ts +++ b/packages/shader-lab/src/common/ShaderPosition.ts @@ -28,6 +28,6 @@ export class ShaderPosition implements IPoolElement { } toString() { - return ``; + return ``; } } diff --git a/packages/shader-lab/src/common/ShaderRange.ts b/packages/shader-lab/src/common/ShaderRange.ts index 41a6e436bc..8b450e51e8 100644 --- a/packages/shader-lab/src/common/ShaderRange.ts +++ b/packages/shader-lab/src/common/ShaderRange.ts @@ -16,6 +16,6 @@ export class ShaderRange implements IPoolElement { } toString() { - return `[Start: ${this.start.toString()}; End: ${this.end.toString()}]`; + return `Start: ${this.start.toString()};\nEnd: ${this.end.toString()}\n`; } } diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 8af73fb6ca..40b2441713 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -22,7 +22,7 @@ export interface ExpandSegment { } /** @internal */ -export default class PpParser { +export class PpParser { private static _definedMacros: Map = new Map(); private static _expandSegmentsStack: ExpandSegment[][] = [[]]; @@ -34,6 +34,10 @@ export default class PpParser { /** @internal */ static _errors: PreprocessorError[] = []; + /** @internal */ + static _scanningText: string; + /** @internal */ + static _scanningFile = "__main__"; static reset(includeMap: Record, basePathForIncludeKey: string) { this._definedMacros.clear(); @@ -60,6 +64,8 @@ export default class PpParser { } static parse(scanner: PpScanner): string | null { + this._scanningText = scanner.source; + this._scanningFile = scanner.file; while (!scanner.isEnd() && this._errors.length === 0) { const directive = scanner.scanDirective(this._onToken.bind(this))!; if (scanner.isEnd()) break; diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index 892f8b87d3..b2f56c8b37 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -15,9 +15,6 @@ export type OnToken = (token: BaseToken, scanner: PpScanner) => void; export default class PpScanner extends BaseScanner { private static _splitCharacters = /[\w#.]/; - private line: number = 0; - private column: number = 0; - private macroLvl = 0; // #if _EDITOR diff --git a/packages/shader-lab/src/preprocessor/Preprocessor.ts b/packages/shader-lab/src/preprocessor/Preprocessor.ts index 1e06f346db..7eb6278792 100644 --- a/packages/shader-lab/src/preprocessor/Preprocessor.ts +++ b/packages/shader-lab/src/preprocessor/Preprocessor.ts @@ -1,14 +1,8 @@ -import { PreprocessorError } from "../Error"; -import PpParser from "./PpParser"; +import { PpParser } from "./PpParser"; import PpScanner from "./PpScanner"; /** @internal */ export class Preprocessor { - /** @internal */ - static get errors(): PreprocessorError[] { - return PpParser._errors; - } - static baseScanner: PpScanner; /** From b8ca43ff5e38a67668ef08238f10def470a427d3 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 22 Jul 2024 14:49:49 +0800 Subject: [PATCH 33/60] feat: add log --- packages/shader-lab/src/Error.ts | 4 +- packages/shader-lab/src/ShaderLab.ts | 38 ++++++++++--------- .../shader-lab/src/parser/SemanticAnalyzer.ts | 14 ++----- .../src/parser/ShaderTargetParser.ts | 14 ++++++- .../src/parser/builtin/functions.ts | 4 +- 5 files changed, 41 insertions(+), 33 deletions(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 669ab2655a..4264c2411b 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -9,7 +9,7 @@ export abstract class GSError extends Error { } override toString(): string { - return `${this.loc.toString()}\nReason: ${this.message}`; + return `>>>>>\n${this.loc.toString()}\nReason: ${this.message}\n<<<<<`; } } @@ -20,7 +20,7 @@ export class PreprocessorError extends GSError { } } -export class SemanticError extends GSError { +export class CompilationError extends GSError { constructor(message: string, loc: ShaderRange, cause?: Error) { super(message, loc, cause); this.name = "SemanticError"; diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 34db4640c5..246eb336ee 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -8,7 +8,7 @@ import { ShaderContentParser } from "./contentParser"; import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget, ShaderProgram } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; -import { PreprocessorError } from "./Error"; +import { PreprocessorError, CompilationError } from "./Error"; import { PpParser } from "./preprocessor/PpParser"; export class ShaderLab implements IShaderLab { @@ -68,13 +68,7 @@ export class ShaderLab implements IShaderLab { Preprocessor.addPredefinedMacro(platformMacros[i]); } - // #if _EDITOR - // TODO: index to position - // Logger.convertSourceIndex = Preprocessor.convertSourceIndex.bind(Preprocessor); - // #endif - const preprocessorStart = performance.now(); - const ppdContent = Preprocessor.process(source); if (PpParser._errors.length > 0) { this._reportPreprocessError(PpParser._errors); @@ -85,8 +79,12 @@ export class ShaderLab implements IShaderLab { const lexer = new Lexer(ppdContent); const tokens = lexer.tokenize(); - const program = ShaderLab._parser.parse(tokens); + + const { _parser: parser } = ShaderLab; + + const program = parser.parse(tokens); if (!program) { + this._reportParserError(parser.errors, ppdContent); return { vertex: "", fragment: "" }; } const codeGen = @@ -138,16 +136,22 @@ export class ShaderLab implements IShaderLab { // #endif private _reportPreprocessError(errors: PreprocessorError[]) { + if (!Logger.isEnabled) return; const errorsMsg = errors.map((item) => item.toString()).join("\n"); - if (Logger.isEnabled) { - Logger.error( - `\nPreprocessor error occur in file ${PpParser._scanningFile}:\n\n` + - errorsMsg + - "ShaderLab source:\n\n" + - ShaderProgram._addLineNum(PpParser._scanningText) - ); - } + Logger.error( + `\nPreprocessor error occur in file ${PpParser._scanningFile}:\n\n` + + errorsMsg + + "\nShaderLab source:\n\n" + + ShaderProgram._addLineNum(PpParser._scanningText) + ); } - // private _reportParserError() + private _reportParserError(errors: CompilationError[], source: string) { + if (!Logger.isEnabled) return; + const errorsMsg = errors.map((item) => item.toString()).join("\n"); + Logger.error( + `\nShaderLab syntax error occur.\n${errorsMsg}\n\nExpanded ShaderLab source:\n\n` + + ShaderProgram._addLineNum(source) + ); + } } diff --git a/packages/shader-lab/src/parser/SemanticAnalyzer.ts b/packages/shader-lab/src/parser/SemanticAnalyzer.ts index ea7b0487bf..fd61bd53c9 100644 --- a/packages/shader-lab/src/parser/SemanticAnalyzer.ts +++ b/packages/shader-lab/src/parser/SemanticAnalyzer.ts @@ -1,7 +1,7 @@ import { ShaderRange } from "../common"; import { TreeNode } from "./AST"; // #if _EDITOR -import { SemanticError } from "../Error"; +import { CompilationError } from "../Error"; // #endif import { ShaderData } from "./ShaderInfo"; import { SymbolInfo, SymbolTable } from "../parser/symbolTable"; @@ -22,9 +22,7 @@ export default class SematicAnalyzer { symbolTable: SymbolTableStack = new SymbolTableStack(); private _shaderData = new ShaderData(); - // #if _EDITOR - readonly errors: SemanticError[] = []; - // #endif + readonly errors: CompilationError[] = []; get shaderData() { return this._shaderData; @@ -41,9 +39,7 @@ export default class SematicAnalyzer { this._shaderData = new ShaderData(); this.symbolTable.clear(); this.newScope(); - // #if _EDITOR this.errors.length = 0; - // #endif } newScope() { @@ -63,13 +59,11 @@ export default class SematicAnalyzer { return this._translationRuleTable.get(pid); } - // #if _EDITOR error(loc: ShaderRange, ...param: any[]) { - Logger.error(loc, ...param); + // Logger.warn(loc, ...param); - const err = new SemanticError(param.join(""), loc); + const err = new CompilationError(param.join(""), loc); this.errors.push(err); return err; } - // #endif } diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index 56250740b7..89d268af36 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -10,6 +10,7 @@ import { addTranslationRule, createGrammar } from "../lalr/CFG"; import { LALR1 } from "../lalr"; import { ParserUtils } from "../Utils"; import { Logger } from "@galacean/engine"; +import { CompilationError } from "../Error"; /** * The syntax parser and sematic analyzer of `ShaderLab` compiler @@ -31,6 +32,11 @@ export class ShaderTargetParser { return this.gotoTable.get(this.curState); } + /** @internal */ + get errors() { + return this.sematicAnalyzer.errors; + } + static _singleton: ShaderTargetParser; static create() { @@ -53,7 +59,7 @@ export class ShaderTargetParser { } parse(tokens: Generator): ASTNode.GLShaderProgram | null { - this.sematicAnalyzer.reset(); + this._reset(); const start = performance.now(); const { _traceBackStack: traceBackStack, sematicAnalyzer } = this; traceBackStack.push(0); @@ -103,12 +109,16 @@ export class ShaderTargetParser { traceBackStack.push(nextState); continue; } else { - Logger.error(token.location, `parse error token ${token.lexeme}`); + this.sematicAnalyzer.errors.push(new CompilationError(`Unexpected token ${token.lexeme}`, token.location)); return null; } } } + private _reset() { + this.sematicAnalyzer.reset(); + } + // #if _EDITOR private _printStack(nextToken: BaseToken) { let str = ""; diff --git a/packages/shader-lab/src/parser/builtin/functions.ts b/packages/shader-lab/src/parser/builtin/functions.ts index d6b5d4dcf3..d43bb85f5c 100644 --- a/packages/shader-lab/src/parser/builtin/functions.ts +++ b/packages/shader-lab/src/parser/builtin/functions.ts @@ -136,8 +136,8 @@ BuiltinFunction._create("max", EGenType.GenType, EGenType.GenType); BuiltinFunction._create("max", EGenType.GenType, EKeyword.FLOAT); BuiltinFunction._create("max", EGenType.GenIntType, EGenType.GenIntType); BuiltinFunction._create("max", EGenType.GenIntType, EKeyword.INT); -BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EGenType.GenUintType); -BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EKeyword.UINT); +// BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EGenType.GenUintType); +// BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EKeyword.UINT); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EGenType.GenType, EGenType.GenType); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT, EKeyword.FLOAT); BuiltinFunction._create("clamp", EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType); From ce23026e1ff15d143bba61490204e1894ef12ca8 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Thu, 1 Aug 2024 16:05:47 +0800 Subject: [PATCH 34/60] fix: multi dist --- packages/shader-lab/package.json | 1 + rollup.config.js | 61 +++++++++++++++----------- tests/src/shader-lab/ShaderLab.test.ts | 12 +---- tsconfig.json | 4 +- 4 files changed, 42 insertions(+), 36 deletions(-) diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index 9c84279881..35a57b309c 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -9,6 +9,7 @@ "main": "dist/main.js", "module": "dist/module.js", "browser": "dist/browser.min.js", + "editor": "dist/editor.js", "debug": "src/index.ts", "types": "types/index.d.ts", "scripts": { diff --git a/rollup.config.js b/rollup.config.js index f616b01aec..eb6a20e866 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,7 +8,6 @@ import serve from "rollup-plugin-serve"; import miniProgramPlugin from "./rollup.miniprogram.plugin"; import replace from "@rollup/plugin-replace"; import { swc, defineRollupSwcOption, minify } from "rollup-plugin-swc3"; -import modify from "rollup-plugin-modify"; import jscc from "rollup-plugin-jscc"; const { BUILD_TYPE, NODE_ENV } = process.env; @@ -26,6 +25,8 @@ const pkgs = fs }; }); +const shaderLabPkg = pkgs.find((item) => item.pkgJson.name === "@galacean/engine-shader-lab"); + // toGlobalName const extensions = [".js", ".jsx", ".ts", ".tsx"]; @@ -49,9 +50,6 @@ const commonPlugins = [ }) ), commonjs(), - jscc({ - values: { _EDITOR: NODE_ENV !== "release" } - }), NODE_ENV === "development" ? serve({ contentBase: "packages", @@ -60,9 +58,15 @@ const commonPlugins = [ : null ]; -function config({ location, pkgJson }) { +function config({ location, pkgJson, editorMode }) { const input = path.join(location, "src", "index.ts"); const dependencies = Object.assign({}, pkgJson.dependencies ?? {}, pkgJson.peerDependencies ?? {}); + commonPlugins.push( + jscc({ + values: { _EDITOR: NODE_ENV !== "release" || editorMode } + }) + ); + const external = Object.keys(dependencies); commonPlugins.push( replace({ @@ -76,17 +80,14 @@ function config({ location, pkgJson }) { const umdConfig = pkgJson.umd; let file = path.join(location, "dist", "browser.js"); - const plugins = [ - modify({ - find: "chevrotain", - replace: path.join(process.cwd(), "packages", "shader-lab", `./node_modules/chevrotain/lib/chevrotain.js`) - }), - ...commonPlugins - ]; + const plugins = commonPlugins; if (compress) { plugins.push(minify({ sourceMap: true })); file = path.join(location, "dist", "browser.min.js"); } + if (editorMode) { + file = path.join(location, "dist", "browser.editor.js"); + } const umdExternal = Object.keys(umdConfig.globals ?? {}); @@ -106,13 +107,17 @@ function config({ location, pkgJson }) { }; }, mini: () => { + let file = path.join(location, "dist", "miniprogram.js"); const plugins = [...commonPlugins, ...miniProgramPlugin]; + if (editorMode) { + file = path.join(location, "dist", "miniprogram.editor.js"); + } return { input, output: [ { format: "cjs", - file: path.join(location, "dist/miniprogram.js"), + file, sourcemap: false } ], @@ -121,24 +126,24 @@ function config({ location, pkgJson }) { }; }, module: () => { - const plugins = [ - modify({ - find: "chevrotain", - replace: path.join(process.cwd(), "packages", "shader-lab", `./node_modules/chevrotain/lib/chevrotain.js`) - }), - ...commonPlugins - ]; + const plugins = commonPlugins; + let esFile = pkgJson.module; + let mainFile = pkgJson.main; + if (editorMode) { + esFile = path.join(location, "dist", "module.editor.js"); + mainFile = path.join(location, "dist", "main.editor.js"); + } return { input, external, output: [ { - file: path.join(location, pkgJson.module), + file: esFile, format: "es", sourcemap: true }, { - file: path.join(location, pkgJson.main), + file: mainFile, sourcemap: true, format: "commonjs" } @@ -174,7 +179,7 @@ switch (BUILD_TYPE) { function getUMD() { const configs = pkgs.filter((pkg) => pkg.pkgJson.umd); - return configs + const umds = configs .map((config) => makeRollupConfig({ ...config, type: "umd" })) .concat( configs.map((config) => @@ -186,16 +191,22 @@ function getUMD() { }) ) ); + umds.push(makeRollupConfig({ ...shaderLabPkg, editorMode: true, type: "umd" })); + return umds; } function getModule() { const configs = [...pkgs]; - return configs.map((config) => makeRollupConfig({ ...config, type: "module" })); + const modules = configs.map((config) => makeRollupConfig({ ...config, type: "module" })); + modules.push(makeRollupConfig({ ...shaderLabPkg, editorMode: true, type: "module" })); + return modules; } function getMini() { const configs = [...pkgs]; - return configs.map((config) => makeRollupConfig({ ...config, type: "mini" })); + const minis = configs.map((config) => makeRollupConfig({ ...config, type: "mini" })); + minis.push(makeRollupConfig({ ...shaderLabPkg, editorMode: true, type: "mini" })); + return minis; } function getAll() { diff --git a/tests/src/shader-lab/ShaderLab.test.ts b/tests/src/shader-lab/ShaderLab.test.ts index 1fc6cbfed4..e6385ef312 100644 --- a/tests/src/shader-lab/ShaderLab.test.ts +++ b/tests/src/shader-lab/ShaderLab.test.ts @@ -1,14 +1,6 @@ -import { - BlendFactor, - BlendOperation, - CompareFunction, - CullMode, - RenderQueueType, - RenderStateDataKey, - StencilOperation -} from "@galacean/engine-core"; +import { BlendOperation, CompareFunction, CullMode, RenderStateDataKey } from "@galacean/engine-core"; import { Color } from "@galacean/engine-math"; -import { ShaderLab } from "@galacean/engine-shader-lab"; +import { ShaderLab } from "@galacean/engine-shader-lab/dist/main.editor"; import { glslValidate } from "./ShaderValidate"; import chai, { expect } from "chai"; diff --git a/tsconfig.json b/tsconfig.json index f62e2e508d..6bef4d478a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,9 @@ "skipLibCheck": true, "paths": { "@/*": ["src/*"] // 配置模块别名,对于 chair 项目需做更改,见下文 - } + }, + "allowJs": true, + "checkJs": false }, "exclude": ["node_modules", "types", "packages/*/tests"] } From 8c907960b645f66f50ca8edeaf96825572daa7f0 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Fri, 23 Aug 2024 14:15:08 +0800 Subject: [PATCH 35/60] feat(shaderlab): [wip] optmize error log --- packages/core/src/index.ts | 2 - packages/shader-lab/src/Error.ts | 70 +++++++++++++++-- packages/shader-lab/src/ShaderLab.ts | 78 +++++++++---------- packages/shader-lab/src/Utils.ts | 8 +- .../shader-lab/src/codeGen/CodeGenVisitor.ts | 2 - .../shader-lab/src/codeGen/GLESVisitor.ts | 26 ++++++- packages/shader-lab/src/common/BaseScanner.ts | 22 +++--- packages/shader-lab/src/common/BaseToken.ts | 8 +- .../shader-lab/src/common/ShaderPosition.ts | 16 +--- .../src/contentParser/ShaderContentParser.ts | 51 +++++++++--- packages/shader-lab/src/lexer/Lexer.ts | 6 +- packages/shader-lab/src/parser/AST.ts | 10 +-- .../shader-lab/src/parser/SemanticAnalyzer.ts | 8 +- .../src/parser/ShaderTargetParser.ts | 5 +- .../src/preprocessor/MacroDefine.ts | 4 +- .../shader-lab/src/preprocessor/PpParser.ts | 29 ++++--- .../shader-lab/src/preprocessor/PpScanner.ts | 8 +- 17 files changed, 210 insertions(+), 143 deletions(-) diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index df404a7cf9..01952de4e2 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -66,5 +66,3 @@ export * from "./Utils"; export { ShaderMacroCollection } from "./shader/ShaderMacroCollection"; export * from "./postProcess"; -/** @internal */ -export { ShaderProgram } from "./shader/ShaderProgram"; diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 4264c2411b..0d71c26375 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -1,28 +1,82 @@ +import { Logger } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; +export enum ErrorLevel { + ERROR = 0, + WARN +} + export abstract class GSError extends Error { + static wrappingLineCount = 2; + readonly loc: ShaderRange | ShaderPosition; + readonly source: string; + readonly file?: string; + level = ErrorLevel.ERROR; - constructor(message: string, loc: ShaderRange | ShaderPosition, cause?: Error) { + constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { super(message, { cause }); this.loc = loc; + this.source = source; + this.file = file; } - override toString(): string { - return `>>>>>\n${this.loc.toString()}\nReason: ${this.message}\n<<<<<`; + log(_source?: string): void { + if (!Logger.enable) return; + const logger = this.level === ErrorLevel.ERROR ? Logger.error : Logger.warn; + + let start: ShaderPosition, end: ShaderPosition; + const { message, loc, source: originSource } = this; + let source = originSource; + if (_source) source = _source; + if (!source) { + logger(message); + } + + if (loc instanceof ShaderPosition) { + start = end = loc; + } else { + start = loc.start; + end = loc.end; + } + const lines = source.split("\n"); + + let diagnosticMessage = `${this.name}: ${message}\n\n`; + const lineSplit = "|···"; + + for (let i = 0; i <= end.line + GSError.wrappingLineCount; i++) { + if (i < start.line - GSError.wrappingLineCount) continue; + + diagnosticMessage += lineSplit; + diagnosticMessage += `${lines[i]}\n`; + if (i >= start.line && i <= end.line) { + diagnosticMessage += " ".repeat(lineSplit.length + start.column); + diagnosticMessage += "^".repeat(Math.max(end.column - start.column, 1)); + diagnosticMessage += "\n"; + } + } + + logger(diagnosticMessage); } } export class PreprocessorError extends GSError { - constructor(message: string, loc: ShaderRange | ShaderPosition, cause?: Error) { - super(message, loc, cause); + constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { + super(message, loc, source, file, cause); this.name = "PreprocessorError"; } } export class CompilationError extends GSError { - constructor(message: string, loc: ShaderRange, cause?: Error) { - super(message, loc, cause); - this.name = "SemanticError"; + constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { + super(message, loc, source, file, cause); + this.name = "CompilationError"; + } +} + +export class ScannerError extends GSError { + constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { + super(message, loc, source, file, cause); + this.name = "ScannerError"; } } diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 246eb336ee..19b5bf44cc 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -2,44 +2,28 @@ import { Lexer } from "./lexer"; import { ShaderTargetParser } from "./parser"; import { Preprocessor } from "./preprocessor"; import { GLES100Visitor, GLES300Visitor } from "./codeGen"; -import { IShaderContent, IShaderLab } from "@galacean/engine-design/src/shader-lab"; +import { IShaderContent, IShaderLab } from "@galacean/engine-design"; import { ShaderContentParser } from "./contentParser"; // @ts-ignore import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget, ShaderProgram } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; -import { PreprocessorError, CompilationError } from "./Error"; +import { GSError } from "./Error"; import { PpParser } from "./preprocessor/PpParser"; export class ShaderLab implements IShaderLab { - /** - * @internal - */ private static _parser = ShaderTargetParser.create(); - /** - * @internal - */ private static _shaderPositionPool = new ShaderLabObjectPool(ShaderPosition); + private static _shaderRangePool = new ShaderLabObjectPool(ShaderRange); + /** * @internal */ - private static _shaderRangePool = new ShaderLabObjectPool(ShaderRange); + static _processingPassText?: string; - static createPosition( - index: number, - // #if _EDITOR - line?: number, - column?: number - // #endif - ): ShaderPosition { + static createPosition(index: number, line?: number, column?: number): ShaderPosition { const position = this._shaderPositionPool.get(); - position.setX( - index, - // #if _EDITOR - line, - column - // #endif - ); + position.setX(index, line, column); return position; } @@ -49,6 +33,15 @@ export class ShaderLab implements IShaderLab { return range; } + private _errors: GSError[] = []; + + /** + * Retrieve the compilation errors + */ + get errors(): GSError[] | undefined { + return this._errors; + } + _parseShaderPass( source: string, vertexEntry: string, @@ -71,7 +64,10 @@ export class ShaderLab implements IShaderLab { const preprocessorStart = performance.now(); const ppdContent = Preprocessor.process(source); if (PpParser._errors.length > 0) { - this._reportPreprocessError(PpParser._errors); + for (const err of PpParser._errors) { + this._errors.push(err); + } + this._logErrors(this._errors); return { vertex: "", fragment: "" }; } @@ -82,9 +78,13 @@ export class ShaderLab implements IShaderLab { const { _parser: parser } = ShaderLab; + ShaderLab._processingPassText = ppdContent; const program = parser.parse(tokens); + for (const err of parser.errors) { + this._errors.push(err); + } if (!program) { - this._reportParserError(parser.errors, ppdContent); + this._logErrors(this._errors); return { vertex: "", fragment: "" }; } const codeGen = @@ -93,11 +93,18 @@ export class ShaderLab implements IShaderLab { const start = performance.now(); const ret = codeGen.visitShaderProgram(program, vertexEntry, fragmentEntry); Logger.info(`[CodeGen] cost time: ${performance.now() - start}ms`); + ShaderLab._processingPassText = undefined; + + for (const err of codeGen.errors) { + this._errors.push(err); + } + this._logErrors(this._errors); return ret; } _parseShaderContent(shaderSource: string): IShaderContent { + this._errors.length = 0; ShaderContentParser.reset(); return ShaderContentParser.parse(shaderSource); } @@ -135,23 +142,10 @@ export class ShaderLab implements IShaderLab { } // #endif - private _reportPreprocessError(errors: PreprocessorError[]) { + private _logErrors(errors: GSError[], source?: string) { if (!Logger.isEnabled) return; - const errorsMsg = errors.map((item) => item.toString()).join("\n"); - Logger.error( - `\nPreprocessor error occur in file ${PpParser._scanningFile}:\n\n` + - errorsMsg + - "\nShaderLab source:\n\n" + - ShaderProgram._addLineNum(PpParser._scanningText) - ); - } - - private _reportParserError(errors: CompilationError[], source: string) { - if (!Logger.isEnabled) return; - const errorsMsg = errors.map((item) => item.toString()).join("\n"); - Logger.error( - `\nShaderLab syntax error occur.\n${errorsMsg}\n\nExpanded ShaderLab source:\n\n` + - ShaderProgram._addLineNum(source) - ); + for (const err of errors) { + err.log(source); + } } } diff --git a/packages/shader-lab/src/Utils.ts b/packages/shader-lab/src/Utils.ts index 38614c1e0e..a84aadaea2 100644 --- a/packages/shader-lab/src/Utils.ts +++ b/packages/shader-lab/src/Utils.ts @@ -1,11 +1,10 @@ import { ENonTerminal, GrammarSymbol } from "./parser/GrammarSymbol"; import { BaseToken as Token } from "./common/BaseToken"; -import { EKeyword, ETokenType, GalaceanDataType, ShaderRange, ShaderPosition } from "./common"; +import { EKeyword, ETokenType, GalaceanDataType } from "./common"; import { TreeNode } from "./parser/AST"; // #if _EDITOR import State from "./lalr/State"; // #endif -import { Logger } from "@galacean/engine"; export class ParserUtils { static unwrapNodeByType(node: TreeNode, type: ENonTerminal): T | undefined { @@ -39,11 +38,6 @@ export class ParserUtils { return sm < ENonTerminal.START; } - static throw(pos: ShaderPosition | ShaderRange | number, ...msgs: any[]) { - Logger.error(pos.toString(), ...msgs); - throw msgs.join(" "); - } - /** * @internal */ diff --git a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts index ba7c2f5780..a79b12a755 100644 --- a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts +++ b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts @@ -11,8 +11,6 @@ import { VisitorContext } from "./VisitorContext"; * The code generator */ export class CodeGenVisitor { - protected constructor() {} - defaultCodeGen(children: NodeChild[]) { let ret: string[] = []; for (const child of children) { diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index 2f8e35cbab..6ed40663dc 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -5,8 +5,10 @@ import { ESymbolType, FnSymbol, StructSymbol, SymbolInfo } from "../parser/symbo import { EShaderStage } from "../common/Enums"; import { IShaderInfo } from "@galacean/engine-design"; import { ICodeSegment } from "./types"; -import { Logger } from "@galacean/engine"; import { VisitorContext } from "./VisitorContext"; +import { CompilationError, GSError } from "../Error"; +import { ShaderPosition, ShaderRange } from "../common"; +import { ShaderLab } from "../ShaderLab"; const defaultPrecision = ` #ifdef GL_FRAGMENT_PRECISION_HIGH @@ -22,10 +24,20 @@ export abstract class GLESVisitor extends CodeGenVisitor { protected _versionText: string = ""; protected _extensions: string = ""; + private _errors: GSError[] = []; + abstract getAttributeDeclare(): ICodeSegment[]; abstract getVaryingDeclare(): ICodeSegment[]; + /** + * @internal + */ + get errors() { + return this._errors; + } + visitShaderProgram(node: ASTNode.GLShaderProgram, vertexEntry: string, fragmentEntry: string): IShaderInfo { + this._errors.length = 0; VisitorContext.reset(); VisitorContext.context._passSymbolTable = node.shaderData.symbolTable; @@ -45,11 +57,11 @@ export abstract class GLESVisitor extends CodeGenVisitor { const returnType = fnNode.protoType.returnType; if (typeof returnType.type !== "string") { - Logger.warn("main entry can only return struct."); + this.reportError(returnType.location, "main entry can only return struct."); } else { const varyStruct = symbolTable.lookup({ ident: returnType.type, symbolType: ESymbolType.STRUCT }); if (!varyStruct) { - Logger.warn("invalid varying struct:", returnType.type); + this.reportError(returnType.location, `invalid varying struct: ${returnType.type}`); } else { VisitorContext.context.varyingStruct = varyStruct.astNode; } @@ -64,7 +76,7 @@ export abstract class GLESVisitor extends CodeGenVisitor { symbolType: ESymbolType.STRUCT }); if (!structSymbol) { - Logger.warn("no attribute struct found."); + this.reportError(paramInfo.astNode.location, `Not found attribute struct "${paramInfo.typeInfo.type}".`); continue; } VisitorContext.context.attributeStructs.push(structSymbol.astNode); @@ -147,4 +159,10 @@ export abstract class GLESVisitor extends CodeGenVisitor { } return this._getGlobalText(data, textList, lastLength, _serialized); } + + private reportError(loc: ShaderRange | ShaderPosition, message: string): CompilationError { + const error = new CompilationError(message, loc, ShaderLab._processingPassText); + this._errors.push(error); + return error; + } } diff --git a/packages/shader-lab/src/common/BaseScanner.ts b/packages/shader-lab/src/common/BaseScanner.ts index 2b28672093..c979c412a4 100644 --- a/packages/shader-lab/src/common/BaseScanner.ts +++ b/packages/shader-lab/src/common/BaseScanner.ts @@ -1,6 +1,6 @@ import { ETokenType, ShaderRange, ShaderPosition } from "."; +import { ScannerError } from "../Error"; import { ShaderLab } from "../ShaderLab"; -import { ParserUtils } from "../Utils"; import { BaseToken } from "./BaseToken"; export type OnToken = (token: BaseToken, scanner: BaseScanner) => void; @@ -35,16 +35,9 @@ export default class BaseScanner { } get curPosition(): ShaderPosition { - return ShaderLab.createPosition( - this._currentIndex, - // #if _EDITOR - this._column, - this._line - // #endif - ); + return ShaderLab.createPosition(this._currentIndex, this._line, this._column); } - // #if _EDITOR get line() { return this._line; } @@ -52,7 +45,6 @@ export default class BaseScanner { get column() { return this._column; } - // #endif protected readonly _keywordsMap: Map; @@ -83,14 +75,12 @@ export default class BaseScanner { return; } - // #if _EDITOR if (this.getCurChar() === "\n") { this._line += 1; this._column = 0; } else { this._column += 1; } - // #endif this._currentIndex++; } @@ -133,11 +123,17 @@ export default class BaseScanner { this.skipCommentsAndSpace(); const peek = this.peek(text.length); if (peek !== text) { - ParserUtils.throw(this._currentIndex, `Expect ${text}, got ${peek}`); + this.throwError(this.curPosition, `Expect text "${text}", but got "${peek}"`); } this.advance(text.length); } + throwError(pos: ShaderPosition | ShaderRange, ...msgs: any[]) { + const error = new ScannerError(msgs.join(" "), pos, this._source); + error.log(); + throw error; + } + scanPairedText(left: string, right: string, balanced = false, skipLeading = false) { if (!skipLeading) { this.scanText(left); diff --git a/packages/shader-lab/src/common/BaseToken.ts b/packages/shader-lab/src/common/BaseToken.ts index 6a7b49541d..087ffd99a6 100644 --- a/packages/shader-lab/src/common/BaseToken.ts +++ b/packages/shader-lab/src/common/BaseToken.ts @@ -20,13 +20,7 @@ export class BaseToken implements IPoolElement { if (arg instanceof ShaderRange) { this.location = arg as ShaderRange; } else { - const end = ShaderLab.createPosition( - arg.index + lexeme.length, - // #if _EDITOR - arg.line, - arg.column - // #endif - ); + const end = ShaderLab.createPosition(arg.index + lexeme.length, arg.line, arg.column + lexeme.length); this.location = ShaderLab.createRange(arg, end); } } diff --git a/packages/shader-lab/src/common/ShaderPosition.ts b/packages/shader-lab/src/common/ShaderPosition.ts index 308e02b58d..e1ab88b619 100644 --- a/packages/shader-lab/src/common/ShaderPosition.ts +++ b/packages/shader-lab/src/common/ShaderPosition.ts @@ -2,23 +2,13 @@ import { IPoolElement } from "@galacean/engine"; export class ShaderPosition implements IPoolElement { index: number; - // #if _EDITOR - line?: number; - column?: number; - // #endif + line: number; + column: number; - setX( - index: number, - /** #if _EDITOR */ - line?: number, - column?: number - /** #endif */ - ) { + setX(index: number, line: number, column: number) { this.index = index; - /** #if _EDITOR */ this.line = line; this.column = column; - /** #endif */ } dispose(): void { diff --git a/packages/shader-lab/src/contentParser/ShaderContentParser.ts b/packages/shader-lab/src/contentParser/ShaderContentParser.ts index 3d4b4a03a7..fbc5e181df 100644 --- a/packages/shader-lab/src/contentParser/ShaderContentParser.ts +++ b/packages/shader-lab/src/contentParser/ShaderContentParser.ts @@ -23,7 +23,7 @@ import { IShaderPassContent, IRenderStates } from "@galacean/engine-design"; -import { ParserUtils } from "../Utils"; +import { CompilationError } from "../Error"; const EngineType = [ EKeyword.GS_RenderQueueType, @@ -88,7 +88,6 @@ export class ShaderContentParser { for (let i = 0; i < subShader.passes.length; i++) { const pass = subShader.passes[i]; - // for (const pass of subShader.passes) { Object.assign(pass.renderStates.constantMap, constMap); Object.assign(pass.renderStates.variableMap, variableMap); if (pass.isUsePass) continue; @@ -174,7 +173,13 @@ export class ShaderContentParser { scanner.scanText(";"); const sm = this._symbolTable.lookup({ type: stateToken.type, ident: variable.lexeme }); if (!sm?.value) { - ParserUtils.throw(scanner.current, `Invalid ${stateToken.lexeme} variable:`, variable.lexeme); + const error = new CompilationError( + `Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`, + scanner.curPosition, + scanner.source + ); + error.log(); + throw error; } const renderState = sm.value as IRenderStates; Object.assign(ret.renderStates.constantMap, renderState.constantMap); @@ -222,15 +227,28 @@ export class ShaderContentParser { scanner.scanText("]"); scanner.scanText("="); } else if (op.lexeme !== "=") { - ParserUtils.throw(scanner.current, "Invalid syntax, expect character '=', but got", op.lexeme); + const error = new CompilationError( + `Invalid syntax, expect character '=', but got ${op.lexeme}`, + scanner.curPosition, + scanner.source + ); + error.log(); + throw error; } renderStateProp += idx; } renderStateProp = state + renderStateProp; const renderStateElementKey = RenderStateDataKey[renderStateProp]; - if (renderStateElementKey == undefined) - ParserUtils.throw(scanner.current, "Invalid render state element", renderStateProp); + if (renderStateElementKey == undefined) { + const error = new CompilationError( + `Invalid render state element ${renderStateProp}`, + scanner.curPosition, + scanner.source + ); + error.log(); + throw error; + } scanner.skipCommentsAndSpace(); let value: any; @@ -258,8 +276,15 @@ export class ShaderContentParser { scanner._advance(); const engineTypeProp = scanner.scanToken(); value = ShaderContentParser._engineType[token.lexeme]?.[engineTypeProp.lexeme]; - if (value == undefined) - ParserUtils.throw(scanner.current, "Invalid engine constant:", `${token.lexeme}.${engineTypeProp.lexeme}`); + if (value == undefined) { + const error = new CompilationError( + `Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`, + scanner.curPosition, + scanner.source + ); + error.log(); + throw error; + } } else { value = token.lexeme; } @@ -278,7 +303,9 @@ export class ShaderContentParser { scanner.scanText(";"); const value = ShaderContentParser._engineType.RenderQueueType[word.lexeme]; if (value == undefined) { - ParserUtils.throw(scanner.current, "Invalid render queue", word.lexeme); + const error = new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); + error.log(); + throw error; } const key = RenderStateDataKey.RenderQueueType; ret.renderStates.constantMap[key] = value; @@ -423,11 +450,11 @@ export class ShaderContentParser { this._addGlobalStatement(ret, scanner, start, word.lexeme.length); scanner.scanText("="); const entry = scanner.scanToken(); - // #if _EDITOR if (ret[word.lexeme]) { - ParserUtils.throw(scanner.current, "reassign main entry"); + const error = new CompilationError("reassign main entry", scanner.curPosition, scanner.source); + error.log(); + throw error; } - // #endif const key = word.type === EKeyword.GS_VertexShader ? "vertexEntry" : "fragmentEntry"; ret[key] = entry.lexeme; scanner.scanText(";"); diff --git a/packages/shader-lab/src/lexer/Lexer.ts b/packages/shader-lab/src/lexer/Lexer.ts index 346e7788f6..84dc9dd08c 100644 --- a/packages/shader-lab/src/lexer/Lexer.ts +++ b/packages/shader-lab/src/lexer/Lexer.ts @@ -278,8 +278,7 @@ export class Lexer extends BaseScanner { return this._scanStringConst(); default: - console.log("at position", start); - throw `Unexpected character ${this.getCurChar()}`; + this.throwError(this.curPosition, `Unexpected character ${this.getCurChar()}`); } return token; } @@ -385,7 +384,8 @@ export class Lexer extends BaseScanner { buffer.push(this.getCurChar()); this.advance(); } - if (!LexerUtils.isNum(this.getCurChar())) throw "lexing error, invalid exponent suffix."; + if (!LexerUtils.isNum(this.getCurChar())) + this.throwError(this.curPosition, "lexing error, invalid exponent suffix."); while (LexerUtils.isNum(this.getCurChar())) { buffer.push(this.getCurChar()); this.advance(); diff --git a/packages/shader-lab/src/parser/AST.ts b/packages/shader-lab/src/parser/AST.ts index 1ebad0decf..71745de4d4 100644 --- a/packages/shader-lab/src/parser/AST.ts +++ b/packages/shader-lab/src/parser/AST.ts @@ -435,7 +435,7 @@ export namespace ASTNode { this.compute = (a, b) => a % b; break; default: - throw `not implemented operator ${operator.lexeme}`; + sa.error(operator.location, `not implemented operator ${operator.lexeme}`); } } } @@ -459,10 +459,10 @@ export namespace ASTNode { else { const id = child as VariableIdentifier; if (!id.symbolInfo) { - sa.error(id.location, "undeclared symbol:", id.lexeme); + sa.error(id.location, "Undeclared symbol:", id.lexeme); } if (!ParserUtils.typeCompatible(EKeyword.INT, id.typeInfo)) { - sa.error(id.location, "invalid integer."); + sa.error(id.location, "Invalid integer."); return; } } @@ -535,7 +535,7 @@ export namespace ASTNode { const arraySpecifier = this.children[3] as ArraySpecifier; // #if _EDITOR if (typeInfo.arraySpecifier && arraySpecifier) { - sa.error(arraySpecifier.location, "array of array is not supported."); + sa.error(arraySpecifier.location, "Array of array is not supported."); } // #endif typeInfo.arraySpecifier = arraySpecifier; @@ -872,7 +872,7 @@ export namespace ASTNode { const fnSymbol = sa.symbolTable.lookup({ ident: fnIdent, symbolType: ESymbolType.FN, signature: paramSig }); if (!fnSymbol) { // #if _EDITOR - sa.error(this.location, "no overload function type found:", functionIdentifier.ident); + sa.error(this.location, "No overload function type found: ", functionIdentifier.ident); // #endif return; } diff --git a/packages/shader-lab/src/parser/SemanticAnalyzer.ts b/packages/shader-lab/src/parser/SemanticAnalyzer.ts index fd61bd53c9..691341026d 100644 --- a/packages/shader-lab/src/parser/SemanticAnalyzer.ts +++ b/packages/shader-lab/src/parser/SemanticAnalyzer.ts @@ -1,13 +1,11 @@ import { ShaderRange } from "../common"; import { TreeNode } from "./AST"; -// #if _EDITOR import { CompilationError } from "../Error"; -// #endif import { ShaderData } from "./ShaderInfo"; import { SymbolInfo, SymbolTable } from "../parser/symbolTable"; import { NodeChild } from "./types"; import { SymbolTableStack } from "../common/BaseSymbolTable"; -import { Logger } from "@galacean/engine"; +import { ShaderLab } from "../ShaderLab"; export type TranslationRule = (sa: SematicAnalyzer, ...tokens: NodeChild[]) => T; @@ -60,9 +58,7 @@ export default class SematicAnalyzer { } error(loc: ShaderRange, ...param: any[]) { - // Logger.warn(loc, ...param); - - const err = new CompilationError(param.join(""), loc); + const err = new CompilationError(param.join(""), loc, ShaderLab._processingPassText); this.errors.push(err); return err; } diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index 89d268af36..f12c8b27d4 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -11,6 +11,7 @@ import { LALR1 } from "../lalr"; import { ParserUtils } from "../Utils"; import { Logger } from "@galacean/engine"; import { CompilationError } from "../Error"; +import { ShaderLab } from "../ShaderLab"; /** * The syntax parser and sematic analyzer of `ShaderLab` compiler @@ -109,7 +110,9 @@ export class ShaderTargetParser { traceBackStack.push(nextState); continue; } else { - this.sematicAnalyzer.errors.push(new CompilationError(`Unexpected token ${token.lexeme}`, token.location)); + this.sematicAnalyzer.errors.push( + new CompilationError(`Unexpected token ${token.lexeme}`, token.location, ShaderLab._processingPassText) + ); return null; } } diff --git a/packages/shader-lab/src/preprocessor/MacroDefine.ts b/packages/shader-lab/src/preprocessor/MacroDefine.ts index e2cca2fa8b..8149799287 100644 --- a/packages/shader-lab/src/preprocessor/MacroDefine.ts +++ b/packages/shader-lab/src/preprocessor/MacroDefine.ts @@ -1,6 +1,6 @@ import { BaseToken } from "../common/BaseToken"; import { ShaderRange } from "../common"; -import { ParserUtils } from "../Utils"; +import { PreprocessorError } from "../Error"; export class MacroDefine { readonly location?: ShaderRange; @@ -29,7 +29,7 @@ export class MacroDefine { // #if _EDITOR if (args.length !== this.args?.length) { - ParserUtils.throw(this.location, "mismatched function macro"); + throw new PreprocessorError("mismatched function macro", this.location, ""); } // #endif const replaceRegex = new RegExp(`\\b(${argsTextList.join("|")})\\b`, "g"); diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 77df9593ac..79e7664641 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -103,8 +103,8 @@ export class PpParser { return this._expandSegmentsStack[this._expandSegmentsStack.length - 1]; } - private static reportError(loc: ShaderRange | ShaderPosition, message: string) { - this._errors.push(new PreprocessorError(message, loc)); + private static reportError(loc: ShaderRange | ShaderPosition, message: string, source: string, file: string) { + this._errors.push(new PreprocessorError(message, loc, source, file)); } private static _parseInclude(scanner: PpScanner) { @@ -126,7 +126,7 @@ export class PpParser { const end = scanner.getShaderPosition(); const chunk = this._includeMap[includedPath]; if (!chunk) { - this.reportError(id.location, `Shader slice "${includedPath}" not founded.`); + this.reportError(id.location, `Shader slice "${includedPath}" not founded.`, scanner.source, scanner.file); return; } @@ -301,7 +301,7 @@ export class PpParser { scanner.skipSpace(false); const operand2 = this._parseRelationalExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - this.reportError(opPos, "invalid operator in relation expression."); + this.reportError(opPos, "invalid operator in relation expression.", scanner.source, scanner.file); return; } switch (operator) { @@ -327,7 +327,7 @@ export class PpParser { scanner.skipSpace(false); const operand2 = this._parseShiftExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - this.reportError(opPos, "invalid operator in shift expression."); + this.reportError(opPos, "invalid operator in shift expression.", scanner.source, scanner.file); return; } switch (operator) { @@ -351,7 +351,7 @@ export class PpParser { scanner.skipSpace(false); const operand2 = this._parseAdditiveExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - this.reportError(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator.", scanner.source, scanner.file); return false; } switch (operator) { @@ -373,7 +373,7 @@ export class PpParser { scanner.skipSpace(false); const operand2 = this._parseMulticativeExpression(scanner) as number; if (typeof operand1 !== typeof operand2 && typeof operand1 !== "number") { - this.reportError(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator.", scanner.source, scanner.file); return; } switch (operator) { @@ -395,7 +395,7 @@ export class PpParser { const opPos = scanner.getShaderPosition(); const parenExpr = this._parseParenthesisExpression(scanner); if ((operator === "!" && typeof parenExpr !== "boolean") || (operator !== "!" && typeof parenExpr !== "number")) { - this.reportError(opPos, "invalid operator."); + this.reportError(opPos, "invalid operator.", scanner.source, scanner.file); } switch (operator) { @@ -440,11 +440,11 @@ export class PpParser { return false; } if (macro.isFunction) { - this.reportError(id.location, "invalid function macro usage"); + this.reportError(id.location, "invalid function macro usage", scanner.source, scanner.file); } const value = Number(macro.body.lexeme); if (!Number.isInteger(value)) { - this.reportError(id.location, `invalid const macro: ${id.lexeme}`); + this.reportError(id.location, `invalid const macro: ${id.lexeme}`, scanner.source, scanner.file); } this._branchMacros.add(id.lexeme); return value; @@ -453,7 +453,12 @@ export class PpParser { const integer = scanner.scanInteger(); return Number(integer.lexeme); } else { - this.reportError(scanner.getShaderPosition(), `invalid token: ${scanner.getCurChar()}`); + this.reportError( + scanner.getShaderPosition(), + `invalid token: ${scanner.getCurChar()}`, + scanner.source, + scanner.file + ); } } @@ -590,7 +595,7 @@ export class PpParser { let end = macro.location.end; if (this._definedMacros.get(macro.lexeme) && macro.lexeme.startsWith("GL_")) { - this.reportError(macro.location, `redefined macro: ${macro.lexeme}`); + this.reportError(macro.location, `redefined macro: ${macro.lexeme}`, scanner.source, scanner.file); } let macroArgs: BaseToken[] | undefined; diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index b2f56c8b37..33a6f7ea30 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -87,7 +87,7 @@ export default class PpScanner extends BaseScanner { const end = this._currentIndex; const word = this._source.slice(start, end); if (end === start) { - ParserUtils.throw(this.getShaderPosition(), "no word found."); + this.throwError(this.getShaderPosition(), "no word found."); } const kw = PpKeyword.get(word); if (kw) { @@ -141,14 +141,14 @@ export default class PpScanner extends BaseScanner { scanQuotedString(): BaseToken { this.skipSpace(true); if (this.getCurChar() !== '"') { - ParserUtils.throw(this.getShaderPosition(), "unexpected char, expected '\"'"); + this.throwError(this.getShaderPosition(), "unexpected char, expected '\"'"); } const ShaderPosition = this.getShaderPosition(); this._advance(); const start = this._currentIndex; while (this.getCurChar() !== '"' && !this.isEnd()) this._advance(); if (this.isEnd()) { - ParserUtils.throw(this.getShaderPosition(), "unexpected char, expected '\"'"); + this.throwError(this.getShaderPosition(), "unexpected char, expected '\"'"); } const word = this._source.slice(start, this._currentIndex); @@ -230,7 +230,7 @@ export default class PpScanner extends BaseScanner { this.advance(); } if (this._currentIndex === start) { - ParserUtils.throw(this.getShaderPosition(), "no integer found"); + this.throwError(this.getShaderPosition(), "no integer found"); } const integer = this._source.slice(start, this._currentIndex); From f12b8f7cce23a5e48ceb0935049f5e9c369753d1 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 09:43:17 +0800 Subject: [PATCH 36/60] feat(shaderlab): multi package --- packages/shader-lab/src/Error.ts | 4 ++++ packages/shader-lab/src/lexer/Lexer.ts | 2 -- .../shader-lab/src/preprocessor/PpScanner.ts | 1 - rollup.config.js | 22 +++++++++---------- tests/src/shader-lab/Preprocessor.test.ts | 2 +- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 0d71c26375..bd4c4aa127 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -23,6 +23,7 @@ export abstract class GSError extends Error { log(_source?: string): void { if (!Logger.enable) return; + // #if _EDITOR const logger = this.level === ErrorLevel.ERROR ? Logger.error : Logger.warn; let start: ShaderPosition, end: ShaderPosition; @@ -57,6 +58,9 @@ export abstract class GSError extends Error { } logger(diagnosticMessage); + // #else + Logger.error("compile error."); + // #endif } } diff --git a/packages/shader-lab/src/lexer/Lexer.ts b/packages/shader-lab/src/lexer/Lexer.ts index 84dc9dd08c..003fa459c7 100644 --- a/packages/shader-lab/src/lexer/Lexer.ts +++ b/packages/shader-lab/src/lexer/Lexer.ts @@ -12,9 +12,7 @@ export class Lexer extends BaseScanner { reset(source: string) { this._source = source; this._currentIndex = 0; - // #if _EDITOR this._line = this._column = 0; - // #endif } *tokenize() { diff --git a/packages/shader-lab/src/preprocessor/PpScanner.ts b/packages/shader-lab/src/preprocessor/PpScanner.ts index 33a6f7ea30..d2a62994b6 100644 --- a/packages/shader-lab/src/preprocessor/PpScanner.ts +++ b/packages/shader-lab/src/preprocessor/PpScanner.ts @@ -5,7 +5,6 @@ import PpSourceMap from "./sourceMap"; // #endif import BaseScanner from "../common/BaseScanner"; import { BaseToken, EOF } from "../common/BaseToken"; -import { ParserUtils } from "../Utils"; import { EPpKeyword, EPpToken, PpKeyword } from "./constants"; import { PpUtils } from "./Utils"; import { ShaderLab } from "../ShaderLab"; diff --git a/rollup.config.js b/rollup.config.js index eb6a20e866..447dfe84ee 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -61,14 +61,16 @@ const commonPlugins = [ function config({ location, pkgJson, editorMode }) { const input = path.join(location, "src", "index.ts"); const dependencies = Object.assign({}, pkgJson.dependencies ?? {}, pkgJson.peerDependencies ?? {}); - commonPlugins.push( + const curPlugins = Array.from(commonPlugins); + + curPlugins.push( jscc({ - values: { _EDITOR: NODE_ENV !== "release" || editorMode } + values: { _EDITOR: editorMode } }) ); const external = Object.keys(dependencies); - commonPlugins.push( + curPlugins.push( replace({ preventAssignment: true, __buildVersion: pkgJson.version @@ -80,9 +82,8 @@ function config({ location, pkgJson, editorMode }) { const umdConfig = pkgJson.umd; let file = path.join(location, "dist", "browser.js"); - const plugins = commonPlugins; if (compress) { - plugins.push(minify({ sourceMap: true })); + curPlugins.push(minify({ sourceMap: true })); file = path.join(location, "dist", "browser.min.js"); } if (editorMode) { @@ -103,12 +104,12 @@ function config({ location, pkgJson, editorMode }) { globals: umdConfig.globals } ], - plugins + plugins: curPlugins }; }, mini: () => { let file = path.join(location, "dist", "miniprogram.js"); - const plugins = [...commonPlugins, ...miniProgramPlugin]; + const plugins = [...curPlugins, ...miniProgramPlugin]; if (editorMode) { file = path.join(location, "dist", "miniprogram.editor.js"); } @@ -126,9 +127,8 @@ function config({ location, pkgJson, editorMode }) { }; }, module: () => { - const plugins = commonPlugins; - let esFile = pkgJson.module; - let mainFile = pkgJson.main; + let esFile = path.join(location, pkgJson.module); + let mainFile = path.join(location, pkgJson.main); if (editorMode) { esFile = path.join(location, "dist", "module.editor.js"); mainFile = path.join(location, "dist", "main.editor.js"); @@ -148,7 +148,7 @@ function config({ location, pkgJson, editorMode }) { format: "commonjs" } ], - plugins + plugins: curPlugins }; } }; diff --git a/tests/src/shader-lab/Preprocessor.test.ts b/tests/src/shader-lab/Preprocessor.test.ts index 315f857c63..87e87471b2 100644 --- a/tests/src/shader-lab/Preprocessor.test.ts +++ b/tests/src/shader-lab/Preprocessor.test.ts @@ -3,7 +3,7 @@ import { testCaseList } from "./test-case"; import { ShaderLib } from "@galacean/engine-core"; import { expect } from "chai"; import { readFileSync } from "fs"; -import { Preprocessor } from "@galacean/engine-shader-lab"; +import { Preprocessor } from "@galacean/engine-shader-lab/dist/main.editor"; import { join } from "path"; const includedSource = readFileSync(join(__dirname, "test-case/included.txt")).toString(); From c32969b7812012e1b98a761217f0978a99364a5c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 11:27:58 +0800 Subject: [PATCH 37/60] feat(shaderlab): opt code --- packages/shader-lab/README.md | 13 +++++ packages/shader-lab/src/Error.ts | 2 + packages/shader-lab/src/ShaderLab.ts | 9 +++- .../shader-lab/src/codeGen/CodeGenVisitor.ts | 34 +++++++++++-- .../shader-lab/src/codeGen/GLESVisitor.ts | 21 ++------ .../shader-lab/src/codeGen/VisitorContext.ts | 49 +++++++++++++------ packages/shader-lab/src/common/BaseScanner.ts | 12 +++-- .../src/contentParser/ShaderContentParser.ts | 11 +++-- .../shader-lab/src/parser/SemanticAnalyzer.ts | 10 +++- .../src/parser/ShaderTargetParser.ts | 7 +++ packages/shader-lab/src/parser/TargetParser.y | 2 +- .../shader-lab/src/preprocessor/PpParser.ts | 8 ++- 12 files changed, 129 insertions(+), 49 deletions(-) diff --git a/packages/shader-lab/README.md b/packages/shader-lab/README.md index 6a6b323460..97c7bf8da4 100644 --- a/packages/shader-lab/README.md +++ b/packages/shader-lab/README.md @@ -26,6 +26,19 @@ const shader = Shader.create(galaceanShaderCode); engine.run() ``` +There are two versions of ShaderLab: `Release` and `Debug`. The Debug version offers more user-friendly diagnostic information for debug ShaderLab compilation errors, while the Release version provides superior performance. + +you can use debug version by import: + +```ts +// umd +import { ShaderLab } from "@galacean/engine-shader-lab/dist/browser.editor"; +// esmoudle +import { ShaderLab } from "@galacean/engine-shader-lab/dist/module.editor"; +// commonjs +import { ShaderLab } from "@galacean/engine-shader-lab/dist/main.editor"; +``` + ## CFG Grammar conflict detection The Galacean ShaderLab syntax is defined using Context-Free Grammar (CFG) and is documented within the `\*.y` file. When modifications to the ShaderLab syntax are required, it is recommended to make changes to the existing CFG syntax file, and employ [Bison](https://www.gnu.org/software/bison/manual/bison.html) to detect any potential grammar conflicts. diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index bd4c4aa127..4936486b17 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -64,6 +64,7 @@ export abstract class GSError extends Error { } } +// #if _EDITOR export class PreprocessorError extends GSError { constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { super(message, loc, source, file, cause); @@ -84,3 +85,4 @@ export class ScannerError extends GSError { this.name = "ScannerError"; } } +// #endif diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 19b5bf44cc..f1905ea92b 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -5,7 +5,7 @@ import { GLES100Visitor, GLES300Visitor } from "./codeGen"; import { IShaderContent, IShaderLab } from "@galacean/engine-design"; import { ShaderContentParser } from "./contentParser"; // @ts-ignore -import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget, ShaderProgram } from "@galacean/engine"; +import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; import { GSError } from "./Error"; @@ -65,7 +65,7 @@ export class ShaderLab implements IShaderLab { const ppdContent = Preprocessor.process(source); if (PpParser._errors.length > 0) { for (const err of PpParser._errors) { - this._errors.push(err); + this._errors.push(err); } this._logErrors(this._errors); return { vertex: "", fragment: "" }; @@ -143,9 +143,14 @@ export class ShaderLab implements IShaderLab { // #endif private _logErrors(errors: GSError[], source?: string) { + // #if !_EDITOR + Logger.error(`${errors.length} errors occur!`); + // #else if (!Logger.isEnabled) return; for (const err of errors) { + if (!err.log) debugger; err.log(source); } + // #endif } } diff --git a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts index a79b12a755..534a1473bc 100644 --- a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts +++ b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts @@ -1,16 +1,27 @@ import { ENonTerminal } from "../parser/GrammarSymbol"; import { BaseToken as Token } from "../common/BaseToken"; -import { EKeyword } from "../common"; +import { EKeyword, ShaderPosition, ShaderRange } from "../common"; import { ASTNode, TreeNode } from "../parser/AST"; import { ESymbolType, FnSymbol, VarSymbol } from "../parser/symbolTable"; import { ParserUtils } from "../Utils"; import { NodeChild } from "../parser/types"; import { VisitorContext } from "./VisitorContext"; +// #if _EDITOR +import { CompilationError, GSError } from "../Error"; +// #endif +import { ShaderLab } from "../ShaderLab"; /** + * @internal * The code generator */ export class CodeGenVisitor { + protected _errors: GSError[] = []; + + get errors() { + return this._errors; + } + defaultCodeGen(children: NodeChild[]) { let ret: string[] = []; for (const child of children) { @@ -33,10 +44,16 @@ export class CodeGenVisitor { if (prop instanceof Token) { if (context.isAttributeStruct(postExpr.type)) { - context.referenceAttribute(prop.lexeme); + const error = context.referenceAttribute(prop); + if (error) { + this._errors.push(error); + } return prop.lexeme; } else if (context.isVaryingStruct(postExpr.type)) { - context.referenceVarying(prop.lexeme); + const error = context.referenceVarying(prop); + if (error) { + this._errors.push(error); + } return prop.lexeme; } @@ -170,4 +187,15 @@ export class CodeGenVisitor { visitFunctionIdentifier(node: ASTNode.FunctionIdentifier): string { return this.defaultCodeGen(node.children); } + + protected reportError(loc: ShaderRange | ShaderPosition, message: string): CompilationError { + let error: Error; + // #if _EDITOR + error = new CompilationError(message, loc, ShaderLab._processingPassText); + // #else + error = new Error(message); + // #endif + this._errors.push(error); + return error; + } } diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index 6ed40663dc..55e39efacf 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -6,9 +6,6 @@ import { EShaderStage } from "../common/Enums"; import { IShaderInfo } from "@galacean/engine-design"; import { ICodeSegment } from "./types"; import { VisitorContext } from "./VisitorContext"; -import { CompilationError, GSError } from "../Error"; -import { ShaderPosition, ShaderRange } from "../common"; -import { ShaderLab } from "../ShaderLab"; const defaultPrecision = ` #ifdef GL_FRAGMENT_PRECISION_HIGH @@ -20,22 +17,16 @@ const defaultPrecision = ` #endif `; +/** + * @internal + */ export abstract class GLESVisitor extends CodeGenVisitor { protected _versionText: string = ""; protected _extensions: string = ""; - private _errors: GSError[] = []; - abstract getAttributeDeclare(): ICodeSegment[]; abstract getVaryingDeclare(): ICodeSegment[]; - /** - * @internal - */ - get errors() { - return this._errors; - } - visitShaderProgram(node: ASTNode.GLShaderProgram, vertexEntry: string, fragmentEntry: string): IShaderInfo { this._errors.length = 0; VisitorContext.reset(); @@ -159,10 +150,4 @@ export abstract class GLESVisitor extends CodeGenVisitor { } return this._getGlobalText(data, textList, lastLength, _serialized); } - - private reportError(loc: ShaderRange | ShaderPosition, message: string): CompilationError { - const error = new CompilationError(message, loc, ShaderLab._processingPassText); - this._errors.push(error); - return error; - } } diff --git a/packages/shader-lab/src/codeGen/VisitorContext.ts b/packages/shader-lab/src/codeGen/VisitorContext.ts index f537450227..d96f42759c 100644 --- a/packages/shader-lab/src/codeGen/VisitorContext.ts +++ b/packages/shader-lab/src/codeGen/VisitorContext.ts @@ -3,7 +3,11 @@ import { EShaderStage } from "../common/Enums"; import { ASTNode } from "../parser/AST"; import { ESymbolType, SymbolTable, SymbolInfo } from "../parser/symbolTable"; import { IParamInfo } from "../parser/types"; +import { CompilationError, GSError } from "../Error"; +import { BaseToken } from "../common/BaseToken"; +import { ShaderLab } from "../ShaderLab"; +/** @internal */ export class VisitorContext { private static _singleton: VisitorContext; static get context() { @@ -30,12 +34,13 @@ export class VisitorContext { _curFn?: ASTNode.FunctionProtoType; _passSymbolTable: SymbolTable; + + private constructor() {} + get passSymbolTable() { return this._passSymbolTable; } - private constructor() {} - reset() { this.attributeList.length = 0; this.attributeStructs.length = 0; @@ -52,26 +57,42 @@ export class VisitorContext { return this.varyingStruct?.ident?.lexeme === type; } - referenceAttribute(ident: string) { - if (this._referencedAttributeList[ident]) return; + referenceAttribute(ident: BaseToken): GSError { + if (this._referencedAttributeList[ident.lexeme]) return; - const prop = this.attributeList.find((item) => item.ident.lexeme === ident); + const prop = this.attributeList.find((item) => item.ident.lexeme === ident.lexeme); if (!prop) { - Logger.error("referenced attribute not found:", ident); - return; + // #if _EDITOR + return new CompilationError( + `referenced attribute not found: ${ident.lexeme}`, + ident.location, + ShaderLab._processingPassText + ); + // #else + // @ts-ignore + return new Error(`referenced attribute not found: ${ident.lexeme}`); + // #endif } - this._referencedAttributeList[ident] = prop; + this._referencedAttributeList[ident.lexeme] = prop; } - referenceVarying(ident: string) { - if (this._referencedVaryingList[ident]) return; + referenceVarying(ident: BaseToken): CompilationError | undefined { + if (this._referencedVaryingList[ident.lexeme]) return; - const prop = this.varyingStruct?.propList.find((item) => item.ident.lexeme === ident); + const prop = this.varyingStruct?.propList.find((item) => item.ident.lexeme === ident.lexeme); if (!prop) { - Logger.error("referenced varying not found:", ident); - return; + // #if _EDITOR + return new CompilationError( + `referenced varying not found: ${ident.lexeme}`, + ident.location, + ShaderLab._processingPassText + ); + // #else + // @ts-ignore + return new Error(`referenced varying not found: ${ident.lexeme}`); + // #endif } - this._referencedVaryingList[ident] = prop; + this._referencedVaryingList[ident.lexeme] = prop; } referenceGlobal(ident: string, type: ESymbolType) { diff --git a/packages/shader-lab/src/common/BaseScanner.ts b/packages/shader-lab/src/common/BaseScanner.ts index c979c412a4..c1d897970f 100644 --- a/packages/shader-lab/src/common/BaseScanner.ts +++ b/packages/shader-lab/src/common/BaseScanner.ts @@ -1,5 +1,7 @@ import { ETokenType, ShaderRange, ShaderPosition } from "."; +// #if _EDITOR import { ScannerError } from "../Error"; +// #endif import { ShaderLab } from "../ShaderLab"; import { BaseToken } from "./BaseToken"; @@ -21,10 +23,8 @@ export default class BaseScanner { protected _currentIndex = 0; protected _source: string; - // #if _EDITOR protected _column = 0; protected _line = 0; - // #endif get current(): number { return this._currentIndex; @@ -129,9 +129,11 @@ export default class BaseScanner { } throwError(pos: ShaderPosition | ShaderRange, ...msgs: any[]) { - const error = new ScannerError(msgs.join(" "), pos, this._source); - error.log(); - throw error; + // #if _EDITOR + throw new ScannerError(msgs.join(" "), pos, this._source); + // #else + throw new Error(msgs.join("")); + // #endif } scanPairedText(left: string, right: string, balanced = false, skipLeading = false) { diff --git a/packages/shader-lab/src/contentParser/ShaderContentParser.ts b/packages/shader-lab/src/contentParser/ShaderContentParser.ts index fbc5e181df..7c22162971 100644 --- a/packages/shader-lab/src/contentParser/ShaderContentParser.ts +++ b/packages/shader-lab/src/contentParser/ShaderContentParser.ts @@ -23,7 +23,9 @@ import { IShaderPassContent, IRenderStates } from "@galacean/engine-design"; +// #if _EDITOR import { CompilationError } from "../Error"; +// #endif const EngineType = [ EKeyword.GS_RenderQueueType, @@ -173,13 +175,16 @@ export class ShaderContentParser { scanner.scanText(";"); const sm = this._symbolTable.lookup({ type: stateToken.type, ident: variable.lexeme }); if (!sm?.value) { - const error = new CompilationError( + let error: CompilationError; + // #if _EDITOR + throw new CompilationError( `Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`, scanner.curPosition, scanner.source ); - error.log(); - throw error; + // #else + throw new Error(`Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`); + // #endif } const renderState = sm.value as IRenderStates; Object.assign(ret.renderStates.constantMap, renderState.constantMap); diff --git a/packages/shader-lab/src/parser/SemanticAnalyzer.ts b/packages/shader-lab/src/parser/SemanticAnalyzer.ts index 691341026d..8972a21411 100644 --- a/packages/shader-lab/src/parser/SemanticAnalyzer.ts +++ b/packages/shader-lab/src/parser/SemanticAnalyzer.ts @@ -1,6 +1,8 @@ import { ShaderRange } from "../common"; import { TreeNode } from "./AST"; +// #if _EDITOR import { CompilationError } from "../Error"; +// #endif import { ShaderData } from "./ShaderInfo"; import { SymbolInfo, SymbolTable } from "../parser/symbolTable"; import { NodeChild } from "./types"; @@ -58,7 +60,13 @@ export default class SematicAnalyzer { } error(loc: ShaderRange, ...param: any[]) { - const err = new CompilationError(param.join(""), loc, ShaderLab._processingPassText); + let err: CompilationError; + // #if !_EDITOR + // @ts-ignore + err = new Error(param.join("")); + // #else + err = new CompilationError(param.join(""), loc, ShaderLab._processingPassText); + // #endif this.errors.push(err); return err; } diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index f12c8b27d4..8a737d4025 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -10,7 +10,9 @@ import { addTranslationRule, createGrammar } from "../lalr/CFG"; import { LALR1 } from "../lalr"; import { ParserUtils } from "../Utils"; import { Logger } from "@galacean/engine"; +// #if _EDITOR import { CompilationError } from "../Error"; +// #endif import { ShaderLab } from "../ShaderLab"; /** @@ -110,9 +112,14 @@ export class ShaderTargetParser { traceBackStack.push(nextState); continue; } else { + // #if _EDITOR this.sematicAnalyzer.errors.push( new CompilationError(`Unexpected token ${token.lexeme}`, token.location, ShaderLab._processingPassText) ); + // #else + // @ts-ignore + this.sematicAnalyzer.errors.push(new Error(`Unexpected token ${token.lexeme}`)); + // #endif return null; } } diff --git a/packages/shader-lab/src/parser/TargetParser.y b/packages/shader-lab/src/parser/TargetParser.y index 17c9b00013..0d943c24be 100644 --- a/packages/shader-lab/src/parser/TargetParser.y +++ b/packages/shader-lab/src/parser/TargetParser.y @@ -432,7 +432,7 @@ expression_statement: // Dangling else ambiguity selection_statement: IF '(' expression ')' statement - | IF '(' expression ')' statement ELSE statement + | IF '(' expression ')' statement ELSE statement ELSE ; iteration_statement: diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 79e7664641..5225623edc 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -3,6 +3,7 @@ import LexerUtils from "../lexer/Utils"; import { MacroDefine } from "./MacroDefine"; // #if _EDITOR import PpSourceMap, { BlockInfo } from "./sourceMap"; +import { PreprocessorError } from "../Error"; // #endif import { BaseToken } from "../common/BaseToken"; import { EPpKeyword, EPpToken, PpConstant } from "./constants"; @@ -10,7 +11,6 @@ import PpScanner from "./PpScanner"; import { PpUtils } from "./Utils"; import { ShaderLab } from "../ShaderLab"; import { ShaderPass } from "@galacean/engine"; -import { PreprocessorError } from "../Error"; export interface ExpandSegment { // #if _EDITOR @@ -32,7 +32,7 @@ export class PpParser { private static _basePathForIncludeKey: string; /** @internal */ - static _errors: PreprocessorError[] = []; + static _errors: Error[] = []; /** @internal */ static _scanningText: string; /** @internal */ @@ -104,7 +104,11 @@ export class PpParser { } private static reportError(loc: ShaderRange | ShaderPosition, message: string, source: string, file: string) { + // #if _EDITOR this._errors.push(new PreprocessorError(message, loc, source, file)); + // #else + this._errors.push(new Error(message)); + // #endif } private static _parseInclude(scanner: PpScanner) { From 9d4d808455e79a0d54a9539ab0d477337e2615b8 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 11:34:00 +0800 Subject: [PATCH 38/60] feat(shaderlab): opt code --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 2f5c761e16..4f775522ab 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,12 @@ "build:editor": "npm run b:module:editor && npm run b:types", "lint": "eslint packages/*/src --ext .ts", "watch": "cross-env NODE_ENV=release BUILD_TYPE=MODULE rollup -cw -m inline", - "watch:editor": "cross-env NODE_ENV=editor BUILD_TYPE=MODULE rollup -cw -m inline", "watch:umd": "cross-env NODE_ENV=release BUILD_TYPE=UMD rollup -cw -m inline", - "watch:umd:editor": "cross-env NODE_ENV=editor BUILD_TYPE=UMD rollup -cw -m inline", "b:types": "pnpm -r --filter=./packages/* run b:types", "b:module": "cross-env BUILD_TYPE=MODULE NODE_ENV=release rollup -c", - "b:module:editor": "cross-env BUILD_TYPE=MODULE NODE_ENV=editor rollup -c", "b:umd": "cross-env BUILD_TYPE=UMD NODE_ENV=release rollup -c", "b:miniprogram": "cross-env BUILD_TYPE=MINI rollup -c", "b:all": "cross-env NODE_ENV=release npm run b:types && cross-env BUILD_TYPE=ALL NODE_ENV=release rollup -c", - "b:all:editor": "cross-env NODE_ENV=editor npm run b:types && cross-env BUILD_TYPE=ALL rollup -c", "clean": "pnpm -r exec rm -rf dist && pnpm -r exec rm -rf types", "e2e:case": "pnpm -C ./e2e run case", "e2e": "cypress run --browser chrome --headless", From f5edeb3c626905bb02aa0f98f80ccc99f35a2815 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 11:38:05 +0800 Subject: [PATCH 39/60] feat(shaderlab): opt code --- .github/workflows/ci.yml | 6 +++--- packages/shader-lab/package.json | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2aa897a514..a86c651de5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: - name: Install run: pnpm install - - run: npm run build:editor + - run: npm run build codecov: runs-on: macos-latest @@ -66,7 +66,7 @@ jobs: - name: Install run: pnpm install - name: Build - run: npm run build:editor + run: npm run build - name: Test run: npm run test-cov - run: pnpm install codecov -w @@ -94,7 +94,7 @@ jobs: - name: Run Cypress Tests uses: cypress-io/github-action@v5 with: - build: npm run build:editor + build: npm run build start: npm run e2e:case wait-on: "http://localhost:5175" wait-on-timeout: 120 diff --git a/packages/shader-lab/package.json b/packages/shader-lab/package.json index 9803e55f33..f521adade1 100644 --- a/packages/shader-lab/package.json +++ b/packages/shader-lab/package.json @@ -9,7 +9,6 @@ "main": "dist/main.js", "module": "dist/module.js", "browser": "dist/browser.min.js", - "editor": "dist/editor.js", "debug": "src/index.ts", "types": "types/index.d.ts", "scripts": { From 68e1556fe764425c72418b195f13211c5277a246 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 11:42:07 +0800 Subject: [PATCH 40/60] feat(shaderlab): opt code --- packages/shader-lab/src/Error.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 4936486b17..a1d5ccfff7 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -1,18 +1,12 @@ import { Logger } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; -export enum ErrorLevel { - ERROR = 0, - WARN -} - export abstract class GSError extends Error { static wrappingLineCount = 2; readonly loc: ShaderRange | ShaderPosition; readonly source: string; readonly file?: string; - level = ErrorLevel.ERROR; constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { super(message, { cause }); @@ -24,14 +18,12 @@ export abstract class GSError extends Error { log(_source?: string): void { if (!Logger.enable) return; // #if _EDITOR - const logger = this.level === ErrorLevel.ERROR ? Logger.error : Logger.warn; - let start: ShaderPosition, end: ShaderPosition; const { message, loc, source: originSource } = this; let source = originSource; if (_source) source = _source; if (!source) { - logger(message); + Logger.error(message); } if (loc instanceof ShaderPosition) { @@ -57,7 +49,7 @@ export abstract class GSError extends Error { } } - logger(diagnosticMessage); + Logger.error(diagnosticMessage); // #else Logger.error("compile error."); // #endif From 337ba2e802d2fdf9d2cf8d47b4b973394e1c6294 Mon Sep 17 00:00:00 2001 From: zhuxudong Date: Tue, 27 Aug 2024 12:02:30 +0800 Subject: [PATCH 41/60] Fix error in node environment (#2362) * fix: error in node environment --- packages/core/src/SystemInfo.ts | 5 +++++ .../loader/src/gltf/extensions/EXT_texture_webp.ts | 13 +++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/core/src/SystemInfo.ts b/packages/core/src/SystemInfo.ts index 776492fd48..314f48ac8d 100644 --- a/packages/core/src/SystemInfo.ts +++ b/packages/core/src/SystemInfo.ts @@ -8,6 +8,10 @@ export class SystemInfo { static platform: Platform = Platform.Unknown; /** The operating system is running on. */ static operatingSystem: string = ""; + + /** @internal */ + static _isBrowser = true; + /** Whether the system support SIMD. */ private static _simdSupported: boolean | null = null; @@ -24,6 +28,7 @@ export class SystemInfo { static _initialize(): void { { if (typeof navigator == "undefined") { + SystemInfo._isBrowser = false; return; } diff --git a/packages/loader/src/gltf/extensions/EXT_texture_webp.ts b/packages/loader/src/gltf/extensions/EXT_texture_webp.ts index 0000c2e127..5fea6f4f7c 100644 --- a/packages/loader/src/gltf/extensions/EXT_texture_webp.ts +++ b/packages/loader/src/gltf/extensions/EXT_texture_webp.ts @@ -1,4 +1,4 @@ -import { Texture2D } from "@galacean/engine-core"; +import { SystemInfo, Texture2D } from "@galacean/engine-core"; import type { ITexture } from "../GLTFSchema"; import { registerGLTFExtension } from "../parser/GLTFParser"; import { GLTFParserContext } from "../parser/GLTFParserContext"; @@ -15,10 +15,15 @@ class EXT_texture_webp extends GLTFExtensionParser { constructor() { super(); - const testCanvas = document.createElement("canvas"); - testCanvas.width = testCanvas.height = 1; - this._supportWebP = testCanvas.toDataURL("image/webp").indexOf("data:image/webp") == 0; + // @ts-ignore + if (SystemInfo._isBrowser) { + const testCanvas = document.createElement("canvas"); + testCanvas.width = testCanvas.height = 1; + this._supportWebP = testCanvas.toDataURL("image/webp").indexOf("data:image/webp") == 0; + } else { + this._supportWebP = false; + } } override async createAndParse( From dd4777c8f1cc4a1c25d6eefb6b4d54a6e89f9a6c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 12:20:23 +0800 Subject: [PATCH 42/60] feat(shaderlab): test case --- packages/shader-lab/src/Error.ts | 6 +----- packages/shader-lab/src/ShaderLab.ts | 12 ++++++++---- packages/shader-lab/src/codeGen/GLES100.ts | 1 - packages/shader-lab/src/codeGen/VisitorContext.ts | 3 ++- packages/shader-lab/src/index.ts | 1 + 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index a1d5ccfff7..77b9bc4e08 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -1,3 +1,4 @@ +// #if _EDITOR import { Logger } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; @@ -17,7 +18,6 @@ export abstract class GSError extends Error { log(_source?: string): void { if (!Logger.enable) return; - // #if _EDITOR let start: ShaderPosition, end: ShaderPosition; const { message, loc, source: originSource } = this; let source = originSource; @@ -50,13 +50,9 @@ export abstract class GSError extends Error { } Logger.error(diagnosticMessage); - // #else - Logger.error("compile error."); - // #endif } } -// #if _EDITOR export class PreprocessorError extends GSError { constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { super(message, loc, source, file, cause); diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index f1905ea92b..8a7aba71e4 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -8,7 +8,9 @@ import { ShaderContentParser } from "./contentParser"; import { Logger, ShaderLib, ShaderMacro, ShaderPass, ShaderPlatformTarget } from "@galacean/engine"; import { ShaderPosition, ShaderRange } from "./common"; import { ShaderLabObjectPool } from "./ShaderLabObjectPool"; +// #if _EDITOR import { GSError } from "./Error"; +// #endif import { PpParser } from "./preprocessor/PpParser"; export class ShaderLab implements IShaderLab { @@ -116,8 +118,8 @@ export class ShaderLab implements IShaderLab { */ _parse( shaderSource: string, - macros: ShaderMacro[], - backend: ShaderPlatformTarget + macros: ShaderMacro[] = [], + backend: ShaderPlatformTarget = ShaderPlatformTarget.GLES100 ): (ReturnType & { name: string })[] { const structInfo = this._parseShaderContent(shaderSource); const passResult = [] as any; @@ -142,13 +144,15 @@ export class ShaderLab implements IShaderLab { } // #endif - private _logErrors(errors: GSError[], source?: string) { + /** + * @internal + */ + _logErrors(errors: GSError[], source?: string) { // #if !_EDITOR Logger.error(`${errors.length} errors occur!`); // #else if (!Logger.isEnabled) return; for (const err of errors) { - if (!err.log) debugger; err.log(source); } // #endif diff --git a/packages/shader-lab/src/codeGen/GLES100.ts b/packages/shader-lab/src/codeGen/GLES100.ts index e590e63c9f..fdfd225f71 100644 --- a/packages/shader-lab/src/codeGen/GLES100.ts +++ b/packages/shader-lab/src/codeGen/GLES100.ts @@ -1,4 +1,3 @@ -import { CodeGenVisitor } from "./CodeGenVisitor"; import { GLESVisitor } from "./GLESVisitor"; import { VisitorContext } from "./VisitorContext"; import { ICodeSegment } from "./types"; diff --git a/packages/shader-lab/src/codeGen/VisitorContext.ts b/packages/shader-lab/src/codeGen/VisitorContext.ts index d96f42759c..8eeb95a5fb 100644 --- a/packages/shader-lab/src/codeGen/VisitorContext.ts +++ b/packages/shader-lab/src/codeGen/VisitorContext.ts @@ -1,9 +1,10 @@ -import { Logger } from "@galacean/engine"; import { EShaderStage } from "../common/Enums"; import { ASTNode } from "../parser/AST"; import { ESymbolType, SymbolTable, SymbolInfo } from "../parser/symbolTable"; import { IParamInfo } from "../parser/types"; +// #if _EDITOR import { CompilationError, GSError } from "../Error"; +// #endif import { BaseToken } from "../common/BaseToken"; import { ShaderLab } from "../ShaderLab"; diff --git a/packages/shader-lab/src/index.ts b/packages/shader-lab/src/index.ts index 7e733a06cc..5877d39f91 100644 --- a/packages/shader-lab/src/index.ts +++ b/packages/shader-lab/src/index.ts @@ -2,6 +2,7 @@ export { ShaderLab } from "./ShaderLab"; // #if _EDITOR export { Preprocessor } from "./preprocessor"; +export * from "./Error"; // #endif //@ts-ignore From 1a918dab02092e3477c5fe8254ac77de2f39489c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 14:03:51 +0800 Subject: [PATCH 43/60] feat: opt code --- packages/shader-lab/src/common/ShaderPosition.ts | 4 ---- packages/shader-lab/src/common/ShaderRange.ts | 4 ---- 2 files changed, 8 deletions(-) diff --git a/packages/shader-lab/src/common/ShaderPosition.ts b/packages/shader-lab/src/common/ShaderPosition.ts index e1ab88b619..f6cb2b19d0 100644 --- a/packages/shader-lab/src/common/ShaderPosition.ts +++ b/packages/shader-lab/src/common/ShaderPosition.ts @@ -16,8 +16,4 @@ export class ShaderPosition implements IPoolElement { this.line = 0; this.column = 0; } - - toString() { - return ``; - } } diff --git a/packages/shader-lab/src/common/ShaderRange.ts b/packages/shader-lab/src/common/ShaderRange.ts index 8b450e51e8..e79d4143e0 100644 --- a/packages/shader-lab/src/common/ShaderRange.ts +++ b/packages/shader-lab/src/common/ShaderRange.ts @@ -14,8 +14,4 @@ export class ShaderRange implements IPoolElement { this.start.dispose(); this.end.dispose(); } - - toString() { - return `Start: ${this.start.toString()};\nEnd: ${this.end.toString()}\n`; - } } From e4d267c81fc03fea8ebd66bb47dda4c2924cf74f Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 14:34:49 +0800 Subject: [PATCH 44/60] feat: opt code --- tests/src/shader-lab/ShaderLab.test.ts | 74 +++++++------- tests/src/shader-lab/ShaderValidate.ts | 29 +++++- .../shaders/compilation-error.shader | 98 +++++++++++++++++++ 3 files changed, 167 insertions(+), 34 deletions(-) create mode 100644 tests/src/shader-lab/shaders/compilation-error.shader diff --git a/tests/src/shader-lab/ShaderLab.test.ts b/tests/src/shader-lab/ShaderLab.test.ts index e6385ef312..9f351b5695 100644 --- a/tests/src/shader-lab/ShaderLab.test.ts +++ b/tests/src/shader-lab/ShaderLab.test.ts @@ -1,9 +1,10 @@ import { BlendOperation, CompareFunction, CullMode, RenderStateDataKey } from "@galacean/engine-core"; import { Color } from "@galacean/engine-math"; -import { ShaderLab } from "@galacean/engine-shader-lab/dist/main.editor"; -import { glslValidate } from "./ShaderValidate"; +import { ShaderLab as ShaderLabEditor, CompilationError } from "@galacean/engine-shader-lab/dist/main.editor"; +import { ShaderLab as ShaderLabRelease } from "@galacean/engine-shader-lab"; +import { glslValidate, shaderParse } from "./ShaderValidate"; -import chai, { expect } from "chai"; +import chai, { expect, assert } from "chai"; import spies from "chai-spies"; import fs from "fs"; import path from "path"; @@ -103,7 +104,8 @@ vec4 linearToGamma(vec4 linearIn){ #endif `; -const shaderLab = new ShaderLab(); +const shaderLabEditor = new ShaderLabEditor(); +const shaderLabRelease = new ShaderLabRelease(); describe("ShaderLab", () => { let shader: IShaderContent; @@ -112,7 +114,7 @@ describe("ShaderLab", () => { let pass1: IShaderContent["subShaders"][number]["passes"][number]; before(() => { - shader = shaderLab._parseShaderContent(demoShader); + shader = shaderLabEditor._parseShaderContent(demoShader); subShader = shader.subShaders[0]; passList = subShader.passes; expect(passList[0].isUsePass).to.be.true; @@ -121,7 +123,7 @@ describe("ShaderLab", () => { }); it("create shaderLab", async () => { - expect(shaderLab).not.be.null; + expect(shaderLabEditor).not.be.null; }); it("shader name", () => { @@ -180,68 +182,74 @@ describe("ShaderLab", () => { }); it("engine shader", async () => { - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("include", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/unlit.shader")).toString(); - glslValidate(demoShader, shaderLab, { test_common: commonSource }); + glslValidate(demoShader, shaderLabEditor, { test_common: commonSource }); }); it("planarShadow shader", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/planarShadow.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("Empty macro shader", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/triangle.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("No frag shader args", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/noFragArgs.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("water full shader(complex)", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/waterfull.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("glass shader", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/glass.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); - // it("shader with duplicate name", () => { - // const demoShader = fs.readFileSync(path.join(__dirname, "shaders/glass.shader")).toString(); - // (Shader as any)._shaderLab = shaderLab; - - // const shaderInstance = Shader.create(demoShader); - // expect(shaderInstance).instanceOf(Shader); - - // const errorSpy = chai.spy.on(console, "error"); - // Shader.create(demoShader); - // expect(errorSpy).to.have.been.called.with('Shader named "Gem" already exists.'); - // shaderInstance.destroy(); - // chai.spy.restore(console, "error"); - - // const sameNameShader = Shader.create(demoShader); - // expect(sameNameShader).instanceOf(Shader); - // }); - it("template shader", () => { const demoShader = fs.readFileSync(path.join(__dirname, "shaders/template.shader")).toString(); - glslValidate(demoShader, shaderLab); + glslValidate(demoShader, shaderLabEditor); + glslValidate(demoShader, shaderLabRelease); }); it("multi-pass", () => { const shaderSource = fs.readFileSync(path.join(__dirname, "shaders/multi-pass.shader")).toString(); - glslValidate(shaderSource, shaderLab); + glslValidate(shaderSource, shaderLabEditor); + glslValidate(shaderSource, shaderLabRelease); }); it("macro-with-preprocessor", () => { const shaderSource = fs.readFileSync(path.join(__dirname, "shaders/macro-pre.shader")).toString(); - glslValidate(shaderSource, shaderLab); + glslValidate(shaderSource, shaderLabEditor); + glslValidate(shaderSource, shaderLabRelease); + }); + + it("compilation-error", () => { + const errorShader = fs.readFileSync(path.join(__dirname, "shaders/compilation-error.shader")).toString(); + // @ts-ignore + shaderLabEditor._parse(errorShader); + expect(shaderLabEditor._errors.length).to.eq(3); + assert.instanceOf(shaderLabEditor._errors[0], CompilationError); + assert.instanceOf(shaderLabEditor._errors[1], CompilationError); + assert.instanceOf(shaderLabEditor._errors[2], CompilationError); + + shaderParse.bind(shaderLabRelease)(errorShader); + // @ts-ignore + expect(shaderLabRelease._errors.length).to.eq(1); }); }); diff --git a/tests/src/shader-lab/ShaderValidate.ts b/tests/src/shader-lab/ShaderValidate.ts index adf297ed42..82d96fcf70 100644 --- a/tests/src/shader-lab/ShaderValidate.ts +++ b/tests/src/shader-lab/ShaderValidate.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; import { ShaderLab } from "@galacean/engine-shader-lab"; -import { Shader, ShaderFactory, ShaderPass, ShaderPlatformTarget } from "@galacean/engine-core"; +import { Shader, ShaderFactory, ShaderPass, ShaderPlatformTarget, ShaderMacro } from "@galacean/engine-core"; import { IShaderContent } from "@galacean/engine-design/src/shader-lab"; function addLineNum(str: string) { @@ -94,3 +94,30 @@ export function glslValidate(shaderSource, _shaderLab?: ShaderLab, includeMap = }); }); } + +export function shaderParse( + shaderSource: string, + macros: ShaderMacro[] = [], + backend: ShaderPlatformTarget = ShaderPlatformTarget.GLES100 +): (ReturnType & { name: string })[] { + const structInfo = this._parseShaderContent(shaderSource); + const passResult = [] as any; + for (const subShader of structInfo.subShaders) { + for (const pass of subShader.passes) { + if (pass.isUsePass) continue; + const passInfo = this._parseShaderPass( + pass.contents, + pass.vertexEntry, + pass.fragmentEntry, + macros, + backend, + [], + // @ts-ignore + new URL(pass.name, ShaderPass._shaderRootPath).href + ) as any; + passInfo.name = pass.name; + passResult.push(passInfo); + } + } + return passResult; +} diff --git a/tests/src/shader-lab/shaders/compilation-error.shader b/tests/src/shader-lab/shaders/compilation-error.shader new file mode 100644 index 0000000000..2f5f66fed5 --- /dev/null +++ b/tests/src/shader-lab/shaders/compilation-error.shader @@ -0,0 +1,98 @@ +Shader "custom/pbr" { + EditorProperties { + material_BaseColor("Main Color", Color) = (0, 0, 0, 1); + material_AlphaCutoff("Alpha Cutoff", Range(0, 1, 0.01)) = 0; + material_BaseTexture("Texture", Texture2D); + } + + EditorMacros { + Header("Conditional Macors") { + MATERIAL_HAS_BASETEXTURE("Base Texture"); + MATERIAL_IS_ALPHA_CUTOFF("Alpha Cutoff"); + MATERIAL_IS_TRANSPARENT("Transparent"); + } + } + + SubShader "Default" { + Pass "Pass0" { + + #ifdef MATERIAL_IS_TRANSPARENT + BlendState { + Enabled = true; + SourceColorBlendFactor = BlendFactor.SourceAlpha; + DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha; + SourceAlphaBlendFactor = BlendFactor.One; + DestinationAlphaBlendFactor = BlendFactor.OneMinusSourceAlpha; + } + DepthState { + WriteEnabled = false; + } + RenderQueueType = Transparent; + #else + BlendState { + Enabled = false; + SourceColorBlendFactor = BlendFactor.SourceAlpha; + DestinationColorBlendFactor = BlendFactor.OneMinusSourceAlpha; + SourceAlphaBlendFactor = BlendFactor.One; + DestinationAlphaBlendFactor = BlendFactor.OneMinusSourceAlpha; + } + DepthState { + WriteEnabled = true; + } + RenderQueueType = Opaque; + #endif + + mat4 renderer_MVPMat; + vec4 material_BaseColor; + float material_AlphaCutoff; + sampler2D material_BaseTexture; + + struct Attributes { + vec4 POSITION; + vec2 TEXCOORD_0; + }; + + struct Varyings { + vec3 v_pos; + vec2 v_uv; + }; + + VertexShader = vert; + FragmentShader = frag; + + Varyings vert(Attributes attr) { + Varyings v; + + gl_Position = renderer_MVPMat * attr2.POSITION; + none(); + v.v_pos = gl_Position.xyz; + v.v_uv = attr.TEXCOORD_023; + return v; + } + + void frag(Varyings v) { + vec4 baseColor = material_BaseColor; + + #ifdef MATERIAL_HAS_BASETEXTURE + vec4 textureColor = texture2D(material_BaseTexture, v.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 + } + } + } + } \ No newline at end of file From 077e00977c5642aed4399471bd6f13f352778768 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 14:44:12 +0800 Subject: [PATCH 45/60] feat: opt code --- .../src/contentParser/ShaderContentParser.ts | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/shader-lab/src/contentParser/ShaderContentParser.ts b/packages/shader-lab/src/contentParser/ShaderContentParser.ts index 7c22162971..4a0c51fd8e 100644 --- a/packages/shader-lab/src/contentParser/ShaderContentParser.ts +++ b/packages/shader-lab/src/contentParser/ShaderContentParser.ts @@ -175,7 +175,6 @@ export class ShaderContentParser { scanner.scanText(";"); const sm = this._symbolTable.lookup({ type: stateToken.type, ident: variable.lexeme }); if (!sm?.value) { - let error: CompilationError; // #if _EDITOR throw new CompilationError( `Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`, @@ -232,13 +231,15 @@ export class ShaderContentParser { scanner.scanText("]"); scanner.scanText("="); } else if (op.lexeme !== "=") { - const error = new CompilationError( + // #if _EDITOR + throw new CompilationError( `Invalid syntax, expect character '=', but got ${op.lexeme}`, scanner.curPosition, scanner.source ); - error.log(); - throw error; + // #else + throw new Error(`Invalid syntax, expect character '=', but got ${op.lexeme}`); + // #endif } renderStateProp += idx; } @@ -246,13 +247,15 @@ export class ShaderContentParser { renderStateProp = state + renderStateProp; const renderStateElementKey = RenderStateDataKey[renderStateProp]; if (renderStateElementKey == undefined) { - const error = new CompilationError( + // #if _EDITOR + throw new CompilationError( `Invalid render state element ${renderStateProp}`, scanner.curPosition, scanner.source ); - error.log(); - throw error; + // #else + throw new Error(`Invalid render state element ${renderStateProp}`); + // #endif } scanner.skipCommentsAndSpace(); @@ -282,13 +285,15 @@ export class ShaderContentParser { const engineTypeProp = scanner.scanToken(); value = ShaderContentParser._engineType[token.lexeme]?.[engineTypeProp.lexeme]; if (value == undefined) { - const error = new CompilationError( + // #if _EDITOR + throw new CompilationError( `Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`, scanner.curPosition, scanner.source ); - error.log(); - throw error; + // #else + throw new Error(`Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`); + // #endif } } else { value = token.lexeme; @@ -308,9 +313,11 @@ export class ShaderContentParser { scanner.scanText(";"); const value = ShaderContentParser._engineType.RenderQueueType[word.lexeme]; if (value == undefined) { - const error = new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); - error.log(); - throw error; + // #if _EDITOR + throw new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); + // #else + throw new Error(`Invalid render queue ${word.lexeme}`); + // #endif } const key = RenderStateDataKey.RenderQueueType; ret.renderStates.constantMap[key] = value; @@ -456,9 +463,11 @@ export class ShaderContentParser { scanner.scanText("="); const entry = scanner.scanToken(); if (ret[word.lexeme]) { - const error = new CompilationError("reassign main entry", scanner.curPosition, scanner.source); - error.log(); - throw error; + // #if _EDITOR + throw new CompilationError("reassign main entry", scanner.curPosition, scanner.source); + // #else + throw new Error("reassign main entry"); + // #endif } const key = word.type === EKeyword.GS_VertexShader ? "vertexEntry" : "fragmentEntry"; ret[key] = entry.lexeme; From 462af900015dae97beea0ded385e436c067b009e Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 14:47:40 +0800 Subject: [PATCH 46/60] feat: opt code --- tsconfig.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 6bef4d478a..f62e2e508d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,9 +14,7 @@ "skipLibCheck": true, "paths": { "@/*": ["src/*"] // 配置模块别名,对于 chair 项目需做更改,见下文 - }, - "allowJs": true, - "checkJs": false + } }, "exclude": ["node_modules", "types", "packages/*/tests"] } From 54f9c79b9c670d195f33eeaedb1722080017e855 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 15:28:36 +0800 Subject: [PATCH 47/60] feat: opt code --- packages/shader-lab/src/ShaderLab.ts | 13 ++-- packages/shader-lab/src/common/BaseScanner.ts | 10 ++- .../shader-lab/src/contentParser/Scanner.ts | 7 ++ .../src/contentParser/ShaderContentParser.ts | 74 +++++++++++++------ 4 files changed, 74 insertions(+), 30 deletions(-) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 8a7aba71e4..b779be907f 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -53,7 +53,6 @@ export class ShaderLab implements IShaderLab { platformMacros: string[], basePathForIncludeKey: string ) { - ShaderLabObjectPool.clearAllShaderLabObjectPool(); Preprocessor.reset(ShaderLib, basePathForIncludeKey); for (const macro of macros) { Preprocessor.addPredefinedMacro(macro.name, macro.value); @@ -106,9 +105,14 @@ export class ShaderLab implements IShaderLab { } _parseShaderContent(shaderSource: string): IShaderContent { + ShaderLabObjectPool.clearAllShaderLabObjectPool(); this._errors.length = 0; + const ret = ShaderContentParser.parse(shaderSource); + for (const error of ShaderContentParser._errors) { + this._errors.push(error); + } ShaderContentParser.reset(); - return ShaderContentParser.parse(shaderSource); + return ret; } // #if _EDITOR @@ -148,10 +152,9 @@ export class ShaderLab implements IShaderLab { * @internal */ _logErrors(errors: GSError[], source?: string) { - // #if !_EDITOR - Logger.error(`${errors.length} errors occur!`); - // #else if (!Logger.isEnabled) return; + Logger.error(`${errors.length} errors occur!`); + // #if _EDITOR for (const err of errors) { err.log(source); } diff --git a/packages/shader-lab/src/common/BaseScanner.ts b/packages/shader-lab/src/common/BaseScanner.ts index c1d897970f..5b02703d5f 100644 --- a/packages/shader-lab/src/common/BaseScanner.ts +++ b/packages/shader-lab/src/common/BaseScanner.ts @@ -7,6 +7,9 @@ import { BaseToken } from "./BaseToken"; export type OnToken = (token: BaseToken, scanner: BaseScanner) => void; +/** + * @internal + */ export default class BaseScanner { private static _spaceCharsWithBreak = [" ", "\t", "\n"]; private static _spaceChars = [" ", "\t"]; @@ -67,9 +70,6 @@ export default class BaseScanner { } } - /** - * @internal - */ _advance(): void { if (this.isEnd()) { return; @@ -130,7 +130,9 @@ export default class BaseScanner { throwError(pos: ShaderPosition | ShaderRange, ...msgs: any[]) { // #if _EDITOR - throw new ScannerError(msgs.join(" "), pos, this._source); + const error = new ScannerError(msgs.join(" "), pos, this._source); + error.log(); + throw error; // #else throw new Error(msgs.join("")); // #endif diff --git a/packages/shader-lab/src/contentParser/Scanner.ts b/packages/shader-lab/src/contentParser/Scanner.ts index 63cdd33404..8052556cc8 100644 --- a/packages/shader-lab/src/contentParser/Scanner.ts +++ b/packages/shader-lab/src/contentParser/Scanner.ts @@ -25,4 +25,11 @@ export default class Scanner extends BaseScanner { } return Number(this._source.substring(start, this._currentIndex)); } + + scanToCharacter(char: string): void { + while (this.getCurChar() !== char) { + this._advance(); + } + this._advance(); + } } diff --git a/packages/shader-lab/src/contentParser/ShaderContentParser.ts b/packages/shader-lab/src/contentParser/ShaderContentParser.ts index 4a0c51fd8e..29cc58596a 100644 --- a/packages/shader-lab/src/contentParser/ShaderContentParser.ts +++ b/packages/shader-lab/src/contentParser/ShaderContentParser.ts @@ -46,8 +46,14 @@ const RenderStateType = [ EKeyword.GS_StencilState ]; +/** + * @internal + */ export class ShaderContentParser { static _engineType = { RenderQueueType, CompareFunction, StencilOperation, BlendOperation, BlendFactor, CullMode }; + + static _errors: CompilationError[] = []; + private static _isRenderStateDeclarator(token: BaseToken) { return RenderStateType.includes(token.type); } @@ -59,6 +65,7 @@ export class ShaderContentParser { private static _symbolTable: SymbolTableStack = new SymbolTableStack(); static reset() { + this._errors.length = 0; this._symbolTable.clear(); this._newScope(); } @@ -175,15 +182,19 @@ export class ShaderContentParser { scanner.scanText(";"); const sm = this._symbolTable.lookup({ type: stateToken.type, ident: variable.lexeme }); if (!sm?.value) { - // #if _EDITOR - throw new CompilationError( + let error: CompilationError; + // #if !_EDITOR + // @ts-ignore + error = new Error(`Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`); + // #else + error = new CompilationError( `Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`, scanner.curPosition, scanner.source ); - // #else - throw new Error(`Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`); // #endif + this._errors.push(error); + return; } const renderState = sm.value as IRenderStates; Object.assign(ret.renderStates.constantMap, renderState.constantMap); @@ -231,15 +242,20 @@ export class ShaderContentParser { scanner.scanText("]"); scanner.scanText("="); } else if (op.lexeme !== "=") { - // #if _EDITOR - throw new CompilationError( + let error: CompilationError; + // #if !_EDITOR + // @ts-ignore + error = new Error(`Invalid syntax, expect character '=', but got ${op.lexeme}`); + // #else + error = new CompilationError( `Invalid syntax, expect character '=', but got ${op.lexeme}`, scanner.curPosition, scanner.source ); - // #else - throw new Error(`Invalid syntax, expect character '=', but got ${op.lexeme}`); // #endif + this._errors.push(error); + scanner.scanToCharacter(";"); + return; } renderStateProp += idx; } @@ -247,15 +263,20 @@ export class ShaderContentParser { renderStateProp = state + renderStateProp; const renderStateElementKey = RenderStateDataKey[renderStateProp]; if (renderStateElementKey == undefined) { - // #if _EDITOR - throw new CompilationError( + let error: CompilationError; + // #if !_EDITOR + // @ts-ignore + error = new Error(`Invalid render state element ${renderStateProp}`); + // #else + error = new CompilationError( `Invalid render state element ${renderStateProp}`, scanner.curPosition, scanner.source ); - // #else - throw new Error(`Invalid render state element ${renderStateProp}`); // #endif + this._errors.push(error); + scanner.scanToCharacter(";"); + return; } scanner.skipCommentsAndSpace(); @@ -285,15 +306,20 @@ export class ShaderContentParser { const engineTypeProp = scanner.scanToken(); value = ShaderContentParser._engineType[token.lexeme]?.[engineTypeProp.lexeme]; if (value == undefined) { - // #if _EDITOR - throw new CompilationError( + let error: CompilationError; + // #if !_EDITOR + // @ts-ignore + error = new Error(`Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`); + // #else + error = new CompilationError( `Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`, - scanner.curPosition, + engineTypeProp.location, scanner.source ); - // #else - throw new Error(`Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`); // #endif + this._errors.push(error); + scanner.scanToCharacter(";"); + return; } } else { value = token.lexeme; @@ -313,11 +339,15 @@ export class ShaderContentParser { scanner.scanText(";"); const value = ShaderContentParser._engineType.RenderQueueType[word.lexeme]; if (value == undefined) { - // #if _EDITOR - throw new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); + let error: CompilationError; + // #if !_EDITOR + // @ts-ignore + error = new Error(`Invalid render queue ${word.lexeme}`); // #else - throw new Error(`Invalid render queue ${word.lexeme}`); + error = new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); // #endif + this._errors.push(error); + return; } const key = RenderStateDataKey.RenderQueueType; ret.renderStates.constantMap[key] = value; @@ -464,7 +494,9 @@ export class ShaderContentParser { const entry = scanner.scanToken(); if (ret[word.lexeme]) { // #if _EDITOR - throw new CompilationError("reassign main entry", scanner.curPosition, scanner.source); + const error = new CompilationError("reassign main entry", scanner.curPosition, scanner.source); + error.log(); + throw error; // #else throw new Error("reassign main entry"); // #endif From d01b0600e0a2fe6bccd50cc85baef26e0ac31175 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 15:38:13 +0800 Subject: [PATCH 48/60] feat: opt code --- packages/shader-lab/src/ShaderLab.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index b779be907f..69b5088e69 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -106,12 +106,12 @@ export class ShaderLab implements IShaderLab { _parseShaderContent(shaderSource: string): IShaderContent { ShaderLabObjectPool.clearAllShaderLabObjectPool(); + ShaderContentParser.reset(); this._errors.length = 0; const ret = ShaderContentParser.parse(shaderSource); for (const error of ShaderContentParser._errors) { this._errors.push(error); } - ShaderContentParser.reset(); return ret; } From df84ce06a597c118daf735f1a0f9ef679a91e04c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 15:59:00 +0800 Subject: [PATCH 49/60] feat: opt code --- packages/shader-lab/src/codeGen/CodeGenVisitor.ts | 6 +++--- packages/shader-lab/src/codeGen/GLESVisitor.ts | 7 ++++--- packages/shader-lab/src/parser/SemanticAnalyzer.ts | 12 +++++------- packages/shader-lab/src/parser/ShaderTargetParser.ts | 5 ++--- tests/src/shader-lab/ShaderLab.test.ts | 4 +--- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts index 534a1473bc..69e3fdee87 100644 --- a/packages/shader-lab/src/codeGen/CodeGenVisitor.ts +++ b/packages/shader-lab/src/codeGen/CodeGenVisitor.ts @@ -192,10 +192,10 @@ export class CodeGenVisitor { let error: Error; // #if _EDITOR error = new CompilationError(message, loc, ShaderLab._processingPassText); - // #else - error = new Error(message); - // #endif this._errors.push(error); return error; + // #else + throw new Error(message); + // #endif } } diff --git a/packages/shader-lab/src/codeGen/GLESVisitor.ts b/packages/shader-lab/src/codeGen/GLESVisitor.ts index 55e39efacf..401bea870e 100644 --- a/packages/shader-lab/src/codeGen/GLESVisitor.ts +++ b/packages/shader-lab/src/codeGen/GLESVisitor.ts @@ -6,6 +6,7 @@ import { EShaderStage } from "../common/Enums"; import { IShaderInfo } from "@galacean/engine-design"; import { ICodeSegment } from "./types"; import { VisitorContext } from "./VisitorContext"; +import { EKeyword } from "../common"; const defaultPrecision = ` #ifdef GL_FRAGMENT_PRECISION_HIGH @@ -47,15 +48,15 @@ export abstract class GLESVisitor extends CodeGenVisitor { VisitorContext.context.stage = EShaderStage.VERTEX; const returnType = fnNode.protoType.returnType; - if (typeof returnType.type !== "string") { - this.reportError(returnType.location, "main entry can only return struct."); - } else { + if (typeof returnType.type === "string") { const varyStruct = symbolTable.lookup({ ident: returnType.type, symbolType: ESymbolType.STRUCT }); if (!varyStruct) { this.reportError(returnType.location, `invalid varying struct: ${returnType.type}`); } else { VisitorContext.context.varyingStruct = varyStruct.astNode; } + } else if (returnType.type !== EKeyword.VOID) { + this.reportError(returnType.location, "main entry can only return struct."); } const paramList = fnNode.protoType.parameterList; diff --git a/packages/shader-lab/src/parser/SemanticAnalyzer.ts b/packages/shader-lab/src/parser/SemanticAnalyzer.ts index 8972a21411..c12e1335f2 100644 --- a/packages/shader-lab/src/parser/SemanticAnalyzer.ts +++ b/packages/shader-lab/src/parser/SemanticAnalyzer.ts @@ -60,14 +60,12 @@ export default class SematicAnalyzer { } error(loc: ShaderRange, ...param: any[]) { - let err: CompilationError; - // #if !_EDITOR - // @ts-ignore - err = new Error(param.join("")); - // #else - err = new CompilationError(param.join(""), loc, ShaderLab._processingPassText); - // #endif + // #if _EDITOR + const err = new CompilationError(param.join(""), loc, ShaderLab._processingPassText); this.errors.push(err); return err; + // #else + throw new Error(param.join("")); + // #endif } } diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index 8a737d4025..809a2e22fb 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -116,11 +116,10 @@ export class ShaderTargetParser { this.sematicAnalyzer.errors.push( new CompilationError(`Unexpected token ${token.lexeme}`, token.location, ShaderLab._processingPassText) ); + return null; // #else - // @ts-ignore - this.sematicAnalyzer.errors.push(new Error(`Unexpected token ${token.lexeme}`)); + throw new Error(`Unexpected token ${token.lexeme}`); // #endif - return null; } } } diff --git a/tests/src/shader-lab/ShaderLab.test.ts b/tests/src/shader-lab/ShaderLab.test.ts index 9f351b5695..b6ba9edfe7 100644 --- a/tests/src/shader-lab/ShaderLab.test.ts +++ b/tests/src/shader-lab/ShaderLab.test.ts @@ -248,8 +248,6 @@ describe("ShaderLab", () => { assert.instanceOf(shaderLabEditor._errors[1], CompilationError); assert.instanceOf(shaderLabEditor._errors[2], CompilationError); - shaderParse.bind(shaderLabRelease)(errorShader); - // @ts-ignore - expect(shaderLabRelease._errors.length).to.eq(1); + expect(shaderParse.bind(shaderLabRelease)).to.throw(Error); }); }); From 1426499e3e5a8f2fc6d96f6f5e7c95cccff7bd78 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:13:03 +0800 Subject: [PATCH 50/60] feat: opt code --- .../shader-lab/src/codeGen/VisitorContext.ts | 4 +- .../src/contentParser/ShaderContentParser.ts | 91 ++++++++----------- .../shader-lab/src/preprocessor/PpParser.ts | 2 +- 3 files changed, 43 insertions(+), 54 deletions(-) diff --git a/packages/shader-lab/src/codeGen/VisitorContext.ts b/packages/shader-lab/src/codeGen/VisitorContext.ts index 8eeb95a5fb..fdbcc47625 100644 --- a/packages/shader-lab/src/codeGen/VisitorContext.ts +++ b/packages/shader-lab/src/codeGen/VisitorContext.ts @@ -71,7 +71,7 @@ export class VisitorContext { ); // #else // @ts-ignore - return new Error(`referenced attribute not found: ${ident.lexeme}`); + throw new Error(`referenced attribute not found: ${ident.lexeme}`); // #endif } this._referencedAttributeList[ident.lexeme] = prop; @@ -90,7 +90,7 @@ export class VisitorContext { ); // #else // @ts-ignore - return new Error(`referenced varying not found: ${ident.lexeme}`); + throw new Error(`referenced varying not found: ${ident.lexeme}`); // #endif } this._referencedVaryingList[ident.lexeme] = prop; diff --git a/packages/shader-lab/src/contentParser/ShaderContentParser.ts b/packages/shader-lab/src/contentParser/ShaderContentParser.ts index 29cc58596a..27677cd605 100644 --- a/packages/shader-lab/src/contentParser/ShaderContentParser.ts +++ b/packages/shader-lab/src/contentParser/ShaderContentParser.ts @@ -182,19 +182,18 @@ export class ShaderContentParser { scanner.scanText(";"); const sm = this._symbolTable.lookup({ type: stateToken.type, ident: variable.lexeme }); if (!sm?.value) { - let error: CompilationError; - // #if !_EDITOR - // @ts-ignore - error = new Error(`Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`); - // #else - error = new CompilationError( - `Invalid ${stateToken.lexeme} variable: ${variable.lexeme}`, - scanner.curPosition, - scanner.source + // #if _EDITOR + this._errors.push( + new CompilationError( + `Invalid "${stateToken.lexeme}" variable: ${variable.lexeme}`, + variable.location, + scanner.source + ) ); - // #endif - this._errors.push(error); return; + // #else + throw new Error(`Invalid "${stateToken.lexeme}" variable: ${variable.lexeme}`); + // #endif } const renderState = sm.value as IRenderStates; Object.assign(ret.renderStates.constantMap, renderState.constantMap); @@ -242,20 +241,19 @@ export class ShaderContentParser { scanner.scanText("]"); scanner.scanText("="); } else if (op.lexeme !== "=") { - let error: CompilationError; - // #if !_EDITOR - // @ts-ignore - error = new Error(`Invalid syntax, expect character '=', but got ${op.lexeme}`); - // #else - error = new CompilationError( - `Invalid syntax, expect character '=', but got ${op.lexeme}`, - scanner.curPosition, - scanner.source + // #if _EDITOR + this._errors.push( + new CompilationError( + `Invalid syntax, expect character '=', but got ${op.lexeme}`, + scanner.curPosition, + scanner.source + ) ); - // #endif - this._errors.push(error); scanner.scanToCharacter(";"); return; + // #else + throw new Error(`Invalid syntax, expect character '=', but got ${op.lexeme}`); + // #endif } renderStateProp += idx; } @@ -263,20 +261,15 @@ export class ShaderContentParser { renderStateProp = state + renderStateProp; const renderStateElementKey = RenderStateDataKey[renderStateProp]; if (renderStateElementKey == undefined) { - let error: CompilationError; - // #if !_EDITOR - // @ts-ignore - error = new Error(`Invalid render state element ${renderStateProp}`); - // #else - error = new CompilationError( - `Invalid render state element ${renderStateProp}`, - scanner.curPosition, - scanner.source + // #if _EDITOR + this._errors.push( + new CompilationError(`Invalid render state element ${renderStateProp}`, scanner.curPosition, scanner.source) ); - // #endif - this._errors.push(error); scanner.scanToCharacter(";"); return; + // #else + throw new Error(`Invalid render state element ${renderStateProp}`); + // #endif } scanner.skipCommentsAndSpace(); @@ -306,20 +299,19 @@ export class ShaderContentParser { const engineTypeProp = scanner.scanToken(); value = ShaderContentParser._engineType[token.lexeme]?.[engineTypeProp.lexeme]; if (value == undefined) { - let error: CompilationError; - // #if !_EDITOR - // @ts-ignore - error = new Error(`Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`); - // #else - error = new CompilationError( - `Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`, - engineTypeProp.location, - scanner.source + // #if _EDITOR + this._errors.push( + new CompilationError( + `Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`, + engineTypeProp.location, + scanner.source + ) ); - // #endif - this._errors.push(error); scanner.scanToCharacter(";"); return; + // #else + throw new Error(`Invalid engine constant: ${token.lexeme}.${engineTypeProp.lexeme}`); + // #endif } } else { value = token.lexeme; @@ -339,15 +331,12 @@ export class ShaderContentParser { scanner.scanText(";"); const value = ShaderContentParser._engineType.RenderQueueType[word.lexeme]; if (value == undefined) { - let error: CompilationError; - // #if !_EDITOR - // @ts-ignore - error = new Error(`Invalid render queue ${word.lexeme}`); + // #if _EDITOR + this._errors.push(new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source)); + return; // #else - error = new CompilationError(`Invalid render queue ${word.lexeme}`, word.location, scanner.source); + throw new Error(`Invalid render queue ${word.lexeme}`); // #endif - this._errors.push(error); - return; } const key = RenderStateDataKey.RenderQueueType; ret.renderStates.constantMap[key] = value; diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 5225623edc..2257e94c51 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -107,7 +107,7 @@ export class PpParser { // #if _EDITOR this._errors.push(new PreprocessorError(message, loc, source, file)); // #else - this._errors.push(new Error(message)); + throw new Error(message); // #endif } From 48eb236b473cf78b266f12ed12dce4d29f7261f1 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:28:52 +0800 Subject: [PATCH 51/60] feat: opt code --- packages/shader-lab/src/ShaderLab.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 69b5088e69..8d57dbdb8a 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -35,6 +35,7 @@ export class ShaderLab implements IShaderLab { return range; } + // #if _EDITOR private _errors: GSError[] = []; /** @@ -43,6 +44,7 @@ export class ShaderLab implements IShaderLab { get errors(): GSError[] | undefined { return this._errors; } + // #endif _parseShaderPass( source: string, @@ -64,6 +66,7 @@ export class ShaderLab implements IShaderLab { const preprocessorStart = performance.now(); const ppdContent = Preprocessor.process(source); + // #if _EDITOR if (PpParser._errors.length > 0) { for (const err of PpParser._errors) { this._errors.push(err); @@ -71,6 +74,7 @@ export class ShaderLab implements IShaderLab { this._logErrors(this._errors); return { vertex: "", fragment: "" }; } + // #endif Logger.info(`[pass compilation - preprocessor] cost time ${performance.now() - preprocessorStart}ms`); @@ -81,6 +85,8 @@ export class ShaderLab implements IShaderLab { ShaderLab._processingPassText = ppdContent; const program = parser.parse(tokens); + + // #if _EDITOR for (const err of parser.errors) { this._errors.push(err); } @@ -88,6 +94,8 @@ export class ShaderLab implements IShaderLab { this._logErrors(this._errors); return { vertex: "", fragment: "" }; } + // #endif + const codeGen = backend === ShaderPlatformTarget.GLES100 ? GLES100Visitor.getVisitor() : GLES300Visitor.getVisitor(); @@ -96,10 +104,12 @@ export class ShaderLab implements IShaderLab { Logger.info(`[CodeGen] cost time: ${performance.now() - start}ms`); ShaderLab._processingPassText = undefined; + // #if _EDITOR for (const err of codeGen.errors) { this._errors.push(err); } this._logErrors(this._errors); + // #endif return ret; } @@ -146,7 +156,6 @@ export class ShaderLab implements IShaderLab { } return passResult; } - // #endif /** * @internal @@ -154,10 +163,9 @@ export class ShaderLab implements IShaderLab { _logErrors(errors: GSError[], source?: string) { if (!Logger.isEnabled) return; Logger.error(`${errors.length} errors occur!`); - // #if _EDITOR for (const err of errors) { err.log(source); } - // #endif } + // #endif } From 3b06a3f676c9f296a5e315c5a564ce7389d553ef Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:31:39 +0800 Subject: [PATCH 52/60] feat: opt code --- packages/shader-lab/src/ShaderLab.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 8d57dbdb8a..52fe636451 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -117,7 +117,9 @@ export class ShaderLab implements IShaderLab { _parseShaderContent(shaderSource: string): IShaderContent { ShaderLabObjectPool.clearAllShaderLabObjectPool(); ShaderContentParser.reset(); + // #if _EDITOR this._errors.length = 0; + // #endif const ret = ShaderContentParser.parse(shaderSource); for (const error of ShaderContentParser._errors) { this._errors.push(error); From ab356b65016b6ea2967043f1f8b249a43d2ebcd4 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:34:46 +0800 Subject: [PATCH 53/60] feat: opt code --- packages/shader-lab/src/parser/SemanticAnalyzer.ts | 4 ++++ packages/shader-lab/src/parser/ShaderTargetParser.ts | 2 ++ 2 files changed, 6 insertions(+) diff --git a/packages/shader-lab/src/parser/SemanticAnalyzer.ts b/packages/shader-lab/src/parser/SemanticAnalyzer.ts index c12e1335f2..f0f2d69886 100644 --- a/packages/shader-lab/src/parser/SemanticAnalyzer.ts +++ b/packages/shader-lab/src/parser/SemanticAnalyzer.ts @@ -22,7 +22,9 @@ export default class SematicAnalyzer { symbolTable: SymbolTableStack = new SymbolTableStack(); private _shaderData = new ShaderData(); + // #if _EDITOR readonly errors: CompilationError[] = []; + // #endif get shaderData() { return this._shaderData; @@ -39,7 +41,9 @@ export default class SematicAnalyzer { this._shaderData = new ShaderData(); this.symbolTable.clear(); this.newScope(); + // #if _EDITOR this.errors.length = 0; + // #endif } newScope() { diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index 809a2e22fb..ad8d322580 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -35,10 +35,12 @@ export class ShaderTargetParser { return this.gotoTable.get(this.curState); } + // #if _EDITOR /** @internal */ get errors() { return this.sematicAnalyzer.errors; } + // #endif static _singleton: ShaderTargetParser; From ab6de2c9cf30552c7e42ac62a6176b2af723069c Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:36:53 +0800 Subject: [PATCH 54/60] feat: opt code --- packages/shader-lab/src/parser/ShaderTargetParser.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/shader-lab/src/parser/ShaderTargetParser.ts b/packages/shader-lab/src/parser/ShaderTargetParser.ts index ad8d322580..9edf858b07 100644 --- a/packages/shader-lab/src/parser/ShaderTargetParser.ts +++ b/packages/shader-lab/src/parser/ShaderTargetParser.ts @@ -64,7 +64,7 @@ export class ShaderTargetParser { } parse(tokens: Generator): ASTNode.GLShaderProgram | null { - this._reset(); + this.sematicAnalyzer.reset(); const start = performance.now(); const { _traceBackStack: traceBackStack, sematicAnalyzer } = this; traceBackStack.push(0); @@ -126,10 +126,6 @@ export class ShaderTargetParser { } } - private _reset() { - this.sematicAnalyzer.reset(); - } - // #if _EDITOR private _printStack(nextToken: BaseToken) { let str = ""; From 5092aabc70e8999f2c59901736957abb226f20d3 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:39:20 +0800 Subject: [PATCH 55/60] feat: opt code --- packages/shader-lab/src/parser/TargetParser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shader-lab/src/parser/TargetParser.y b/packages/shader-lab/src/parser/TargetParser.y index 0d943c24be..17c9b00013 100644 --- a/packages/shader-lab/src/parser/TargetParser.y +++ b/packages/shader-lab/src/parser/TargetParser.y @@ -432,7 +432,7 @@ expression_statement: // Dangling else ambiguity selection_statement: IF '(' expression ')' statement - | IF '(' expression ')' statement ELSE statement ELSE + | IF '(' expression ')' statement ELSE statement ; iteration_statement: From 8a5f8382a5179cf4afc975c92689b0c82e38881f Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:41:11 +0800 Subject: [PATCH 56/60] feat: opt code --- packages/shader-lab/src/parser/builtin/functions.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/shader-lab/src/parser/builtin/functions.ts b/packages/shader-lab/src/parser/builtin/functions.ts index d43bb85f5c..1ff01771f6 100644 --- a/packages/shader-lab/src/parser/builtin/functions.ts +++ b/packages/shader-lab/src/parser/builtin/functions.ts @@ -136,8 +136,6 @@ BuiltinFunction._create("max", EGenType.GenType, EGenType.GenType); BuiltinFunction._create("max", EGenType.GenType, EKeyword.FLOAT); BuiltinFunction._create("max", EGenType.GenIntType, EGenType.GenIntType); BuiltinFunction._create("max", EGenType.GenIntType, EKeyword.INT); -// BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EGenType.GenUintType); -// BuiltinFunction._create("max", EGenType.GenUintType, EGenType.GenUintType, EKeyword.UINT); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EGenType.GenType, EGenType.GenType); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT, EKeyword.FLOAT); BuiltinFunction._create("clamp", EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType); From ff3f5aea5e9f5e2c7abb1bfd1546f9be0f732f1b Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:50:35 +0800 Subject: [PATCH 57/60] feat: opt code --- .../shader-lab/src/parser/builtin/functions.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/shader-lab/src/parser/builtin/functions.ts b/packages/shader-lab/src/parser/builtin/functions.ts index 1ff01771f6..c65b1883eb 100644 --- a/packages/shader-lab/src/parser/builtin/functions.ts +++ b/packages/shader-lab/src/parser/builtin/functions.ts @@ -126,16 +126,16 @@ BuiltinFunction._create("ceil", EGenType.GenType, EGenType.GenType); BuiltinFunction._create("fract", EGenType.GenType, EGenType.GenType); BuiltinFunction._create("mod", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT); BuiltinFunction._create("mod", EGenType.GenType, EGenType.GenType, EGenType.GenType); -BuiltinFunction._create("min", EGenType.GenType, EGenType.GenType); -BuiltinFunction._create("min", EGenType.GenType, EKeyword.FLOAT); -BuiltinFunction._create("min", EGenType.GenIntType, EGenType.GenIntType); -BuiltinFunction._create("min", EGenType.GenIntType, EKeyword.INT); +BuiltinFunction._create("min", EGenType.GenType, EGenType.GenType, EGenType.GenType); +BuiltinFunction._create("min", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT); +BuiltinFunction._create("min", EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType); +BuiltinFunction._create("min", EGenType.GenIntType, EGenType.GenIntType, EKeyword.INT); BuiltinFunction._create("min", EGenType.GenUintType, EGenType.GenUintType, EGenType.GenUintType); BuiltinFunction._create("min", EGenType.GenUintType, EGenType.GenUintType, EKeyword.UINT); -BuiltinFunction._create("max", EGenType.GenType, EGenType.GenType); -BuiltinFunction._create("max", EGenType.GenType, EKeyword.FLOAT); -BuiltinFunction._create("max", EGenType.GenIntType, EGenType.GenIntType); -BuiltinFunction._create("max", EGenType.GenIntType, EKeyword.INT); +BuiltinFunction._create("max", EGenType.GenType, EGenType.GenType, EGenType.GenType); +BuiltinFunction._create("max", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT); +BuiltinFunction._create("max", EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType); +BuiltinFunction._create("max", EGenType.GenIntType, EGenType.GenIntType, EKeyword.INT); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EGenType.GenType, EGenType.GenType); BuiltinFunction._create("clamp", EGenType.GenType, EGenType.GenType, EKeyword.FLOAT, EKeyword.FLOAT); BuiltinFunction._create("clamp", EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType, EGenType.GenIntType); From c679a9e125f433cfd35f50706073df1e45009555 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Tue, 27 Aug 2024 16:56:51 +0800 Subject: [PATCH 58/60] feat: opt code --- packages/shader-lab/src/preprocessor/PpParser.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/shader-lab/src/preprocessor/PpParser.ts b/packages/shader-lab/src/preprocessor/PpParser.ts index 2257e94c51..55581c7274 100644 --- a/packages/shader-lab/src/preprocessor/PpParser.ts +++ b/packages/shader-lab/src/preprocessor/PpParser.ts @@ -31,11 +31,10 @@ export class PpParser { private static _includeMap: Record; private static _basePathForIncludeKey: string; - /** @internal */ + // #if _EDITOR static _errors: Error[] = []; - /** @internal */ + // #endif static _scanningText: string; - /** @internal */ static _scanningFile = "__main__"; static reset(includeMap: Record, basePathForIncludeKey: string) { @@ -46,7 +45,9 @@ export class PpParser { this.addPredefinedMacro("GL_ES"); this._includeMap = includeMap; this._basePathForIncludeKey = basePathForIncludeKey; + // #if _EDITOR this._errors.length = 0; + // #endif } static addPredefinedMacro(macro: string, value?: string) { @@ -65,7 +66,7 @@ export class PpParser { static parse(scanner: PpScanner): string | null { this._scanningText = scanner.source; this._scanningFile = scanner.file; - while (!scanner.isEnd() && this._errors.length === 0) { + while (!scanner.isEnd()) { const directive = scanner.scanDirective(this._onToken.bind(this))!; if (scanner.isEnd()) break; switch (directive.type) { @@ -94,7 +95,9 @@ export class PpParser { break; } } + // #if _EDITOR if (this._errors.length > 0) return null; + // #endif return PpUtils.expand(this.expandSegments, scanner.source, scanner.sourceMap); } From 44b7e84ec951e12da520498e041abc09e933a230 Mon Sep 17 00:00:00 2001 From: Sway007 Date: Mon, 2 Sep 2024 17:23:56 +0800 Subject: [PATCH 59/60] feat: opt code --- packages/shader-lab/src/Error.ts | 1 + packages/shader-lab/src/ShaderLab.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/shader-lab/src/Error.ts b/packages/shader-lab/src/Error.ts index 77b9bc4e08..1082af414c 100644 --- a/packages/shader-lab/src/Error.ts +++ b/packages/shader-lab/src/Error.ts @@ -24,6 +24,7 @@ export abstract class GSError extends Error { if (_source) source = _source; if (!source) { Logger.error(message); + return; } if (loc instanceof ShaderPosition) { diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index 52fe636451..b8474f1fa9 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -163,7 +163,7 @@ export class ShaderLab implements IShaderLab { * @internal */ _logErrors(errors: GSError[], source?: string) { - if (!Logger.isEnabled) return; + if (errors.length === 0 || !Logger.isEnabled) return; Logger.error(`${errors.length} errors occur!`); for (const err of errors) { err.log(source); From eb0bcdea62a8d3986f2e5a45d3bbac7db7865e0b Mon Sep 17 00:00:00 2001 From: Sway007 Date: Wed, 11 Sep 2024 10:00:48 +0800 Subject: [PATCH 60/60] feat: code opt --- packages/shader-lab/src/ShaderLab.ts | 2 +- packages/shader-lab/src/contentParser/Scanner.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/shader-lab/src/ShaderLab.ts b/packages/shader-lab/src/ShaderLab.ts index b8474f1fa9..19bf8c363a 100644 --- a/packages/shader-lab/src/ShaderLab.ts +++ b/packages/shader-lab/src/ShaderLab.ts @@ -41,7 +41,7 @@ export class ShaderLab implements IShaderLab { /** * Retrieve the compilation errors */ - get errors(): GSError[] | undefined { + get errors(): GSError[] { return this._errors; } // #endif diff --git a/packages/shader-lab/src/contentParser/Scanner.ts b/packages/shader-lab/src/contentParser/Scanner.ts index 8052556cc8..3d3aa9b527 100644 --- a/packages/shader-lab/src/contentParser/Scanner.ts +++ b/packages/shader-lab/src/contentParser/Scanner.ts @@ -27,7 +27,7 @@ export default class Scanner extends BaseScanner { } scanToCharacter(char: string): void { - while (this.getCurChar() !== char) { + while (this.getCurChar() !== char && !this.isEnd()) { this._advance(); } this._advance();