39 个版本
0.40.0-beta.1 | 2024 年 8 月 11 日 |
---|---|
0.3.3 | 2024 年 8 月 22 日 |
0.2.8 | 2024 年 7 月 29 日 |
0.2.7 | 2024 年 3 月 8 日 |
0.1.3 | 2023 年 2 月 22 日 |
377 在 模拟器 中排名
每月 798 次下载
在 8 个crate(7 个直接)中使用
300KB
5K SLoC
librashader
DirectX 11上的Mega Bezel SMOOTH-ADV
librashader(发音为 /ˈli:brəʃeɪdɚ/)是一个用于RetroArch 'slang' 着色器的预处理器、编译器和运行时,用纯Rust重写。
安装
对于最终用户,librashader可以从Open Build Service获取,适用于多种Linux发行版和平台。Windows和macOS用户可以从GitHub Releases下载最新版本。
支持的渲染API
librashader支持所有现代图形运行时,包括wgpu、Vulkan、OpenGL 3.3+ 和 4.6(带有DSA)、Direct3D 11、Direct3D 12和Metal。
librashader不支持旧的渲染API,如较旧的OpenGL或Direct3D版本,除非实验性地支持Direct3D 9。
API | 状态 | librashader 功能 |
---|---|---|
OpenGL 3.3+ | ✅ | gl |
OpenGL 4.6 | ✅ | gl |
Vulkan | ✅ | vk |
Direct3D 9 | ⚠️ | d3d9 |
Direct3D 11 | ✅ | d3d11 |
Direct3D 12 | ✅ | d3d12 |
Metal | ✅ | metal |
wgpu | 🆗 | wgpu |
✅ 完全支持 — 🆗 二级支持 — ⚠️ 实验性支持
由于WGSL的限制,wgpu可能不支持所有着色器。Direct3D 9支持是实验性的,并且不完全支持如前帧反馈或历史记录等功能,同时无法支持仅需要Direct3D 10+功能的着色器。
使用
librashader提供了在 librashader
crate下的Rust API和C API。这两个API都是一等API并且完全受支持。C API更多地面向与现有项目的集成。如果你希望部分使用librashader,Rust librashader
crate会暴露更多内部结构。
librashader C API最佳的使用方法是在项目中包含librashader_ld.h
,该文件实现了一个动态加载器,它会在搜索路径中加载librashader实现(librashader.so
、librashader.dll
或librashader.dylib
)。
C兼容性
将librashader
集成到项目中的推荐方法是使用librashader_ld
单头文件库,该库实现了对librashader.dll
/ librashader.so
/ librashader.dylib
的动态加载器。有关librashader如何处理库更新时C ABI和API稳定性的详细信息,请参阅版本策略。您也可以仅通过librashader.h
及其等价物-lrashader
进行动态链接。
静态链接到librashader.h
是可能的,但不受官方支持。您需要确保链接参数正确,以便成功链接到librashader.lib
或librashader.a
。强烈推荐使用corrosion CMake包。
线程安全
除了Metal运行时外,通常可以从不同的线程创建过滤器链实例,但绘图帧需要对过滤器链对象进行外部同步。
过滤器链可以从任何线程创建,但适用的情况下(在Direct3D 11中,即时上下文被视为图形设备队列)需要外部同步图形设备队列。可以使用filter_chain_create_deferred
函数异步延迟初始化GPU资源,但调用者负责将记录的命令提交到图形设备队列,并在绘制着色器传递帧之前确保工作完成。
OpenGL有一个额外的限制,即在不同线程中创建过滤器链实例仅在仅当
线程局部OpenGL上下文初始化为与绘图线程相同的上下文时才是安全的。OpenGL不支持GPU资源初始化的延迟。
Metal运行时不支持线程安全。但是,您仍然可以通过filter_chain_create_deferred
函数延迟提交GPU资源初始化。
四边形顶点和旋转
所有运行时都使用单位矩阵MVP和范围在[-1, 1]
的VBO渲染中间传递。默认情况下,最终传递使用范围在[0, 1]
的Quad VBO和以下投影矩阵。
static DEFAULT_MVP: &[f32; 16] = &[
2.0, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
-1.0, -1.0, 0.0, 1.0,
];
与RetroArch一样,这些运行时将对MVP应用旋转,仅在最终传递中。这是将方向信息传递给着色器的唯一方式。
构建
对于Rust项目,只需将crate添加到您的Cargo.toml
文件中。
cargo add librashader
要构建兼容C的动态库,运行构建脚本。
cargo run -p librashader-build-script -- --profile optimized
这将输出目标文件夹中的librashader.dll
或librashader.so
。配置可以是debug
、release
或optimized
以进行全LTO。
虽然librashader没有构建时的依赖,但使用librashader_ld.h
可能需要相关运行时图形API的头文件。
编写librashader运行时
如果您想贡献一个尚未提供的运行时实现,请参阅librashader-runtime crate以获取所有librashader运行时实现使用的辅助程序和共享逻辑。使用这些辅助程序和特性将确保您的运行时在统一和纹理语义绑定方面具有与现有librashader运行时一致的行为。
这些类型不应该在运行时的公共API中公开,而应保留在运行时实现的内部。
示例
以下Rust示例显示了如何使用每个librashader运行时。
还提供了一些使用C API的基本示例。
兼容性
librashader实现了整个RetroArch着色器管道,并且与现有着色器高度兼容。
如果您遇到在RetroArch中工作但在librashader中不工作的着色器,请报告问题。
- 过滤器链不会在后缓冲区终止。
- 与RetroArch不同,librashader并不完全了解整个渲染状态,并且设计成可以在渲染管道的任何位置插入。相反,过滤器链在调用者提供的输出表面和视口中终止。将表面复制回后缓冲区是调用者的责任。
- 尽可能并行编译着色器。这应该会明显减少预设编译时间。OpenGL不支持并行着色器编译。
- HDR10支持不是任何着色器运行时的一部分,并且librashader不支持HDR10。
- 出于性能原因,从不为输入纹理生成Mipmap。从理论上讲,这意味着具有
mipmap_input0 = "true"
的预设将不会得到Mipmap输入。实际上,没有已知的着色器预设设置mipmap_input0 = "true"
。 - 预设解析器是一个比RetroArch中的实现更加严格的实现。并非所有着色器预设都可能兼容。如果您发现这是这种情况,请提交问题以便添加一个解决方案。
运行时特定差异
- OpenGL
- 通过
glBlitFramebuffer
将正在传输的帧缓冲区内容复制到历史记录,而不是将一个四边形绘制到中间的FBO中。 - 使用采样器对象而不是
glTexParameter
。 - 采样器输入和输出不会被重命名。这对于在RenderDoc中调试着色器很有用。
- UBO和Push Constant Buffer的大小填充到16字节边界。
- OpenGL运行时与其他运行时使用相同的VBO,以及中间传递的恒等矩阵MVP。RetroArch的OpenGL驱动程序仅使用最终的VBO。
- 通过
- OpenGL 4.6+
- 应考虑OpenGL 3.3+部分的所有注意事项。
- 应能在OpenGL 4.5上工作,但这不能保证。OpenGL 4.6运行时最终可能切换到使用
ARB_spirv_extensions
来加载着色器,并且这不会被视为破坏性更改。 - OpenGL 4.6运行时使用直接状态访问来最小化对OpenGL状态的变化。对于过去5年内发布的GPU,这可能会提高性能。
- OpenGL运行时与其他运行时使用相同的VBO,以及中间传递的恒等矩阵MVP。RetroArch的OpenGL驱动程序仅使用最终的VBO。
- Vulkan
- Vulkan运行时可以使用
VK_KHR_dynamic_rendering
扩展。必须在创建设备时启用此扩展。启用动态渲染并支持主机硬件时,可能会提高性能。 - 在运行时中,通过gpu-allocator进行分配,而不是手动处理。
- Vulkan运行时可以使用
- Direct3D 11
- 通过
ID3D11DeviceContext::CopySubresourceRegion
而不是CPU转换+复制来完成帧缓冲区复制。
- 通过
- Direct3D 12
- Direct3D 12运行时使用渲染通道。这个功能自Windows 10版本1809开始可用,该版本于2018年底发布。
- 为了与着色器实现最大兼容性,使用了基于
spirv-to-dxil
的着色器编译管道,SPIRV-Cross HLSL管道作为后备方案。这使着色器兼容性超越了RetroArch Direct3D 12驱动器提供的兼容性。随着spirv-to-dxil
的改进,HLSL管道的后备方案可能会在未来被移除。 - Direct3D 12运行时需要从DirectX Shader Compiler中获取
dxcompiler.dll
,这可能已经作为Direct3D12的一部分安装。不需要dxil.dll
。
- Metal
- Metal运行时与其它运行时使用相同的VBO,以及中间通道的恒等矩阵MVP。RetroArch的Metal驱动器仅使用最终的VBO。
大多数(如果不是所有)着色器预设应该在librashader上正常工作。运行时特定的差异不应该影响输出,更多的是为了将librashader集成到您的项目中提供警告。
版本号
librashader通常遵循语义版本控制,特别是关于Rust API,其中次要版本号的增加表示在0.x.y
期间存在“破坏性变更”,而在1.x.y
之后不是“破坏性变更”。然而,导致版本号增加的“破坏性变更”在0.1.0版本之后的C API中没有中断。
C API以单独的版本进行版本控制,并通过两个单调递增的版本号导出到librashader C头文件中。
LIBRASHADER_CURRENT_VERSION
指定由librashader实现导出的API版本。LIBRASHADER_CURRENT_ABI
指定由librashader实现导出的ABI版本。
LIBRASHADER_CURRENT_VERSION
的增加保证与相同的LIBRASHADER_CURRENT_ABI
保持向后兼容。它在语义版本控制术语中相当于“次要”版本,只是它总是单调递增。向后兼容的C API添加将导致LIBRASHADER_CURRENT_VERSION
的增加。
在某个LIBRASHADER_CURRENT_VERSION
之后引入的API可能可能或可能不适用于先前版本。特别是,由过滤器或帧选项结构体启用的功能需要LIBRASHADER_CURRENT_VERSION
大于或等于引入该选项的版本,否则将传递默认值,这可能会或可能不会启用该功能,具体取决于该特定功能的向后兼容性。
对LIBRASHADER_CURRENT_ABI
的任何更改都表示C ABI的破坏性变更。出于安全考虑,librashader_ld.h
将检查确保LIBRASHADER_CURRENT_ABI
与加载的librashader二进制文件匹配。如果不匹配,则librashader将不会加载。当没有找到兼容的librashader实现时,LIBRASHADER_CURRENT_ABI
的值为0
,这表示“空”实例,其中每个操作都是no-op。
通过包管理器安装的librashader.so
的SONAME
设置为LIBRASHADER_CURRENT_ABI
。
以上内容不适用于版本号低于 0.1.0
的 librashader 版本,这些版本在 Rust 和 C API 中允许在不增加 LIBRASHADER_CURRENT_VERSION
或 LIBRASHADER_CURRENT_ABI
的情况下破坏 API 和 ABI 兼容性。
MSRV 政策
虽然 librashader 需要使用 nightly Rust,但对于不稳定库特性,实施了以下 MSRV 政策。
- Windows 和 macOS:最新版 nightly
- Linux:1.76
每周运行 CI 作业以确保 librashader 继续在 nightly 上构建。请注意,MSRV 仅用于简化 Linux 上的分发,并且可以随时更改。它通常跟踪 Ubuntu 最新版本中可用的最新 Rust 版本,但在补丁版本中可能会没有警告地更改。
许可证
librashader 的核心部分,如预处理器、预设解析器、反射库和运行时,均在 Mozilla 公共许可证第 2.0 版下授权。
librashader 的 C API,即其头文件和定义(不包括在 librashader-capi
中的实现),授权更为宽松,可能允许你在许可宽松或专有项目中使用 librashader。
为了便于在不符合 MPL-2.0 的项目中使用 librashader,librashader_ld
实现了一个加载器,该加载器将调用委托给在加载路径中找到的任何 librashader.so
、librashader.dll
或 librashader.dylib
库。一个非 MPL-2.0 兼容的项目可以通过链接到 librashader_ld
来使用 librashader 运行时,前提是 librashader.so
、librashader.dll
或 librashader.dylib
在 MPLv2 的限制下分发。
请注意,这意味着如果你的项目无法遵守 MPL-2.0 的要求,你 不能 与你的项目一起分发 librashader.so
、librashader.dll
或 librashader.dylib
。最终用户必须自己获取 librashader 的实现。更多信息请参阅 MPL 2.0 常见问题解答。
根据您的意愿,您可以选择在 GPLv3 的条款下而不是 MPL-2.0 下分发 librashader
。
依赖项
~23–74MB
~1.5M SLoC