galacean / engine

A typescript interactive engine, support 2D, 3D, animation, physics, built on WebGL and glTF.
https://www.galacean.com/engine
MIT License
4.29k stars 307 forks source link

`ShaderLab` should expose an extra api for syntax error detection #2405

Open Sway007 opened 1 month ago

Sway007 commented 1 month ago

Is your feature request related to a problem? Please describe.

EN

Due to the presence of macros, a single Shader code may contain multiple branches of code. During runtime, the compiler only needs to compile one specific branch of code when all macros are known. However, for syntax error detection tools, it is preferable for the compiler to compile all branches of code and report all detected errors. Currently, the compilation of ShaderLab requires providing all macros related to the code. If one wants to perform syntax checks on all branch codes, it is necessary to explore all combinations of macros, which leads to an exponential explosion problem. Therefore, a separate API needs to be designed specifically for syntax error detection tools, employing a specific compilation algorithm to address the exponential explosion issue.

CN

因为宏的存在,一份Shader代码可能包含多份分支代码,运行时阶段编译器只需要在所有宏都确定的情况下对唯一的一份分支代码进行编译。但对于语法错误检测工具而言,则希望编译器能够对所有分支代码进行编译,并提示所有检测到的错误。当前ShaderLab的编译需要提供代码关联的所有宏,如果想要对所有分支代码都进行语法检查则需要遍历所有宏组合情况,存在指数爆炸问题,需要针对语法错误检测工具单独设计一个API,走特定的编译算法,并解决指数爆炸问题

Describe the solution you'd like

  1. A sperate parse api should be exposed by ShaderLab for VERBOSE package (used by editor and VSCode extension).
  2. In the compilation of VERBOSE version, all branch-macro-statements, like #if, #ifdef, #else, are transpiled into normal if-else branch statements, then the same compilation process are performed by compiler.

    There are still several different grammar rule after all macro-branch are transpiled into if-else branch. For instance, use undeclared variable should be allowed under below situation

    ...
    #ifdef XXX_MACRO
    float ior = 1.0;
    #else 
    float ior = 0.0;
    #endif
    float v = ior * factor ...;
    ...

    the snippets above will be transpiled into

    if (exist(XXX_MACRO)) {
     float ior = 1.0;
    } else {
     float ior = 0.0;
    }
    float v = ior * factor ...;