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

nightly librashader-runtime-d3d12

适用于所有 RetroArch 着色器

47 个版本

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

#177 in 模拟器

Download history 8/week @ 2024-05-17 3/week @ 2024-05-24 5/week @ 2024-05-31 8/week @ 2024-06-07 6/week @ 2024-06-14 1/week @ 2024-06-21 132/week @ 2024-07-26 157/week @ 2024-08-02 86/week @ 2024-08-09 295/week @ 2024-08-16

每月 670 次下载
2 个软件包中使用(通过 librashader

MPL-2.0 OR GPL-3.0-only

675KB
12K 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 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 软件包下的 Rust API 和 C API。这两个 API 都是第一类并且完全受支持。C API 更适合与现有项目集成。Rust 的 librashader 软件包如果需要使用 librashader 的部分功能,会暴露更多内部结构。

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 资源初始化的延迟。

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 项目,只需将包添加到您的 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着色器管道,并且与现有着色器高度兼容。

如果您发现某个着色器在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运行时使用Direct State Access来最小化对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 Compilerdxcompiler.dll,这可能会作为 Direct3D12 的一部分已经安装。不需要 dxil.dll
  • Metal
    • Metal 运行时使用与其他运行时相同的 VBO,以及用于中间过程的单位矩阵 MVP。RetroArch 的 Metal 驱动器只使用最终的 VBO。

大多数,如果不是所有的着色器预设都可以在 librashader 上正常工作。运行时特定的差异不应影响输出,而是更多地作为将 librashader 集成到您项目中的提示。

版本控制

Latest Version C ABI C API

librashader 通常遵循 语义版本控制,其中次要版本号的增加表示在 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 实现了一个加载器,它将调用 thunk 到在加载路径中找到的任何 librashader.solibrashader.dlllibrashader.dylib 库。项目可以链接到 librashader_ld 来使用 librashader 运行时,前提是 librashader.solibrashader.dlllibrashader.dylib 在 MPLv2 的限制下分发

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

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

依赖项

~33–83MB
~1.5M SLoC