61 个版本

新版本 0.3.3 2024 年 8 月 22 日
0.2.8 2024 年 7 月 29 日
0.2.7 2024 年 3 月 8 日
0.2.0-beta.22023 年 11 月 30 日
0.1.0-alpha.42022 年 12 月 5 日

仿真器 中排名 380

Download history 130/week @ 2024-07-27 142/week @ 2024-08-03 4/week @ 2024-08-10 297/week @ 2024-08-17

每月下载量 573

MPL-2.0 OR GPL-3.0-only

200KB
2.5K SLoC

librashader

Mega Bezel SMOOTH-ADV

Mega Bezel SMOOTH-ADV 在 DirectX 11 上

librashader(/ˈli:brəʃeɪdɚ/)是一个为 RetroArch 'slang' 着色器重写的预处理器、编译器和运行时,使用纯 Rust 实现。

Latest Version Docs build result License Nightly rust

安装

对于各种 Linux 发行版和平台,可以在 GitHub 发布 获取最新版本的二进制文件。

支持的渲染 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

✅ 全支持 — 🆗 二级支持

在具有二级支持的渲染 API 上,着色器的兼容性无法保证。

wgpu 对无法转换为 WGSL 的着色器有限制,例如使用 inverse 的着色器。Direct3D 9 不支持需要 Direct3D 10+ 功能的着色器,或无法编译到 Shader Model 3.0 的着色器。

使用

librashader提供了在librashadercrate下的Rust API和C API。这两个API都是一等API且得到全面支持。C API更多地倾向于与现有项目集成。如果你希望逐部分使用librashader,Rust librashader crate会暴露更多内部功能。

最佳使用librashader C API的方法是在你的项目中包含librashader_ld.h,它实现了一个动态加载librashader(librashader.solibrashader.dlllibrashader.dylib)实现并在搜索路径中查找的加载器。

C 兼容性

推荐使用librashader的方式是通过实现librashader_ld的单头库,该库为librashader.dll / librashader.so / librashader.dylib实现动态加载器。有关librashader如何处理库更新时C ABI和API稳定性的详细信息,请参阅版本策略。你也可以仅使用librashader.h和等效的-lrashader进行动态链接。

使用librashader.h进行静态链接是可能的,但官方不支持。你需要确保链接参数正确,以便成功链接到librashader.liblibrashader.a。强烈推荐使用corrosion CMake包。

线程安全

除了Metal运行时外,通常从不同的线程创建过滤器链实例是安全的,但绘制帧需要外部同步过滤器链对象。

过滤器链可以在任何线程中创建,但在适用的情况下需要外部同步图形设备队列(在Direct3D 11中,即时上下文被认为是图形设备队列),因为加载查找表需要向GPU提交命令。可以使用filter_chain_create_deferred函数异步延迟初始化GPU资源,但调用者负责将记录的命令提交到图形设备队列,并在绘制着色器传递帧之前确保工作完成。

OpenGL有一个额外的限制,即在不同的线程中创建过滤器链实例只有在且仅当线程本地OpenGL上下文初始化为与绘图线程相同的上下文时才是安全的。OpenGL不支持GPU资源初始化的延迟。

金属运行时不支持线程安全。但是,你仍然可以通过filter_chain_create_deferred函数延迟提交GPU资源初始化。

Direct3D 9 API不是线程安全的,除非在设备创建时启用了D3DCREATE_MULTITHREADED

四边形顶点和旋转

所有运行时都使用单位矩阵MVP和范围在[-1, 1]的VBO渲染中间传递。默认情况下,最终传递使用范围在[0, 1]的四边形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一样,对这些运行时应用旋转只会发生在最终传递。这是将方向信息传递给着色器的唯一方法。

构建

对于Rust项目,只需将crate添加到你的Cargo.toml文件中即可。

cargo add librashader

要构建与C兼容的动态库,请运行构建脚本。

cargo run -p librashader-build-script -- --profile optimized

这将输出目标文件夹中的librashader.dlllibrashader.so。配置可以是debugreleaseoptimized以支持全LTO。

尽管librashader没有构建时的依赖,但使用librashader_ld.h可能需要相关运行时图形API的头文件。

编写librashader运行时

如果您希望贡献一个尚不存在的运行时实现,请查看librashader-runtime crate以获取用于所有librashader运行时实现的帮助和共享逻辑。使用这些帮助器和特质将确保您的运行时在统一和纹理语义绑定方面与现有librashader运行时具有一致的行为。

这些类型不应在运行时的公共API中暴露,而应保留在运行时实现的内部。

示例

以下Rust示例展示了如何使用每个librashader运行时。

还提供了一些使用C API的基本示例。

兼容性

librashader实现了整个RetroArch着色器管道,并与现有着色器高度兼容。

如果您在librashader中遇到在RetroArch中工作但在librashader中不工作的着色器,请报告问题。

  • 过滤器链不会终止在后缓冲区。
    • 与RetroArch不同,librashader不知道整个渲染状态,并设计成可以在渲染管道的任何位置插入。相反,过滤器链终止在调用者提供的输出表面和视口。将表面复制回后缓冲区的责任在调用者。
  • 尽可能并行编译着色器。这应该会显著减少预置编译时间。OpenGL不支持并行着色器编译。
  • HDR10支持不是任何着色器运行时的组成部分,并且librashader不支持。
  • 出于性能考虑,永远不会为输入纹理生成米普贴图。在理论上,这意味着具有mipmap_input0 = "true"的预置不会获得米普贴图输入。在实践中,没有已知的着色器预置设置了mipmap_input0 = "true"
  • 预置解析器是一个比RetroArch中的实现更为严格的实现。并非所有着色器预置都兼容。如果您发现这种情况,请提交问题以便添加解决方法。
  • 着色器在传递给驱动程序之前在SPIR-V级别预先链接。片段着色器中未使用的输入被删除,并且相应的顶点着色器中的输入被降级为全局变量。

运行时特定差异

  • 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而不是手动处理的。
  • Direct3D 11
    • 帧缓冲区复制是通过ID3D11DeviceContext::CopySubresourceRegion而不是CPU转换+复制来完成的。
  • Direct3D 12
    • Direct3D 12运行时使用渲染通道。这个功能自2018年底发布的Windows 10版本1809以来就已经可用。
    • 为了与着色器实现最大兼容性,使用基于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集成到项目中。

版本

Latest Version C ABI C API

librashader通常遵循语义版本,特别是对于Rust API,其中次要版本号的增加表示在0.x.y期间的“破坏性变更”,而在1.x.y之后则不是“破坏性变更”。然而,导致版本号增加的“破坏性变更”并不对应于0.1.0版本之后的C API中断。

C API以独立的方式进行了版本控制,并将两个单调递增的版本号导出到librashader C头文件中

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_CURRENT_ABI0 值表示“null”实例,其中每个操作都是无操作,如果找不到兼容的 librashader 实现,就会发生这种情况。

当通过包管理器安装时,librashader.soSONAME 被设置为 LIBRASHADER_CURRENT_ABI

上述内容不适用于 0.1.0 之前的 librashader 版本,这些版本可以在不增加 LIBRASHADER_CURRENT_VERSIONLIBRASHADER_CURRENT_ABI 的情况下,在 Rust 和 C API 中破坏 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.solibrashader.dlllibrashader.dylib 库。一个非 MPL-2.0 兼容的项目可以通过链接到 librashader_ld 来使用 librashader 运行时,前提是 librashader.solibrashader.dlllibrashader.dylib 在 MPLv2 的限制下分发

请注意,这意味着如果您的项目无法遵守MPL-2.0的要求,您不能与您的项目一起分发librashader.solibrashader.dlllibrashader.dylib。最终用户必须自行获取librashader的实现。更多信息,请参阅MPL 2.0 FAQ

您可以根据自己的意愿,选择在GPLv3的条款下分发librashader,而不是MPL-2.0。

依赖关系

~31–85MB
~1.5M SLoC