Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put commands in their own files and some stricter lints #25

Merged
merged 4 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/push.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: push

on:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised my editor is leaving this whitespace!

on:
push:
branches:
branches:
- main
pull_request:

Expand All @@ -13,18 +13,18 @@ env:
jobs:
install-and-build-shaders:
strategy:
matrix:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
defaults:
run:
run:
shell: bash
env:
env:
RUST_LOG: debug
steps:
- uses: actions/checkout@v2
- uses: moonrepo/setup-rust@v1
- run: rustup default stable
- run: rustup default stable
- run: rustup update
- run: cargo test
- run: cargo install --path crates/cargo-gpu
Expand Down
31 changes: 30 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
members = [
"crates/cargo-gpu",
"crates/cargo-gpu",
"crates/shader-crate-template"
]

Expand All @@ -21,3 +21,32 @@ relative-path = "1.9.3"
serde = { version = "1.0.214", features = ["derive"] }
serde_json = "1.0.132"
toml = "0.8.19"

[workspace.lints.rust]
missing_docs = "warn"

[workspace.lints.clippy]
all = { level = "warn", priority = 0 }
pedantic = { level = "warn", priority = 0 }
nursery = { level = "warn", priority = 0 }
cargo = { level = "warn", priority = 0 }
restriction = { level = "warn", priority = 0 }
blanket_clippy_restriction_lints = { level = "allow", priority = 1 }

arithmetic_side_effects = { level = "allow", priority = 1 }
absolute_paths = { level = "allow", priority = 1 }
cargo_common_metadata = { level = "allow", priority = 1 }
implicit_return = { level = "allow", priority = 1 }
single_call_fn = { level = "allow", priority = 1 }
question_mark_used = { level = "allow", priority = 1 }
multiple_crate_versions = { level = "allow", priority = 1 }
pub_with_shorthand = { level = "allow", priority = 1 }
partial_pub_fields = { level = "allow", priority = 1 }
pattern_type_mismatch = { level = "allow", priority = 1 }
print_stdout = { level = "allow", priority = 1 }
std_instead_of_alloc = { level = "allow", priority = 1 }

# TODO: Try to not depend on these lints
unwrap_used = { level = "allow", priority = 1 }
panic = { level = "allow", priority = 1 }

6 changes: 5 additions & 1 deletion crates/cargo-gpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ name = "cargo-gpu"
version = "0.1.0"
edition = "2021"
description = "Generates shader .spv files from rust-gpu shader crates"
repository = "https://github.com/Rust-GPU/cargo-gpu"
readme = "../../README.md"

keywords = ["gpu", "compiler"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand Down Expand Up @@ -33,3 +34,6 @@ codegen-units = 256
opt-level = 3
incremental = true
codegen-units = 256

[lints]
workspace = true
142 changes: 142 additions & 0 deletions crates/cargo-gpu/src/builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//! `cargo gpu build`, analogous to `cargo build`

use std::io::Write as _;

use clap::Parser;
use spirv_builder_cli::{Linkage, ShaderModule};

use crate::{install::Install, target_spec_dir};

/// `cargo build` subcommands
#[derive(Parser, Debug)]
pub struct Build {
/// Install the `rust-gpu` compiler and components
#[clap(flatten)]
install: Install,

/// Directory containing the shader crate to compile.
#[clap(long, default_value = "./")]
pub shader_crate: std::path::PathBuf,

/// Shader target.
#[clap(long, default_value = "spirv-unknown-vulkan1.2")]
shader_target: String,

/// Set cargo default-features.
#[clap(long)]
no_default_features: bool,

/// Set cargo features.
#[clap(long)]
features: Vec<String>,

/// Path to the output directory for the compiled shaders.
#[clap(long, short, default_value = "./")]
pub output_dir: std::path::PathBuf,
}

impl Build {
/// Entrypoint
pub fn run(&mut self) {
let (dylib_path, spirv_builder_cli_path) = self.install.run();

// Ensure the shader output dir exists
log::debug!("ensuring output-dir '{}' exists", self.output_dir.display());
std::fs::create_dir_all(&self.output_dir).unwrap();
self.output_dir = self.output_dir.canonicalize().unwrap();

// Ensure the shader crate exists
self.shader_crate = self.shader_crate.canonicalize().unwrap();
assert!(
self.shader_crate.exists(),
"shader crate '{}' does not exist. (Current dir is '{}')",
self.shader_crate.display(),
std::env::current_dir().unwrap().display()
);

let spirv_builder_args = spirv_builder_cli::Args {
dylib_path,
shader_crate: self.shader_crate.clone(),
shader_target: self.shader_target.clone(),
path_to_target_spec: target_spec_dir().join(format!("{}.json", self.shader_target)),
no_default_features: self.no_default_features,
features: self.features.clone(),
output_dir: self.output_dir.clone(),
};

// UNWRAP: safe because we know this always serializes
let arg = serde_json::to_string_pretty(&spirv_builder_args).unwrap();
log::info!("using spirv-builder-cli arg: {arg}");

// Call spirv-builder-cli to compile the shaders.
let output = std::process::Command::new(spirv_builder_cli_path)
.arg(arg)
.stdout(std::process::Stdio::inherit())
.stderr(std::process::Stdio::inherit())
.output()
.unwrap();
assert!(output.status.success(), "build failed");

let spirv_manifest = self.output_dir.join("spirv-manifest.json");
if spirv_manifest.is_file() {
log::debug!(
"successfully built shaders, raw manifest is at '{}'",
spirv_manifest.display()
);
} else {
log::error!("missing raw manifest '{}'", spirv_manifest.display());
panic!("missing raw manifest");
}

let shaders: Vec<ShaderModule> =
serde_json::from_reader(std::fs::File::open(&spirv_manifest).unwrap()).unwrap();

let mut linkage: Vec<_> = shaders
.into_iter()
.map(
|ShaderModule {
entry,
path: filepath,
}| {
use relative_path::PathExt as _;
let path = self.output_dir.join(filepath.file_name().unwrap());
std::fs::copy(&filepath, &path).unwrap();
let path_relative_to_shader_crate =
path.relative_to(&self.shader_crate).unwrap().to_path("");
Linkage::new(entry, path_relative_to_shader_crate)
},
)
.collect();

// Write the shader manifest json file
let manifest_path = self.output_dir.join("manifest.json");
// Sort the contents so the output is deterministic
linkage.sort();
// UNWRAP: safe because we know this always serializes
let json = serde_json::to_string_pretty(&linkage).unwrap();
let mut file = std::fs::File::create(&manifest_path).unwrap_or_else(|error| {
log::error!(
"could not create shader manifest file '{}': {error}",
manifest_path.display(),
);
panic!("{error}")
});
file.write_all(json.as_bytes()).unwrap_or_else(|error| {
log::error!(
"could not write shader manifest file '{}': {error}",
manifest_path.display(),
);
panic!("{error}")
});

log::info!("wrote manifest to '{}'", manifest_path.display());

if spirv_manifest.is_file() {
log::debug!(
"removing spirv-manifest.json file '{}'",
spirv_manifest.display()
);
std::fs::remove_file(spirv_manifest).unwrap();
}
}
}
Loading
Loading