split the spirv builder out of the runtime spirv executable
this means that we unconditionally build the spirv runner, and hence it requires that the user setup the proper rustc toolchain, etc. may want to hide this behind a feature flag.
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -328,6 +328,7 @@ dependencies = [
|
||||
"spirv-std",
|
||||
"spirv-std-macros",
|
||||
"spirv_backend_lib",
|
||||
"spirv_backend_runner",
|
||||
"structopt",
|
||||
"threadpool",
|
||||
"typetag",
|
||||
@@ -2037,6 +2038,10 @@ dependencies = [
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv_backend_runner"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
@@ -51,6 +51,7 @@ spirv-builder = { git = "https://github.com/EmbarkStudios/rust-gpu", features =
|
||||
spirv-std = { git = "https://github.com/EmbarkStudios/rust-gpu" }
|
||||
spirv-std-macros = { git = "https://github.com/EmbarkStudios/rust-gpu" }
|
||||
spirv_backend_lib = { path = "src/sim/spirv/spirv_backend_lib" }
|
||||
spirv_backend_runner = { path = "src/sim/spirv/spirv_backend_runner" }
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -1,15 +1,13 @@
|
||||
use futures::FutureExt as _;
|
||||
use log::trace;
|
||||
use ndarray::{self, Array3};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use spirv_builder::{Capability, MetadataPrintout, SpirvBuilder};
|
||||
use std::borrow::Cow;
|
||||
use std::num::NonZeroU64;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use wgpu;
|
||||
use wgpu::util::DeviceExt as _;
|
||||
use log::{info, warn};
|
||||
use log::{info, trace, warn};
|
||||
|
||||
use crate::geom::{Coord, Index, Meters, Vec3};
|
||||
use crate::real::Real as _;
|
||||
@@ -51,6 +49,7 @@ impl WgpuData {
|
||||
pub fn new<M: IntoFfi>(volume: u64) -> Self
|
||||
where M::Ffi: 'static
|
||||
{
|
||||
info!("WgpuData::new({})", volume);
|
||||
use std::mem::size_of;
|
||||
let max_elem_size = size_of::<M>().max(size_of::<Vec3<f32>>());
|
||||
let max_buf_size = volume * max_elem_size as u64 + 0x1000;
|
||||
@@ -489,37 +488,9 @@ unsafe fn from_bytes<T>(slice: &[u8]) -> &[T] {
|
||||
std::slice::from_raw_parts(slice.as_ptr() as *const T, new_len)
|
||||
}
|
||||
|
||||
/// Compiles the compute shader to spirv
|
||||
/// Loads the shader
|
||||
fn get_shader() -> wgpu::ShaderModuleDescriptorSpirV<'static> {
|
||||
// based on rust-gpu/examples/runners/wgpu/src/lib.rs:maybe_watch
|
||||
// Hack: spirv_builder builds into a custom directory if running under cargo, to not
|
||||
// deadlock, and the default target directory if not. However, packages like `proc-macro2`
|
||||
// have different configurations when being built here vs. when building
|
||||
// rustc_codegen_spirv normally, so we *want* to build into a separate target directory, to
|
||||
// not have to rebuild half the crate graph every time we run. So, pretend we're running
|
||||
// under cargo by setting these environment variables.
|
||||
// std::env::set_var("OUT_DIR", env!("OUT_DIR"));
|
||||
// std::env::set_var("PROFILE", env!("PROFILE"));
|
||||
// Capabilities documented here: https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Capability
|
||||
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||
let crate_path = [manifest_dir, "src", "sim", "spirv", "spirv_backend"]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<PathBuf>();
|
||||
let builder = SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.1")
|
||||
//let builder = SpirvBuilder::new(crate_path, "spirv-unknown-spv1.3")
|
||||
.print_metadata(MetadataPrintout::None)
|
||||
.capability(Capability::Int8)
|
||||
// .capability(Capability::PhysicalStorageBufferAddresses)
|
||||
// .capability(Capability::Addresses)
|
||||
// .capability(Capability::GenericPointer)
|
||||
;
|
||||
|
||||
let initial_result = builder.build().unwrap();
|
||||
|
||||
let module_path = initial_result.module.unwrap_single();
|
||||
let data = std::fs::read(module_path.clone()).unwrap_or_else(|e| { panic!("module path: {:?}: {:?}", module_path, e) });
|
||||
|
||||
let data = spirv_backend_runner::spirv_module();
|
||||
let spirv = Cow::Owned(wgpu::util::make_spirv_raw(&data).into_owned());
|
||||
|
||||
wgpu::ShaderModuleDescriptorSpirV {
|
||||
@@ -531,14 +502,16 @@ fn get_shader() -> wgpu::ShaderModuleDescriptorSpirV<'static> {
|
||||
async fn open_device(max_buf_size: u64) -> (wgpu::Device, wgpu::Queue) {
|
||||
// based on rust-gpu/examples/runners/wgpu/src/compute.rs:start_internal
|
||||
let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
|
||||
info!("open_device: got instance");
|
||||
let adapter = instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::default(),
|
||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
})
|
||||
.await
|
||||
.expect("Failed to find an appropriate adapter");
|
||||
info!("open_device: got adapter");
|
||||
|
||||
// XXX not all adapters will support non-default limits, and it could
|
||||
// cause perf degradations even on the ones that do. May want to consider
|
||||
@@ -562,6 +535,7 @@ async fn open_device(max_buf_size: u64) -> (wgpu::Device, wgpu::Queue) {
|
||||
)
|
||||
.await
|
||||
.expect("Failed to create device");
|
||||
info!("open_device: got device");
|
||||
(device, queue)
|
||||
}
|
||||
|
||||
|
9
src/sim/spirv/spirv_backend_builder/Cargo.toml
Normal file
9
src/sim/spirv/spirv_backend_builder/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "spirv_backend_builder"
|
||||
version = "0.1.0"
|
||||
authors = ["Colin <colin@uninsane.org>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
spirv-builder = { git = "https://github.com/EmbarkStudios/rust-gpu", features = ["use-compiled-tools"] }
|
30
src/sim/spirv/spirv_backend_builder/src/main.rs
Normal file
30
src/sim/spirv/spirv_backend_builder/src/main.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use spirv_builder::{Capability, MetadataPrintout, SpirvBuilder};
|
||||
use log::info;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// based on EmbarkStudios/rust-gpu/examples/runners/wgpu/src/lib.rs:maybe_watch
|
||||
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
||||
let crate_path = [manifest_dir, "../", "spirv_backend"]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<PathBuf>();
|
||||
info!("get_shader: constructing builder");
|
||||
let builder = SpirvBuilder::new(crate_path, "spirv-unknown-vulkan1.1")
|
||||
//let builder = SpirvBuilder::new(crate_path, "spirv-unknown-spv1.3")
|
||||
.print_metadata(MetadataPrintout::None)
|
||||
.capability(Capability::Int8)
|
||||
// .capability(Capability::PhysicalStorageBufferAddresses)
|
||||
// .capability(Capability::Addresses)
|
||||
// .capability(Capability::GenericPointer)
|
||||
;
|
||||
|
||||
info!("get_shader: building");
|
||||
let initial_result = builder.build()?;
|
||||
|
||||
let module_path = initial_result.module.unwrap_single();
|
||||
info!("get_shader: built: {:?}", module_path);
|
||||
Ok(())
|
||||
}
|
8
src/sim/spirv/spirv_backend_runner/Cargo.toml
Normal file
8
src/sim/spirv/spirv_backend_runner/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "spirv_backend_runner"
|
||||
version = "0.1.0"
|
||||
authors = ["Colin <colin@uninsane.org>"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
69
src/sim/spirv/spirv_backend_runner/build.rs
Normal file
69
src/sim/spirv/spirv_backend_runner/build.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// heavily inspired from EmbarkStudios/rust-gpu/examples/runners/wgpu/build.rs
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS");
|
||||
println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH");
|
||||
// While OUT_DIR is set for both build.rs and compiling the crate, PROFILE is only set in
|
||||
// build.rs. So, export it to crate compilation as well.
|
||||
let profile = env::var("PROFILE").unwrap();
|
||||
println!("cargo:rustc-env=PROFILE={}", profile);
|
||||
let mut dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
// recover the directory from which this was invoked
|
||||
assert!(
|
||||
dir.ends_with("out")
|
||||
&& dir.pop()
|
||||
&& dir.pop()
|
||||
&& dir.ends_with("build")
|
||||
&& dir.pop()
|
||||
&& dir.ends_with(profile)
|
||||
&& dir.pop()
|
||||
);
|
||||
|
||||
// recover the toplevel directory
|
||||
assert!(
|
||||
dir.ends_with("target")
|
||||
&& dir.pop()
|
||||
);
|
||||
if dir.ends_with("spirv_backend_runner") {
|
||||
// being run from this dir
|
||||
assert!(
|
||||
dir.pop()
|
||||
&& dir.ends_with("spirv")
|
||||
&& dir.pop()
|
||||
&& dir.ends_with("sim")
|
||||
&& dir.pop()
|
||||
&& dir.ends_with("src")
|
||||
&& dir.pop()
|
||||
);
|
||||
} // else already at the top-level dir
|
||||
|
||||
let target_dir = dir.join("target/spirv_backend_builder");
|
||||
let manifest_path = dir.join("src/sim/spirv/spirv_backend_builder/Cargo.toml");
|
||||
println!("target_dir: {:?}", target_dir);
|
||||
println!("manifest_path: {:?}", manifest_path);
|
||||
|
||||
let status = std::process::Command::new("cargo")
|
||||
.args([
|
||||
"run",
|
||||
"--release",
|
||||
"--manifest-path",
|
||||
])
|
||||
.arg(manifest_path)
|
||||
.arg("--target-dir")
|
||||
.arg(target_dir)
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
if let Some(code) = status.code() {
|
||||
std::process::exit(code);
|
||||
} else {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
8
src/sim/spirv/spirv_backend_runner/src/lib.rs
Normal file
8
src/sim/spirv/spirv_backend_runner/src/lib.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
/// returns the compiled spirv module
|
||||
/// for use with e.g. `wgpu::util::make_spirv_raw`.
|
||||
pub fn spirv_module() -> &'static [u8] {
|
||||
// we specifically include the bytes into this binary, for ease of packaging (v.s. attempting
|
||||
// to locate the compiled result at runtime).
|
||||
include_bytes!("../../../../../target/spirv-builder/spirv-unknown-vulkan1.1/release/deps/spirv_backend.spv.dir/module")
|
||||
}
|
||||
|
Reference in New Issue
Block a user