Initial xtask check-in
This commit is contained in:
commit
52110f4e29
4
.cargo/config.toml
Normal file
4
.cargo/config.toml
Normal file
@ -0,0 +1,4 @@
|
||||
[alias]
|
||||
shader-compile = "run --package xtask -- shader-compile"
|
||||
shader-test = "run --package xtask -- shader-test"
|
||||
xtask = "run --package xtask --"
|
13
.devcontainer/devcontainer.json
Normal file
13
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Rust",
|
||||
"image": "mcr.microsoft.com/devcontainers/rust:1-1-bookworm",
|
||||
"runArgs": ["--userns=keep-id"],
|
||||
"containerUser": "vscode",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"shader-slang.slang-language-extension"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/target
|
||||
|
||||
.idea/
|
||||
cmake-build-*
|
48
Cargo.lock
generated
Normal file
48
Cargo.lock
generated
Normal file
@ -0,0 +1,48 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
|
||||
[[package]]
|
||||
name = "xflags"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944"
|
||||
dependencies = [
|
||||
"xflags-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xflags-macros"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
|
||||
|
||||
[[package]]
|
||||
name = "xshell"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d"
|
||||
dependencies = [
|
||||
"xshell-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xshell-macros"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"xflags",
|
||||
"xshell",
|
||||
]
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/xtask"
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0"
|
10
crates/flare/Cargo.toml
Normal file
10
crates/flare/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "flare"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
||||
[build-dependencies]
|
||||
reqwest.workspace = true
|
||||
zip-extract.workspace = true
|
29
crates/flare/build.rs
Normal file
29
crates/flare/build.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use std::env;
|
||||
use std::fs::{File};
|
||||
use std::io::{BufReader, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
pub fn main() {
|
||||
/*
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=../shader");
|
||||
|
||||
let url = "https://github.com/shader-slang/slang/releases/download/v2024.17/slang-2024.17-linux-x86_64.zip";
|
||||
let output_path = PathBuf::from(format!("{}/slang.zip", env::var("OUT_DIR").unwrap()));
|
||||
let output_dir = PathBuf::from(format!("{}/slang", env::var("OUT_DIR").unwrap()));
|
||||
|
||||
let mut response = reqwest::blocking::get(url).expect("Unable to fetch shader compiler");
|
||||
|
||||
let mut response_out = File::create(&output_path).unwrap();
|
||||
response.copy_to(&mut response_out).expect("Unable to copy file");
|
||||
response_out.flush().expect("Unable to flush output file");
|
||||
|
||||
let response_out = File::open(output_path).expect("Unable to create output file");
|
||||
let output_reader = BufReader::new(response_out);
|
||||
zip_extract::extract(output_reader, output_dir.as_path(), true).expect("Unable to extract shader compiler");
|
||||
|
||||
let slangc_path = output_dir.join("bin/slangc");
|
||||
let shader_path= PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("../../shader");
|
||||
*/
|
||||
}
|
14
crates/flare/src/lib.rs
Normal file
14
crates/flare/src/lib.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
10
crates/xtask/Cargo.toml
Normal file
10
crates/xtask/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "xtask"
|
||||
edition.workspace = true
|
||||
version.workspace = true
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
xflags = "0.3"
|
||||
xshell = "0.2"
|
56
crates/xtask/src/flags.rs
Normal file
56
crates/xtask/src/flags.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
xflags::xflags! {
|
||||
src "./src/flags.rs"
|
||||
|
||||
cmd xtask {
|
||||
cmd shader-compile {
|
||||
optional -S, --source source: PathBuf
|
||||
}
|
||||
|
||||
cmd shader-test {
|
||||
optional -S, --source source: PathBuf
|
||||
}
|
||||
}
|
||||
}
|
||||
// generated start
|
||||
// The following code is generated by `xflags` macro.
|
||||
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
|
||||
#[derive(Debug)]
|
||||
pub struct Xtask {
|
||||
pub subcommand: XtaskCmd,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum XtaskCmd {
|
||||
ShaderCompile(ShaderCompile),
|
||||
ShaderTest(ShaderTest),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderCompile {
|
||||
pub source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderTest {
|
||||
pub source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Xtask {
|
||||
#[allow(dead_code)]
|
||||
pub fn from_env_or_exit() -> Self {
|
||||
Self::from_env_or_exit_()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn from_env() -> xflags::Result<Self> {
|
||||
Self::from_env_()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
|
||||
Self::from_vec_(args)
|
||||
}
|
||||
}
|
||||
// generated end
|
21
crates/xtask/src/main.rs
Normal file
21
crates/xtask/src/main.rs
Normal file
@ -0,0 +1,21 @@
|
||||
mod flags;
|
||||
mod shader_compile;
|
||||
mod shader_test;
|
||||
mod slang_build;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use xshell::{Shell};
|
||||
use crate::flags::XtaskCmd;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
|
||||
|
||||
let sh = Shell::new()?;
|
||||
sh.change_dir(project_root);
|
||||
|
||||
let flags = flags::Xtask::from_env_or_exit();
|
||||
match flags.subcommand {
|
||||
XtaskCmd::ShaderCompile(cmd) => cmd.run(&sh),
|
||||
XtaskCmd::ShaderTest(cmd) => cmd.run(&sh),
|
||||
}
|
||||
}
|
19
crates/xtask/src/shader_compile.rs
Normal file
19
crates/xtask/src/shader_compile.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::flags;
|
||||
use crate::slang_build::SlangBuild;
|
||||
use xshell::Shell;
|
||||
|
||||
impl flags::ShaderCompile {
|
||||
pub(crate) fn run(&self, sh: &Shell) -> anyhow::Result<()> {
|
||||
let targets = ["slangc", "slang-glslang"];
|
||||
let build_path = SlangBuild::new(self.source.as_ref()).build_targets(&sh, &targets)?;
|
||||
let slangc_path = format!("{}/Release/bin/slangc", build_path.display());
|
||||
|
||||
sh.create_dir("target/xtask/shader")?;
|
||||
sh.cmd(&slangc_path)
|
||||
.args(["-target", "spirv"])
|
||||
.args(["-o", "target/xtask/shader/hello-world.spv"])
|
||||
.arg("shader/hello-world.slang")
|
||||
.run()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
34
crates/xtask/src/shader_test.rs
Normal file
34
crates/xtask/src/shader_test.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use crate::flags::ShaderTest;
|
||||
use crate::slang_build::SlangBuild;
|
||||
use xshell::Shell;
|
||||
|
||||
impl ShaderTest {
|
||||
pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
|
||||
// Pending resolution of https://github.com/shader-slang/slang/issues/5979
|
||||
/*
|
||||
sh.cmd(format!("{}/Release/bin/slang-test", build_dir.display()))
|
||||
.args(["-category", "compute"])
|
||||
.args(["-test-dir", "shader-tests"])
|
||||
.run()?;
|
||||
Ok(())
|
||||
*/
|
||||
|
||||
let targets = ["slang-test"];
|
||||
let build_dir = SlangBuild::new(self.source.as_ref()).build_targets(&sh, &targets)?;
|
||||
let build_dir = build_dir.to_str().unwrap();
|
||||
|
||||
// slang-test currently relies on a folder named `tests/` in the current directory
|
||||
sh.cmd("cp")
|
||||
.arg("-r")
|
||||
.arg("shader-tests")
|
||||
.arg(format!("{build_dir}/tests"))
|
||||
.run()?;
|
||||
|
||||
let _dir_guard = sh.push_dir(&build_dir);
|
||||
sh.cmd(format!("Release/bin/slang-test"))
|
||||
.args(["-category", "compute"])
|
||||
.run()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
83
crates/xtask/src/slang_build.rs
Normal file
83
crates/xtask/src/slang_build.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use anyhow::Context;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::thread::available_parallelism;
|
||||
use xshell::Shell;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub(crate) struct SlangBuild {
|
||||
source: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl SlangBuild {
|
||||
pub(crate) fn new<P: AsRef<Path>>(source: Option<P>) -> Self {
|
||||
Self {
|
||||
source: source.map(|path| path.as_ref().to_path_buf()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SlangBuild {
|
||||
pub(crate) fn assure_source(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
if self.source.as_ref().is_some_and(|source| source.exists()) {
|
||||
return Ok(self.source.as_ref().unwrap().clone());
|
||||
}
|
||||
|
||||
let clone_dir = PathBuf::from("target/xtask/slang");
|
||||
if clone_dir.exists() {
|
||||
return Ok(clone_dir);
|
||||
}
|
||||
|
||||
let _ = sh
|
||||
.cmd("git")
|
||||
.arg("clone")
|
||||
.args(["--branch", "v2024.17"])
|
||||
.args(["--depth", "1"])
|
||||
.arg("--recurse-submodules")
|
||||
.arg("--shallow-submodules")
|
||||
.arg(format!("-j{}", available_parallelism()?))
|
||||
.arg("https://github.com/shader-slang/slang")
|
||||
.arg(clone_dir.to_str().unwrap())
|
||||
.run()?;
|
||||
Ok(clone_dir)
|
||||
}
|
||||
|
||||
pub(crate) fn assure_build(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
let build_dir = sh.create_dir("target/xtask/slang-build")?;
|
||||
Ok(build_dir)
|
||||
}
|
||||
|
||||
pub(crate) fn configure(self: &Self, sh: &Shell) -> anyhow::Result<PathBuf> {
|
||||
let source_dir = self.assure_source(&sh)?;
|
||||
let build_dir = self.assure_build(&sh)?;
|
||||
|
||||
sh.cmd("cmake")
|
||||
.args(["-S", source_dir.to_str().unwrap()])
|
||||
.args(["-B", build_dir.to_str().unwrap()])
|
||||
.arg("-DCMAKE_BUILD_TYPE=Release")
|
||||
// https://github.com/shader-slang/slang/issues/5832#issuecomment-2533324982
|
||||
.arg("-DCMAKE_SKIP_INSTALL_RULES=ON")
|
||||
.run()
|
||||
.context("slang-build configure")?;
|
||||
|
||||
Ok(PathBuf::from(build_dir))
|
||||
}
|
||||
|
||||
pub(crate) fn build_targets(
|
||||
self: &Self,
|
||||
sh: &Shell,
|
||||
targets: &[&str],
|
||||
) -> anyhow::Result<PathBuf> {
|
||||
let build_dir = self.configure(&sh)?;
|
||||
let cmd = sh
|
||||
.cmd("cmake")
|
||||
.args(["--build", build_dir.to_str().unwrap()])
|
||||
.arg(format!("-j{}", available_parallelism()?));
|
||||
|
||||
targets
|
||||
.iter()
|
||||
.fold(cmd, |cmd, target| cmd.args(["--target", target]))
|
||||
.run()?;
|
||||
|
||||
Ok(build_dir)
|
||||
}
|
||||
}
|
67
shader-tests/enum.slang
Normal file
67
shader-tests/enum.slang
Normal file
@ -0,0 +1,67 @@
|
||||
// enum.slang
|
||||
//TEST(compute):COMPARE_COMPUTE_EX:-slang -compute -shaderobj
|
||||
//TEST(compute, vulkan):COMPARE_COMPUTE_EX:-vk -compute -shaderobj
|
||||
//TEST(compute):COMPARE_COMPUTE_EX:-cpu -compute -shaderobj
|
||||
|
||||
// Confirm that basic `enum` declarations are supported.
|
||||
|
||||
enum Color
|
||||
{
|
||||
Red,
|
||||
Green = (1 << 1),
|
||||
Blue,
|
||||
}
|
||||
|
||||
|
||||
int test(int val)
|
||||
{
|
||||
Color c = Color.Red;
|
||||
|
||||
if(val > 1)
|
||||
{
|
||||
c = Color.Green;
|
||||
}
|
||||
|
||||
if(c == Color.Red)
|
||||
{
|
||||
if((val & 1) != 0)
|
||||
{
|
||||
c = Color.Blue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case Color.Red:
|
||||
val = 1;
|
||||
break;
|
||||
|
||||
case Color.Green:
|
||||
val = 2;
|
||||
break;
|
||||
|
||||
case Color.Blue:
|
||||
val = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
val = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return (val << 4) + int(c);
|
||||
}
|
||||
|
||||
//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer
|
||||
RWStructuredBuffer<int> outputBuffer;
|
||||
|
||||
[numthreads(4, 1, 1)]
|
||||
void computeMain(int3 dispatchThreadID : SV_DispatchThreadID)
|
||||
{
|
||||
int tid = dispatchThreadID.x;
|
||||
|
||||
int val = int(tid);
|
||||
val = test(val);
|
||||
|
||||
outputBuffer[tid] = val;
|
||||
}
|
4
shader-tests/enum.slang.expected.txt
Normal file
4
shader-tests/enum.slang.expected.txt
Normal file
@ -0,0 +1,4 @@
|
||||
10
|
||||
33
|
||||
22
|
||||
22
|
11
shader/hello-world.slang
Normal file
11
shader/hello-world.slang
Normal file
@ -0,0 +1,11 @@
|
||||
StructuredBuffer<float> buffer0;
|
||||
StructuredBuffer<float> buffer1;
|
||||
RWStructuredBuffer<float> result;
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(1,1,1)]
|
||||
void computeMain(uint3 threadId : SV_DispatchThreadID)
|
||||
{
|
||||
uint index = threadId.x;
|
||||
result[index] = buffer0[index] + buffer1[index];
|
||||
}
|
Loading…
Reference in New Issue
Block a user