DreamShaderLang
插件参考Graph

名称解析

名称解析

名称解析

DreamShader » Graph » 名称解析

在 Graph 块内,裸标识符和调用目标是如何被查找的,按照编译器尝试它们的固定顺序,以及每个层面会遮蔽什么。

声明位置.dsm、.dsf —— 适用于 Graph { … } 体内的每个表达式、Outputs 绑定表达式以及 Outputs 声明默认值
类型解析规则

名称的查找分为两个阶段 (自 2.0.0 起)。旧版前端在解析时会读取若干 1.x 写法——布尔字面量、类型名称、N::F、1.x 调用简写以及会变成节点的属性——而 2.0 绑定器会以与处理 .dss 相同的方式解析其余所有内容。绑定器以区分大小写的方式比较名称;当名称仅在大小写上不同但仍匹配时,1.x 源码仍会通过旧版规则 L19 构建成功,并会就此发出警告。

概要

存在两个不同的阶梯。运行哪一个完全取决于名称后面是否跟着 (。

<identifier>                 // bare-identifier ladder
<identifier> ( … )           // call-name ladder
<identifier> :: <identifier> ( … )   // call-name ladder, qualified callee

Common::ApplyTint 被读取为单个标识符 Common_ApplyTint,即命名空间函数声明时所用的名称。UE.TexCoord 和 Substrate.Slab 是节点调用。不属于以上任何一种的被调方——比如对括号表达式调用——是 DSH4208。

裸标识符

顺序阶段层面大小写结果
1解析布尔字面量 true 和 false不敏感具有一个分量的 bool 值
2解析类型名称——float3、vec3、half、Texture2D……不敏感一个类型,不是值:DSH4204
3解析类型为参数节点的属性(TextureSampleParameter2D、ChannelMaskParameter……),StaticSwitchParameter 除外不敏感该属性的节点,在此读取处写出
4绑定Graph 变量——本体的声明、Shader 的 Outputs 声明,或本体读取的 UE.* 属性——最内层块优先敏感该变量
5绑定函数的参数:ShaderFunction 的输入或输出,或 Base,即 Shader 所构建的材质敏感该参数
6绑定文件作用域声明:标量、向量、纹理或 static-bool 属性敏感材质参数
7绑定4–6 中恰好一个在忽略大小写时匹配不敏感那一个,并带有警告 DSH5275(旧版规则 L19)
8—(无匹配)—DSH4200;单独 UE 或 Substrate 为 DSH4203

步骤 1–3 在任何变量已知之前运行,因此它们会胜过同名的变量。在步骤 6 读取的属性每次都是参数节点;在去重过程之后,相等的节点为一个节点。步骤 7 需要唯一匹配:当两个声明在忽略大小写时匹配,则二者都不会被选中,该名称为 DSH4200。

[!NOTE] StaticSwitchParameter 属性故意不会作为裸标识符解析——它需要它的两个分支。按名称读取它会失败并给出 DSH4200。请使用调用形式 Switch(True = …, False = …);参见调用。

调用名称

严格按照此顺序探测。第一个认领该名称的层面胜出;后续层面永远不会被查询。

顺序阶段层面大小写备注
1解析Path(…)不敏感资源引用,不是调用
2解析类型名称不敏感构造函数:构造函数
3解析N::F—读取为标识符 N_F,然后从步骤 9 开始查找
4解析类型为参数节点的属性不敏感StaticSwitchParameter:静态开关调用;其他:引脚调用
5解析SampleTexture2D敏感UE.Expression(Class="TextureSample", …);除两个位置参数之外的任何内容都是 DSH5256
6解析BreakOutFloat2Components … BreakOutFloat4Components 带输出选择器不敏感第一个参数的 swizzle;参见调用
7解析1.x UE.* 简写——UE.TexCoord、UE.Time、UE.SceneTexture、UE.StaticSwitchParameter……不敏感它们的参数按 1.x 方式读取,简写从未读取的参数会被丢弃并带有警告 DSH5254;UE.SceneTexture 和 UE.StaticSwitchParameter 会变成 UE.Expression 调用。参见 UE 内置函数
8绑定UE.<Node> / Substrate.<Node>节点名称:精确,然后不敏感并给出 DSH5276UE.* 目录和 Substrate.* 目录,UE 5.4+
9绑定数学内置函数敏感数学内置函数中的 HLSL 写法
10绑定mix、fract、mod、inversesqrt敏感内置函数的 GLSL 写法:该内置函数,并带有警告 DSH5277
11绑定Function、GraphFunction、ShaderFunction、VirtualFunction——本文件或导入头文件的敏感见下文
12绑定恰好一个内置函数,否则恰好一个函数,在忽略大小写时匹配不敏感那一个,并带有 DSH5275(旧版规则 L19)
13—(无匹配)—DSH4208

绑定器精确比较节点前的 UE (自 2.0.0 起):ue.TexCoord() 会把 ue 读取为未声明名称 DSH4200。

内置函数直接认领其名称。格式错误的 clamp(x) 是该内置函数的参数数量错误 DSH4224;不存在同名的用户函数可供回退,因为声明一个用户函数是 DSH6206。

在步骤 11 没有需要解决的歧义:一个名称声明一个事物,而某个名称的第二次声明在声明处就是 DSH4210 (自 2.0.0 起)。

每种声明类型如何被匹配

类型声明所用名称
Function、GraphFunction其名称。在 Namespace(Name="N") 内,名称为 N_F,即写法 N::F 被读取为的名称。
ShaderFunction其 Name 中最后一个以 / 分隔的段,其中标识符不能包含的每个字符都被替换为 _:声明为 Name="Functions/F_Tint" 的块可作为 F_Tint 调用。当在它之前声明的函数已具有该名称时,<Name>_Asset(信息 DSH5290)。
ShaderLayer、ShaderLayerBlend同 ShaderFunction,但调用为 DSH6208 (自 2.0.0 起)。
VirtualFunction其 Name,必须是标识符(DSH6311)。

生成的 HLSL 符号 DreamShaderFn_<name> 不再是调用可使用的名称 (自 2.0.0 起)。

这里是没有重载解析:名称不会按元数或参数类型划分作用域。导入的标头被声明进文件中,而不是作为文本粘贴进去,且它声明的名称不可以被再次声明:DSH4210 同时命名两个文件。此处名称同样区分大小写比较,因此 Foo 和 foo 是两个函数*(自 2.0.0 起;1.x 曾将它们报告为声明了两次)*,而 N::F 与一个名为 N_F 的函数是同一个名称,DSH4210。

带命名空间的函数只能通过 N::F 或其读取形式 N_F 访问。这里没有 using 风格的导入,也没有无限定的回退。

遮蔽

因为层级是严格有序的,"遮蔽"总是单向进行:靠前的表层隐藏靠后的表层,绝不会反过来。

情况结果
一个名为 lerp、dot、pow、saturate、frac、fmod、… 或 mix、fract、mod 的 FunctionDSH6206(自 2.0.0 起)。该函数未被声明,每次调用都是该内置函数。
一个名为 float、float2、vec3、int4、bool2 或任何其他类型名称的 Function永远不会被调用。 在解析调用时该名称被读取为类型,因此每次调用都会构建一个构造函数。
一个名为 SampleTexture2D 的 Function永远不会被调用。 每个 SampleTexture2D(…) 在解析时都会被改写。名为 sampletexture2d 的函数会被该写法调用:改写会进行精确比较。
一个名称以 UE. 或 Substrate. 开头的 Function不是名称:UE.X(…) 是一个节点调用。
与标量、向量、纹理或静态布尔属性同名的 Graph 变量该变量从其声明处起生效,声明会以警告 DSH4251 说明这一点。
与参数节点属性同名的 Graph 变量属性生效,无论何种情况:上述第 3 步和第 4 步会在该行被解析时运行。
与 Function 同名的属性DSH4210:属性是文件作用域声明,与函数共享同一个命名空间*(自 2.0.0 起)*。参数节点属性不是声明;它在其被使用处写出,因此以其名称进行的调用是该属性的引脚调用。
同一文件两个块中相同的属性名DSH4210:每个块的标量、向量、纹理和静态布尔属性都在文件作用域声明*(自 2.0.0 起)*。参数节点属性属于它们各自的块。
一个名为 True 或 False(任意大小写)的变量或属性不可读:true 和 false 在任何名称之前被读取为字面量*(自 2.0.0 起;1.x 曾让该名称遮蔽字面量)*。
一个名为类型名称的变量,例如 Half 或 Float3不可读:该名称被读取为类型,DSH4204(自 2.0.0 起)。

[!WARNING] 遮蔽构造函数是静默的。Function vec3(in float x, out float3 r) 会被解析、被声明,并且 在 Graph 块中根本不会被调用 —— 每次 vec3(…) 调用都会构建一个构造函数。请重命名该 函数。

标识符大小写

元素大小写敏感性
if、else敏感
顶层块关键字(Shader、Function、GraphFunction、Namespace、VirtualFunction、ShaderFunction、ShaderLayer、ShaderLayerBlend)敏感
SampleTexture2D敏感
节点前的 UE敏感*(自 2.0.0 起)*
区段名称(Properties、Settings、Outputs、Graph、Layout)不敏感
类型记号(float3、vec3、MaterialAttributes、Texture2D、Substrate)不敏感
构造函数名称不敏感
true / false不敏感
in / out 参数限定符不敏感
分量重组通道(.RGB、.xyZ)不敏感
输出选择器与静态开关分支名称(Output、OutputName、OutputIndex、True、False、A、B)不敏感
数学内置函数名称敏感*(自 2.0.0 起)*;其他大小写以 DSH5275 解析
Graph 变量、属性和参数名称敏感*(自 2.0.0 起)*;当恰好有一个声明匹配时,其他大小写以 DSH5275 解析
参数节点属性名称不敏感 —— 在该行被解析时进行匹配
Function / GraphFunction / 材质函数名称敏感*(自 2.0.0 起)*;其他大小写以 DSH5275 解析
命名调用参数名称函数的参数:作为名称,DSH5275;节点的引脚和属性:DSH5276;内置函数的参数(A、B、Alpha):敏感,DSH4216
UE.* / Substrate.* 节点、引脚、属性和输出名称引擎的拼写;其他大小写以 DSH5276 解析
MaterialAttributes 成员名称引擎的拼写;其他大小写以 DSH5276 解析
default 调用参数敏感*(自 2.0.0 起)*

[!NOTE] 以与声明不同的大小写写出的名称就是该声明,并带有 DSH5275。 float3 Color = …; 后跟 color = …; 写出 Color(自 2.0.0 起;1.x 曾创建名为 color 的第二个条目)。只有在任何大小写下都不匹配任何内容的名称才会由赋值声明(旧 规则 L26,信息 DSH5292)。dsc migrate 会按照每个此类 名称被声明的方式重新拼写它。

命名参数匹配

参数名称会精确比较。函数的参数名称会以 DSH5275 回退到唯一的不区分大小写匹配,节点的引脚和 属性名称会以 DSH5276 回退;内置函数的参数名称没有回退。上述 1.x 伪参数在匹配时忽略大小写。 位置参数在前面并按顺序填充参数;位于命名参数之后的位置参数是 DSH2158(自 2.0.0 起)。

哪些被调用者接受命名参数已记录于 调用。

诊断

代码触发条件
DSH4200一个裸名称,既不是 Graph 变量、参数或文件作用域声明,或者忽略大小写时匹配到多个此类名称。此外,一个 StaticSwitchParameter 属性在未调用时被读取。
DSH4203UE 或 Substrate 被作为值读取。
DSH4204一个类型名称被作为值读取。
DSH4208一个调用名称到达了阶梯的末端,或者被调用者不是名称。
DSH5275(警告) 一个名称仅在忽略大小写时才与其声明匹配。
DSH5276(警告) 一个引擎名称——节点、引脚、属性、输出、材质特性——仅在忽略大小写时才匹配。
DSH5277(警告) 内置项的 GLSL 拼写。
DSH4210一个名称在文件中或被导入的头文件中被声明了两次——包括 N::F 与函数 N_F 的重名。
DSH6206一个与内置项同名的函数。
DSH6208对 Shader、ShaderLayer 或 ShaderLayerBlend 的调用。
DSH4251(警告) 一个 Graph 变量隐藏了同名的属性。
DSH5260:: 后面没有跟名称。
DSH2161. 后面没有跟名称。

示例

import "Helpers.dsh";

Shader(Name="Docs/M_Resolution")
{
    Properties {
        vec3                  Tint    = vec3(1.0, 0.5, 0.2);
        StaticSwitchParameter UseTint = true;
    }

    Settings { Domain = "UI"; ShadingModel = "Unlit"; }

    Outputs {
        vec3 Color;
        Base.EmissiveColor = Color;
    }

    Graph {
        // 'Tint' is the file-scope property: a VectorParameter node.
        vec3 Base1 = Tint;

        // 'TINT' matches 'Tint' only ignoring case: the same parameter, warning DSH5275.
        vec3 Base2 = TINT;

        // 'lerp' is the builtin; a function of that name in Helpers.dsh would be DSH6206.
        vec3 Mixed = lerp(Base1, Base2, 0.5);

        // A namespaced Function needs its full name.
        vec3 Lit = Common::ApplyTint(Mixed, Tint);

        // 'UseTint' is a StaticSwitchParameter: callable, not readable.
        Color = UseTint(True = Lit, False = Mixed);
    }
}

解析轨迹:

Tint                  -> bare 6   file-scope property               -> VectorParameter node
TINT                  -> bare 7   'Tint', ignoring case (DSH5275)   -> the same node
lerp(...)             -> call 9   math builtin                      -> LinearInterpolate node
Common::ApplyTint(..) -> call 3   read as Common_ApplyTint
                         call 11  Function (namespaced)             -> Custom node
UseTint(True=,False=) -> call 4   StaticSwitchParameter             -> StaticSwitchParameter node
UseTint               -> (bare read) ERROR: DSH4200

另请参阅

本页目录