#retro-arch #shader #spir-v #graphics

librashader-preprocess

适用于所有 RetroArch 着色器

68 个发布版本

0.40.0-beta.12024年8月11日
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日

#375模拟器

Download history 32/week @ 2024-05-04 23/week @ 2024-05-11 51/week @ 2024-05-18 34/week @ 2024-05-25 39/week @ 2024-06-01 25/week @ 2024-06-08 37/week @ 2024-06-15 40/week @ 2024-06-22 8/week @ 2024-06-29 14/week @ 2024-07-06 49/week @ 2024-07-13 29/week @ 2024-07-20 184/week @ 2024-07-27 224/week @ 2024-08-03 150/week @ 2024-08-10 383/week @ 2024-08-17

每月942 次下载
用于 12 个crate(11 个直接使用)

MPL-2.0 OR GPL-3.0-only

94KB
1K SLoC

librashader

Mega Bezel SMOOTH-ADV

DirectX 11上的Mega Bezel SMOOTH-ADV

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

Latest Version Docs build result License Nightly rust

安装

对于最终用户,librashader 可从 Open Build Service 获取,适用于各种 Linux 发行版和平台。Windows 和 macOS 用户可以从 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

✅ 完全支持 — 🆗 二级支持 — ⚠️ 实验性支持

由于 WGSL 的限制,wgpu 可能无法支持所有着色器。Direct3D 9 的支持是实验性的,并且不完全支持诸如前帧反馈或历史记录等功能,同时也无法支持需要 Direct3D 10+ 特性的着色器。

用法

librashader 提供了 Rust API,位于 librashader crate 中,以及 C API。这两个 API 都是第一等的,并完全受支持。C API 更适合与现有项目集成。如果你希望部分使用 librashader,Rust librashader crate 会暴露更多内部结构。

librashader C API的最佳使用方法是在项目中包含librashader_ld.h,该文件实现了一个加载器,可以动态加载librashader(librashader.solibrashader.dlllibrashader.dylib)实现,并将其放在搜索路径中。

C 兼容性

推荐通过包含librashader_ld单个头文件库来集成librashader,该库实现了对librashader.dll / librashader.so / librashader.dylib的动态加载。有关librashader如何处理库更新时的C ABI和API稳定性的详细信息,请参阅版本策略。您也可以仅使用librashader.h及其等效项-lrashader进行动态链接。

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

线程安全

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

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

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

金属运行时不具备线程安全性。然而,您仍然可以通过filter_chain_create_deferred函数延迟提交GPU资源初始化。

四边形顶点和旋转

所有运行时都以单位矩阵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一样,对这些运行时,MVP上的旋转将仅应用于最终传递。这是将方向信息传递给着色器的唯一方式。

构建

对于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 运行时实现所使用的辅助工具和共享逻辑。使用这些辅助工具和特性能确保您的运行时在 uniform 和 texture 语义绑定方面与现有 librashader 运行时具有一致的行为。

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

示例

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

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

兼容性

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

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

  • 过滤器链不会在后缓冲区终止。
    • 与 RetroArch 不同,librashader 并不完全了解整个渲染状态,并且设计为可以在渲染管道的任何位置插入。相反,过滤器链在调用者提供的输出表面和视口中终止。将表面复制回后缓冲区是调用者的责任。
  • 尽可能并行编译着色器。这应该会显著减少预置编译时间。OpenGL 不支持并行着色器编译。
  • HDR10 支持不是任何着色器运行时的一部分,并且 librashader 不支持 HDR10。
  • 出于性能原因,永远不会为输入纹理生成贴图。在理论上,这意味着具有 mipmap_input0 = "true" 的预置将不会获得贴图输入。实际上,没有已知的着色器预置设置了 mipmap_input0 = "true"
  • 预置解析器是一个比 RetroArch 中的更严格的实现。并非所有着色器预置都可能是兼容的。如果您发现这种情况,请提交问题以便添加解决方案。

运行时特定差异

  • OpenGL
    • 通过 glBlitFramebuffer 而不是绘制一个四边形到中间的 FBO 来将正在传输的帧缓冲区内容复制到历史记录中。
    • 使用采样器对象而不是 glTexParameter
    • 采样器输入和输出不会被重命名。这对于在 RenderDoc 中调试着色器很有用。
    • UBO 和 Push Constant 缓冲区大小被填充到 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 着色器编译器 中的 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_ABI 的值为 0 表示“空”实例,其中每个操作都是无操作,这种情况发生在找不到兼容的 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 常见问题解答

您可以选择在 GPLv3 而不是 MPL-2.0 的条款下分发 librashader

依赖项

~7MB
~182K SLoC