mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 08:14:12 +00:00
Add spirv-std crate
This commit is contained in:
parent
b345d519bf
commit
2a66153840
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -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"
|
||||
|
@ -1,5 +1,6 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"rustc_codegen_spirv",
|
||||
"rspirv-linker",
|
||||
"rustc_codegen_spirv",
|
||||
"spirv-std",
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -8,5 +8,6 @@ edition = "2018"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
spirv-std = { path = "../../spirv-std" }
|
||||
|
||||
[workspace]
|
||||
|
@ -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) -> ! {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
9
spirv-std/Cargo.toml
Normal 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
21
spirv-std/src/lib.rs
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user