-
-
Notifications
You must be signed in to change notification settings - Fork 299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve ShaderLab
compilation error log and package build
#2364
base: dev/1.4
Are you sure you want to change the base?
Changes from all commits
5a26f3d
5ecc318
cafc24f
dc69489
221b7b6
0d45d9c
0f14c3f
8871d9b
3b4ffd7
f649a58
598fc56
e33a66f
41ef06f
b5214fc
f36ce02
ff8b7c2
634236f
91e6fa4
3932448
671cace
92b972e
9226d38
ff6a69a
83b9ca2
f510c2a
94e30f5
e3c7aa5
36b77e0
b2e07fc
93df92e
8e0cc28
7652250
c92e674
3fefbe9
9eb7398
9f5b5bc
82f73b2
964b846
f6fed8b
519ab40
ee6a813
d7e0ac8
8f75c28
00447fb
d5a3c0c
c176226
b8ca43f
a6d21d6
ce23026
3bcaeb0
79a7a0c
fa7131c
3093bd2
6eba20a
8c90796
dab8003
f12b8f7
c32969b
9d4d808
f5edeb3
68e1556
337ba2e
dd4777c
1a918da
4c9e16c
e4d267c
077e009
462af90
54f9c79
d01b060
df84ce0
1426499
48eb236
3b06a3f
ab356b6
ab6de2c
5092aab
8a5f838
ff3f5ae
c679a9e
44b7e84
eb0bcde
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,77 @@ | ||
// #if _EDITOR | ||
import { ShaderRange } from "./common"; | ||
import { Logger } from "@galacean/engine"; | ||
import { ShaderPosition, ShaderRange } from "./common"; | ||
|
||
export abstract class GSError extends Error { | ||
readonly loc: ShaderRange; | ||
static wrappingLineCount = 2; | ||
|
||
constructor(message: string, loc: ShaderRange, cause?: Error) { | ||
readonly loc: ShaderRange | ShaderPosition; | ||
readonly source: string; | ||
readonly file?: string; | ||
|
||
constructor(message: string, loc: ShaderRange | ShaderPosition, source: string, file?: string, cause?: Error) { | ||
super(message, { cause }); | ||
this.loc = loc; | ||
this.source = source; | ||
this.file = file; | ||
} | ||
|
||
log(_source?: string): void { | ||
if (!Logger.enable) return; | ||
let start: ShaderPosition, end: ShaderPosition; | ||
const { message, loc, source: originSource } = this; | ||
let source = originSource; | ||
if (_source) source = _source; | ||
if (!source) { | ||
Logger.error(message); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里没有 source 可以直接 return 了 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
return; | ||
} | ||
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for 循环要特别注意这种高频操作,别浪费性能,移到外面去 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个类都是在Editor版本里的,release版本没有这些性能损耗 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 哥,Editor 就不用管性能了吗 |
||
diagnosticMessage += "^".repeat(Math.max(end.column - start.column, 1)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 同上,max 更耗性能了 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 同上 |
||
diagnosticMessage += "\n"; | ||
} | ||
} | ||
|
||
Logger.error(diagnosticMessage); | ||
} | ||
} | ||
|
||
export class PreprocessorError extends GSError { | ||
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 | ShaderPosition, source: string, file?: string, cause?: Error) { | ||
super(message, loc, source, file, cause); | ||
this.name = "CompilationError"; | ||
} | ||
} | ||
|
||
export class SemanticError extends GSError { | ||
constructor(message: string, loc: ShaderRange, cause?: Error) { | ||
super(message, loc, cause); | ||
this.name = "SemanticError"; | ||
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"; | ||
} | ||
} | ||
// #endif |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,42 +2,30 @@ 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 } 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 { | ||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||
* @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); | ||||||||||||||||||||||||||||
Comment on lines
+26
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor suggestion: Use class name instead of Using Apply this diff to refactor the code: - const position = this._shaderPositionPool.get();
+ const position = ShaderLab._shaderPositionPool.get(); Committable suggestion
Suggested change
ToolsBiome
|
||||||||||||||||||||||||||||
return position; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
|
@@ -47,6 +35,17 @@ export class ShaderLab implements IShaderLab { | |||||||||||||||||||||||||||
return range; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// #if _EDITOR | ||||||||||||||||||||||||||||
private _errors: GSError[] = []; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||
* Retrieve the compilation errors | ||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
get errors(): GSError[] { | ||||||||||||||||||||||||||||
return this._errors; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// #endif | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
_parseShaderPass( | ||||||||||||||||||||||||||||
source: string, | ||||||||||||||||||||||||||||
vertexEntry: string, | ||||||||||||||||||||||||||||
|
@@ -56,7 +55,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); | ||||||||||||||||||||||||||||
|
@@ -66,36 +64,67 @@ 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 _EDITOR | ||||||||||||||||||||||||||||
if (PpParser._errors.length > 0) { | ||||||||||||||||||||||||||||
for (const err of PpParser._errors) { | ||||||||||||||||||||||||||||
this._errors.push(<GSError>err); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
this._logErrors(this._errors); | ||||||||||||||||||||||||||||
return { vertex: "", fragment: "" }; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// #endif | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
Logger.info(`[pass compilation - preprocessor] cost time ${performance.now() - preprocessorStart}ms`); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const lexer = new Lexer(ppdContent); | ||||||||||||||||||||||||||||
const tokens = lexer.tokenize(); | ||||||||||||||||||||||||||||
const program = ShaderLab._parser.parse(tokens); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const { _parser: parser } = ShaderLab; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
ShaderLab._processingPassText = ppdContent; | ||||||||||||||||||||||||||||
const program = parser.parse(tokens); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// #if _EDITOR | ||||||||||||||||||||||||||||
for (const err of parser.errors) { | ||||||||||||||||||||||||||||
this._errors.push(err); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
if (!program) { | ||||||||||||||||||||||||||||
this._logErrors(this._errors); | ||||||||||||||||||||||||||||
return { vertex: "", fragment: "" }; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// #endif | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const codeGen = | ||||||||||||||||||||||||||||
backend === ShaderPlatformTarget.GLES100 ? GLES100Visitor.getVisitor() : GLES300Visitor.getVisitor(); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const start = performance.now(); | ||||||||||||||||||||||||||||
const ret = codeGen.visitShaderProgram(program, vertexEntry, fragmentEntry); | ||||||||||||||||||||||||||||
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; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
_parseShaderContent(shaderSource: string): IShaderContent { | ||||||||||||||||||||||||||||
ShaderLabObjectPool.clearAllShaderLabObjectPool(); | ||||||||||||||||||||||||||||
ShaderContentParser.reset(); | ||||||||||||||||||||||||||||
return ShaderContentParser.parse(shaderSource); | ||||||||||||||||||||||||||||
// #if _EDITOR | ||||||||||||||||||||||||||||
this._errors.length = 0; | ||||||||||||||||||||||||||||
// #endif | ||||||||||||||||||||||||||||
const ret = ShaderContentParser.parse(shaderSource); | ||||||||||||||||||||||||||||
for (const error of ShaderContentParser._errors) { | ||||||||||||||||||||||||||||
this._errors.push(error); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
return ret; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
// #if _EDITOR | ||||||||||||||||||||||||||||
|
@@ -105,8 +134,8 @@ export class ShaderLab implements IShaderLab { | |||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
_parse( | ||||||||||||||||||||||||||||
shaderSource: string, | ||||||||||||||||||||||||||||
macros: ShaderMacro[], | ||||||||||||||||||||||||||||
backend: ShaderPlatformTarget | ||||||||||||||||||||||||||||
macros: ShaderMacro[] = [], | ||||||||||||||||||||||||||||
backend: ShaderPlatformTarget = ShaderPlatformTarget.GLES100 | ||||||||||||||||||||||||||||
): (ReturnType<ShaderLab["_parseShaderPass"]> & { name: string })[] { | ||||||||||||||||||||||||||||
const structInfo = this._parseShaderContent(shaderSource); | ||||||||||||||||||||||||||||
const passResult = [] as any; | ||||||||||||||||||||||||||||
|
@@ -129,5 +158,16 @@ export class ShaderLab implements IShaderLab { | |||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
return passResult; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||
* @internal | ||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||
_logErrors(errors: GSError[], source?: string) { | ||||||||||||||||||||||||||||
if (errors.length === 0 || !Logger.isEnabled) return; | ||||||||||||||||||||||||||||
Logger.error(`${errors.length} errors occur!`); | ||||||||||||||||||||||||||||
for (const err of errors) { | ||||||||||||||||||||||||||||
err.log(source); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
// #endif | ||||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个也是用平台编译带来的缺点,带来这么多潜规则