Skip to content

Commit e90fa86

Browse files
committed
add spirv-unknown-wgsl target, transpiling with naga
1 parent 0e4a769 commit e90fa86

File tree

9 files changed

+119
-1
lines changed

9 files changed

+119
-1
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rustc_codegen_spirv-target-specs/src/include_str.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ impl SpirvTargetEnv {
5959
SpirvTargetEnv::Vulkan_1_4 => {
6060
include_str!("../target-specs/spirv-unknown-vulkan1.4.json")
6161
}
62+
SpirvTargetEnv::Wgsl => {
63+
include_str!("../target-specs/spirv-unknown-wgsl.json")
64+
}
6265
}
6366
}
6467
}

crates/rustc_codegen_spirv-target-specs/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ pub enum SpirvTargetEnv {
5252
Vulkan_1_3,
5353
#[strum(to_string = "vulkan1.4")]
5454
Vulkan_1_4,
55+
#[strum(to_string = "wgsl")]
56+
Wgsl,
5557
}
5658

5759
impl SpirvTargetEnv {
@@ -93,7 +95,7 @@ mod tests {
9395
#[test]
9496
pub fn test_parse_as_str_loop() {
9597
for target in SpirvTargetEnv::iter() {
96-
let parsed = SpirvTargetEnv::parse_triple(target.as_str()).unwrap();
98+
let parsed = SpirvTargetEnv::parse_triple(&target.target_triple()).unwrap();
9799
assert_eq!(target, parsed);
98100
}
99101
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"allows-weak-linkage": false,
3+
"arch": "spirv",
4+
"crt-objects-fallback": "false",
5+
"crt-static-allows-dylibs": true,
6+
"data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64",
7+
"dll-prefix": "",
8+
"dll-suffix": ".spv.json",
9+
"dynamic-linking": true,
10+
"emit-debug-gdb-scripts": false,
11+
"env": "wgsl",
12+
"linker-flavor": "unix",
13+
"linker-is-gnu": false,
14+
"llvm-target": "spirv-unknown-wgsl",
15+
"main-needs-argc-argv": false,
16+
"metadata": {
17+
"description": null,
18+
"host_tools": null,
19+
"std": null,
20+
"tier": null
21+
},
22+
"os": "unknown",
23+
"panic-strategy": "abort",
24+
"simd-types-indirect": false,
25+
"target-pointer-width": "32"
26+
}

crates/rustc_codegen_spirv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ itertools = "0.10.5"
6060
tracing.workspace = true
6161
tracing-subscriber.workspace = true
6262
tracing-tree = "0.3.0"
63+
naga = { version = "25.0.1", features = ["spv-in", "wgsl-out"] }
6364

6465
# required for cargo gpu to resolve the needed target specs
6566
rustc_codegen_spirv-target-specs.workspace = true

crates/rustc_codegen_spirv/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ mod custom_decorations;
129129
mod custom_insts;
130130
mod link;
131131
mod linker;
132+
mod naga_transpile;
132133
mod spirv_type;
133134
mod spirv_type_constraints;
134135
mod symbols;

crates/rustc_codegen_spirv/src/link.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa;
33

44
use crate::codegen_cx::{CodegenArgs, SpirvMetadata};
5+
use crate::naga_transpile::should_transpile;
56
use crate::{SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer, linker};
67
use ar::{Archive, GnuBuilder, Header};
78
use rspirv::binary::Assemble;
@@ -311,6 +312,10 @@ fn post_link_single_module(
311312

312313
drop(save_modules_timer);
313314
}
315+
316+
if let Some(transpile) = should_transpile(sess) {
317+
transpile(sess, &cg_args, &spv_binary, out_filename).ok();
318+
}
314319
}
315320

316321
fn do_spirv_opt(
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use crate::codegen_cx::CodegenArgs;
2+
use rustc_codegen_spirv_target_specs::SpirvTargetEnv;
3+
use rustc_session::Session;
4+
use rustc_span::ErrorGuaranteed;
5+
use std::path::Path;
6+
7+
pub type NagaTranspile = fn(
8+
sess: &Session,
9+
cg_args: &CodegenArgs,
10+
spv_binary: &[u32],
11+
out_filename: &Path,
12+
) -> Result<(), ErrorGuaranteed>;
13+
14+
pub fn should_transpile(sess: &Session) -> Option<NagaTranspile> {
15+
let target = SpirvTargetEnv::parse_triple(sess.opts.target_triple.tuple())
16+
.expect("parsing should fail earlier");
17+
match target {
18+
SpirvTargetEnv::Wgsl => Some(transpile::wgsl_transpile),
19+
_ => None,
20+
}
21+
}
22+
23+
mod transpile {
24+
use crate::codegen_cx::CodegenArgs;
25+
use naga::error::ShaderError;
26+
use naga::valid::Capabilities;
27+
use rustc_session::Session;
28+
use rustc_span::ErrorGuaranteed;
29+
use std::path::Path;
30+
31+
pub fn wgsl_transpile(
32+
sess: &Session,
33+
_cg_args: &CodegenArgs,
34+
spv_binary: &[u32],
35+
out_filename: &Path,
36+
) -> Result<(), ErrorGuaranteed> {
37+
// these should be params via spirv-builder
38+
let opts = naga::front::spv::Options::default();
39+
let capabilities = Capabilities::default();
40+
let writer_flags = naga::back::wgsl::WriterFlags::empty();
41+
42+
let module = naga::front::spv::parse_u8_slice(&bytemuck::cast_slice(spv_binary), &opts)
43+
.map_err(|err| {
44+
sess.dcx()
45+
.err(format!("Naga failed to parse spv: \n{}", ShaderError {
46+
source: String::new(),
47+
label: None,
48+
inner: Box::new(err),
49+
}))
50+
})?;
51+
let mut validator =
52+
naga::valid::Validator::new(naga::valid::ValidationFlags::default(), capabilities);
53+
let info = validator.validate(&module).map_err(|err| {
54+
sess.dcx()
55+
.err(format!("Naga validation failed: \n{}", ShaderError {
56+
source: String::new(),
57+
label: None,
58+
inner: Box::new(err),
59+
}))
60+
})?;
61+
62+
let wgsl_dst = out_filename.with_extension("wgsl");
63+
let wgsl = naga::back::wgsl::write_string(&module, &info, writer_flags).map_err(|err| {
64+
sess.dcx()
65+
.err(format!("Naga failed to write wgsl : \n{}", err))
66+
})?;
67+
68+
std::fs::write(&wgsl_dst, wgsl).map_err(|err| {
69+
sess.dcx()
70+
.err(format!("failed to write wgsl to file: {}", err))
71+
})?;
72+
73+
Ok(())
74+
}
75+
}

crates/rustc_codegen_spirv/src/target.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ impl TargetsExt for SpirvTargetEnv {
3333
| SpirvTargetEnv::Vulkan_1_2
3434
| SpirvTargetEnv::Vulkan_1_3
3535
| SpirvTargetEnv::Vulkan_1_4 => MemoryModel::Vulkan,
36+
37+
SpirvTargetEnv::Wgsl => MemoryModel::Vulkan,
3638
}
3739
}
3840

@@ -57,6 +59,8 @@ impl TargetsExt for SpirvTargetEnv {
5759
SpirvTargetEnv::Vulkan_1_2 => spirv_tools::TargetEnv::Vulkan_1_2,
5860
SpirvTargetEnv::Vulkan_1_3 => spirv_tools::TargetEnv::Vulkan_1_3,
5961
SpirvTargetEnv::Vulkan_1_4 => spirv_tools::TargetEnv::Vulkan_1_4,
62+
63+
SpirvTargetEnv::Wgsl => spirv_tools::TargetEnv::Vulkan_1_2,
6064
}
6165
}
6266

0 commit comments

Comments
 (0)