ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Slang 编译器架构全景:从源码树分层到编译请求生命周期

Slang 编译器架构全景:从源码树分层到编译请求生命周期 Slang 编译器架构全景从源码树分层到编译请求生命周期【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang本篇技术指南以 docs/generated/design/architecture/overview.md 为骨架面向尚未打开过 Slang 源码树的 C 工程师系统梳理 Slang一个着色语言编译器的顶层源码树分层、四大公开产物、贯穿一次编译的中央数据对象以及公开 API 的二进制兼容演化策略。读完本文你将能回答某个关注点应该在source/下哪个子目录实现编译请求如何流转为什么头文件里新增接口只能追加不能插入等架构级问题并知道下一步该去docs/generated/design/下哪一份文档深入。1. 项目定位与四大公开产物Slang 是一个着色语言编译器。它的职责是接收 Slang以及 HLSL 兼容源码为目标图形/计算工具链产出目标代码——DXIL、SPIR-V、GLSL、Metal Shading Language、WGSL、C、CUDA 或 PyTorch 胶水代码——同时附带关于着色器参数的反射reflection/布局layout信息。构建会产出四个主要的公开产物产物说明源码位置slangc命令行编译驱动source/slangc/入口 main.cppslang-compiler共享库可嵌入的编译器公开 C API 与 COM 风格接口声明于 include/slang.h库体构建于 source/slang/WebAssembly 绑定将编译器暴露给 JavaScript附带生成的interface.d.tssource/slang-wasm/绑定实现 slang-wasm-bindings.cppslang-rt可选运行时支持供发射到非 GPU 目标的代码链接使用source/slang-rt/两个值得注意的兼容细节在SLANG_ENABLE_SLANG_PROXY开启时历史命名仍会以向后兼容别名形式产出Unix 上是libslang符号链接Windows 上是转发用的slang.dll。slang-compiler共享库形态下如果关闭SLANG_EMBED_CORE_MODULE构建会额外生成generate_core_module_cache目标把预编译的slang-core-module.bin缓存写到库文件旁边使首次 global-session 请求加载该归档而不是现场编译 core module见 source/slang/CMakeLists.txt 中相关逻辑及 docs/generated/design/cross-cutting/core-module.md。1.1 CMake 构建组织编译器用 CMake 构建核心库的完整构建配置位于 source/slang/CMakeLists.txtsource/下每个同级子目录各自维护一个CMakeLists.txt加入同一构建。其中有一个关键路径约定该文件中的路径相对slang_BINARY_DIR而非CMAKE_BINARY_DIR书写。copy_slang_headers目标会把 include/ 加上生成的slang-tag-version.h暂存到${slang_BINARY_DIR}/$CONFIG/include对应 source/slang/CMakeLists.txtadd_custom_target( copy_slang_headers COMMAND ${CMAKE_COMMAND} -E make_directory ${slang_BINARY_DIR}/$CONFIG/include COMMAND ${CMAKE_COMMAND} -E copy_directory ${slang_SOURCE_DIR}/include ${slang_BINARY_DIR}/$CONFIG/include COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/slang-version-header/slang-tag-version.h ${slang_BINARY_DIR}/$CONFIG/include/slang-tag-version.h )这样做的目的是当父项目通过add_subdirectory嵌入 Slang 时暂存头文件会收集在 Slang 自己的构建目录下而不是污染顶层构建目录。2. 源码树顶层分层source/下的目录是分层的下层不依赖上层而 include/ 中的公开 API 悬浮在最上层充当不可变的边界。从架构文档看主要分成以下若干层。2.1 基础层Foundational layerssource/core/—— 平台无关的 C 工具集容器、字符串、智能指针、文件系统抽象、哈希、分配器。项目内没有其他部分能在不链接它的前提下工作。代表性文件 slang-basic.h。分配器可选用 mimalloc 作为后端设置SLANG_ENABLE_MIMALLOC后source/core/CMakeLists.txt 会把mimalloc-static链入core并对所有依赖目标定义SLANG_ENABLE_MIMALLOC1。source/compiler-core/—— 与语言无关的编译器基础设施原则上可被另一门语言复用词法分析器slang-lexer.cpp、诊断接收器slang-diagnostic-sink.h、源码位置编码、下游编译器胶水DXC、FXC、GCC、glslang以及用于携带编译产物的 artifact/blob 模型。2.2 编译器主体The compiler propersource/slang/—— Slang 前端、AST、中间表示、IR passes 与各 emit 后端是编译器的绝大部分。其内部按文件名前缀约定分族slang-ast-*ASTslang-parser*/slang-preprocessor*前端解析与预处理slang-check*语义检查slang-lower-to-ir*AST→IR 降级slang-ir.*/slang-ir-insts.*IR 核心slang-ir-*.cppIR passesslang-emit*代码发射slang-serialize*AST/IR/RIFF 序列化slang-capability*能力格capability latticeslang-diagnostics*Slang 专属诊断目录。逐文件的详细清单一览见 docs/generated/design/architecture/module-map.md。prelude/—— 各文本目标的 prelude 头文件编译器随发射出的文本目标一起分发供下游工具链编译结果使用每个文本目标族一份HLSL、CUDA、C、Torch。2.3 标准库Standard librariessource/slang-core-module/与 source/slang/ 下的*.meta.slang文件core.meta.slang、hlsl.meta.slang、diff.meta.slang——定义内建类型、内建函数与运算符映射的 core module构建期嵌入slang-compiler。source/slang-glsl-module/与 glsl.meta.slang——面向 GLSL 风格内建函数的同类模块。source/standard-modules/——随发行提供但不以同样方式嵌入的标准模块源码每个子目录构建独立的.slang-module产物neuralsource/standard-modules/neural/与experimentalsource/standard-modules/experimental/目前承载 work-graph 模块。2.4 下游编译器垫片Downstream-compiler shimssource/slang-llvm/—— 基于 LLVM 的 JIT/静态编译胶水slang-llvm.cpp。source/slang-glslang/—— 通往 Khronosglslang的桥用于经 GLSL 生成 SPIR-Vslang-glslang.cpp。注意该垫片的导出符号并非仅由 C 决定——入口点还必须在slang-glslang.version-script中列出ELF 与 macOS 构建都从它派生导出表否则客户端的符号查找会返回 null、入口点静默不可用。source/slang-dispatcher/—— 派发到下游工具的共享支撑main.cpp。下游编译器统一通过IDownstreamCompiler抵达声明于 source/compiler-core/slang-downstream-compiler.h。只有部分编译器具备的能力被建模为独立接口而不是给主接口加方法。典型例子是IDownstreamCompilerPathProviderslang-downstream-compiler.h它的单个getPath返回所加载编译器库在磁盘上的路径DownstreamCompilerBase提供默认实现返回SLANG_E_NOT_AVAILABLE只有共享库承载的编译器会覆写它——基于可执行文件、在PATH上找到的命令行编译器或缺少共享库内省能力的平台没有这样的路径可返回。该接口刻意不继承ICastable只作为借用对象通过castAs/getObject分发绝不通过getInterface因为getInterface同时支撑带引用计数的queryInterface只能返回可释放的ISlangUnknown派生接口若再给能力接口加一个ICastable基类会让具体编译器类出现两个有歧义的ISlangUnknown子对象。这一模式在 slang-llvm.cpp 的LLVMDownstreamCompiler上有完整实现。2.5 运行时与绑定Runtime and bindingssource/slang-rt/CMakeLists.txt——链接进宿主机风格 CPU 输出的运行时库包括 PyTorch 绑定输出CUDA 源码是 kernel 风格不依赖它。source/slang-record-replay/——公开 Slang API 的记录/重放器replay-context.cpp。source/slang-wasm/——WebAssembly 绑定slang-wasm-bindings.cpp。Emscripten 绑定块是JavaScript 能碰到什么的权威清单GlobalSession当前暴露createSession与getBuiltinModuleSource后者按名字把内建模块的源码文本交回给调用方。2.6 驱动与工具Driver and toolingsource/slangc/——slangc命令行驱动main.cpp。tools/——辅助开发者工具测试、反射、代码生成、fiddle、embed、性能剖析。2.7source/之外的辅助树tests/——项目测试语料库。绝大多数文件是.slang输入由slang-test驱动见 tools/slang-test/。新增回归测试放这里目录结构镜像被测区域如 tests/language-feature/、tests/diagnostics/、tests/spirv/。extras/——不编进任何二进制的开发者脚本与小工具格式化extras/formatting.sh、IR dump 拆分extras/split-ir-dump.py、Windows 沙箱构建辅助等。该树只服务于开发者不随发行交付。external/——第三方依赖与 git 子模块spirv-headers、glslang、lz4、miniz 等。这里只 vendoring不改动。2.8 构建期生成代码Slang 重度依赖构建期代码生成。AST 与 IR 头文件中的FIDDLE(...)宏会展开为构建输出目录build/source/slang/fiddle/下生成的成员/访问器/序列化表——例如slang-ir-insts-enum.h.fiddle从 source/slang/slang-ir-insts.lua 的 Lua 表枚举出 IR 操作码。诊断目录同样从 slang-diagnostics.lua 与 source/slang/diagnostics/ 下各区域的 Lua 表生成。3. 编译请求生命周期贯穿一次编译的中央对象一次 Slang 编译流经一小撮中央对象其声明散布在 include/slang.h 与 source/slang/ 的多个头文件中包括slang-translation-unit.h、slang-session.h、slang-target.h、slang-compile-request.h、slang-end-to-end-request.h与slang-module.h。下面是核心对象的职责速览。对象职责声明位置Session全局会话级编译器状态持有内建模块、AST builder 与全局类型检查环境。公开 COM 风格接口为slang::IGlobalSessioninclude/slang.h实现类是Sessionsource/slang/slang-global-session.hLinkage配置作用域打包搜索路径、预处理宏、目标设置与 source manager。多个模块共享同一Linkage从而彼此一致地解析import。公开接口slang::ISession实际实现的就是它source/slang/slang-session.hTranslationUnitRequest共享同一命名空间的一组源文件。默认情况下slangc传入的所有 Slang 源文件进入单个TranslationUnitRequestHLSL 输入则每单元一个source/slang/slang-compile-request.hFrontEndEntryPointRequest一个函数名 其入口点所针对的 profile 阶段如main作为computesource/slang/slang-compile-request.hTargetRequest输出格式 profile 的组合如glsl_450下的 SPIR-Vsource/slang/slang-target.hFrontEndCompileRequest驱动一组翻译单元的前端parse、check、lower to IRsource/slang/slang-compile-request.hCodeGenContext驱动一组入口点与目标的后端IR passes、emit取代了历史上名为BackEndCompileRequest的对象source/slang/slang-code-gen.hEndToEndCompileRequest单次slangc调用背后的总伞对象source/slang/slang-end-to-end-request.hModule一个翻译单元的前端输出同时包含检查后的 AST 与降级后的 IR也是.slang-module序列化格式描述的单位。实现公开的slang::IModulesource/slang/slang-module.hIComponentType可链接程序抽象一个Module、一个入口点绑定或它们的组合都能呈现为IComponentType后端消费单个复合组件做代码生成include/slang.h一个必须澄清的命名陷阱本代码库中 session 指两个不同的东西。IGlobalSession持有全局会话级状态应用通常创建一次并复用以摊薄启动成本不同全局会话可以共存而ISession即Linkage才是大多数调用方理解的编译会话。这些对象的划分解释了为什么translation unittarget等概念是一等公民Slang 的流水线以参数化方式把前端工作与后端工作干净地分离。解析与可复用模块检查大体与目标无关但入口点验证会咨询请求的目标——它把推断出的能力需求与 profile 阶段逐一对照每个TargetRequest见 source/slang/slang-check-shader.cpp——而所有代码生成都发生在后端。4. 公开 API 位于何处以及它如何保持二进制兼容include/slang.h 是权威公开头文件。它声明 COM 风格接口ISession、IModule、IComponentType等与少量用于创建会话的自由函数连同 include/slang-com-helper.h 与 include/slang-com-ptr.h构成下游应用链接所依赖的二进制稳定表面。source/ 之下的一切都是实现。公开头文件规则见 CLAUDE.md枚举不许重排、vtable 中段不许改虚函数、不许删除反映了该表面必须对旧调用方保持 ABI 兼容。因此新 API 一律通过追加增长头文件展示了四种互不冲突的增长机制接口追加方法——新方法放 vtable 末尾如IGlobalSession::saveBuiltinModule实现见 source/slang/slang-global-session.h。全新带 UUID 的接口——并非每个实现都具备的能力变成独立接口通过castAs/queryInterface获取如IBindlessResourceMetadata、ICoverageTracingMetadata、ISyntheticResourceMetadata而不是给既有接口加方法。追加枚举值——新的CompilerOptionName值以显式整数追加在CountOf哨兵之前CountOf是唯一刻意不写显式值的枚举项。最近新增的两个是TraceCoverageBindlessIndex 158与GetCompilerPath 159include/slang.h 中对应位置。对带structSize的普通结构做尾部扩展——跨边界传递的结构把自身大小作为首字段只有调用方structSize覆盖到时才写入新尾部成员。SyntheticResourceInfo::bindlessIndex是当前例子它位于 v1 结构大小之后用旧头文件编译的调用方保持自身布局永远看不到该字段。被取代的入口通常废弃而非删除。替代者落地时旧声明留在原 vtable/重载位置并标注 deprecated既有调用方继续可编译、可链接。VariableReflection展示了该模式getDefaultValueBlob把变量默认初始化器作为打包字节 blob 返回而被它取代的更窄接口hasDefaultValue、getDefaultValueInt、getDefaultValueFloat仍保留声明并标记 deprecated。IGlobalSession::addBuiltins同样如此——在声明上标注[[deprecated]]占住 vtable 槽位从而保住其后每个方法的位置。4.1 两条偏离规则的例外仅读头文件会以为上述规则是绝对的但有两个值得了解的例外就地替换IGlobalSession的最后一个方法不是追加而是原地替换——getDownstreamCompilerVersion(SlangPassThrough, int*, int*)在提交b9a17f86b1中变成了getDownstreamCompilerPath(SlangPassThrough, ISlangBlob**)实现见 source/slang/slang-global-session.h占据同一个末位 vtable 槽、换了名字与签名。替换回答的是另一个问题——Slang 选中的库实际位于磁盘何处客户端可以自己加载并查询能力——而不是一个多个下游编译器只能报(0, 0)的版本对。因为它位于末位槽且引入不久该改动不扰动任何更早方法的位置。直接移除枚举值驱动旧 CLI 查询的CompilerOptionName枚举值CompilerVersion 153被直接移除而不是改名为REMOVED_CompilerVersion。整数153现在成了序列中的空洞——SPIRVUnifiedDescriptorHeapStride 154紧随其后——退休值至少不会被复用这正是规则中保护持有陈旧整数的调用方的部分。4.2 语言版本与 ABI 版本是两回事编译器接受的语言版本与上述 ABI 表面相互独立由SlangLanguageVersion枚举。除按年份编号的SLANG_LANGUAGE_VERSION_2025/_2026外现在还有同一整数的字母后缀别名_202A 2025、_202B 2026以及进行中的_202C 2027——头文件明确警告该版本一旦获得正式名称其数值可能变化。SLANG_LANGUAGE_VERSION_LATEST指最新稳定版本_NEXT指开发中版本。5. 下一步阅读指南架构文档是docs/generated/design/树的入口。要深入可沿以下路径按子系统分组的穷举文件清单读 docs/generated/design/architecture/module-map.md子系统间依赖读 docs/generated/design/architecture/dependency-graph.md端到端编译流程每阶段一篇文档从 docs/generated/design/pipeline/overview.md 开始依次可看 01-lex-preprocess.md、02-parse-ast.md、03-semantic-check.md、04-ast-to-ir.md、05-ir-passes.md、06-emit.md 等横切各阶段的关注点见 docs/generated/design/cross-cutting/ 树下的 diagnostics.md、ir-instructions.md、targets.md、core-module.md 与 serialization.md表层语法见 docs/generated/design/syntax-reference/。此外docs/design/ 下的手写开发者笔记与本树内容交叠同样值得参考尤其是 overview.md、ir.md 与 parsing.md。【免费下载链接】slangMaking it easier to work with shaders项目地址: https://gitcode.com/GitHub_Trending/sl/slang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表