mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-21 14:24:13 +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]
|
||||
members = [
|
||||
"examples/example-runner",
|
||||
"rspirv-linker",
|
||||
"rustc_codegen_spirv",
|
||||
"spirv-builder",
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
[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);
|
||||
self.store(val, cast_dst, arg_abi.layout.align.abi);
|
||||
} else {
|
||||
// TODO: Does this need a from_immediate? The LLVM backend doesn't have one here.
|
||||
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> {
|
||||
fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {
|
||||
// TODO: Implement this?
|
||||
}
|
||||
fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {}
|
||||
|
||||
fn get_param(&self, index: usize) -> Self::Value {
|
||||
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