diff --git a/Cargo.lock b/Cargo.lock
index 64ee62a4795..7317a504562 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -229,7 +229,16 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
dependencies = [
- "bit-vec",
+ "bit-vec 0.8.0",
+]
+
+[[package]]
+name = "bit-set"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34ddef2995421ab6a5c779542c81ee77c115206f4ad9d5a8e05f4ff49716a3dd"
+dependencies = [
+ "bit-vec 0.9.1",
]
[[package]]
@@ -238,6 +247,12 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
+[[package]]
+name = "bit-vec"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51"
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -547,6 +562,15 @@ dependencies = [
"unicode-width",
]
+[[package]]
+name = "codespan-reporting"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681"
+dependencies = [
+ "unicode-width",
+]
+
[[package]]
name = "colorchoice"
version = "1.0.4"
@@ -2098,11 +2122,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8"
dependencies = [
"arrayvec",
- "bit-set",
+ "bit-set 0.8.0",
"bitflags 2.10.0",
"cfg-if",
"cfg_aliases",
- "codespan-reporting",
+ "codespan-reporting 0.12.0",
"half",
"hashbrown 0.16.1",
"hexf-parse",
@@ -2113,11 +2137,36 @@ dependencies = [
"once_cell",
"petgraph",
"rustc-hash",
- "spirv",
+ "spirv 0.3.0+sdk-1.3.268.0",
"thiserror 2.0.18",
"unicode-ident",
]
+[[package]]
+name = "naga"
+version = "29.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2630921705b9b01dcdd0b6864b9562ca3c1951eecd0f0c4f5f04f61e412647"
+dependencies = [
+ "arrayvec",
+ "bit-set 0.9.1",
+ "bitflags 2.10.0",
+ "cfg-if",
+ "cfg_aliases",
+ "codespan-reporting 0.13.1",
+ "half",
+ "hashbrown 0.16.1",
+ "indexmap 2.13.0",
+ "libm",
+ "log",
+ "num-traits",
+ "once_cell",
+ "petgraph",
+ "rustc-hash",
+ "spirv 0.4.0+sdk-1.4.341.0",
+ "thiserror 2.0.18",
+]
+
[[package]]
name = "ndk"
version = "0.9.0"
@@ -2906,7 +2955,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d"
dependencies = [
"rustc-hash",
- "spirv",
+ "spirv 0.3.0+sdk-1.3.268.0",
]
[[package]]
@@ -2941,6 +2990,7 @@ dependencies = [
"lazy_static",
"libc",
"log",
+ "naga 29.0.1",
"object 0.37.3",
"pretty_assertions",
"regex",
@@ -2953,6 +3003,7 @@ dependencies = [
"spirt",
"spirv-std-types",
"spirv-tools",
+ "strum",
"termcolor",
"thorin-dwp",
"tracing",
@@ -2968,7 +3019,7 @@ dependencies = [
"semver",
"serde",
"serde_json",
- "spirv",
+ "spirv 0.3.0+sdk-1.3.268.0",
"thiserror 2.0.18",
]
@@ -3358,6 +3409,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "spirv"
+version = "0.4.0+sdk-1.4.341.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f"
+dependencies = [
+ "bitflags 2.10.0",
+]
+
[[package]]
name = "spirv-builder"
version = "0.9.0"
@@ -4320,7 +4380,7 @@ dependencies = [
"hashbrown 0.16.1",
"js-sys",
"log",
- "naga",
+ "naga 27.0.3",
"parking_lot",
"portable-atomic",
"profiling",
@@ -4342,8 +4402,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7"
dependencies = [
"arrayvec",
- "bit-set",
- "bit-vec",
+ "bit-set 0.8.0",
+ "bit-vec 0.8.0",
"bitflags 2.10.0",
"bytemuck",
"cfg_aliases",
@@ -4351,7 +4411,7 @@ dependencies = [
"hashbrown 0.16.1",
"indexmap 2.13.0",
"log",
- "naga",
+ "naga 27.0.3",
"once_cell",
"parking_lot",
"portable-atomic",
@@ -4403,7 +4463,7 @@ dependencies = [
"android_system_properties",
"arrayvec",
"ash",
- "bit-set",
+ "bit-set 0.8.0",
"bitflags 2.10.0",
"block",
"bytemuck",
@@ -4422,7 +4482,7 @@ dependencies = [
"libloading",
"log",
"metal",
- "naga",
+ "naga 27.0.3",
"ndk-sys",
"objc",
"once_cell",
diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml
index ed72fbd2800..00b58caa5dc 100644
--- a/crates/rustc_codegen_spirv/Cargo.toml
+++ b/crates/rustc_codegen_spirv/Cargo.toml
@@ -20,15 +20,16 @@ crate-type = ["dylib"]
default = ["use-compiled-tools"]
# If enabled, uses spirv-tools binaries installed in PATH, instead of
# compiling and linking the spirv-tools C++ code
-use-installed-tools = ["spirv-tools/use-installed-tools"]
+use-installed-tools = ["spirv-tools/use-installed-tools", "naga"]
# If enabled will compile and link the C++ code for the spirv tools, the compiled
# version is preferred if both this and `use-installed-tools` are enabled
-use-compiled-tools = ["spirv-tools/use-compiled-tools"]
+use-compiled-tools = ["spirv-tools/use-compiled-tools", "naga"]
# If enabled, this will not check whether the current rustc version is set to the
# appropriate channel. rustc_cogeden_spirv requires a specific nightly version,
# and will likely produce compile errors when built against a different toolchain.
# Enable this feature to be able to experiment with other versions.
skip-toolchain-check = []
+naga = ["dep:naga"]
[dependencies]
# HACK(eddyb) these only exist to unify features across dependency trees,
@@ -61,6 +62,8 @@ itertools = "0.14.0"
tracing.workspace = true
tracing-subscriber.workspace = true
tracing-tree = "0.4.0"
+naga = { version = "29.0.1", features = ["spv-in", "wgsl-out"], optional = true }
+strum = { version = "0.27.2", features = ["derive"] }
[dev-dependencies]
pretty_assertions = "1.0"
diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs
index 5c891706ea8..fb68dcf687b 100644
--- a/crates/rustc_codegen_spirv/src/lib.rs
+++ b/crates/rustc_codegen_spirv/src/lib.rs
@@ -127,6 +127,7 @@ mod custom_decorations;
mod custom_insts;
mod link;
mod linker;
+mod naga_transpile;
mod spirv_type;
mod spirv_type_constraints;
mod symbols;
diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs
index fd903a52d08..ebefbcae4a1 100644
--- a/crates/rustc_codegen_spirv/src/link.rs
+++ b/crates/rustc_codegen_spirv/src/link.rs
@@ -3,6 +3,7 @@ use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa;
use crate::codegen_cx::{CodegenArgs, SpirvMetadata};
use crate::linker;
+use crate::naga_transpile::should_transpile;
use crate::target::{SpirvTarget, SpirvTargetVariant};
use ar::{Archive, GnuBuilder, Header};
use rspirv::binary::Assemble;
@@ -319,6 +320,10 @@ fn post_link_single_module(
drop(save_modules_timer);
}
+
+ if let Ok(Some(transpile)) = should_transpile(sess) {
+ transpile(sess, cg_args, &spv_binary, out_filename).ok();
+ }
}
fn do_spirv_opt(
diff --git a/crates/rustc_codegen_spirv/src/naga_transpile.rs b/crates/rustc_codegen_spirv/src/naga_transpile.rs
new file mode 100644
index 00000000000..6f6b8131107
--- /dev/null
+++ b/crates/rustc_codegen_spirv/src/naga_transpile.rs
@@ -0,0 +1,89 @@
+use crate::codegen_cx::CodegenArgs;
+use crate::target::{NagaTarget, SpirvTarget};
+use rustc_session::Session;
+use rustc_span::ErrorGuaranteed;
+use std::path::Path;
+
+pub type NagaTranspile = fn(
+ sess: &Session,
+ cg_args: &CodegenArgs,
+ spv_binary: &[u32],
+ out_filename: &Path,
+) -> Result<(), ErrorGuaranteed>;
+
+pub fn should_transpile(sess: &Session) -> Result