mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 22:34:34 +00:00
First try at spirv-builder
This commit is contained in:
parent
6323fc609f
commit
1516d864f3
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
/target
|
target/
|
||||||
|
1037
Cargo.lock
generated
1037
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,11 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"examples/example-runner",
|
||||||
"rspirv-linker",
|
"rspirv-linker",
|
||||||
"rustc_codegen_spirv",
|
"rustc_codegen_spirv",
|
||||||
|
"spirv-builder",
|
||||||
"spirv-std",
|
"spirv-std",
|
||||||
]
|
]
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "1addc7d33ae1460ffa683e2e6311e466ac876c23" }
|
rspirv = { git = "https://github.com/gfx-rs/rspirv.git", rev = "1addc7d33ae1460ffa683e2e6311e466ac876c23" }
|
||||||
|
14
examples/example-runner/Cargo.toml
Normal file
14
examples/example-runner/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "example-runner"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Embark <opensource@embark-studios.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
winit = "0.19.5"
|
||||||
|
image = "0.10.4"
|
||||||
|
ash = "0.31"
|
||||||
|
ash-window = "0.5"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
spirv-builder = { path = "../../spirv-builder" }
|
8
examples/example-runner/build.rs
Normal file
8
examples/example-runner/build.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use spirv_builder::build_spirv;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
// This will set the env var `example-shader.spv` to a spir-v file that can be include!()'d
|
||||||
|
build_spirv("../../rustc_codegen_spirv", "../example-shader")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
1076
examples/example-runner/src/main.rs
Normal file
1076
examples/example-runner/src/main.rs
Normal file
File diff suppressed because it is too large
Load Diff
BIN
examples/example-runner/src/vert.spv
Normal file
BIN
examples/example-runner/src/vert.spv
Normal file
Binary file not shown.
12
examples/example-shader/Cargo.lock
generated
Normal file
12
examples/example-shader/Cargo.lock
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "example-shader"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"spirv-std",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv-std"
|
||||||
|
version = "0.1.0"
|
15
examples/example-shader/Cargo.toml
Normal file
15
examples/example-shader/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "example-shader"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Embark <opensource@embark-studios.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
spirv-std = { path = "../../spirv-std" }
|
||||||
|
|
||||||
|
# This crate is built specially by the example-runner crate, and so therefore
|
||||||
|
# should be excluded from the top-level `cargo build` etc.
|
||||||
|
[workspace]
|
17
examples/example-shader/src/lib.rs
Normal file
17
examples/example-shader/src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![feature(register_attr)]
|
||||||
|
#![register_attr(spirv)]
|
||||||
|
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use spirv_std::{f32x4, Input, Output};
|
||||||
|
|
||||||
|
#[allow(unused_attributes)]
|
||||||
|
#[spirv(entry = "fragment")]
|
||||||
|
pub fn main(input: Input<f32x4>, mut output: Output<f32x4>) {
|
||||||
|
output.store(input.load())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
fn panic(_: &PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
setlocal
|
|
||||||
cargo build
|
|
||||||
|
|
||||||
set RUSTFLAGS=-Zcodegen-backend=%cd%/../target/debug/rustc_codegen_spirv.dll
|
|
||||||
|
|
||||||
pushd build_libcore_test
|
|
||||||
set SPIRV_VAL=1
|
|
||||||
cargo build -Z build-std=core --target spirv-unknown-unknown --release
|
|
||||||
popd
|
|
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# exit on cmd failure
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# build rustc_codegen_spirv
|
|
||||||
cargo build
|
|
||||||
|
|
||||||
export RUSTFLAGS="-Zcodegen-backend=$PWD/../target/debug/librustc_codegen_spirv.so"
|
|
||||||
|
|
||||||
pushd build_libcore_test
|
|
||||||
SPIRV_VAL=${SPIRV_VAL-1} cargo build -Z build-std=core --target spirv-unknown-unknown --release
|
|
||||||
popd
|
|
@ -1,2 +0,0 @@
|
|||||||
/target/
|
|
||||||
/Cargo.lock
|
|
@ -1,13 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "build_libcore_test"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Ashley Hauck <ashley.hauck@embark-studios.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["dylib"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
spirv-std = { path = "../../spirv-std" }
|
|
||||||
|
|
||||||
[workspace]
|
|
@ -1,28 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![feature(register_attr)]
|
|
||||||
#![register_attr(spirv)]
|
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
#[cfg(not(target_feature = "shader"))]
|
|
||||||
use spirv_std::CrossWorkgroup;
|
|
||||||
#[cfg(target_feature = "shader")]
|
|
||||||
use spirv_std::{f32x4, Input, Output};
|
|
||||||
|
|
||||||
#[cfg(target_feature = "shader")]
|
|
||||||
#[allow(unused_attributes)]
|
|
||||||
#[spirv(entry = "fragment")]
|
|
||||||
pub fn main(input: Input<f32x4>, mut output: Output<f32x4>) {
|
|
||||||
output.store(input.load())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_feature = "shader"))]
|
|
||||||
#[allow(unused_attributes)]
|
|
||||||
#[spirv(entry = "kernel")]
|
|
||||||
pub fn add_two_ints(x: CrossWorkgroup<u32>, y: CrossWorkgroup<u32>, mut z: CrossWorkgroup<u32>) {
|
|
||||||
z.store(x.load() + y.load())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[panic_handler]
|
|
||||||
fn panic(_: &PanicInfo) -> ! {
|
|
||||||
loop {}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
/target/
|
|
||||||
/Cargo.lock
|
|
@ -1,10 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "run_libcore_test"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Ashley Hauck <ashley.hauck@embark-studios.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
ocl = { version = "", features = ["opencl_version_2_1"] }
|
|
||||||
|
|
||||||
[workspace]
|
|
@ -1,80 +0,0 @@
|
|||||||
use ocl::enums::ProgramInfo;
|
|
||||||
use ocl::{Buffer, Context, Kernel, Platform, Program, Queue};
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let path = "../build_libcore_test/target/spirv-unknown-unknown/release/build_libcore_test.spv";
|
|
||||||
let mut spirv = Vec::new();
|
|
||||||
File::open(path).unwrap().read_to_end(&mut spirv).unwrap();
|
|
||||||
|
|
||||||
let platform = Platform::list()
|
|
||||||
.into_iter()
|
|
||||||
.find(|p| p.version().unwrap().contains("2."))
|
|
||||||
.unwrap();
|
|
||||||
let context = Context::builder().platform(platform).build().unwrap();
|
|
||||||
let device = context.devices()[0];
|
|
||||||
println!(
|
|
||||||
"Using {} -> {}",
|
|
||||||
platform.name().unwrap(),
|
|
||||||
device.name().unwrap()
|
|
||||||
);
|
|
||||||
let queue = Queue::new(&context, device, None).unwrap();
|
|
||||||
let program = Program::with_il(
|
|
||||||
&spirv,
|
|
||||||
Some(&[device]),
|
|
||||||
&CString::new("").unwrap(),
|
|
||||||
&context,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
println!(
|
|
||||||
"Kernel names: {:?}",
|
|
||||||
program.info(ProgramInfo::KernelNames).unwrap()
|
|
||||||
);
|
|
||||||
let one = Buffer::<u32>::builder()
|
|
||||||
.queue(queue.clone())
|
|
||||||
.len(1)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
let two = Buffer::<u32>::builder()
|
|
||||||
.queue(queue.clone())
|
|
||||||
.len(1)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
let three = Buffer::<u32>::builder()
|
|
||||||
.queue(queue.clone())
|
|
||||||
.len(1)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
one.write(&[1u32] as &[u32]).enq().unwrap();
|
|
||||||
two.write(&[2u32] as &[u32]).enq().unwrap();
|
|
||||||
three.write(&[5u32] as &[u32]).enq().unwrap();
|
|
||||||
|
|
||||||
let kernel = Kernel::builder()
|
|
||||||
.queue(queue.clone())
|
|
||||||
.program(&program)
|
|
||||||
.name("add_two_ints.1")
|
|
||||||
.local_work_size(&[1])
|
|
||||||
.global_work_size(&[1])
|
|
||||||
.arg(&one)
|
|
||||||
.arg(&two)
|
|
||||||
.arg(&three)
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
kernel.enq().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read(buf: Buffer<u32>) {
|
|
||||||
let mut vec = vec![0; 1];
|
|
||||||
buf.read(&mut vec).enq().unwrap();
|
|
||||||
println!("{:?}", vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
read(one);
|
|
||||||
read(two);
|
|
||||||
read(three);
|
|
||||||
}
|
|
@ -273,7 +273,6 @@ impl<'a, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'tcx> {
|
|||||||
let cast_dst = self.pointercast(dst.llval, cast_ptr_ty);
|
let cast_dst = self.pointercast(dst.llval, cast_ptr_ty);
|
||||||
self.store(val, cast_dst, arg_abi.layout.align.abi);
|
self.store(val, cast_dst, arg_abi.layout.align.abi);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Does this need a from_immediate? The LLVM backend doesn't have one here.
|
|
||||||
OperandValue::Immediate(val).store(self, dst);
|
OperandValue::Immediate(val).store(self, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,9 +283,7 @@ impl<'a, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'tcx> {
|
impl<'a, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'tcx> {
|
||||||
fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {
|
fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {}
|
||||||
// TODO: Implement this?
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_param(&self, index: usize) -> Self::Value {
|
fn get_param(&self, index: usize) -> Self::Value {
|
||||||
self.function_parameter_values.borrow()[&self.current_fn.def][index]
|
self.function_parameter_values.borrow()[&self.current_fn.def][index]
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
pub fn build_libcore_test() {
|
|
||||||
{
|
|
||||||
// Unfortunately, as of right now, cargo does not rebuild projects if the .so provided by
|
|
||||||
// codegen-backend has changed. So, force a full rebuild always by deleting the target dir.
|
|
||||||
let target_dir = Path::new("build_libcore_test/target");
|
|
||||||
if target_dir.exists() {
|
|
||||||
std::fs::remove_dir_all(target_dir).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let rustflags = format!(
|
|
||||||
"-Z codegen-backend={}rustc_codegen_spirv{}",
|
|
||||||
std::env::consts::DLL_PREFIX,
|
|
||||||
std::env::consts::DLL_SUFFIX
|
|
||||||
);
|
|
||||||
let build = Command::new("cargo")
|
|
||||||
.args(&[
|
|
||||||
"build",
|
|
||||||
"-Z",
|
|
||||||
"build-std=core",
|
|
||||||
"--target",
|
|
||||||
"spirv-unknown-unknown",
|
|
||||||
"--release",
|
|
||||||
])
|
|
||||||
.current_dir(Path::new("build_libcore_test").canonicalize().unwrap())
|
|
||||||
.env("RUSTFLAGS", rustflags)
|
|
||||||
.env("SPIRV_VAL", "1")
|
|
||||||
.status()
|
|
||||||
.expect("failed to execute cargo build");
|
|
||||||
if !build.success() {
|
|
||||||
panic!("build_libcore_test compilation failed with code {}", build);
|
|
||||||
}
|
|
||||||
}
|
|
11
spirv-builder/Cargo.toml
Normal file
11
spirv-builder/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "spirv-builder"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["khyperia <github@khyperia.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "", features = ["derive"] }
|
||||||
|
serde_json = ""
|
103
spirv-builder/src/lib.rs
Normal file
103
spirv-builder/src/lib.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::{Command, Output};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SpirvBuilderError {
|
||||||
|
BuildFailed(Output),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SpirvBuilderError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
SpirvBuilderError::BuildFailed(output) => write!(
|
||||||
|
f,
|
||||||
|
"{}\nstdout:\n{}\nstderr:\n{}",
|
||||||
|
output.status,
|
||||||
|
String::from_utf8_lossy(&output.stdout),
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for SpirvBuilderError {}
|
||||||
|
|
||||||
|
pub fn build_spirv(
|
||||||
|
path_to_rustc_codegen_spirv: impl AsRef<Path>,
|
||||||
|
path_to_crate: impl AsRef<Path>,
|
||||||
|
) -> Result<(), SpirvBuilderError> {
|
||||||
|
let path_to_built_codegen = build_rustc_codegen_spirv(path_to_rustc_codegen_spirv.as_ref())?;
|
||||||
|
let spirv_module = invoke_rustc(path_to_built_codegen, path_to_crate.as_ref())?;
|
||||||
|
let spirv_path: &Path = spirv_module.as_ref();
|
||||||
|
let env_var = spirv_path.file_name().unwrap().to_str().unwrap();
|
||||||
|
println!("cargo:rustc-env={}={}", env_var, spirv_module);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct RustcOutput {
|
||||||
|
reason: String,
|
||||||
|
filenames: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
fn get_last_artifact(out: &str) -> String {
|
||||||
|
let out = serde_json::Deserializer::from_str(out).into_iter::<RustcOutput>();
|
||||||
|
let last = out
|
||||||
|
.map(|line| line.unwrap())
|
||||||
|
.filter(|line| line.reason == "compiler-artifact")
|
||||||
|
.last()
|
||||||
|
.expect("Did not find output file in rustc output");
|
||||||
|
let mut filenames = last.filenames.unwrap();
|
||||||
|
println!("{:?}", filenames);
|
||||||
|
assert_eq!(filenames.len(), 1);
|
||||||
|
filenames.pop().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_rustc_codegen_spirv(path_to_codegen: &Path) -> Result<String, SpirvBuilderError> {
|
||||||
|
let build = Command::new("cargo")
|
||||||
|
.args(&[
|
||||||
|
"build",
|
||||||
|
"--message-format=json-render-diagnostics",
|
||||||
|
"--release",
|
||||||
|
])
|
||||||
|
.current_dir(path_to_codegen.canonicalize().unwrap())
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute cargo build");
|
||||||
|
if build.status.success() {
|
||||||
|
Ok(get_last_artifact(&String::from_utf8(build.stdout).unwrap()))
|
||||||
|
} else {
|
||||||
|
Err(SpirvBuilderError::BuildFailed(build))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invoke_rustc(
|
||||||
|
path_to_built_codegen: String,
|
||||||
|
path_to_crate: &Path,
|
||||||
|
) -> Result<String, SpirvBuilderError> {
|
||||||
|
let rustflags = format!(
|
||||||
|
"-Z codegen-backend={} -C target-feature=+shader",
|
||||||
|
path_to_built_codegen
|
||||||
|
);
|
||||||
|
let build = Command::new("cargo")
|
||||||
|
.args(&[
|
||||||
|
"build",
|
||||||
|
"--message-format=json-render-diagnostics",
|
||||||
|
"-Z",
|
||||||
|
"build-std=core",
|
||||||
|
"--target",
|
||||||
|
"spirv-unknown-unknown",
|
||||||
|
"--release",
|
||||||
|
])
|
||||||
|
.current_dir(path_to_crate.canonicalize().unwrap())
|
||||||
|
.env("RUSTFLAGS", rustflags)
|
||||||
|
.env("SPIRV_VAL", "1")
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute cargo build");
|
||||||
|
if build.status.success() {
|
||||||
|
Ok(get_last_artifact(&String::from_utf8(build.stdout).unwrap()))
|
||||||
|
} else {
|
||||||
|
Err(SpirvBuilderError::BuildFailed(build))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user