DreamShaderLang
诊断

诊断

诊断

诊断

DreamShader » 诊断

DreamShader 的诊断出现在哪里、如何读懂一条诊断,以及 1.x 生成器的消息后来怎么样了。一次编译报出的每条诊断都有一个稳定的 DSHnnnn 码*(自 2.0.0 起)*;码是契约,措辞不是。目录在 README.md——每个码及其严重级别和消息——每个码在其页面上都有一节,DSH1xxx.md … DSH9xxx.md,列有它名下报出的每条消息、报出它的位置、原因和修复方法。

产生者DreamShaderLang——预处理器、两个前端、绑定器、IR 及其校验器 · DreamShaderCompiler——流水线、include 解析器、发射器、资产层 · DreamShaderEditor——bridge、commandlet 命令和工具
日志分类LogDreamShader
线上格式<file>(<line>,<column>): DSHnnnn: <message>,无论编辑器是什么语言都是英文
严重级别error、warning 或 info——一次编译的记录保留各自的级别*(自 2.1.0 起)*;编译不解释的少数记录是 error
Bridge 产物<Project>/Saved/DreamShader/Bridge/diagnostics.json、.../Bridge/diagnostics/、.../Bridge/bridge.db

[!NOTE] 到 1.9.x 为止大多数消息没有码:1.x parser 给自己的消息编了码,1.x 生成器约 560 个 报错点只报裸文本,本页当时也逐字收录那些文本。生成器和 parser 已经删掉,那些字符串 一条都不会再报出。如果你在旧日志或搜索结果里见到一条,1.x 消息及其码 列出了常见的那些。

诊断出现在哪里

界面显示什么实现方
Output Log分类 LogDreamShader 下的编译报告:失败时记 Error——每条记录一行线上格式,先错误、再警告、再 note——成功时记 Display——Generated … / Skipped … 行,再跟一个 Warnings: 块插件
Material Content Browser每个源文件的记录,从 bridge 的内存诊断存储读出;源文件那一行显示第一个错误插件
Bridge/diagnostics.json{ version, updatedAtUtc, files[] },每个文件一项插件
Bridge/diagnostics/每个文件一个 <md5-of-normalized-path>.json 分片,外加 index.json;每次写入都会删掉过期分片插件
Bridge/bridge.dbSQLite 表 diagnostics(path, json, updated_at_utc),在一个事务里整体替换插件
-DiagnosticsOut=<file>一次 commandlet 运行的诊断,JSON(schema dreamshader-diagnostics)——见 Commandlet插件
VSCode / Rider 扩展波浪线由上面三份 bridge 产物渲染扩展侧,不是插件

三个 bridge sink 每次诊断更新都一起写,所以它们永远不会互相矛盾。Output Log 是另一条独立路径,也是唯一会显示成功行的界面。

诊断归属于产生它的源文件和产生它的那次运行。运行有三种:一个源文件的编译、它生成的某个材质的 shader 编译,以及对一个文件的启动时 VirtualFunction 扫描。

运行它替换什么
A.dsm 的编译恰好是 A 上次编译登记的那些——登记在 A 上的,和登记在 A 导入的任何头文件上的。B.dsm 登记在同一个头文件上的记录保留。它也会撤掉启动时 VirtualFunction 扫描对 A 及其头文件说过的话
一个材质的 shader 编译该材质的 shader 编译记录,在其 shader 编译结束时——比生成它的那次编译晚几帧;绝不会动编译自己的警告
启动时的 VirtualFunction 扫描它对所扫文件的记录
删除一个文件这个文件拥有的一切记录,来自每种运行,以及登记在它上面的每条记录,无论谁登记

同一个文件里,记录按「编译、shader 编译、VirtualFunction 扫描」排序,各自内部按源文件排,所以一个文件的第一个错误是它编译时的错误。见 Bridge。

[!NOTE] bridge 从不在 commandlet 里运行。-run=DreamShader、-run=Cook 以及任何其他 commandlet 进程都不写 diagnostics.json、不写分片、不写 bridge.db 行;消息只存在于 日志中(以及一个 -DiagnosticsOut 文件中)。bridge 也会被 -NoDreamShaderEditorBridge 禁用。 见 Commandlet。

严重级别

一次编译按每条记录被报出时的级别登记它自己的记录——失败的编译登记全部,成功的编译登记它的警告和 note*(自 2.1.0 起;在此之前,每条入库的诊断都是 error,成功编译的警告只到达 Output Log)*。编译不解释的记录——generate-error、material-compile、virtual-function-sync——是 error。该字段及其取值见 Bridge。

不属于任何编译记录、只写日志的警告(UE_LOG(LogDreamShader, Warning, …))从不进入存储。客户端遇到缺失或未知的严重级别时,按 error 处理。

消息位置

诊断按 MSVC 风格打印,带着它的码:

I:/Project/DShader/Materials/M_Sample.dsm(8,19): DSH4200: 'Tin' is not declared in this scope.
诊断它的位置从哪来
一次编译的记录构造本身的行和列,取自报错时所在的 token——在 section 体里、在 Graph 里、在被 import 的头文件里都一样。在头文件里报的记录指向头文件,不是导入它的文件
关于整个文件的——解析不了的 include、编译器不构建的源文件文件的第 1 行第 1 列
材质编译引擎自己的 <path>(<line>,<col>): 前缀,被重新解析并归回它来自的源码行
generate-error——记录解释不了的失败从一行 <path>(<line>,<column>): <message> 里取;取不到就是 1,1

(自 2.0.0 起) 每个文件单独做词法和语法分析,所以位置从不从拼起来的文本映射回去。到 1.9.x 为止,解析错误带的是一个指向「import 内联之后的文本」的 near index {Index} 偏移,section 体里的位置是错的,大多数语句级消息根本没有位置。

一个阶段会报出它的全部错误——parser 和绑定器遇到一个错误后会继续往下走——而有错误的阶段会在下一阶段开始前停下流水线:有语法错误的文件不会进入绑定,绑定不过的文件不会被发射。

读懂一个码

首位数字是报出它的阶段;完整分配见 DreamShaderLang 2.0。

范围阶段
DSH1xxx预处理器(#if、#define),1.x 纹理默认值中的资产引用
DSH2xxx词法分析器和解析器 —— DSH2200–DSH2258 是旧版前端的:1.x Graph 语句和顶层块
DSH3xxx声明、#pragma、/// 块;DSH3250–DSH3278 是旧版前端的 section
DSH4xxx绑定器(名称、类型、语句)、IR 校验器、降低拒绝
DSH5xxxUE.* / Substrate.* 调用和节点目录;DSH5250–DSH5292 是 1.x 调用写法和编了号的 旧版规则
DSH6xxx函数种类、内联、/// @custom HLSL;DSH6300–DSH6330 是 1.x 的 Function / GraphFunction / Namespace / VirtualFunction
DSH7xxxuniform、指令、#pragma material、材质设置写入器、.dsi、.dsp 检查
DSH8xxx发射器、资产层、include 解析器(DSH8291–DSH8295)、Custom Pass 发射
DSH9xxx工具 —— check、dump-ir、反编译器、migrate、导航、pass-registry

旧版规则(DSH5275–DSH5292)是 1.x 做过、而 1.x 源文件今天仍然会得到的行为,只是现在会说出来:只靠大小写才对得上的名字(DSH5275、DSH5276)、GLSL 拼写(DSH5277)、宽向量被截到窄位置(DSH5289)、一条赋值顺带声明了变量(DSH5292)。它是 .dsm / .dsf 上的 warning 或 info,从不出现在 .dss 里,而 dsc migrate 会把每一条都写成显式的 2.0 文本。

1.x 消息及其代码

1.x 解析器和生成器的常见消息,以及今天由什么报告同样的状况。{…} 代表消息里填入的内容。

1.x 消息今天
Unknown Graph identifier '{Name}'.DSH4200 —— 当已声明的名字只差大小写时附带 did you mean
Unknown Graph function '{Name}'.DSH4208
Math function '{Name}' expects exactly {N} argument(s).DSH4224;命名参数现在选择 pin,未知的名字是 DSH4216 —— 见 数学内置
Math function '{Name}' only accepts numeric scalar/vector arguments. · Operator '{Op}' requires matching vector sizes … · Arithmetic operators cannot be applied to …DSH4226
Integer division is not supported by the material graph …DSH4243
Expected {N} component(s) but got {M}.DSH4228;宽值写进窄位置在 1.x 源文件里是 info DSH5289
Swizzle '{Swizzle}' is invalid … · Unsupported swizzle '{Swizzle}'.DSH4230
Constructor '{Name}' expects {N} total components but got {M}.DSH4222;float3() 后面什么都不写是 DSH4221
Graph variable '{Name}' is declared more than once.在一个块里是 DSH4220;在文件作用域是 DSH4210
Graph variable type '{Type}' requires an explicit initializer.DSH2215
Unsupported Graph variable type '{Type}'.未知类型是 DSH4201;return、for、while、switch 是 DSH2208
Graph if statement is missing a '{ ... }' body.DSH2209
Graph if statement could not resolve both branch values for '{Name}'.DSH4372
Graph if statement cannot select texture value '{Name}'. · … Substrate value …DSH4379 · DSH4378
Unsupported material output '{Name}'.DSH5200
Unsupported property type '{Type}'.DSH3252;七个没有 2.0 拼写的节点 token 之一是 DSH3253
Metadata 'Slider(min, max)' requires exactly two numeric bounds … · Metadata key '{Key}' is declared more than once. · Metadata SortPriority value '{Value}' is not an integer.DSH3257 · DSH3256 · DSH3258
Unsupported UE builtin call '{Name}' in Graph. …DSH5210 —— 目录认得的节点不需要 OutputType
UE.{Name} could not resolve MaterialExpression class '{Class}'.DSH5212
UE.Expression requires Class="MaterialExpressionName".DSH5218
UE.{Name}: '{Argument}' is not a property on '{Class}'.DSH5213
Generic {Namespace}.{Name} calls require named arguments.DSH5220 / DSH5221
UE.SceneTexture expects exactly Id="..." … · SampleTexture2D expects exactly two positional arguments …DSH5255 · DSH5256
UE.StaticSwitchParameter requires Name="ParameterName". · StaticSwitchParameter '{Name}' requires True=... and False=... inputs.DSH5257 · DSH5258
{Kind} '{Name}' is missing required input '{Input}'. · … does not have an input named '{Input}'.DSH4217 · DSH4216
GraphFunction cycle detected: {Chain}. · SelfContained Function cycle detected: …互相调用的 Function / GraphFunction 体是 DSH6260;环经由从体中提升出来的调用运行时是 DSH6330;被内联的 .dss helper 是 DSH6220
Function '{Name}' has a return type and cannot also declare out parameters. … · Function '{Name}' must declare at least one out parameter.DSH6304 · DSH6305
Function '{Name}' parameter '{Parameter}' uses unsupported qualifier '{Qualifier}'. … · … '__return' is reserved …DSH6302 · DSH6303
Namespace(Name="...") is required. · Namespace '{Name}' may only contain Function or GraphFunction blocks.DSH6309 · DSH6310
VirtualFunction(Name="...") is required. · … must provide Options = { Asset = Path(...); }. · … must declare at least one output.DSH6311 · DSH6312 · DSH6313
Shader(Name="...") is required. · {Block}(Name="...") is required.DSH2242
Shader must provide a Graph block.DSH2255
{File}: Outputs block is required. · No Outputs block was provided. …warning DSH2256;材质照样构建,只是没有任何东西接到它上面
Unknown shader section '{Section}'. · Unknown material function section '{Section}'. · Unknown VirtualFunction section '{Section}'.DSH2245
Shader graph sections now use Graph = { ... }. …DSH2246
MaterialLayer is deprecated; use ShaderLayer instead. · MaterialLayerBlend is deprecated; …warning DSH2251
Only one top-level Shader block is currently supported.DSH2250 —— 现在按 文件 判定;它过去跨越整个 import 闭包
DreamShader header '{File}' may only declare …DSH2249,按声明判定:注释里提到 Shader( 没问题
DreamShader function file '{File}' may only declare … · {File}: .dsf files cannot define top-level Shader blocks.DSH2259 —— 见 源文件
A top-level Shader, Function, … block was not found.DSH2254
Unexpected token near index {Index}.DSH2240;.dsm / .dsf 里的 2.0 语法是 DSH2248
Expected '{' near index {Index}. · Expected ',' or ')' near index {Index}. · Expected identifier near index {Index}. · Expected value near index {Index}.DSH2257 · DSH2243
Unterminated block. · Unterminated string literal.DSH2150 · DSH2103
DreamShader import '{Specifier}' referenced from '{File}' could not be resolved.DSH8292;import 一个 .dsf / .dsm 或根限定写法是 DSH2252
DreamShader could not read '{File}'. · DreamShader import cycle detected at '{File}'.DSH8293 · DSH4211
Unsupported Backend '{Value}'. Supported values: Graph, Instance, ThinCustom.DSH7202;空值是 DSH7201,Instance 是 warning DSH7204
Unsupported BlendMode/RenderType '{Value}'. · Unsupported ShadingModel '{Value}'. · Unsupported MaterialDomain '{Value}'. · Unsupported material setting '{Key}'.DSH7127 · DSH7129 · DSH7130 · DSH7118 —— 材质设置写入器保留了它的 1.x 消息
Asset '{ObjectPath}' already exists and is not a Material. · … was not generated by DreamShader. …DSH8201,原因附带 DSH8102 / DSH8103
Asset '{ObjectPath}' is open in an asset editor, so it was NOT rebuilt. …DSH8206,附带 DSH8101
Asset '{ObjectPath}' was edited by hand since DreamShader generated it …DSH8207,附带 DSH8115 —— 见 Divergence

不在表里的消息:到 README.md 里搜它所描述情况的一个词, 或者把文件编译一遍、读它现在报的码。

1.x 静默接受的写法

1.x 生成器一声不吭地接受、然后构建出与文本不符的东西(或者把文本说的东西丢掉)的情况。(自 2.0.0 起)每一种都有诊断。

1.x 文本1.x 的做法今天
a % b、a & b、a | b、a ^ b、a << b 在 Graph 表达式里读到运算符就停:表达式就是 aDSH2201
a ? b : c,或 if 条件之外的 a < b一样:表达式就是 aDSH2200
v[0]丢掉下标和它后面的一切DSH2202
if (a > 0 && b > 0)只测 a > 0DSH2210
(float3)x没有强制转换DSH2203
a += b读成一个以运算符命名的变量的声明DSH2205
x++没有这个运算符DSH2207
作为语句的 a + b;建出没人读的节点DSH2211
Graph 表达式里的 0x10读成了另一个数DSH2222
当作数字的 1abc 或 0.5.5取前面的数字DSH2105
没闭合的 /* …吃掉文件剩下的部分DSH2102
属性写了两遍:Shader(Name="A", Name="B")保留后一个值warning DSH2244,仍保留后一个值
Settings 键写了两遍保留后一个值warning DSH3262,仍保留后一个值
材质函数 Settings 里的未知键忽略warning DSH3263,仍然忽略
不收位置参数的 UE.* 调用上的位置参数忽略warning DSH5254,仍然丢掉
函数 Outputs 条目上的默认值忽略warning DSH3273,仍然丢掉
第二个 Graph 或 Layout section保留后一个warning DSH2258,仍保留后一个
与内置同名、从 Graph 调用的 ShaderFunction调到了内置在声明处报 DSH6206
dot(vec3Value, vec2Value)接受;后来 Unreal 自己的材质翻译失败DSH4226

1.x 写进文档、1.x 源文件仍在依赖的写法 —— 换了大小写的名字、GLSL 拼写、写进 float3 位置的 float4 —— 照样构建, 作为一条把它说出来的 legacy 规则。

VirtualFunction 同步

启动服务会重新读取每一个 VirtualFunction 声明,并从它的 UMaterialFunction 资产刷新它,以及 Material Function 工具栏和上下文菜单上的编辑器操作。 这些消息没有 DSHnnnn 码,DSH9001 除外 —— 用于使用 #if 的源文件。

同步诊断通过 stage = virtualFunctionSync、code = virtual-function-sync 和 source = DreamShader VirtualFunction 进入存储。编辑器操作消息是 toast 通知和 日志行;它们不会被存储。

消息原因修复参见
Created VirtualFunction file but could not open it: {File}.dsh 已写入,但 VSCode 无法启动手动打开该文件VirtualFunction 工具
DreamShader could not find a VirtualFunction definition for {Asset}.对没有声明的资产执行 Open VirtualFunction改用 CreateVirtualFunctionVirtualFunction 工具
DreamShader could not find the selected Material Function.所选资产在菜单构建与执行操作之间消失了重新选择该资产VirtualFunction 工具
DreamShader could not open VirtualFunction file: {File}编辑器启动失败手动打开该文件VirtualFunction 工具
DreamShader could not read VirtualFunction source file '{File}'.源文件不可读;报在第 1 行第 1 列检查文件锁和权限VirtualFunction 工具
DreamShader failed to build VirtualFunction call: {Detail}无法生成调用片段看内层消息VirtualFunction 工具
DreamShader failed to build VirtualFunction reference: {Detail}无法生成引用片段看内层消息VirtualFunction 工具
DreamShader failed to build VirtualFunction: {Detail}无法生成声明文本看内层消息VirtualFunction 工具
DreamShader failed to create directory: {Dir}无法创建 DShader/VirtualFunctions检查权限VirtualFunction 工具
DreamShader failed to update VirtualFunction source file '{File}'.刷新后的声明写不回去;报在第 1 行第 1 列检查文件锁和版本控制VirtualFunction 工具
DreamShader failed to write VirtualFunction file: {File}无法写入新的 .dsh检查权限VirtualFunction 工具
Expected exactly one VirtualFunction block.重新解析的声明区域得到零个或多个块每个声明区域只保留一个 VirtualFunctionVirtualFunction
MaterialFunction '{Name}' does not have a valid package path.资产最外层的包名为空,或不以 / 开头把资产重新保存到已挂载内容根目录下的某处VirtualFunction 工具
MaterialFunction '{Name}' does not expose any outputs.资产没有 FunctionOutput 节点给材质函数加一个输出VirtualFunction
VirtualFunction '{Name}' asset reference is invalid: {Detail}Options.Asset 解析不了;原始字面量作为诊断的 assetPath 报出改正 Path( … )Path
VirtualFunction '{Name}' could not be refreshed from MaterialFunction '{Path}': {Detail}声明构建器失败看内层消息VirtualFunction 工具
VirtualFunction '{Name}' references missing MaterialFunction '{Path}'.LoadObject 返回 null恢复资产,或者更新 Options.AssetVirtualFunction
VirtualFunction attributes are missing a closing ')'.头部中 ( 不配平配平圆括号VirtualFunction
VirtualFunction body is missing a closing '}'.主体中 { 不配平配平花括号VirtualFunction
VirtualFunction declaration is invalid: {Detail}重新解析失败;解析错误携带在 detail 中改正声明VirtualFunction
VirtualFunction name cannot be empty.声明构建器收到了空名字提供一个名字VirtualFunction

[!NOTE] 同步服务按裸关键字 VirtualFunction 找声明,区分大小写, 两边要有标识符边界 —— 和 legacy 前端对块关键字的要求一样。 小写的 virtualfunction 两边都看不见。

其他日志行

不属于任何编译、永远不入库的行。

消息含义
Failed to open DreamShader bridge database for diagnostics: {Path}bridge.db 打不开;JSON sink 仍然会写
'{ObjectPath}' exists as a saved asset, so it is rebuilt and saved on disk rather than in memory. Run Tools > DreamShader > Make Ephemeral to make it Ephemeral again.编译落到了一个背后有文件的 ThinCustom 产物上;由存储决定,所以它被重建并存盘
Skipping automatic layout for large DreamShader graph ({Count} nodes). Existing generated positions will be used.记在 Display 级别;1.x 的 Classic 布局跳过了大图

commandlet 自己的运行行、用法横幅和退出码在 命令行;反编译器的在反编译导出。

示例

Graph 块里的一个拼写错误,到达各个界面时的样子。

// DShader/Materials/M_Sample.dsm
Shader(Name="Materials/M_Sample")
{
    Properties = { vec3 Tint = vec3(1.0, 0.4, 0.1); }
    Outputs    = { vec3 Color; Base.EmissiveColor = Color; }
    Graph      = {
        vec2 UV = UE.TexCoord(Index = 0);
        Color   = Tin * UV.x;          // typo: Tin, not Tint
    }
}

Output Log:

LogDreamShader: Error: I:/Project/DShader/Materials/M_Sample.dsm(8,19): DSH4200: 'Tin' is not declared in this scope.

Saved/DreamShader/Bridge/diagnostics.json:

{
  "version": 1,
  "updatedAtUtc": "2026-10-04T11:04:22Z",
  "files": [
    {
      "path": "I:/Project/DShader/Materials/M_Sample.dsm",
      "diagnostics": [
        {
          "message": "'Tin' is not declared in this scope.",
          "detail": "I:/Project/DShader/Materials/M_Sample.dsm(8,19): DSH4200: 'Tin' is not declared in this scope.",
          "stage": "bind",
          "code": "DSH4200",
          "line": 8,
          "column": 19,
          "severity": "error",
          "source": "DreamShader Lang2"
        }
      ]
    }
  ]
}

同一条记录还会写进 Bridge/diagnostics/<md5>.json 和 Bridge/bridge.db 的 diagnostics 表,并出现在 Material Content Browser 里这个源文件的那一行。stage 由 码的范围决定:preprocess、parse、bind、ir、generate 或 tools。

另请参阅

  • README.md — 每个码,及其严重级别和消息
  • 桥接 — 请求文件、WebSocket 协议和诊断产物
  • Material Content Browser — 显示每个源文件记录的那个标签页
  • 命令行 — -run=DreamShader、-DiagnosticsOut、它的开关和退出码
  • DreamShaderLang 2.0 — 完整的码范围
  • dsc migrate — 以 2.0 文本写出的 legacy 规则
  • 源文件 — 多个码所强制执行的文​件类型规则
  • import — 头部如何被读取,以及 import 的码
  • 测试 — 固定了许多这些码的语料库夹具

本页目录