马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
从第一行代码写下 GraphicsContext.CreateDirectX12() 到本日 GraphicsContext.CreateMetal() 跑通全部测试,Zenith.NET 终于实现了最初的答应——用同一套 .NET API 覆盖三大图形后端。
这篇文章聊聊 Metal 后端的技能选型、架构操持,以及 Zenith.NET 作为一个 .NET GPU 抽象层的操持哲学。
为什么要做 Zenith.NET?
.NET 生态有不少图形干系的库——绑定层如 Silk.NET、Vortice,抽象层如 Veldrid、Evergine。但现有的抽象层要么停顿在较旧的 API 版本(如 DX11/OpenGL),要么是贸易引擎的一部分,难以作为独立的 GPU 抽象层使用。
Zenith.NET 的定位是:一个面向当代图形 API(DirectX 12、Metal 4、Vulkan 1.4)的轻量 GPU 抽象层,只做抽象、不做引擎,让开发者写一次代码、跑在全部平台上。
这就是 Zenith.NET 要做的事:
后端战略DirectX 12Windows 独占,性能天花板Metal 4Apple 全平台,仅支持 Apple SiliconVulkan 1.4跨平台兜底,覆盖 Linux/Android三个后端不是相互替换的关系,而是各守一方——在每个平台上选最原生的谁人 API。
Metal 后端:架构决定
为什么选 Metal.NET?
v0.0.6 的 release notes 里提到过,其时在 SharpMetal 和 .NET macios TFM 之间评估。终极选了 Metal.NET(NuGet 包 Metal.NET 2.3.0)——这是我在开发期间制作的绑定库。相比 SharpMetal,Metal.NET 提供更美满的 Metal 4 API 覆盖,而且全部接口都是范例安全的。
不外坦率地说,Metal.NET 基于 class 封装 Objective-C 对象,在 GC 方面会有肯定开销。
团体结构
Zenith.NET 抽象Metal 实现GraphicsContextMTLDevice + MTL4Compiler + MTLResidencySetCommandBufferMTL4CommandBuffer + 双编码器(Render/Compute)ResourceLayout绑定槽位计数(Buffer/Texture/Sampler)ResourceTableMTL4ArgumentTable,通过 GPU 所在绑定资源PipelineMTLRenderPipelineState + MTLDepthStencilStateSwapChainCAMetalLayer + CAMetalDrawableAccelerationStructureMTLAccelerationStructure + 实例缓冲区Metal 4 新特性的应用
Metal 4 引入了几个对抽象层至关紧张的新特性,Zenith.NET 的 Metal 后端全面采取了它们。
MTL4ArgumentTable——这是 Metal 4 全新的资源绑定模子。相比旧版 Metal 须要逐个 setBuffer/setTexture/setSampler 绑定资源,Argument Table 答应将全部资源打包到一张表中,通过 GPU 所在一次性绑定。这与 Zenith.NET 的 ResourceLayout + ResourceTable 抽象自然符合:
Zenith.NETMetal 4ResourceLayout声明 Buffer/Texture/Sampler 槽位计数ResourceTable创建 MTL4ArgumentTable,填入 GPU 所在SetResourceTable()一次调用绑定整张表MTL4CommandBuffer 采取双编码器模子——同一时间只能有一种生动编码器。CommandBuffer 默认开启 Compute 编码器,当用户开启渲染 Pass 时关闭 Compute、切换到 Render 编码器;Pass 竣事后自动切回 Compute:- [Compute 编码器] → 开启 Pass → [Render 编码器] → 结束 Pass → [Compute 编码器]
复制代码 如许操持的利益是:Compute 编码器始终可用于拷贝(Blit)和盘算调治,用户无需手动管理编码器生命周期。全部拷贝操纵都走 Compute Encoder 的 Blit 路径,同一了屏蔽语义。
MTL4Compiler 支持装备端编译——把 Slang 输出的 metallib IR 在目标 GPU 上编译为终极 ISA,比传统 offline 编译能更好地使用 GPU 特定优化。
Objective-C 内存桥接
Metal API 基于 Objective-C 运行时,返回的对象都是 autoreleased 的——出了当前 autorelease pool 就会被采取。在 .NET 的托管情况里,这是个潜伏的坑。
办理方案是一个同一的桥接工具:- public static T Own<T>(Func<T> func) where T : NSObject
- {
- using NSAutoreleasePool _ = new();
- return func().Retain();
- }
复制代码 全部从 Metal API 获取的对象都通过 NSAutorelease.Own() 包装,确保 Retain 延伸生命周期,后续由 .NET 的 Dispose 模式开释。
Shader 编译:Slang 同一管线
三个后端共享同一套 Slang 着色器源码:- .slang 源文件
- ├─→ metallib (Metal Shader Library)
- ├─→ dxil (DirectX Intermediate Language)
- └─→ spirv (SPIR-V for Vulkan)
复制代码 开发者只需维护一份 .slang 着色器,编译到哪个后端由 Slangc.NET 自动处置惩罚。
光线追踪
Metal 后端完备支持硬件光线追踪:
- BLAS/TLAS:尺度的两级加速结构
- 实例缓冲区:CPU 可写的间接寻址,更新 transform 无需重修 TLAS
- RayQuery:在恣意着色器阶段内联查询,无需专用光追管线
这与 v0.0.6 移除 RayTracingPipeline 的决定一脉相承——同一用 RayQuery,三个后端的光追本事完全对齐。
操持哲学
只袒露共同本事
Zenith.NET 的焦点原则是:采取最新 API 版本,只袒露三个后端共同支持的本事。平台特有的特性被刻意打扫,以维护划一的跨平台体验。
这意味着你不会在 Zenith.NET 的 API 里看到 DX12 的 Enhanced Barriers、Vulkan 的 Push Descriptors 或 Metal 的 Tile Shading——这些都是某个 API 独有的。暴袒露来只会让其他后端无法实现,粉碎"一次编写、随处运行"的答应。
对于硬件本事差异(好比并非全部 GPU 都支持光追),则通过 Capabilities 动态查询:- if (context.Capabilities.RayTracingSupported) { /* 光追路径 */ }
- if (context.Capabilities.MeshShadingSupported) { /* Mesh Shader 路径 */ }
复制代码 共同本事同一袒露,硬件差异动态检测——这是 Zenith.NET 和其他抽象层最大的区别。
每个平台用最原生的 API
Zenith.NET 不像 bgfx 那样用 Vulkan 覆盖全部平台。在 Windows 上用 DirectX 12,在 Apple 上用 Metal 4,在 Linux/Android 上用 Vulkan 1.4。
固然上层只袒露共同本事,但每个后端内部都用对应 API 最隧道的方式实现——不须要在一种 API 上模拟另一种 API 的活动模式。
AOT 友好
整个库从第一天就为 Native AOT 操持。没有反射、没有动态代码天生、没有 Activator.CreateInstance。Metal.NET 和 Silk.NET 底层都是 P/Invoke + 函数指针,AOT 编译器能完备处置惩罚。
下一步
Metal 后端落地后,Zenith.NET 的三大后端全部就位。接下来的重点:
- SkiaSharp 集成——用 GPU 后端加速 2D 渲染
- API 稳固化——向 1.0 迈进
Zenith.NET 是开源项目,欢迎关注:
- GitHub:github.com/qian-o/Zenith.NET
- 文档站:qian-o.github.io/Zenith.NET
- NuGet:搜刮 Zenith.NET
本文由 AI 辅助天生,经作者稽核校对。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |