ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

rust-gpu 迁移到 register_tool:`[spirv(..)]` 属性宏机制的演进与 shader 工程适配指南

rust-gpu 迁移到 register_tool:`[spirv(..)]` 属性宏机制的演进与 shader 工程适配指南 图形学编译器游戏开发【免费下载链接】rust-gpu Making Rust a first-class language and ecosystem for GPU shaders 项目地址https://gitcode.com/gh_mirrors/ru/rust-gpu点击查看免费下载本文围绕 rust-gpucrates/目录下的工作区中一次影响所有 shader 开发者的工具链迁移展开随着 2022 年 9 月 nightly Rust 移除register_attr特性rust-gpu 将全局属性注册机制从register_attr(spirv)切换到register_tool(rust_gpu)并由spirv-std提供同名过程宏属性来保持#[spirv(..)]写法不变。读完本文你将掌握这次迁移的前因后果、shader crate 需要做出的最小改动、spirv过程宏的展开原理以及SpirvBuilder与非自动构建场景下的两种配置方式。迁移背景为什么register_attr(spirv)会失效在迁移之前rust-gpu 依赖 nightly Rust 的register_attr特性在 shader crate 顶部写入#![feature(register_attr)] #![register_attr(spirv)]以此把spirv注册为一个全局可见的属性随后便可以在函数上直接书写#[spirv(vertex)]、#[spirv(fragment)]等。问题在于register_attr特性在较新的 nightly Rust 中被移除取而代之的是register_tool。register_tool不再允许注册一个“裸”的全局属性名而是强制把属性放入一个工具命名空间tool namespace。这意味着如果直接沿用新机制你不得不把代码中所有#[spirv(..)]改写成#[rust_gpu::spirv(..)]——对于一个已经大量使用#[spirv(..)]的代码库而言这既繁琐又容易出错而且工具命名空间中的名称无法通过use语句引入作用域来简化书写。该迁移对应 rust-gpu 的 PR#926 中被标记为破坏性变更BREAKING并在 docs/src/migration-to-register-tool.md 中给出了官方迁移说明。迁移方案用过程宏属性保住#[spirv(..)]写法为了让 shader 代码不必大规模改写rust-gpu 选择实现一个名为spirv的过程宏属性proc macro attribute来“翻译”旧写法。该宏由spirv-std-macroscrate 提供实现在 crates/spirv-std/macros/src/lib.rs/// Replaces all (nested) occurrences of the #[spirv(..)] attribute with /// #[cfg_attr(target_archspirv, rust_gpu::spirv(..))]. #[proc_macro_attribute] pub fn spirv(attr: TokenStream, item: TokenStream) - TokenStream { // 在 item 头部插入: // #[cfg_attr(target_archspirv, rust_gpu::spirv(#attr))] // 并递归扫描 item 内部所有 #[spirv(..)] 子属性 // 将其改写为 [cfg_attr(target_archspirv, rust_gpu::#inner)] ... }宏的工作方式可以概括为两步对应用了#[spirv(..)]的函数等条目在展开结果的最前面追加一段#[cfg_attr(target_arch spirv, rust_gpu::spirv(..))]把外层属性转移到rust_gpu工具命名空间下同时保证在非 SPIR-V 目标例如 CPU 侧构建上这些属性会被cfg_attr直接剔除、不会报错。递归遍历条目内部出现的所有#[spirv(..)]嵌套属性例如函数参数上的#[spirv(descriptor_set 0, binding 0)]逐一把它们改写为#[cfg_attr(target_arch spirv, rust_gpu::spirv(..))]。值得注意的是迁移前spirv过程宏属性就已经存在只是仅用于非 SPIR-V 构建时把#[spirv(..)]变成空操作no-op本次迁移后该宏在所有平台上都会被使用既保留了 CPU 侧构建的兼容性又在 SPIR-V 目标上完成到rust_gpu::spirv(..)的翻译。spirv宏通过 crates/spirv-std/src/lib.rs 中的pub use macros::spirv;从spirv_std公开导出因此 shader crate 只需导入即可使用。shader crate 需要做的改动1. 显式导入spirv宏属性由于spirv现在是一个过程宏属性不再是编译器注册的全局属性必须把它导入到当前 crate 的全局作用域编译器才能识别#[spirv(..)]。在 shader crate 的根lib.rs或main.rs加入use spirv_std::spirv;2. 处理条件导入去掉#[cfg(..)]如果你的 shader 代码里原本为了兼容 CPU 构建而写了条件导入#[cfg(not(target_arch spirv))] use spirv_std::spirv;必须删除外层那条#[cfg(..)]直接无条件导入。原因有二该过程宏属性在所有平台上都需要可见否则 CPU 侧构建同样会因无法解析#[spirv(..)]而报错宏本身已经通过cfg_attr(target_arch spirv, ...)处理了平台差异条件导入既无必要、还会导致 SPIR-V 目标上属性不可见。3. 保持全局可见不要使用限定路径请继续像以前一样书写#[spirv(..)]。不要尝试写成#[spirv_std::spirv(..)]这样的限定形式——这会干扰过程宏对属性的解析很可能直接编译失败。官方文档特别强调必须保证spirv在全局作用域可见并沿用#[spirv(..)]的原始用法。4. 删除旧的register_attr属性改用register_tool将 shader crate 顶部旧的注册属性#![feature(register_attr)] #![register_attr(spirv)]替换为#![feature(register_tool)] #![register_tool(rust_gpu)]register_tool(rust_gpu)的作用是告诉编译器允许使用rust_gpu这个工具命名空间下的属性从而让宏展开出的rust_gpu::spirv(..)能够被合法接受避免“unknown attribute”类错误。5. 使用SpirvBuilder的场景无需任何额外操作如果你通过spirv-builder在构建脚本中编译 shader那么第 4 步已经自动完成你只需要完成前 3 步即可。在 crates/spirv-builder/src/lib.rs 的invoke_rustc函数中SpirvBuilder组装 rustc 调用参数时会自动注入以下两条 rustflags-Zcrate-attrfeature(register_tool).to_string(), -Zcrate-attrregister_tool(rust_gpu).to_string(),也就是说通过SpirvBuilder::new(shader_crate, target).build()?编译时编译器会在 crate 层面自动带上feature(register_tool)与register_tool(rust_gpu)开发者无需在 shader crate 源码中手写这两个属性。6. 非自动构建场景在.cargo/config中配置如果你不使用SpirvBuilder而是选择手动配置 cargo 来构建 shader crate见 docs/src/writing-shader-crates.md需要在项目根目录的.cargo/config中把这两条 rustflags 补上。仓库文档给出了一套完整可用的配置[build] target spirv-unknown-spv1.3 rustflags [ -Zcodegen-backendpath_to_librustc_codegen_spirv, -Zbinary-dep-depinfo, -Csymbol-mangling-versionv0, -Zcrate-attrfeature(register_tool), -Zcrate-attrregister_tool(rust_gpu) ] [unstable] build-std[core] build-std-features[compiler-builtins-mem]其中path_to_librustc_codegen_spirv需要替换为你本机编译出的 codegen 后端动态库实际路径先cargo build --release构建整个 rust-gpu 仓库产物位于target/release。target的值依据目标平台选择例如 Vulkan 1.1 对应spirv-unknown-vulkan1.1详见 docs/src/platform-support.md。tests/src/main.rs的测试入口同样采用这两条-Zcrate-attr参数见 tests/src/main.rs印证了这套配置是当前仓库的标准做法。技术原理命名空间、cfg_attr 与 CPU 侧兼容为什么use无法从工具命名空间导入register_tool的特性决定了工具命名空间内的属性名不是普通的 Rust 路径编译器不允许通过use rust_gpu::spirv之类的方式把它引入普通作用域。这正是迁移文档中强调“无法use工具命名空间名称”的原因也正是必须由过程宏代为完成命名空间转移的根本动机。宏展开的核心cfg_attr(target_arch spirv, ...)spirv过程宏的输出中大量使用cfg_attr(target_arch spirv, ...)在 SPIR-V 目标上cfg_attr激活属性变成rust_gpu::spirv(..)交给 rust-gpu 的 codegen 后端rustc_codegen_spirv处理在其他平台如开发机的 CPU 架构上cfg_attr条件不成立属性被整体移除从而保证同一份 shader 源码可以被宿主程序正常编译、做类型检查或供代码补全使用。建议优先使用spirv宏而非rust_gpu::spirv官方迁移文档明确建议优先使用spirv过程宏属性本身而不是它翻译后得到的rust_gpu::spirv(..)因为后者属于实现细节未来可能发生变化。对 shader 开发者而言#[spirv(..)]就是稳定、面向用户的 API 表面。完整的 shader crate 示例结合 docs/src/writing-shader-crates.md 中的示例一个完成迁移的最小 shader crate 骨架如下# Cargo.toml [lib] crate-type [dylib] [dependencies] spirv-std { version 0.9 }// src/lib.rs #![no_std] use spirv_std::spirv; use spirv_std::glam::{vec4, Vec4}; #[spirv(fragment)] pub fn main_fs(output: mut Vec4) { *output vec4(1.0, 0.0, 0.0, 1.0); }关键点回顾#![no_std]声明 shader 运行在无标准库环境use spirv_std::spirv;把spirv宏引入全局作用域不再需要#[cfg(..)]包裹#[spirv(fragment)]标记入口函数阶段函数参数上的#[spirv(descriptor_set 0, binding 0)]等属性则由宏递归改写后由后端处理。常见问题速查症状原因解决方案编译报spirv是未知属性未导入spirv宏或宏未在全局作用域可见在 crate 根添加use spirv_std::spirv;编译报register_tool相关属性缺失shader crate 未注册rust_gpu工具命名空间添加#![feature(register_tool)]与#![register_tool(rust_gpu)]或用SpirvBuilder自动注入#[spirv_std::spirv(..)]写法编译失败限定路径干扰过程宏解析改为全局导入后继续使用#[spirv(..)]CPU 侧构建报属性错误旧代码用#[cfg(not(target_arch spirv))]条件导入spirv删除#[cfg(..)]无条件导入总结这次从register_attr到register_tool的迁移本质上是 rust-gpu 对 nightly 编译器特性变更的一次兼容性应对通过一个在 crates/spirv-std/macros/src/lib.rs 中实现的过程宏属性把用户侧#[spirv(..)]的写法完整保留下来同时把属性安全地转移到rust_gpu工具命名空间。对 shader 维护者来说改动收敛为三步无条件导入spirv宏、保持#[spirv(..)]写法、删除旧的register_attr属性使用SpirvBuilder时此步自动完成。这一模式也说明过程宏属性是 rust-gpu 在 unstable 编译器特性频繁变动环境下维持稳定用户接口的重要手段。赞分享图形学编译器游戏开发【免费下载链接】rust-gpu Making Rust a first-class language and ecosystem for GPU shaders 项目地址https://gitcode.com/gh_mirrors/ru/rust-gpu点击查看免费下载相关推荐pytest funcarg 到 fixture 机制演进从 cached_setup 到 pytest.fixture 的迁移指南pytest funcarg 到 fixture 机制演进从 cached_setup 到 pytest.fixture 的迁移指南 pytest 的 fi测试开发工具Rust 宏系统终极演变指南从声明式宏到过程宏的完整进化史Rust 宏系统终极演变指南从声明式宏到过程宏的完整进化史 Rust 宏系统是 Rust 语言的核心特性之一它允许开发者编写代码生成代码极大地提升了代码的文档Zed Agent 的 Rules 机制演进从 Rules 库到 Skills 与 Instructions 的迁移实践指南Zed Agent 的 Rules 机制演进从 Rules 库到 Skills 与 Instructions 的迁移实践指南 本指南围绕 Zed当前仓库为开发工具代码编辑器桌面应用上一篇Julia语言入门高性能科学计算的新选择下一篇探索未来文本编辑器Goneovim —— 高性能的Neovim图形界面创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表