新闻详情

新闻详情

首页 / 资讯中心 / 详情

Stride 引擎 SDSL 着色器语言的解析与编译:从语法设计到源码实现

发布时间:2026/10/7 19:13:08来源:尧图网络
Stride 引擎 SDSL 着色器语言的解析与编译:从语法设计到源码实现
游戏开发图形学VR【免费下载链接】strideStride (formerly Xenko), a free and open-source cross-platform C# game engine.项目地址https://gitcode.com/gh_mirrors/st/stride点击查看免费下载Stride前身 Xenko是一款免费开源、跨平台的 C# 游戏引擎。本文围绕 sources/shaders/README.md 介绍 SDSLStride Shading Language——引擎内置的着色器语言它是 HLSL 的超集新增了面向对象式的可扩展性、模块化与复用机制。文章将深入解析 SDSL 的语法要素、在 sources/shaders 目录中解析Parser—语义分析Analysis—SPIR-V 构建—合并Mixin的完整编译流水线并给出可直接参考的语法示例与测试用例帮助你理解 Stride 如何把高级着色器代码最终编译为可运行字节码。SDSL 是什么为游戏引擎而生的着色语言SDSLStride Shading Language是 Stride 游戏引擎专门设计的着色器语言核心定位是HLSL 的超集它完整继承了 HLSL 的语法与能力同时引入面向对象编程OOP理念让着色器代码获得三方面的提升可扩展性extensibility通过类shader、继承mixin、组合compose等概念着色器可以被轻松扩展不必复制粘贴整段代码模块化modularity每个着色器只聚焦一种渲染技术例如光照、阴影、后处理整体更易管理与组合可复用性reusability最大化着色器之间的代码复用公共逻辑沉淀为基类或工具着色器被多个效果引用。这套实现位于 sources/shaders由多个项目协作完成Stride.Shaders.Parsers词法/语法解析、Stride.Shaders.Compilers语义分析、SPIR-V 构建与合并、Stride.Shaders.SpirvSPIR-V 数据结构、Stride.Shaders.Effects效果编译器与缓存、Stride.Shaders.Generators与Stride.Shaders.Generators.Internal代码生成/内置函数生成等。本文所有结论均来自当前仓库实际内容。仓库为只读以下均用于查看、运行与配置说明。从一份 SDSL 文件看语言骨架仓库 sources/shaders/assets/SDSL 提供了一批可直接阅读的示例。以Test.sdsl为例namespace Machin; shader Test { stream float4 Position : SV_POSITION; stream float4 Color : SV_TARGET; bool machin false; void PSMain() { streams.Position.w 1.0; } void VSMain() { int a 0; a 3; if(machin) streams.Color * 2; if(a 2) a * 3; streams.Color float4(1.0,0.0,1.0,1f32); } }这份代码揭示了 SDSL 的几个关键概念namespaceSDSL 支持命名空间组织着色器支持namespace a.b.c;或namespace a { ... }两种写法。在 ShaderFileParsers.cs 中NamespaceParsers会循环读取点分标识符并允许在命名空间内声明 shader、effect 或 paramsshader声明一个着色器类是 SDSL 的基本组织单元stream声明流变量顶点/像素阶段间传递的插值数据后面的语义如SV_POSITION、SV_TARGET决定其在管线中的含义streams.xxx在方法体内通过streams.前缀访问流变量——这是 SDSL 相对 HLSL 在写法上的显著差异HLSL 通常通过结构体形参传递字面量后缀1f32表示 32 位浮点、3f16表示 16 位浮点也支持1.带尾点等 HLSL 语法变体测试用例 ParsingTests.cs 专门验证了这些边界情况。再看Simple.sdsl中更激进的语法形态namespace machin { namespace hello; namespace other.thing { internal partial effect class.heloo { } shader MyCLassint a, Link machin : Hello1,2,3.0f32,Hello { patchstream float a 5; float3x3 b; float Foo(int a, int b) { elif(a b) { float a Comm(); } const int a 3; machin 5; streams.a.machin.hello[1] 9; } } shader other; } }这里出现了更完整的语法要素partial分部类、带泛型参数int a, Link machin与泛型实参Hello1,2,3.0f32,Hello的类声明、patchstream流变量、elif语句等说明 SDSL 的语法面比传统 HLSL 宽得多。类、继承与组合SDSL 面向对象三要素SDSL 的面向对象能力通过三种语法机制体现它们分别对应扩展、模块化、复用三大设计目标。继承 / mixinshader之间通过冒号进行继承子类可以覆盖父类方法、继承父类流变量与常量shader TestBasic : TestBase { stream float4 InputPosition : POSITION; stream float4 Position : SV_POSITION; stream float4 ExtraColor : COLOR; cbuffer Test123 { float4 CBufferValue1; } void Test() { streams.ColorTarget streams.ExtraColor; SetColor(streams.ExtraColor); // 调用继承自 TestBase 的方法 } // ... }其中TestBase.sdsl定义了stream float4 ColorTarget : SV_Target0;和SetColor(float4)方法TestBasic直接继承并复用。在源码层面Shader.cs 中ShaderClass的Mixins字段保存了所有被 mixin 的父类继承链的处理在编译期ShaderMixer完成而不是运行时动态解析。泛型generic着色器SDSL 支持带类型参数与值参数的泛型着色器用于生成同一模板、多种尺寸的代码。仓库 CompilerTests/ConstUIntGeneric.sdsl 是一个完整示例shader ConstUIntGenericBaseint TCount { static const uint Count TCount; static const uint CountPlusOne TCount 1; } shader ConstUIntGeneric : ConstUIntGenericBase3 { stream float4 ColorTarget : SV_Target0; cbuffer Test { uint Selector; float Values[CountPlusOne]; // 数组长度由继承的泛型常量决定 } void PSMain() { uint count Count; float v Selector count ? Values[3] : 0.0; streams.ColorTarget float4(v, v, v, v); } }泛型实参可以是值字面量3、类型int a甚至字符串Hello...,Hello。AST 侧由 ShaderGenericsValues.cs 的ValueTypeGenerics承载值类型泛型。这一机制配合static const常量传播可让数组维度、循环次数等在编译期确定类似模板元编程的效果。组合compose组合用于把一个或多个子着色器内嵌到当前着色器中子着色器的方法通过引用调用shader ComposePlainRoot : ComposeSharedBase { RWTexture3Dfloat4 WriteTex; compose ComposePlainHelper helper; override void Compute() { WriteTex[streams.DispatchThreadId] helper.Value(); // 调用组合子着色器的方法 } };compose引入的是对象级复用相对于继承的类型级复用组合关系在语义分析阶段被解析ShaderMixer会把被组合的着色器代码合并进最终产物。测试目录中还包含ComposeSharedRoot、ComposePlainHelper、ComposeNumThreadsRoot等配套文件验证组合与继承并存时的行为例如 ComposePlainRoot.sdsl 与共享基类的对照。模块化封装cbuffer、stream、stage 与 attributesSDSL 在类体内支持多种成员声明均在 ShaderElements.cs 中有对应 AST 节点关键字含义仓库示例stream顶点/像素阶段间传递的插值数据TestBasic.sdsl中的Position : SV_POSITIONpatchstream细分阶段hull/domain使用的 patch 流数据Simple.sdsl中的patchstream float a 5;stage声明只能被特定阶段使用的方法/变量如 compute 入口CSMainStaticCallRoot.sdsl中的stage stream uint3 DispatchThreadId、stage void CSMain()static const编译期常量可参与数组维度计算ConstUIntGeneric.sdslcbuffer常量缓冲区声明TestBasic.sdsl中的cbuffer Test123compose组合子着色器ComposePlainRoot.sdsloverride覆盖父类或组合对象的方法ComposePlainRoot.sdsl中的override void Compute()abstract抽象方法由子类/组合对象实现Parent.sdsl中的stage abstract void DoSomething();attributes[...]附加元数据如布局、numthreadsCommented.sdsl中的[Layout(1, 2)]典型的 attribute 应用是 compute shader 的线程数声明[numthreads(8, 8, 8)] stage void CSMain() { WriteTex[streams.DispatchThreadId] float4(...); }示例见 CompilerTests/StaticCallRoot.sdsl。编译器测试目录还覆盖了CSNumThreadsInherit、CSNumThreadsOverride、CSNumThreadsOnNonEntry等场景说明numthreads在继承/覆盖/非入口函数等情况下有严格校验。预处理与宏与 C 兼容的条件编译SDSL 保留并兼容 C 风格的预处理指令。Macroed.sdsl展示了条件编译#ifdef cond shader Machin { } #endif shader Machin2 { }预处理管线位于 Parsing/PreProcessing由多个阶段组成CommentPhase处理注释、CodeProcessor处理宏展开等。解析入口 SDSLParser.cs 展示了完整调用链public static ParseResult Parse(string code) { var c new CommentProcessedCode(code); return Grammar.MatchCommentProcessedCode, ShaderFileParser, ShaderFile(c); }即原始代码 → 注释预处理CommentProcessedCode→ 文法匹配Grammar.Match→ 得到 ShaderFile AST。解析器架构Parser Grammar AST解析器位于Stride.Shaders.Parsers设计上分为三层扫描器ScannerParsing/Scanners目录下的Scanner/ScannerGeneric等负责把源码切分成 token 流并记录TextLocation/ErrorLocation用于精确报错文法GrammarGrammar.cs 是解析核心Match方法创建Scanner、执行IParserTValue.Match并在 token 未消耗完时追加SDSL0009错误额外 token类错误ASTParsing/SDSL/AST目录定义了ShaderFile、ShaderNamespace、ShaderClass、ShaderElement、Expression、Statement等节点层级。解析结果用 ParseResult.cs 承载ParseResult.AST保存成功解析的语法树Errors保存ParseError包含消息、位置与出错 token 的上下文预览。ParseError.ToString()会基于出错位置自动摘取下一个 token方便快速定位。各语法要素按职责拆分到Parsing/SDSL/Parsers子目录Terminals/终结符标识符、字面量、操作符解析ExpressionParsers/表达式解析StatementParsers/语句解析ShaderParsers/着色器级解析其中 ShaderClassParser.cs 的SimpleShaderClassParser展示了最朴素的shader Name { ... }匹配流程匹配shader关键字 → 空格 → 标识符 →{→ 循环匹配成员元素直到}DirectiveExpressions/指令表达式解析Common/共享辅助解析器。语义分析与符号解析语法解析之后编译进入语义分析阶段核心组件包括符号表SymbolTable与符号帧SymbolFrameSymbolFrame.cs 实现作用域内符号的按名索引并支持方法组MethodGroup当多个同名函数重载出现在同一作用域时自动归并为FunctionGroupType符号符号类型SymbolTypes与类型访问器Node.Visitors / SymbolTypes.Visitors负责类型推断与表达式类型检查分析AnalysisParsing/Analysis 包含控制流图CFG.cs、SDIR.cs与符号表扩展为后续代码生成提供静态信息常量求值ConstantEvaluatorCore/ConstantEvaluator.cs可在编译期求值常量表达式——这正是ConstUIntGeneric中CountPlusOne TCount 1能用于数组维度的原因。从 AST 到 SPIR-VSDSL 编译器的中间表示语义分析完成后代码被降级为SPIR-V而不是直接生成 HLSL/GLSL这一设计让一份 SDSL 源码 → 多后端输出成为可能。相关代码位于Stride.Shaders.Compilers/SDSLSDSLC.cs 是单文件编译入口SDSLParser.Parse→ 逐个ShaderClass创建CompilerUnit→ 注册调试信息OpString/OpSource/OpSourceHashSDSL后者用于着色器缓存校验→ 执行shader.Compile(table, compiler)生成 SPIR-V 指令ShaderMixer.cs 是合并器mixin 编译器创建全局SpirvContext写入OpCapability(Shader)、OpExtension(SPV_GOOGLE_user_type)、OpMemoryModel(GLSL450)等模块头然后递归解析 mixin/compose 关系把多个 shader 的 SPIR-V 合并为一个可执行模块校验ShaderMixer.Validation.cs 负责在合并后做语义校验例如检测在无法计算屏幕空间导数的阶段非 Fragment/GLCompute使用隐式 LOD 纹理采样或ddx/ddy/fwidth提前给出可读错误而非等后端优化器失败SPIR-V 数据结构与读写由Stride.Shaders.Spirv项目提供OpData、SpirvBuffer、SpirvReader等。SDSLC.CompileOptionsSDSLC.cs还支持两个编译选项RegisterInCache是否将编译结果注册进缓存与OriginalCode预处理前的原始源码用于OpSource调试信息。后端输出SPIR-V 翻译回 HLSL 及其他Stride.Shaders.Compilers提供了从 SPIR-V 到具体后端代码的翻译SpirvTranslator.csGetEntryPoints(Backend)枚举入口点按 ExecutionModel 区分 VS/PS/CS 等Translate(Backend, entryPoint)把 SPIR-V 翻译为目标后端文本Backend枚举支持 HLSL 与 SPIR-V 两类目标EffectCompiler.cs 在编译效果effect时调用translator.Translate(Backend.Hlsl, entryPoint)生成最终 HLSLShaderMixer.OptionsShaderMixer.cs有两个关键开关ResourcesRegisterSeparateD3D11/12 下 t/b/s 寄存器各自独立编号从 0 开始与StripGoogleUserType移除SPV_GOOGLE_user_type扩展与UserTypeGOOGLE装饰——Vulkan 在不支持该扩展时会拒绝。测试 StrideShaderTests.cs 展示了完整链路ShaderLoader加载.sdsl→ShaderMixer.MergeSDSL产出字节码 →SpirvTranslator翻译为 HLSL → 断言数组维度[2][3][5]保持声明顺序。这类回归测试印证了解析—合并—翻译流水线的真实可用性。效果文件SDFX组合的声明式入口SDSL 着色器类之上还有一层SDFXeffect 文件用声明式语法描述如何把若干 shader mixin 组合成一个 effect。仓库示例 assets/SDFX/BasicEffect.sdfxnamespace Stride.Rendering.Images; shader A { int a; } shader B { float b; } params BasicParams { bool MixA; bool MixB; } effect BasicEffect { using params BasicParams; mixin compose Target1 Test123; mixin compose Target2 Test123; mixin macro Test 1; mixin A; mixin (A); if(BasicParams.MixA) mixin (A); if(BasicParams.MixB) mixin (B); }mixin声明把 shader 并入 effectmixin compose Target1 Test123将组合绑定到指定名称params定义可由外部如材质传入的参数集合条件mixin则允许按开关组合不同 shader。SDFX 的解析器位于 Parsing/SDFX与 SDSL 解析器共用文法基础设施。测试体系验证解析与编译的正确性仓库为 SDSL 提供了分层测试均位于Stride.Shaders.Tests解析测试ParsingTests.cs 遍历assets/SDSL、assets/SDFX下所有.sdsl/.sdfx文件执行SDSLParser.Parse并断言零错误另有大量针对悬空后置访问器如a.;、a[1];、1..;的负向用例确保这些语法错误被正确报告而非静默吞掉编译/翻译测试StrideShaderTests.cs 覆盖多维数组维度顺序、字段名与内置方法名冲突、numthreads继承/覆盖、组合与继承共存等回归场景资产语料assets/SDSL/CompilerTests 包含 50 个.sdsl文件ArrayDims3D、SwitchDuplicateLabel、HSOverride、GeometryStreamsAssignKeepsOthers等本身就是一份极佳的语法学习与边界行为参考ParserTests、RenderTests、ComputeTests等目录则分别覆盖解析、渲染与计算场景。如何贡献本地克隆与开发如需在本地查看、运行或继续开发这套解析/编译实现README 中说明的贡献方式git clone https://gitcode.com/gh_mirrors/st/stride cd ./stride随后可打开 sources/shaders 目录下的解决方案如Stride.Shaders.Tests测试项目进行调试测试项目内置了ShaderLoader见 StrideShaderTests.cs可指定资产目录加载.sdsl文件是了解整个编译链路最直接的入口。总结SDSL 是 Stride 渲染系统的语言基石它用shader类、继承/泛型/compose 赋予着色器代码面向对象的组织能力用stream/stage/cbuffer/attributes 实现模块化封装再经预处理 → 解析 → 语义分析 → SPIR-V → 后端翻译的流水线最终输出 HLSL/SPIR-V 字节码供 Direct3D 或 Vulkan 使用。当前仓库的sources/shaders目录正是这套新实现Parser Compiler的完整落地从 README 出发配合assets/SDSL的示例与Stride.Shaders.Tests的测试开发者可以快速掌握 SDSL 的语言特性、编译原理与调试方法。赞分享游戏开发图形学VR【免费下载链接】strideStride (formerly Xenko), a free and open-source cross-platform C# game engine.项目地址https://gitcode.com/gh_mirrors/st/stride点击查看免费下载相关推荐从源码到ASTchibicc编译器如何解析C语言语法从源码到ASTchibicc编译器如何解析C语言语法 chibicc是一款轻量级C编译器它能够将C语言源代码转换为抽象语法树AST这是编译器前端的核心编译器Quick Picture Viewer插件系统深度解析如何扩展图片处理能力Quick Picture Viewer插件系统深度解析如何扩展图片处理能力 Quick Picture Viewer是一款轻量级、功能丰富的Windows桌Roc 语言 return 语句深度解析从语法快照测试到编译器源码实现Roc 语言 return 语句深度解析从语法快照测试到编译器源码实现 本篇以 Roc 编译器仓库中的快照测试文档 test/snapshots/statem上一篇【亲测免费】 ElementUI 主题生成器教程下一篇BitBLAS 开源项目使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/10/6 15:16:42

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/10/7 8:13:40

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/10/6 15:18:24

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/10/6 16:48:59

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/10/7 12:13:57

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/10/6 16:58:56

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉