Add spirv-std crate

This commit is contained in:
khyperia 2020-09-15 15:17:27 +02:00
parent b345d519bf
commit 2a66153840
9 changed files with 74 additions and 23 deletions

4
Cargo.lock generated
View File

@ -326,6 +326,10 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "spirv-std"
version = "0.1.0"
[[package]]
name = "spirv_headers"
version = "1.5.0"

View File

@ -1,5 +1,6 @@
[workspace]
members = [
"rustc_codegen_spirv",
"rspirv-linker",
"rustc_codegen_spirv",
"spirv-std",
]

View File

@ -12,5 +12,5 @@ pushd build_libcore_test
# Use wasm32 because it's a relatively simple platform - if the x86 libcore is used, there's all sorts of "feature sse2
# not found" and the like, and our spirv backend is never reached. With wasm32, it at least gets reached.
# (We probably want to add our own target eventually)
cargo build -Z build-std=core --target ../spirv-target.json
cargo build -Z build-std=core --target ../spirv-target.json --release
popd

View File

@ -8,5 +8,6 @@ edition = "2018"
crate-type = ["cdylib"]
[dependencies]
spirv-std = { path = "../../spirv-std" }
[workspace]

View File

@ -3,14 +3,12 @@
#![register_attr(spirv)]
use core::panic::PanicInfo;
#[spirv(storage_class = "private")]
pub struct Private<'a, T> {
x: &'a T,
}
use spirv_std::Private;
#[no_mangle]
pub extern "C" fn screaming_bananans(x: Private<u32>) {}
pub extern "C" fn screaming_bananans(mut x: Private<u32>) {
x.store(x.load() + 1);
}
#[panic_handler]
fn panic(_: &PanicInfo) -> ! {

View File

@ -1,7 +1,7 @@
use crate::abi::ConvSpirvType;
use crate::builder::ExtInst;
use crate::builder_spirv::{BuilderCursor, BuilderSpirv, SpirvValue, SpirvValueExt};
use crate::finalizing_passes::{block_ordering_pass, zombie_pass};
use crate::finalizing_passes::{block_ordering_pass, delete_dead_blocks, zombie_pass};
use crate::spirv_type::{SpirvType, SpirvTypePrinter, TypeCache};
use crate::symbols::Symbols;
use rspirv::dr::{Module, Operand};
@ -144,12 +144,14 @@ impl<'tcx> CodegenCx<'tcx> {
pub fn finalize_module(self) -> Module {
let mut result = self.builder.finalize();
zombie_pass(&mut result, &mut self.zombie_values.borrow_mut());
// defs go before fns
result.functions.sort_by_key(|f| !f.blocks.is_empty());
for function in &mut result.functions {
// Should delete dead code blocks before zombie pass, in case a dead block references a zombie id.
delete_dead_blocks(function);
block_ordering_pass(function);
}
zombie_pass(&mut result, &mut self.zombie_values.borrow_mut());
result
}

View File

@ -190,7 +190,30 @@ fn export_zombies(module: &mut Module, zombie: &HashMap<Word, &'static str>) {
}
}
// https://en.wikipedia.org/wiki/Topological_sorting#Kahn's_algorithm
fn label_of(block: &Block) -> Word {
block.label.as_ref().unwrap().result_id.unwrap()
}
pub fn delete_dead_blocks(func: &mut Function) {
if func.blocks.len() < 2 {
return;
}
let entry_label = label_of(&func.blocks[0]);
let mut stack = Vec::new();
let mut visited = HashSet::new();
stack.push(entry_label);
visited.insert(entry_label);
while let Some(label) = stack.pop() {
let block = func.blocks.iter().find(|b| label_of(b) == label).unwrap();
for outgoing in outgoing_edges(block) {
if visited.insert(outgoing) {
stack.push(outgoing);
}
}
}
func.blocks.retain(|b| visited.contains(&label_of(b)))
}
pub fn block_ordering_pass(func: &mut Function) {
if func.blocks.len() < 2 {
return;
@ -198,14 +221,9 @@ pub fn block_ordering_pass(func: &mut Function) {
let mut graph = func
.blocks
.iter()
.map(|block| {
(
block.label.as_ref().unwrap().result_id.unwrap(),
outgoing_edges(block),
)
})
.map(|block| (label_of(block), outgoing_edges(block)))
.collect();
let entry_label = func.blocks[0].label.as_ref().unwrap().result_id.unwrap();
let entry_label = label_of(&func.blocks[0]);
delete_backedges(&mut graph, entry_label);
let mut sorter = topological_sort::TopologicalSort::<Word>::new();
@ -216,16 +234,13 @@ pub fn block_ordering_pass(func: &mut Function) {
}
let mut old_blocks = replace(&mut func.blocks, Vec::new());
while let Some(item) = sorter.pop() {
let index = old_blocks
.iter()
.position(|b| b.label.as_ref().unwrap().result_id.unwrap() == item)
.unwrap();
let index = old_blocks.iter().position(|b| label_of(b) == item).unwrap();
func.blocks.push(old_blocks.remove(index));
}
assert!(sorter.is_empty());
assert!(old_blocks.is_empty());
assert_eq!(
func.blocks[0].label.as_ref().unwrap().result_id.unwrap(),
label_of(&func.blocks[0]),
entry_label,
"Topo sorter did something weird (unreachable blocks?)"
);

9
spirv-std/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "spirv-std"
version = "0.1.0"
authors = ["Embark <opensource@embark-studios.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
repository = "https://github.com/EmbarkStudios/rust-gpu"
[dependencies]

21
spirv-std/src/lib.rs Normal file
View File

@ -0,0 +1,21 @@
#![no_std]
#![feature(register_attr)]
#![register_attr(spirv)]
#[allow(unused_attributes)]
#[spirv(storage_class = "private")]
pub struct Private<'a, T> {
x: &'a mut T,
}
impl<'a, T: Copy> Private<'a, T> {
#[inline]
pub fn load(&self) -> T {
*self.x
}
#[inline]
pub fn store(&mut self, v: T) {
*self.x = v
}
}