feat(build): compile SPIR-V with rust native code
Some checks failed
Build Zenyx ⚡ / 🧪 Run Cargo Tests (push) Successful in 4m14s
Build Zenyx ⚡ / 🏗️ Build x86_64-apple-darwin (push) Failing after 8m32s
Build Zenyx ⚡ / 🏗️ Build aarch64-apple-darwin (push) Failing after 8m43s
Build Zenyx ⚡ / 🏗️ Build aarch64-unknown-linux-gnu (push) Successful in 9m13s
Build Zenyx ⚡ / 🏗️ Build aarch64-pc-windows-msvc (push) Successful in 9m19s
Build Zenyx ⚡ / 🏗️ Build x86_64-pc-windows-msvc (push) Successful in 6m21s
Build Zenyx ⚡ / 🏗️ Build x86_64-unknown-linux-gnu (push) Successful in 6m22s
Some checks failed
Build Zenyx ⚡ / 🧪 Run Cargo Tests (push) Successful in 4m14s
Build Zenyx ⚡ / 🏗️ Build x86_64-apple-darwin (push) Failing after 8m32s
Build Zenyx ⚡ / 🏗️ Build aarch64-apple-darwin (push) Failing after 8m43s
Build Zenyx ⚡ / 🏗️ Build aarch64-unknown-linux-gnu (push) Successful in 9m13s
Build Zenyx ⚡ / 🏗️ Build aarch64-pc-windows-msvc (push) Successful in 9m19s
Build Zenyx ⚡ / 🏗️ Build x86_64-pc-windows-msvc (push) Successful in 6m21s
Build Zenyx ⚡ / 🏗️ Build x86_64-unknown-linux-gnu (push) Successful in 6m22s
This commit is contained in:
parent
c86be3ca3d
commit
25068a7679
3 changed files with 127 additions and 23 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -384,6 +384,12 @@ dependencies = [
|
|||
"piper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build-print"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a2128d00b7061b82b72844a351e80acd29e05afc60e9261e2ac90dca9ecc2ac"
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.7.7"
|
||||
|
@ -1359,6 +1365,7 @@ dependencies = [
|
|||
"num-traits",
|
||||
"once_cell",
|
||||
"petgraph",
|
||||
"pp-rs",
|
||||
"rustc-hash",
|
||||
"spirv",
|
||||
"strum",
|
||||
|
@ -1944,6 +1951,15 @@ version = "1.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
|
||||
|
||||
[[package]]
|
||||
name = "pp-rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
|
@ -2775,6 +2791,12 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "v_frame"
|
||||
version = "0.3.8"
|
||||
|
@ -3686,9 +3708,11 @@ name = "zenyx"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"build-print",
|
||||
"bytemuck",
|
||||
"cgmath",
|
||||
"image",
|
||||
"naga",
|
||||
"smol",
|
||||
"terminator",
|
||||
"thiserror 2.0.12",
|
||||
|
|
|
@ -58,3 +58,9 @@ allocator-api2 = "0.2.21"
|
|||
|
||||
[target.aarch64-linux-android.dependencies]
|
||||
winit = { version = "0.30.9", features = ["android-native-activity"] }
|
||||
|
||||
[build-dependencies]
|
||||
build-print = "0.1.1"
|
||||
bytemuck = "1.22.0"
|
||||
naga = { version = "25.0.1", features = ["glsl-in", "spv-out"] }
|
||||
thiserror = "2.0.12"
|
||||
|
|
120
build.rs
120
build.rs
|
@ -1,26 +1,100 @@
|
|||
use std::{env, process::Command};
|
||||
use build_print::{info, warn};
|
||||
use naga::{
|
||||
ShaderStage,
|
||||
back::spv::{self, WriterFlags},
|
||||
front::glsl::{self, Options as GlslOptions, ParseErrors},
|
||||
valid::{ValidationError, ValidationFlags, Validator},
|
||||
};
|
||||
use std::{
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
fn main() {
|
||||
println!("cargo::rerun-if-changed=shaders");
|
||||
let outdir = env::var("OUT_DIR").unwrap();
|
||||
let vert = Command::new("glslc")
|
||||
.args(["shaders/shader.vert", "-o", &format!("{outdir}/vert.spv")])
|
||||
.output()
|
||||
.expect("Failed to execute 'glslc'");
|
||||
let frag = Command::new("glslc")
|
||||
.args(["shaders/shader.frag", "-o", &format!("{outdir}/frag.spv")])
|
||||
.output()
|
||||
.expect("Failed to execute 'glslc'");
|
||||
if !vert.status.success() {
|
||||
panic!(
|
||||
"Failed to compile vertex shader: {}",
|
||||
String::from_utf8(vert.stderr).unwrap()
|
||||
)
|
||||
}
|
||||
if !frag.status.success() {
|
||||
panic!(
|
||||
"Failed to compile fragment shader: {}",
|
||||
String::from_utf8(frag.stderr).unwrap()
|
||||
)
|
||||
#[derive(Debug, Error)]
|
||||
pub enum BuildError {
|
||||
#[error("I/O error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("environment variable error: {0}")]
|
||||
EnvVar(#[from] env::VarError),
|
||||
#[error("unsupported shader extension: {0}")]
|
||||
UnsupportedExt(String),
|
||||
#[error("GLSL parse errors in `{0}`:\n{1}")]
|
||||
ParseErrors(String, ParseErrors),
|
||||
#[error("validation errors in `{0}`: {1}")]
|
||||
ValidateErrors(String, ValidationError),
|
||||
#[error("SPIR-V write error for `{0}`: {1}")]
|
||||
Spv(String, spv::Error),
|
||||
}
|
||||
|
||||
impl From<(String, ParseErrors)> for BuildError {
|
||||
fn from((s, e): (String, ParseErrors)) -> Self {
|
||||
BuildError::ParseErrors(s, e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(String, ValidationError)> for BuildError {
|
||||
fn from((s, e): (String, ValidationError)) -> Self {
|
||||
BuildError::ValidateErrors(s, e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(String, spv::Error)> for BuildError {
|
||||
fn from((s, e): (String, spv::Error)) -> Self {
|
||||
BuildError::Spv(s, e)
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_shader(path: &Path, out_dir: &Path) -> Result<(), BuildError> {
|
||||
let ext = path
|
||||
.extension()
|
||||
.and_then(|e| e.to_str())
|
||||
.map(str::to_string)
|
||||
.ok_or_else(|| BuildError::UnsupportedExt(path.display().to_string()))?;
|
||||
let stage = match ext.as_str() {
|
||||
"vert" => ShaderStage::Vertex,
|
||||
"frag" => ShaderStage::Fragment,
|
||||
"comp" => ShaderStage::Compute,
|
||||
_ => return Err(BuildError::UnsupportedExt(ext)),
|
||||
};
|
||||
let src = fs::read_to_string(path)?;
|
||||
|
||||
let module = glsl::Frontend::default()
|
||||
.parse(&GlslOptions::from(stage), &src)
|
||||
.map_err(|e| (ext.clone(), e))?;
|
||||
let info = Validator::new(ValidationFlags::all(), Default::default())
|
||||
.validate(&module)
|
||||
.map_err(|e| (ext.clone(), e.into_inner()))?;
|
||||
let mut writer = spv::Writer::new(&spv::Options {
|
||||
flags: WriterFlags::empty(),
|
||||
..Default::default()
|
||||
})
|
||||
.map_err(|e| (ext.clone(), e))?;
|
||||
let mut spirv = Vec::new();
|
||||
writer
|
||||
.write(&module, &info, None, &None, &mut spirv)
|
||||
.map_err(|e| (ext.clone(), e))?;
|
||||
let out_path = out_dir.join(format!("{}.spv", ext));
|
||||
fs::write(&out_path, bytemuck::cast_slice(&spirv))?;
|
||||
info!("Compiled {} → {}", path.display(), out_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), BuildError> {
|
||||
println!("cargo:rerun-if-changed=shaders");
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR")?);
|
||||
for entry in fs::read_dir("shaders")? {
|
||||
let path = entry?.path();
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = compile_shader(&path, &out_dir) {
|
||||
if matches!(e, BuildError::UnsupportedExt(_)) {
|
||||
warn!("{}", e);
|
||||
continue;
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue