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