- 编译器
- 图形学
- 编程语言
【免费下载链接】slang
Making it easier to work with shaders
本篇技术指南以 Slang 编译器仓库中docs/generated/design/ir-reference/decorations.md的 gap-intake(文档缺口接收/校正)报告为核心主体,系统梳理 Slang IR 中Decoration家族 196 个具体 opcode 的语义、操作数编码与产生路径,并结合-dump-ir编译器实测与源码证据,逐条讲解报告中 8 个已修正(fixed)、2 个被驳回(rejected-bogus)、1 个判定越界(rejected-out-of-scope)的缺口结论。读完本文,你将掌握:如何阅读 Slang IR 转储中的各种 decoration,entryPoint、interpolationMode、synthesizedParameterGroup等关键装饰的精确编码规则,以及 decoration 从 AST 修饰符到 IR 的完整产生链路。
背景:什么是 gap-intake,以及本次重跑解决了什么
docs/generated/design/ir-reference/decorations.md是 Slang 仓库中按 opcode 逐个讲解Decoration家族的参考文档,覆盖 slang-ir-insts.lua 第 1756 行起的整个Decoration条目(在source_commit时共 196 个具体 opcode)。为了让这类生成式文档与源码保持同步,仓库维护了一套 gap-intake 流程:由docs/generated/design/_meta/prompts/ir-reference-decorations.md定义写作边界,逐条审计文档中的每个断言,找出"与源码不符"的缺口(gap),给出证据并决定修文(fixed)、驳回(rejected-bogus)、越界(rejected-out-of-scope)或延期(deferred)。
本报告是decorations.md页面的重跑:第一轮曾把单个缺口901ca639c751以"本机无法运行编译器、只能靠-dump-ir裁决"为由标记为 deferred。这一前提被证明是错的——构建目录中存在一个与HEAD编译器源码一致的原生 macOS-arm64slangc(-version输出为2026.14.1-80-g6122d03def,且git diff --stat 6122d03def HEAD -- source/ include/为空,说明其编译器源码即HEAD本身)。实际运行-dump-ir后,该缺口从deferred转为fixed,deferred 计数归零。最终行动分布为:8 个 fixed、2 个 rejected-bogus、1 个 rejected-out-of-scope、0 个 deferred、0 个 escalated。
缺口判定总览
报告对 11 个缺口逐条给出了 Action、Evidence(源码/测试/实测证据)与 Fix summary,完整汇总如下:
| Gap ID | Action | Evidence | Fix summary |
|---|---|---|---|
| a13d8a468a77 | rejected-out-of-scope | docs/generated/design/_meta/prompts/ir-reference-decorations.mdlines 75-81,## Forbidden content: "Backend-specific consumption of decorations — see [../pipeline/06-emit.md]"。逐 target 列出[unroll]/[branch]在 hlsl / glsl / spirv / metal / wgsl 中变成什么的表,正属于该禁写范畴,且 callout 已链接06-emit.md | — |
| 33fbeb8b7617 | fixed | slang-lower-to-ir.cpp,位于TargetProgram::createIRModuleForLayout(行 16381):decoration 由asFuncDecl->inferredCapabilityRequirements构建,过滤出_spirv_1_0..latestSpirvAtom与metallib_2_3..latestMetalAtom;没有任何[require(...)]路径会添加它。Builder 位于 slang-ir-insts.h | 将错误的require(...)AST 起源替换为 layout-IR 生产者与推断能力集路径,并注明只记录 SPIR-V 版本与 Metal-library 两种原子 |
| 320bf7714a3d | fixed | slang-ir-insts.h:getProfile()返回Profile(Profile::RawVal(getIntVal(getProfileInst())));slang-ir-insts.h 存储profile.raw;slang-lower-to-ir.cpp 传入entryPoint->getProfile()。编码见 slang-profile.h。-stage vertex时的值1由entry-point-vertex-profile.slang验证 | 扩展entryPointcallout:tag 是Profile::RawVal(高 16 位ProfileVersion、低 16 位Stage),而非裸 stage 代码 |
| dbe97ebb7283 | fixed | core.meta.slang 与 L4756-4757:attribute_syntax [format(format : String)]/[vk_image_format(format : String)] : FormatAttribute;slang-ir-insts.h:addFormatDecoration(IRInst*, ImageFormat)存储getIntValue(getIntType(), IRIntegerValue(format)) | 在format行展示带引号实参,并说明操作数是字符串解析出的整数ImageFormat值 |
| e19c29a6b653 | fixed | slang-ir-insts.h:enum class IRInterpolationMode { Linear, NoPerspective, NoInterpolation, Centroid, Sample, PerVertex };修饰符映射见 slang-lower-to-ir.cpp;源码拼写见 slang-parser.cpp 与 core.meta.slang。值 0/2/4 由interpolation-mode-{linear,nointerpolation,sample}.slang钉死 | 为interpolationMode增加完整六值映射 callout(缺口原列表漏掉了PerVertex5),并让表格行指向该 callout |
| 7bb8913f2a18 | rejected-bogus | core.meta.slang 声明attribute_syntax [vk_location(location : int)] : GLSLLocationAttribute,故vk_location是该属性的真实名字且可写;slang-parser.cpp(parseAttributeName)把作用域属性名中的每个::重写为_,这正是[vk::location(7)]在glsl-location-decoration.slang中到达同一属性的原因。缺口"[vk_location(...)]不可写"的前提不成立 | 行仍被改写为以用户实际书写的拼写开头 |
| 863b0c0f87dc | fixed | core.meta.slang:__attributeTarget(LoopStmt)+attribute_syntax [ForceUnroll(count: int = 0)];slang-lower-to-ir.cpp 从循环语句上读取修饰符;slang-ir-insts.h:addLoopForceUnrollDecoration追加getIntValue(getIntType(), iters),尽管 Lua 条目(slang-ir-insts.lua)声明为无操作数。操作数形式由force-unroll-on-loop.slang钉死,E31002 由force-unroll-on-function-error.slang钉死 | 将ForceUnroll行修正为 builder 追加count: IRIntLit的写法(与vulkanRayPayload行一致),并记录仅限LoopStmt的属性目标和默认值0 |
| 69f3396b03eb | rejected-bogus | 这是两个不同 opcode 而非同一名字的两种拼写。slang-ir-insts.lua 声明 decorationstreamOutputTypeDecoration;slang-ir-insts.lua 在TypeLayout下声明streamOutputTypeLayout,由 slang-ir-insts.h 的IRStreamOutputTypeLayout : IRTypeLayout包装。stream-output-type-decoration.slang匹配到的是 type-layout inst。decoration 本身仅由 slang-ir-glsl-legalize.cpp 产生,故-target hlsl转储中不可能出现 | — |
| bd7183d2d708 | fixed | slang-ir-insts.h 是addBuiltinDecoration的唯一定义,slang-lower-to-ir.cpp 是其唯一调用点,位于visitInterfaceDecl(行 12073)内、decl->findModifier<BuiltinAttribute>()之下。[builtin]声明于 core.meta.slang;core.meta.slang中 12 处、hlsl.meta.slang中 6 处使用全部位于interface声明上,包括 hlsl.meta.slang 的IBufferDataLayout——它是RWStructuredBuffer(hlsl.meta.slang:74)的默认布局约束 | 将行从 "Core-module lowering" / "an inst" 收窄为interface声明上的[builtin]属性,并点名IBufferDataLayout作为普通代码会接触到的案例 |
| 93335aeba9c7 | fixed | slang-ir-insts.h:IRConstructorDecoration::getSynthesizedStatus()读取cast<IRBoolLit>(getOperand(0));slang-ir-insts.h:addConstructorDecoration(IRInst*, bool synthesizedConstructor);唯一调用者 slang-lower-to-ir.cpp 传入constructorDecl->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault) | 将已废弃的(variadic, min=1)单元格替换为(1 个无名操作数:IRBoolLit,由 getSynthesizedStatus() 读取),并说明true标记编译器合成的默认构造函数而非用户手写的__init |
| 901ca639c751 | fixed | 重跑:通过运行编译器裁决(第一轮误以为不可能)。build-arm64/Debug/bin/slangc(-version2026.14.1-80-g6122d03def)配合SLANG_ASSERT=release-assert-only,对[shader("compute")] [numthreads(1,1,1)] void computeMain(uniform float scale, uint3 tid : SV_DispatchThreadID)(函数体写outBuf[tid.x] = scale)执行slangc -dump-ir -target hlsl -entry computeMain -o out.hlsl x.slang:在AFTER collectEntryPointUniformParams及之后的所有快照中,struct %EntryPointParams上都打印[synthesizedParameterGroup];把scale移到文件作用域成为全局uniform float scale后,从AFTER collectGlobalUniformParameters起打印在struct %GlobalParams上。两者与受监控的生产者 slang-ir-entry-point-uniforms.cpp(ensureCollectedParamAndTypeHaveBeenCreated)和 slang-ir-collect-global-uniforms.cpp 一致。两个结构都不出现在LOWER-TO-IR快照中,因为 slang-emit.cpp 与 L1275 在目标降级(target lowering)期间运行两个 pass。普通数据前置条件是 slang-ir-collect-global-uniforms.cpp,用只含RWStructuredBuffer与Texture2D的对照组程序验证:整个转储零匹配。glsl / spirv / metal / wgsl 结果相同 | 为synthesizedParameterGroupcallout 追加第二段:给出可达的 entry-point 与 global 两种写法(含 target 与 options)、全局收集的普通数据前置条件,以及两个结构均不出现在LOWER-TO-IR快照中的说明 |
八个已修正缺口(fixed):文档修正背后的技术事实
requireCapabilityAtom:来自推断能力集而非[require(...)]
33fbeb8b7617指出原文档把该 decoration 的 AST 起源错误地写成require(...)属性。实际上它由 slang-lower-to-ir.cpp 中TargetProgram::createIRModuleForLayout(行 16381)从 entry point 的inferredCapabilityRequirements(推断能力需求)构建,并只记录 SPIR-V 版本原子(_spirv_1_0..latestSpirvAtom)与 Metal-library 原子(metallib_2_3..latestMetalAtom)两类。推论:若在 IR 转储中看到requireCapabilityAtom,它反映的是编译器在布局阶段推断出的能力集合,而不是源码里某个[require(...)]的直接产物。Builder 入口在 slang-ir-insts.h。
entryPoint:profile tag 是Profile::RawVal,不是裸 stage 代码
320bf7714a3d修正了entryPoint装饰的 profile 操作数编码。IREntryPointDecoration::getProfile(slang-ir-insts.h)通过Profile(Profile::RawVal(getIntVal(getProfileInst())))重建Profile;slang-ir-insts.h 存储的是profile.raw;lowering 侧由 slang-lower-to-ir.cpp 传入entryPoint->getProfile()。
Profile::RawVal的位布局由 slang-profile.h 的PROFILE宏钉死:TAG = (uint32_t(ProfileVersion::VERSION) << 16) | uint32_t(Stage::STAGE)——高 16 位是ProfileVersion,低 16 位是Stage(getStage()用raw & 0xFFFF取出,getVersion()用raw >> 16取出)。因此一个用-stage vertex编译、未显式指定 profile 版本的 entry point,其 profile tag 打印为1(即裸Stage值),这一行为由entry-point-vertex-profile.slang测试钉死。读懂这一点,你在-dump-ir输出里看到[entryPoint(1, "computeMain", ...)]时就能立刻反推出 stage 与版本位。
format:操作数是字符串解析出的整数ImageFormat
dbe97ebb7283澄清了formatdecoration 的实参形态。AST 侧,core.meta.slang 与 L4756-4757 声明attribute_syntax [format(format : String)]与[vk_image_format(format : String)] : FormatAttribute——实参是带引号的字符串,如[format("rgba32f")],而非裸标识符。IR 侧,addFormatDecoration(IRInst*, ImageFormat)(slang-ir-insts.h)把该字符串解析出的ImageFormat枚举值经getIntValue(getIntType(), IRIntegerValue(format))存储为整数常量。所以转储中[format(N)]里的N是ImageFormat枚举的整数值。
interpolationMode:六值编码,不是位掩码
e19c29a6b653补充了interpolationMode的完整编码表。modeOperand是普通的整数IRInterpolationMode值(slang-ir-insts.h),不是位掩码:
| 值 | 枚举 | 源码修饰符 |
|---|---|---|
| 0 | Linear | linear |
| 1 | NoPerspective | noperspective |
| 2 | NoInterpolation | nointerpolation |
| 3 | Centroid | centroid |
| 4 | Sample | sample |
| 5 | PerVertex | pervertex(Slang 自有) |
映射发生在addVarDecorations(slang-lower-to-ir.cpp),一个源码修饰符对应一个值;源码拼写见 slang-parser.cpp 与 core.meta.slang。因此转储中出现[interpolationMode(2 : Int)]就意味着源码写的是nointerpolation。缺口原列表遗漏了PerVertex(5),这正是本次修正补齐的内容。值 0/2/4 由interpolation-mode-{linear,nointerpolation,sample}.slang三个测试钉死。
ForceUnroll:builder 追加的count: IRIntLit,且只作用于循环语句
863b0c0f87dc修正了ForceUnroll的操作数形态与属性目标。AST 侧,core.meta.slang 声明__attributeTarget(LoopStmt)+attribute_syntax [ForceUnroll(count: int = 0)],因此[ForceUnroll]只能写在循环语句上,count省略时默认0。lowering 在 slang-lower-to-ir.cpp 从循环语句读取修饰符;addLoopForceUnrollDecoration(slang-ir-insts.h)总是追加getIntValue(getIntType(), iters)作为操作数——即使 Lua 条目(slang-ir-insts.lua)声明该 decoration 无操作数。这就是"builder 追加操作数"的典型例子:表格不能只看 Lua 声明,还要看 C++ builder 的实际行为。操作数形式由force-unroll-on-loop.slang钉死;把[ForceUnroll]写到函数上触发的诊断 E31002 由force-unroll-on-function-error.slang钉死。
BuiltinDecoration:只来自[builtin]属性 +interface声明
bd7183d2d708把BuiltinDecoration的来源从笼统的 "Core-module lowering" 收窄为精确的"[builtin]属性(BuiltinAttribute)标注的interface声明"。证据链:addBuiltinDecoration的唯一定义在 slang-ir-insts.h,唯一调用点在 slang-lower-to-ir.cpp 的visitInterfaceDecl(行 12073)内,且受decl->findModifier<BuiltinAttribute>()保护。属性本身声明于 core.meta.slang(实际位于 L4900-L4901,__attributeTarget(DeclBase)+attribute_syntax [builtin] : BuiltinAttribute)。全仓*.meta.slang中共 18 处使用(core.meta.slang12 处、hlsl.meta.slang6 处)全部落在interface声明上,典型代表是 hlsl.meta.slang 的IBufferDataLayout——它是RWStructuredBuffer(hlsl.meta.slang:74)的默认布局约束,也就是说普通代码里每个RWStructuredBuffer都会通过它间接关联到BuiltinDecoration。
constructor:单个无名IRBoolLit操作数标记合成构造函数
93335aeba9c7修正了constructordecoration 的操作数规格。原文档单元格写的(variadic, min=1)已过时;实际是恰好 1 个无名操作数:一个IRBoolLit,由IRConstructorDecoration::getSynthesizedStatus()(slang-ir-insts.h)以cast<IRBoolLit>(getOperand(0))读取。addConstructorDecoration(IRInst*, bool synthesizedConstructor)(slang-ir-insts.h)的唯一调用者 slang-lower-to-ir.cpp 传入constructorDecl->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault)——即true表示这是编译器合成的默认构造函数,false表示用户手写的__init。
synthesizedParameterGroup:用-dump-ir实测钉死的产生时机
901ca639c751是本轮重跑的核心成果,也是唯一动用真实编译器实测裁决的缺口。第一轮因"本机无法运行编译器"将其延期,但build-arm64/Debug/bin/slangc的存在推翻了这个前提。实测条件与结论如下:
- 工具链:
slangc -version为2026.14.1-80-g6122d03def,且git diff --stat 6122d03def HEAD -- source/ include/为空,保证二进制与HEAD源码一致;配合SLANG_ASSERT=release-assert-only运行。 - entry-point 形态:源码
[shader("compute")] [numthreads(1,1,1)] void computeMain(uniform float scale, uint3 tid : SV_DispatchThreadID) { outBuf[tid.x] = scale; }用
slangc -dump-ir -target hlsl -entry computeMain -o out.hlsl x.slang编译,在AFTER collectEntryPointUniformParams及之后所有快照中,struct %EntryPointParams上都出现[synthesizedParameterGroup]。 - 全局形态:把
scale移到文件作用域成为uniform float scale,marker 从AFTER collectGlobalUniformParameters起出现在struct %GlobalParams上。 - 生产者:两者分别与 slang-ir-entry-point-uniforms.cpp(
ensureCollectedParamAndTypeHaveBeenCreated,注释明确说明该 struct 是编译器为收集 entry point 的uniform/资源参数而合成的,标记它可避免类型合法化阶段对"资源从常量缓冲泄漏"的 E31106/E31107 误报)和 slang-ir-collect-global-uniforms.cpp 一致。 - 快照时机:两个结构都不出现在
LOWER-TO-IR快照中,因为 slang-emit.cpp 与 L1275 在目标降级期间运行这两个 pass——这解释了第一轮观察为何扑空:在LOWER-TO-IR阶段本来就不可能看到它们。 - 普通数据前置条件:全局收集在全局作用域不含 "ordinary" 数据(
LayoutResourceKind::Uniform)时整体跳过,见 slang-ir-collect-global-uniforms.cpp(代码注释也确认了该特殊分支的存在)。对照组程序只含RWStructuredBuffer与Texture2D,整个-dump-ir输出零匹配,验证了该前置条件。 - 跨 target 一致性:glsl / spirv / metal / wgsl 目标下计数与结论相同。
这个案例示范了文档校正的完整方法论:当静态阅读无法裁决时,用与HEAD源码一致的编译器做-dump-ir差分实验,并用对照组验证边界条件。
两个被驳回的缺口(rejected-bogus):文档原样成立
[vk_location(...)]可写:缺口前提本身是错的
7bb8913f2a18声称[vk_location(...)]不可写,但这与源码矛盾。core.meta.slang 明确声明attribute_syntax [vk_location(location : int)] : GLSLLocationAttribute——vk_location正是该属性的真实名字,当然可写。[vk::location(7)]这种写法之所以也能用,是因为parseAttributeName(slang-parser.cpp)会把作用域属性名中的每个::重写为_,两条拼写最终到达同一个GLSLLocationAttribute。该行仍被改写为以用户实际书写的[vk::location(N)]拼写开头,但判定的核心结论是:原缺口不成立,驳回。
streamOutputTypeDecoration与streamOutputTypeLayout是两个 opcode
69f3396b03eb把两者误认为同一 opcode 的两种拼写。实际上:streamOutputTypeDecoration(decoration 家族)声明于 slang-ir-insts.lua,唯一生产者是 slang-ir-glsl-legalize.cpp;streamOutputTypeLayout则位于TypeLayout条目下(slang-ir-insts.lua),由 slang-ir-insts.h 的IRStreamOutputTypeLayout : IRTypeLayout包装。缺口作者在stream-output-type-decoration.slang里匹配到的其实是 type-layout inst——而真正的 decoration 只在 GLSL 合法化中产生,所以-target hlsl转储里自然找不到它。教训:同名前缀的 opcode 可能分属不同家族,判断前先查 Lua 条目所在的顶级分类。
一个越界缺口(rejected-out-of-scope):边界即文档边界
a13d8a468a77提议为[unroll]/[branch]在 hlsl / glsl / spirv / metal / wgsl 各后端中的最终形态建一张 per-target 表。这被驳回为越界,依据是 ir-reference-decorations.md 中## Forbidden content的明文规定:"Backend-specific consumption of decorations — see [../pipeline/06-emit.md]"(后端对 decoration 的消费,见 pipeline/06-emit.md)。也就是说,decorations.md只负责"decoration 是什么、怎么产生","后端怎么消费"归06-emit.md,两者以 callout 链接衔接。这条判定同时是本文读者理解文档边界的注脚:控制流提示装饰(branch/flatten/loopControl)本身不携带 IR 语义,只是透传到后端 emit 阶段选择对应的目标控制流结构。
文档主体速览:Decoration 家族的分类骨架
为了让上面每个缺口落在上下文里,这里给出decorations.md的家族分类骨架(opcode 全表见 decorations.md)。Decoration是所有装饰的公共基类,其下按用途分为十余个族:
- Naming and provenance:
nameHint、highLevelDecl、BuiltinDecoration、KnownBuiltinDecoration、UserTypeName、COMInterface、COMWitnessDecoration、UserExtern、transitory; - Layout and binding:
layout、AlignedAddressDecoration、SizeAndAlignment、Offset、packoffset、glslLocation、glslOffset、vkStructOffset、HasExplicitHLSLBinding、synthesizedParameterGroup、BinaryInterfaceType、PhysicalType、output/input、glslOuterArray; - Loop and branch hints:
branch、flatten、loopControl、loopMaxIters、loopExitPrimalValue、ForceUnroll、loopCounterDecoration/loopCounterUpdateDecoration; - Target-specific definition and intrinsics:
target、targetIntrinsic、requirePrelude、intrinsicOp、spirvOpDecoration; - Capability and availability:
requireCapabilityAtom、requireSPIRVVersion、requireGLSLVersion、requireGLSLExtension、requireWGSLExtension、requireCUDASMVersion、shader64BitIndexing、availableInDownstreamIR、SPIR-V 描述符索引、NVAPI 相关(requiresNVAPI/nvapiMagic/nvapiSlot); - Interpolation and shader IO:
interpolationMode、TargetSystemValue、semantic、射线载荷一族(raypayload/vulkanRayPayload/vulkanRayPayloadIn/vulkanHitAttributes/vulkanHitObjectAttributes/vulkanCallablePayload/vulkanCallablePayloadIn)、earlyDepthStencil、glslFragDepthGreater/glslFragDepthLess、precise、format、perprimitive; - Mesh shader, geometry shader, and per-vertex:图元类型一族(
pointPrimitiveType…triangleAdjPrimitiveType)、streamOutputTypeDecoration、vertices/indices/primitives、HLSLMeshPayloadDecoration、PositionOutput/PositionInput、PerVertex、stageReadAccess/stageWriteAccess; - Entry-point and stage:
entryPoint、entryPointParam、细分/几何属性(patchConstantFunc、maxTessFactor、outputControlPoints、outputTopology、partitioning、domain、maxVertexCount、instance)、numThreads、fpDenormalPreserve/fpDenormalFlushToZero、waveSize、派生组与收敛(DerivativeGroupQuad/DerivativeGroupLinear/MaximallyReconverges/QuadDerivatives/RequireFullQuads); - Work-graph nodes:
nodeLaunch、nodeMaxDispatchGrid、nodeDispatchGrid、maxRecords、nodeID、nodeIsProgramEntry、nodeArraySize、allowSparseNodes、workGraphRecordType/workGraphRecordElementType; - Linkage and lifetime:
import/export/public/hlslExport、externCpp/externC、dllImport/dllExport、CUDA/PyTorch 一族(cudaDeviceExport/CudaKernel/CudaHost/TorchEntryPoint/AutoPyBindCUDA/前后向导数引用/PyExportDecoration)、dependsOn、keepAlive、TargetBuiltinVar; - Inlining and optimization:
unsafeForceInlineEarly、ForceInline、AllowPreTranslationInlining、noInline、noRefInline、alwaysFold、noSideEffect、readNone、DynamicUniform、DefaultValue等; - Specialization, conformance, and existentials:
SpecializeDecoration、SpecializationDepthDecoration、SequentialIDDecoration、DynamicDispatchWitnessDecoration、StaticRequirementDecoration、BuiltinRequirementDecoration、DispatchFuncDecoration、TypeConstraintDecoration、ResultWitness、RTTI_typeSize、AnyValueSize、SpecializationConstantDecoration; - Differentiation markers:
AutoDiffOriginalValueDecoration、BackwardDerivativePrimalContextDecoration、PrimalContextDecoration、primalInstDecoration/diffInstDecoration/mixedDiffInstDecoration、RecomputeBlockDecoration、PreferCheckpointDecoration/PreferRecomputeDecoration等; - SPIR-V backend hints:
spvBufferBlock、spvBlock、NonUniformResource、MemoryQualifierSetDecoration; - Debug and reflection:
DebugLocation、DebugFunction、CounterBuffer; - Other:
BitFieldAccessorDecoration、constructor、method、FloatingPointModeOverride、experimentalModule、DisallowSpecializationWithExistentialsDecoration。
几个值得单列的关键装饰(详情见 decorations.md 的 Notable opcodes 一节):
nameHint携带可读名字穿越所有 IR pass,绝大多数后端用它选择输出变量/函数名,pass 作者重写 inst 时应保留它;layout把Layoutopcode(offset/size/register 绑定信息,见 metadata.md)挂到参数/类型上;targetIntrinsic编码"该函数由目标特定拼写实现",2 操作数形式(capability-set +IRStringLit)与 4 操作数形式(再追加 predicate 字符串与 type scrutinee)由IRBuilder::addTargetIntrinsicDecoration(slang-ir-insts.h)按需构建,同一函数可挂多个;intrinsicOp是核心模块内置函数到实际 IR opcode 的链接,单个整数操作数即kIROp_*标签;branch/flatten/loopControl是纯控制流提示,无自身 IR 语义,透传给后端 emit;keepAlive是 DCE 抑制装饰,前端(entry point、export 等)与 IR pass 都会添加;shader64BitIndexing只挂在 entry-point 函数上(lowerFrontEndEntryPointToIR,slang-lower-to-ir.cpp),lowering 从推断能力集中查找spvShader64BitIndexingEXT原子,统一覆盖"属性写在 entry point 上 / 写在可调用函数上 / 显式[require(spvShader64BitIndexingEXT)]"三种拼写,因为 SPIR-V 的Shader64BitIndexingEXT执行模式是 entry-point 作用域的;workGraphRecordType/workGraphRecordElementType声明但无生产者/消费者,名字在 slang-ir-insts-stable-names.lua 中保留,防止未来不相关 opcode 复用这些稳定身份(新式 work-graph 记录改用Type.WorkGraphRecordTypeBaseopcode);BuiltinRequirementDecoration给接口的 requirement key 打上BuiltinRequirementKind角色标签(如IDifferentiable.Differential),使后续 pass 按角色而非按(语义无序的)requirement 列表位置定位内置需求。
本次重跑的方法论沉淀
从这轮 gap-intake 中可以提炼出一套可复用的文档校验方法:
- 静态证据优先:每条断言都能锚定到源码(Lua 声明、C++ builder/accessor、lowering 调用点、
.meta.slang属性声明)或测试(*.slang测试钉死操作数值); - 生成器 vs builder 的落差:
ForceUnroll案例表明 Lua 条目声明的操作数未必等于实际形态,必须核对 C++ builder 是否追加操作数; - 同名前缀须查家族:
streamOutputTypeDecorationvsstreamOutputTypeLayout案例表明,opcode 归属(Decoration vs TypeLayout)决定其产生路径与可见目标; - 必要时运行编译器:
synthesizedParameterGroup案例表明,静态阅读无法裁决时,用与HEAD一致的编译器跑-dump-ir,对照快照名(LOWER-TO-IRvsAFTER collectEntryPointUniformParams)定位 pass 时机,再用对照组验证边界条件(普通数据前置条件); - 受监控路径闭环:第一轮标记的四个"被引用但未被监控"的源码文件(slang-profile.h、slang-ir-glsl-legalize.cpp、slang-ir-entry-point-uniforms.cpp、slang-ir-collect-global-uniforms.cpp)在
HEAD上均已进入watched_paths(可用regenerate.py show ir-reference/decorations.md查询),且新修文本引用的901ca639c751也指向受监控路径,追踪闭环。
延伸阅读
- ir-reference/decorations.md — 本文校验的目标文档本体,含全部 196 个 opcode 的完整表格;
- ir-instructions.md — opcode schema、op flags、hoistable/parent 约定与"新增 opcode"工作流;
- metadata.md —
layoutdecoration 挂接的Layoutopcode 与Attropcode; - differentiation.md — 与 autodiff decoration 互补的 autodiffopcode;
- resources-and-atomics.md — 绑定/插值/mesh-shader decoration 所作用的资源与 shader-IO opcode;
- modifiers.md — 产生多数 decoration 的 AST 侧修饰符;
- 04-ast-to-ir.md — AST 修饰符如何降级为 IR decoration;
- 05-ir-passes.md — 引入合成 decoration 的各个 pass(autodiff、linker、specialization 等);
- 06-emit.md — 各后端在 emit 阶段如何消费 decoration(也是 out-of-scope 缺口被指向的去处);
- glossary.md —
decoration、target intrinsic、entry point、differential pair等术语定义。
- 编译器
- 图形学
- 编程语言
【免费下载链接】slang
Making it easier to work with shaders
相关推荐
Slang IR 值指令参考的缺口校验(gap-intake)机制:12 个指令起源疑点的验证与修复全记录
Slang IR 值指令参考的缺口校验(gap intake)机制:12 个指令起源疑点的验证与修复全记录 Slang 编译器将数以百计的 IR 指令(opco
编译器图形学编程语言基于评审报告的质量审计:Slang IR Type 家族逐操作码参考文档的准确性校验
基于评审报告的质量审计:Slang IR Type 家族逐操作码参考文档的准确性校验 导读 本文以 docs/generated/design/_meta/re
编译器图形学编程语言Slang IR Type 家族逐操作码参考:从设计文档到 `-dump-ir` 自动化测试目录
Slang IR Type 家族逐操作码参考:从设计文档到 dump ir 自动化测试目录 导读 本文以 Slang 编译器仓库中的 IR 类型家族测试生成提示
编译器图形学编程语言
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考