Skip to main content

spirv_webgpu_transform/
lib.rs

1//! ##
2//!
3//! ## Features
4//!
5//! At the moment, the following transformations are supported:
6//!
7//! | Feature                   | `spirv-val` | `naga` | `tint` |
8//! | ------------------------- | ----------- | ------ | ------ |
9//! | Combined Image Samplers   | ✅          | ✅     | ✅     |
10//! | Mixed Depth / Comparison  | ✅          | ⚠️\*   | ❌     |
11//! | isnan / isinf Patching    | ✅          | ✅     | ✅     |
12//! | Storage Cube Patching     | ✅          | ✅     | ✅     |
13//!
14//! > \* Simple cases are OK.
15//! > With some [special patches](https://github.com/davnotdev/wgpu/tree/trunk-naga-patches), `naga` can process these.
16//!
17//! ## Using the result
18//!
19//! After running an individual shader through one or multiple transformations, you will want to:
20//!
21//! 1. Know which set bindings were affected, use the output [`CorrectionMap`] for this purpose.
22//! 2. Ensure that your vertex and fragment shaders shader the same binding layout, use [`mirrorpatch`] for this purpose
23//!
24//! ## For more details
25//!
26//! See [https://github.com/davnotdev/spirv-webgpu-transform](https://github.com/davnotdev/spirv-webgpu-transform) for more details.
27//!
28
29use std::collections::{HashMap, HashSet};
30
31mod correction;
32mod isnanisinfpatch;
33mod mirrorpatch;
34mod splitcombined;
35mod splitdref;
36mod spv;
37mod storagecubepatch;
38mod util;
39
40#[cfg(test)]
41mod test;
42
43use spv::*;
44use util::*;
45
46pub use correction::*;
47pub use isnanisinfpatch::*;
48pub use mirrorpatch::*;
49pub use splitcombined::*;
50pub use splitdref::*;
51pub use storagecubepatch::*;
52
53#[derive(Debug, Clone)]
54struct InstructionInsert {
55    previous_spv_idx: usize,
56    instruction: Vec<u32>,
57}
58
59#[derive(Debug, Clone)]
60struct WordInsert {
61    idx: usize,
62    word: u32,
63    head_idx: usize,
64}
65
66/// Helper to convert a `&[u8]` into a `Vec<u32>`.
67pub fn u8_slice_to_u32_vec(vec: &[u8]) -> Vec<u32> {
68    assert_eq!(
69        vec.len() % 4,
70        0,
71        "Input slice length must be a multiple of 4."
72    );
73
74    vec.chunks_exact(4)
75        .map(|chunk| {
76            (chunk[0] as u32)
77                | ((chunk[1] as u32) << 8)
78                | ((chunk[2] as u32) << 16)
79                | ((chunk[3] as u32) << 24)
80        })
81        .collect::<Vec<_>>()
82}
83
84/// Helper to convert a `&[u32]` into a `Vec<u8>`.
85pub fn u32_slice_to_u8_vec(vec: &[u32]) -> Vec<u8> {
86    vec.iter()
87        .flat_map(|&num| {
88            vec![
89                (num & 0xFF) as u8,
90                ((num >> 8) & 0xFF) as u8,
91                ((num >> 16) & 0xFF) as u8,
92                ((num >> 24) & 0xFF) as u8,
93            ]
94        })
95        .collect::<Vec<u8>>()
96}