mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 08:14:12 +00:00
Add some tests
This commit is contained in:
parent
1f4a2d0eb0
commit
733008a993
233
rspirv-linker/Cargo.lock
generated
233
rspirv-linker/Cargo.lock
generated
@ -9,6 +9,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
@ -27,6 +36,22 @@ version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227"
|
||||
dependencies = [
|
||||
"quote 1.0.7",
|
||||
"syn 1.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.15.0"
|
||||
@ -34,13 +59,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"regex",
|
||||
"rustc_version",
|
||||
"syn",
|
||||
"syn 0.15.44",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
@ -50,12 +81,29 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
@ -71,13 +119,49 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "output_vt100"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"ctor",
|
||||
"difference",
|
||||
"output_vt100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -86,9 +170,65 @@ version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2 0.4.30",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.9"
|
||||
@ -107,6 +247,15 @@ version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rspirv"
|
||||
version = "0.7.0"
|
||||
@ -121,7 +270,10 @@ dependencies = [
|
||||
name = "rspirv-linker"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"pretty_assertions",
|
||||
"rspirv",
|
||||
"tempfile",
|
||||
"topological-sort",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -162,9 +314,34 @@ version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"proc-macro2 0.4.30",
|
||||
"quote 0.6.13",
|
||||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891d8d6567fe7c7f8835a3a98af4208f3846fba258c1bc3c31d6e506239f11f9"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.19",
|
||||
"quote 1.0.7",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -176,8 +353,48 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "topological-sort"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
@ -7,4 +7,9 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rspirv = { path = "C:/Users/Jasper/traverse/rspirv/rspirv/"}
|
||||
rspirv = { path = "C:/Users/Jasper/traverse/rspirv/rspirv/"}
|
||||
topological-sort = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1"
|
||||
pretty_assertions = "0.6"
|
||||
|
@ -1,8 +1,10 @@
|
||||
use rspirv::binary::Assemble;
|
||||
mod test;
|
||||
|
||||
use rspirv::binary::Consumer;
|
||||
use rspirv::binary::Disassemble;
|
||||
use rspirv::spirv;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use topological_sort::TopologicalSort;
|
||||
|
||||
fn load(bytes: &[u8]) -> rspirv::dr::Module {
|
||||
let mut loader = rspirv::dr::Loader::new();
|
||||
@ -104,6 +106,10 @@ fn kill_with<F>(insts: &mut Vec<rspirv::dr::Instruction>, f: F)
|
||||
where
|
||||
F: Fn(&rspirv::dr::Instruction) -> bool,
|
||||
{
|
||||
if insts.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut idx = insts.len() - 1;
|
||||
// odd backwards loop so we can swap_remove
|
||||
loop {
|
||||
@ -283,7 +289,7 @@ impl LinkInfo {
|
||||
}
|
||||
|
||||
/// returns the list of matching import / export pairs after validation the list of potential pairs
|
||||
fn ensure_matching_import_export_pairs(&self, defs: &DefAnalyzer) -> &Vec<ImportExportPair> {
|
||||
fn ensure_matching_import_export_pairs(&self) -> &Vec<ImportExportPair> {
|
||||
for pair in &self.potential_pairs {
|
||||
for (import_param, export_param) in pair
|
||||
.import
|
||||
@ -339,7 +345,28 @@ fn import_kill_annotations_and_debug(module: &mut rspirv::dr::Module, info: &Lin
|
||||
}
|
||||
}
|
||||
|
||||
fn kill_linkage_instructions(pairs: &Vec<ImportExportPair>, module: &mut rspirv::dr::Module) {
|
||||
struct Options {
|
||||
/// `true` if we're creating a library
|
||||
lib: bool,
|
||||
|
||||
/// `true` if partial linking is allowed
|
||||
partial: bool,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
lib: false,
|
||||
partial: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn kill_linkage_instructions(
|
||||
pairs: &Vec<ImportExportPair>,
|
||||
module: &mut rspirv::dr::Module,
|
||||
opts: &Options,
|
||||
) {
|
||||
// drop imported functions
|
||||
for pair in pairs.iter() {
|
||||
module
|
||||
@ -372,6 +399,15 @@ fn kill_linkage_instructions(pairs: &Vec<ImportExportPair>, module: &mut rspirv:
|
||||
== rspirv::dr::Operand::Decoration(spirv::Decoration::LinkageAttributes)
|
||||
});
|
||||
|
||||
if !opts.lib {
|
||||
kill_with(&mut module.annotations, |inst| {
|
||||
inst.class.opcode == spirv::Op::Decorate
|
||||
&& inst.operands[1]
|
||||
== rspirv::dr::Operand::Decoration(spirv::Decoration::LinkageAttributes)
|
||||
&& inst.operands[3] == rspirv::dr::Operand::LinkageType(spirv::LinkageType::Export)
|
||||
});
|
||||
}
|
||||
|
||||
// drop OpCapability Linkage
|
||||
kill_with(&mut module.capabilities, |inst| {
|
||||
inst.class.opcode == spirv::Op::Capability
|
||||
@ -414,8 +450,52 @@ fn compact_ids(module: &mut rspirv::dr::Module) -> u32 {
|
||||
remap.len() as u32 + 1
|
||||
}
|
||||
|
||||
fn link(inputs: &mut [&mut rspirv::dr::Module]) -> rspirv::dr::Module {
|
||||
// 1. shift all the ids
|
||||
fn sort_globals(module: &mut rspirv::dr::Module) {
|
||||
let mut ts = TopologicalSort::<u32>::new();
|
||||
|
||||
for t in module.types_global_values.iter() {
|
||||
if let Some(result_type) = t.result_type {
|
||||
if let Some(result_id) = t.result_id {
|
||||
ts.add_dependency(result_type, result_id);
|
||||
|
||||
for op in &t.operands {
|
||||
match op {
|
||||
rspirv::dr::Operand::IdMemorySemantics(w)
|
||||
| rspirv::dr::Operand::IdScope(w)
|
||||
| rspirv::dr::Operand::IdRef(w) => {
|
||||
ts.add_dependency(*w, result_id); // the op defining the IdRef should come before our op / result_id
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let defs = DefAnalyzer::new(&module);
|
||||
|
||||
let mut new_types_global_values = vec![];
|
||||
|
||||
loop {
|
||||
let mut v = ts.pop_all();
|
||||
v.sort();
|
||||
|
||||
for result_id in v {
|
||||
new_types_global_values.push(defs.def(result_id).unwrap().clone());
|
||||
}
|
||||
|
||||
if ts.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(module.types_global_values.len() == new_types_global_values.len());
|
||||
|
||||
module.types_global_values = new_types_global_values;
|
||||
}
|
||||
|
||||
fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> rspirv::dr::Module {
|
||||
// shift all the ids
|
||||
let mut bound = inputs[0].header.as_ref().unwrap().bound - 1;
|
||||
|
||||
for mut module in inputs.iter_mut().skip(1) {
|
||||
@ -423,11 +503,11 @@ fn link(inputs: &mut [&mut rspirv::dr::Module]) -> rspirv::dr::Module {
|
||||
bound += module.header.as_ref().unwrap().bound - 1;
|
||||
}
|
||||
|
||||
println!("{}\n\n", inputs[0].disassemble());
|
||||
println!("{}\n\n", inputs[1].disassemble());
|
||||
for i in inputs.iter() {
|
||||
println!("{}\n\n", i.disassemble());
|
||||
}
|
||||
|
||||
// 2. generate the header (todo)
|
||||
// 3. merge the binaries
|
||||
// merge the binaries
|
||||
let mut loader = rspirv::dr::Loader::new();
|
||||
|
||||
for module in inputs.iter() {
|
||||
@ -438,33 +518,45 @@ fn link(inputs: &mut [&mut rspirv::dr::Module]) -> rspirv::dr::Module {
|
||||
|
||||
let mut output = loader.module();
|
||||
|
||||
// 4. find import / export pairs
|
||||
// find import / export pairs
|
||||
let defs = DefAnalyzer::new(&output);
|
||||
let info = find_import_export_pairs(&output, &defs);
|
||||
|
||||
// 5. ensure import / export pairs have matching types and defintions
|
||||
let matching_pairs = info.ensure_matching_import_export_pairs(&defs);
|
||||
// ensure import / export pairs have matching types and defintions
|
||||
let matching_pairs = info.ensure_matching_import_export_pairs();
|
||||
|
||||
// 6. remove duplicates (https://github.com/KhronosGroup/SPIRV-Tools/blob/e7866de4b1dc2a7e8672867caeb0bdca49f458d3/source/opt/remove_duplicates_pass.cpp)
|
||||
// remove duplicates (https://github.com/KhronosGroup/SPIRV-Tools/blob/e7866de4b1dc2a7e8672867caeb0bdca49f458d3/source/opt/remove_duplicates_pass.cpp)
|
||||
remove_duplicates(&mut output);
|
||||
|
||||
// 7. remove names and decorations of import variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L404
|
||||
// remove names and decorations of import variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L404
|
||||
import_kill_annotations_and_debug(&mut output, &info);
|
||||
|
||||
// 8. rematch import variables and functions to export variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L255
|
||||
// rematch import variables and functions to export variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L255
|
||||
for pair in matching_pairs {
|
||||
replace_all_uses_with(&mut output, pair.import.id, pair.export.id);
|
||||
}
|
||||
|
||||
// 9. remove linkage specific instructions
|
||||
kill_linkage_instructions(&matching_pairs, &mut output);
|
||||
// remove linkage specific instructions
|
||||
kill_linkage_instructions(&matching_pairs, &mut output, &opts);
|
||||
|
||||
// 10. compact the ids https://github.com/KhronosGroup/SPIRV-Tools/blob/e02f178a716b0c3c803ce31b9df4088596537872/source/opt/compact_ids_pass.cpp#L43
|
||||
sort_globals(&mut output);
|
||||
|
||||
// compact the ids https://github.com/KhronosGroup/SPIRV-Tools/blob/e02f178a716b0c3c803ce31b9df4088596537872/source/opt/compact_ids_pass.cpp#L43
|
||||
let bound = compact_ids(&mut output);
|
||||
|
||||
output.header = Some(rspirv::dr::ModuleHeader::new(bound));
|
||||
|
||||
// 11. output the module
|
||||
output.debugs.push(rspirv::dr::Instruction::new(
|
||||
spirv::Op::ModuleProcessed,
|
||||
None,
|
||||
None,
|
||||
vec![rspirv::dr::Operand::LiteralString(
|
||||
"Linked by rspirv-linker".to_string(),
|
||||
)],
|
||||
));
|
||||
|
||||
println!("{}\n\n", output.disassemble());
|
||||
|
||||
// output the module
|
||||
output
|
||||
}
|
||||
|
||||
@ -475,6 +567,11 @@ fn main() {
|
||||
let mut body1 = load(&body1[..]);
|
||||
let mut body2 = load(&body2[..]);
|
||||
|
||||
let output = link(&mut [&mut body1, &mut body2]);
|
||||
let opts = Options {
|
||||
lib: false,
|
||||
partial: false,
|
||||
};
|
||||
|
||||
let output = link(&mut [&mut body1, &mut body2], &opts);
|
||||
println!("{}\n\n", output.disassemble());
|
||||
}
|
||||
|
184
rspirv-linker/src/test.rs
Normal file
184
rspirv-linker/src/test.rs
Normal file
@ -0,0 +1,184 @@
|
||||
use crate::link;
|
||||
|
||||
// https://github.com/colin-kiegel/rust-pretty-assertions/issues/24
|
||||
#[derive(PartialEq, Eq)]
|
||||
#[doc(hidden)]
|
||||
pub struct PrettyString<'a>(pub &'a str);
|
||||
/// Make diff to display string as multi-line string
|
||||
impl<'a> std::fmt::Debug for PrettyString<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.write_str(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_spirv(spirv: &str) -> Vec<u8> {
|
||||
use std::process::Command;
|
||||
use tempfile::tempdir;
|
||||
|
||||
let temp = tempdir().expect("Unable to create temp dir");
|
||||
let input = temp.path().join("code.txt");
|
||||
let output = temp.path().join("code.spv");
|
||||
|
||||
std::fs::write(&input, spirv).unwrap();
|
||||
|
||||
let process = Command::new("spirv-as.exe")
|
||||
.arg(input.to_str().unwrap())
|
||||
.arg("-o")
|
||||
.arg(output.to_str().unwrap())
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", process.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&process.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&process.stderr));
|
||||
|
||||
assert!(process.status.success());
|
||||
|
||||
std::fs::read(&output).unwrap()
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn validate(spirv: &[u32]) {
|
||||
use std::process::Command;
|
||||
use tempfile::tempdir;
|
||||
|
||||
let temp = tempdir().expect("Unable to create temp dir");
|
||||
let input = temp.path().join("code.spv");
|
||||
|
||||
let spirv = unsafe { std::slice::from_raw_parts(spirv.as_ptr() as *const u8, spirv.len() * 4) };
|
||||
|
||||
std::fs::write(&input, spirv).unwrap();
|
||||
|
||||
let process = Command::new("spirv-val.exe")
|
||||
.arg(input.to_str().unwrap())
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
println!("status: {}", process.status);
|
||||
println!("stdout: {}", String::from_utf8_lossy(&process.stdout));
|
||||
println!("stderr: {}", String::from_utf8_lossy(&process.stderr));
|
||||
|
||||
assert!(process.status.success());
|
||||
}
|
||||
|
||||
fn load(bytes: &[u8]) -> rspirv::dr::Module {
|
||||
let mut loader = rspirv::dr::Loader::new();
|
||||
rspirv::binary::parse_bytes(&bytes, &mut loader).unwrap();
|
||||
let module = loader.module();
|
||||
module
|
||||
}
|
||||
|
||||
fn assemble_and_link(binaries: &[&[u8]], opts: &crate::Options) -> rspirv::dr::Module {
|
||||
let mut modules = binaries.iter().cloned().map(load).collect::<Vec<_>>();
|
||||
let mut modules = modules.iter_mut().map(|m| m).collect::<Vec<_>>();
|
||||
|
||||
link(&mut modules, opts)
|
||||
}
|
||||
|
||||
fn without_header_eq(mut result: rspirv::dr::Module, expected: &str) {
|
||||
use rspirv::binary::Disassemble;
|
||||
//use rspirv::binary::Assemble;
|
||||
|
||||
// validate(&result.assemble());
|
||||
|
||||
result.header = None;
|
||||
let result = result.disassemble();
|
||||
|
||||
let expected = expected
|
||||
.split("\n")
|
||||
.map(|l| l.trim())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let result = result
|
||||
.split("\n")
|
||||
.map(|l| l.trim().replace(" ", " ")) // rspirv outputs multiple spaces between operands
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
if result != expected {
|
||||
panic!(
|
||||
"assertion failed: `(left.contains(right))`\
|
||||
\n\
|
||||
\n{}\
|
||||
\n",
|
||||
pretty_assertions::Comparison::new(&PrettyString(&result), &PrettyString(&expected))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
use crate::test::assemble_and_link;
|
||||
use crate::test::assemble_spirv;
|
||||
use crate::test::without_header_eq;
|
||||
use crate::Options;
|
||||
|
||||
#[test]
|
||||
fn standard() {
|
||||
let a = assemble_spirv(
|
||||
r#"OpCapability Linkage
|
||||
OpDecorate %1 LinkageAttributes "foo" Import
|
||||
%2 = OpTypeFloat 32
|
||||
%1 = OpVariable %2 Uniform
|
||||
%3 = OpVariable %2 Input"#,
|
||||
);
|
||||
|
||||
let b = assemble_spirv(
|
||||
r#"OpCapability Linkage
|
||||
OpDecorate %1 LinkageAttributes "foo" Export
|
||||
%2 = OpTypeFloat 32
|
||||
%3 = OpConstant %2 42
|
||||
%1 = OpVariable %2 Uniform %3
|
||||
"#,
|
||||
);
|
||||
|
||||
let result = assemble_and_link(&[&a, &b], &Options::default());
|
||||
let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
|
||||
%1 = OpTypeFloat 32
|
||||
%2 = OpVariable %1 Input
|
||||
%3 = OpConstant %1 42.0
|
||||
%4 = OpVariable %1 Uniform %3"#;
|
||||
|
||||
without_header_eq(result, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_a_lib_extra_exports() {
|
||||
let a = assemble_spirv(
|
||||
r#"OpCapability Linkage
|
||||
OpDecorate %1 LinkageAttributes "foo" Export
|
||||
%2 = OpTypeFloat 32
|
||||
%1 = OpVariable %2 Uniform"#,
|
||||
);
|
||||
|
||||
let result = assemble_and_link(&[&a], &Options::default());
|
||||
let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
|
||||
%1 = OpTypeFloat 32
|
||||
%2 = OpVariable %1 Uniform"#;
|
||||
without_header_eq(result, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lib_extra_exports() {
|
||||
let a = assemble_spirv(
|
||||
r#"OpCapability Linkage
|
||||
OpDecorate %1 LinkageAttributes "foo" Export
|
||||
%2 = OpTypeFloat 32
|
||||
%1 = OpVariable %2 Uniform"#,
|
||||
);
|
||||
|
||||
let result = assemble_and_link(
|
||||
&[&a],
|
||||
&Options {
|
||||
lib: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
let expect = r#"OpModuleProcessed "Linked by rspirv-linker"
|
||||
OpDecorate %1 LinkageAttributes "foo" Export
|
||||
%2 = OpTypeFloat 32
|
||||
%1 = OpVariable %2 Uniform"#;
|
||||
without_header_eq(result, expect);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user