spirv-webgpu-transform 0.1.6

Transform SPIRV to be webgpu friendly
Documentation
use super::{
    combimgsampsplitter, drefsplitter, immediatespatch, isnanisinfpatch, mirrorpatch,
    pruneunuseddref, splitbindingarray, storagecubepatch, u8_slice_to_u32_vec, u32_slice_to_u8_vec,
};

use naga::{back, front, valid};
use spirv_tools::val::{self, Validator};

mod test_mirrorpatch;

const SPV_VALIDATE: u8 = 0b0000001;
const NAGA_VALIDATE: u8 = 0b0000010;
const NAGA_CONVERT: u8 = 0b0000100;
const NAGA_FRONT_ONLY: u8 = 0b0001000;
const DO_ALL: u8 = 0xff;

#[macro_export]
macro_rules! test_with_spv_and_fn {
    ($NAME:ident, $FLAGS: expr, $SPV:expr, $FN:expr) => {
        #[test]
        fn $NAME() {
            let spv = include_bytes!($SPV);
            let spv = u8_slice_to_u32_vec(spv);
            let out_spv = $FN(&spv, &mut None).unwrap();
            try_spv_to_wgsl(&out_spv, $FLAGS);
        }
    };
}

#[macro_export]
macro_rules! test_with_spv_and_fn_no_correction {
    ($NAME:ident, $FLAGS: expr, $SPV:expr, $FN:expr) => {
        #[test]
        fn $NAME() {
            let spv = include_bytes!($SPV);
            let spv = u8_slice_to_u32_vec(spv);
            let out_spv = $FN(&spv).unwrap();
            try_spv_to_wgsl(&out_spv, $FLAGS);
        }
    };
}

fn try_spv_to_wgsl(spv: &[u32], flags: u8) {
    let spv_u8 = u32_slice_to_u8_vec(spv);
    if flags & SPV_VALIDATE != 0 {
        let validator = val::create(None);
        validator.validate(spv, None).unwrap();
    }

    if flags & NAGA_FRONT_ONLY != 0 {
        front::spv::parse_u8_slice(&spv_u8, &front::spv::Options::default()).unwrap();
    }

    if flags & NAGA_VALIDATE != 0 {
        let module = front::spv::parse_u8_slice(&spv_u8, &front::spv::Options::default()).unwrap();
        let caps = valid::Capabilities::default();
        let mut info = valid::Validator::new(valid::ValidationFlags::all(), caps);
        let info = info.validate(&module).unwrap();

        if flags & NAGA_CONVERT != 0 {
            back::wgsl::write_string(&module, &info, back::wgsl::WriterFlags::all()).unwrap();
        }
    }
}

test_with_spv_and_fn!(
    splitcombined_test,
    DO_ALL,
    "./test/splitcombined/test.spv",
    combimgsampsplitter
);
test_with_spv_and_fn!(
    splitcombined_test_arrayed,
    DO_ALL,
    "./test/splitcombined/test_arrayed.spv",
    combimgsampsplitter
);
test_with_spv_and_fn!(
    splitcombined_test_nested,
    DO_ALL,
    "./test/splitcombined/test_nested.spv",
    combimgsampsplitter
);
test_with_spv_and_fn!(
    splitcombined_test_mixed,
    DO_ALL,
    "./test/splitcombined/test_mixed.spv",
    combimgsampsplitter
);

// ---

test_with_spv_and_fn!(
    splitdref_test_wrong_type_image,
    DO_ALL,
    "./test/splitdref/test_wrong_type_image.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_image,
    DO_ALL,
    "./test/splitdref/test_image.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_nested_image,
    SPV_VALIDATE,
    "./test/splitdref/test_nested_image.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_nested2_image,
    SPV_VALIDATE,
    "./test/splitdref/test_nested2_image.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_sampler,
    DO_ALL,
    "./test/splitdref/test_sampler.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_nested_sampler,
    SPV_VALIDATE,
    "./test/splitdref/test_nested_sampler.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_nested2_sampler,
    SPV_VALIDATE,
    "./test/splitdref/test_nested2_sampler.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_hidden_dref,
    SPV_VALIDATE | NAGA_FRONT_ONLY,
    "./test/splitdref/test_hidden_dref.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_hidden2_dref,
    SPV_VALIDATE | NAGA_FRONT_ONLY,
    "./test/splitdref/test_hidden2_dref.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_hidden3_dref,
    SPV_VALIDATE | NAGA_FRONT_ONLY,
    "./test/splitdref/test_hidden3_dref.spv",
    drefsplitter
);
test_with_spv_and_fn!(
    splitdref_test_cross_dref,
    SPV_VALIDATE | NAGA_FRONT_ONLY,
    "./test/splitdref/test_cross_dref.spv",
    drefsplitter
);

// ---

test_with_spv_and_fn_no_correction![
    isnanisinfpatch_isnanisinf,
    DO_ALL,
    "./test/isnanisinfpatch/isnanisinf.spv",
    isnanisinfpatch
];
test_with_spv_and_fn_no_correction![
    isnanisinfpatch_isnanisinf_vectored,
    DO_ALL,
    "./test/isnanisinfpatch/isnanisinf_vectored.spv",
    isnanisinfpatch
];
test_with_spv_and_fn_no_correction![
    isnanisinfpatch_isnanisinf_immediate,
    DO_ALL,
    "./test/isnanisinfpatch/isnanisinf_immediate.spv",
    isnanisinfpatch
];

// ---

test_with_spv_and_fn!(
    storagecubepatch_storagecube,
    DO_ALL,
    "./test/storagecubepatch/storagecube.spv",
    storagecubepatch
);
test_with_spv_and_fn!(
    storagecubepatch_storagecube_nested,
    SPV_VALIDATE,
    "./test/storagecubepatch/storagecube_nested.spv",
    storagecubepatch
);
test_with_spv_and_fn!(
    storagecubepatch_storagecube_immediate,
    DO_ALL,
    "./test/storagecubepatch/storagecube_immediate.spv",
    storagecubepatch
);

// ---

// TODO: This only tests shader validity, not functionality
test_with_spv_and_fn_no_correction![
    pruneunuseddref_pruneunuseddref,
    DO_ALL,
    "./test/pruneunuseddref/pruneunuseddref.spv",
    pruneunuseddref
];
test_with_spv_and_fn_no_correction![
    pruneunuseddref_pruneunuseddref_nested,
    DO_ALL,
    "./test/pruneunuseddref/pruneunuseddref_nested.spv",
    pruneunuseddref
];
test_with_spv_and_fn_no_correction![
    pruneunuseddref_pruneunuseddref_storage,
    DO_ALL,
    "./test/pruneunuseddref/pruneunuseddref_storage.spv",
    pruneunuseddref
];

// ---

test_with_spv_and_fn_no_correction![
    immediatespatch_immediatespatch_immediates,
    DO_ALL,
    "./test/immediatespatch/immediates.spv",
    immediatespatch
];
// TODO: This is valid, just not supported in current naga.
// Someone check on this in a month or so, I think the fix has been merged.
test_with_spv_and_fn_no_correction![
    immediatespatch_mat2_direct,
    SPV_VALIDATE,
    "./test/immediatespatch/mat2_direct.spv",
    immediatespatch
];
test_with_spv_and_fn_no_correction![
    immediatespatch_array_of_mat2,
    DO_ALL,
    "./test/immediatespatch/array_of_mat2.spv",
    immediatespatch
];
test_with_spv_and_fn_no_correction![
    immediatespatch_nested_struct,
    DO_ALL,
    "./test/immediatespatch/nested_struct.spv",
    immediatespatch
];
test_with_spv_and_fn_no_correction![
    immediatespatch_row_major,
    DO_ALL,
    "./test/immediatespatch/row_major.spv",
    immediatespatch
];

// ---

test_with_spv_and_fn![
    splitbinding_buffer_binding_array,
    DO_ALL,
    "./test/splitbindingarray/buffer_binding_array.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_storage_binding_array,
    DO_ALL,
    "./test/splitbindingarray/storage_binding_array.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_texture_binding_array,
    DO_ALL,
    "./test/splitbindingarray/texture_binding_array.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_nested_texture_binding_array,
    DO_ALL,
    "./test/splitbindingarray/nested_texture_binding_array.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_sampler_binding_array,
    DO_ALL,
    "./test/splitbindingarray/sampler_binding_array.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_sampler_stub,
    DO_ALL,
    "./test/splitbindingarray/sampler_stub.spv",
    splitbindingarray
];
test_with_spv_and_fn![
    splitbinding_texture_array_binding_array,
    DO_ALL,
    "./test/splitbindingarray/texture_array_binding_array.spv",
    splitbindingarray
];