Stash
This commit is contained in:
1586
Cargo.lock
generated
1586
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -1,11 +1,28 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/flare-kernel",
|
||||
"crates/flare-lib",
|
||||
"crates/flare-shader",
|
||||
"crates/flare-xml"
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.dependencies]
|
||||
bytemuck = { version = "1.21.0", features = ["derive"] }
|
||||
futures-executor = "0.3.31"
|
||||
glam = { version = "0.29.2", features = ["cuda", "bytemuck"] }
|
||||
serde = { version = "1.0.216", features = ["derive"] }
|
||||
serde-xml-rs = "0.6.0"
|
||||
spirv-std = { git = "https://github.com/rust-gpu/rust-gpu", rev = "1d76d59471eef54da481d63cfb9cbf3a5daded6c" }
|
||||
spirv-builder = { git = "https://github.com/rust-gpu/rust-gpu", rev = "1d76d59471eef54da481d63cfb9cbf3a5daded6c" }
|
||||
thiserror = "2.0.8"
|
||||
xml-rs = "0.8.24"
|
||||
wgpu = { version = "23.0.1", features = ["spirv"] }
|
||||
xml-rs = "0.8.24"
|
||||
|
||||
# Compile build-dependencies in release mode with
|
||||
# the same settings as regular dependencies.
|
||||
[profile.release.build-override]
|
||||
opt-level = 3
|
||||
codegen-units = 16
|
||||
[profile.dev.build-override]
|
||||
opt-level = 3
|
||||
|
9
crates/flare-kernel/Cargo.toml
Normal file
9
crates/flare-kernel/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "flare-kernel"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytemuck.workspace = true
|
||||
glam.workspace = true
|
||||
spirv-std.workspace = true
|
17
crates/flare-kernel/src/lib.rs
Normal file
17
crates/flare-kernel/src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![no_std]
|
||||
|
||||
macro_rules! import_glam {
|
||||
() => {
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::glam;
|
||||
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
use glam;
|
||||
};
|
||||
}
|
||||
|
||||
mod transforms;
|
||||
mod variations;
|
||||
|
||||
pub use transforms::*;
|
||||
pub use variations::*;
|
15
crates/flare-kernel/src/transforms.rs
Normal file
15
crates/flare-kernel/src/transforms.rs
Normal file
@ -0,0 +1,15 @@
|
||||
import_glam!();
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct TransformSpec {
|
||||
pub coefs: glam::Affine2,
|
||||
pub post_coefs: glam::Affine2,
|
||||
pub variation_offset: u32,
|
||||
pub variation_count: u32,
|
||||
}
|
||||
|
||||
// UNSAFE: Can't derive these types because Affine2 doesn't implement Pod
|
||||
// Safe because all individual elements are the same size, so byte aligned
|
||||
unsafe impl bytemuck::Zeroable for TransformSpec {}
|
||||
unsafe impl bytemuck::Pod for TransformSpec {}
|
36
crates/flare-kernel/src/variations.rs
Normal file
36
crates/flare-kernel/src/variations.rs
Normal file
@ -0,0 +1,36 @@
|
||||
import_glam!();
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub enum VariationKind {
|
||||
Linear,
|
||||
}
|
||||
|
||||
// UNSAFE: I think this is fine for repr(C) enums?
|
||||
unsafe impl bytemuck::Zeroable for VariationKind {}
|
||||
unsafe impl bytemuck::Pod for VariationKind {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[repr(transparent)]
|
||||
pub struct VariationParams([f32; 8]);
|
||||
|
||||
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct VariationSpec {
|
||||
kind: VariationKind,
|
||||
weight: f32,
|
||||
params: VariationParams,
|
||||
}
|
||||
|
||||
impl VariationSpec {
|
||||
pub fn apply(&self, point: glam::Vec2) -> glam::Vec2 {
|
||||
let point = match self.kind {
|
||||
VariationKind::Linear => apply_linear(&self.params, point),
|
||||
};
|
||||
point * self.weight
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_linear(_params: &VariationParams, point: glam::Vec2) -> glam::Vec2 {
|
||||
point
|
||||
}
|
14
crates/flare-lib/Cargo.toml
Normal file
14
crates/flare-lib/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "flare-lib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytemuck.workspace = true
|
||||
flare-kernel = { path = "../flare-kernel" }
|
||||
futures-executor.workspace = true
|
||||
glam.workspace = true
|
||||
wgpu.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
spirv-builder.workspace = true
|
22
crates/flare-lib/build.rs
Normal file
22
crates/flare-lib/build.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use spirv_builder::{MetadataPrintout, SpirvBuilder};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let gpu_crate_path = Path::new("../flare-shader/");
|
||||
|
||||
// Compile the shader crate with SpirvBuilder.
|
||||
let result = SpirvBuilder::new(gpu_crate_path, "spirv-unknown-vulkan1.2")
|
||||
.print_metadata(MetadataPrintout::Full)
|
||||
.build()?;
|
||||
|
||||
// Copy the SPIR-V to this crate's output directory
|
||||
let shader_path = result.module.unwrap_single();
|
||||
let output_path = PathBuf::from(env::var("OUT_DIR")?).join("shader_binary.spv");
|
||||
|
||||
fs::copy(shader_path, &output_path)?;
|
||||
|
||||
println!("Generated shader binary constant at {:?}", output_path);
|
||||
Ok(())
|
||||
}
|
151
crates/flare-lib/src/lib.rs
Normal file
151
crates/flare-lib/src/lib.rs
Normal file
@ -0,0 +1,151 @@
|
||||
use glam;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use std::default::Default;
|
||||
use wgpu::util::DeviceExt;
|
||||
use flare_kernel::{TransformSpec, VariationSpec};
|
||||
|
||||
async fn create_instance() -> wgpu::Instance {
|
||||
let backends = wgpu::util::backend_bits_from_env().unwrap_or_default();
|
||||
wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||
backends,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_adapter(instance: &wgpu::Instance) -> wgpu::Adapter {
|
||||
instance
|
||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||
force_fallback_adapter: false,
|
||||
compatible_surface: None,
|
||||
})
|
||||
.await
|
||||
.expect("Failed to create adapter")
|
||||
}
|
||||
|
||||
async fn create_device_queue(adapter: &wgpu::Adapter) -> (wgpu::Device, wgpu::Queue) {
|
||||
adapter
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: Some("unit test"),
|
||||
required_features: wgpu::Features::empty(),
|
||||
required_limits: wgpu::Limits::default(),
|
||||
memory_hints: wgpu::MemoryHints::default(),
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.expect("Failed to request device queue")
|
||||
}
|
||||
|
||||
async fn create_shader(device: &wgpu::Device) -> wgpu::ShaderModule {
|
||||
device.create_shader_module(wgpu::include_spirv!(concat!(env!("OUT_DIR"), "/shader_binary.spv")))
|
||||
}
|
||||
|
||||
async fn create_pipeline_layout(device: &wgpu::Device, layout: &wgpu::BindGroupLayout) -> wgpu::PipelineLayout {
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("pipeline"),
|
||||
bind_group_layouts: &[layout],
|
||||
push_constant_ranges: &[],
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_apply_transform_f32_bind_group_layout(device: &wgpu::Device) -> wgpu::BindGroupLayout{
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("apply_transform_f32"),
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Storage {
|
||||
read_only: true,
|
||||
},
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Storage {
|
||||
read_only: true,
|
||||
},
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Storage {
|
||||
read_only: false,
|
||||
},
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_apply_transform_f32_compute_pipeline(device: &wgpu::Device, pipeline_layout: &wgpu::PipelineLayout, shader: &wgpu::ShaderModule) -> wgpu::ComputePipeline {
|
||||
device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
|
||||
label: Some("apply_transform_f32_compute_pipeline"),
|
||||
layout: Some(pipeline_layout),
|
||||
module: shader,
|
||||
entry_point: Some("apply_transform_f32"),
|
||||
compilation_options: Default::default(),
|
||||
cache: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn do_apply_transform_f32(
|
||||
transform: &TransformSpec,
|
||||
variations: &[VariationSpec],
|
||||
point: &glam::Vec2,
|
||||
) -> glam::Vec2 {
|
||||
let instance = create_instance().await;
|
||||
let adapter = create_adapter(&instance).await;
|
||||
let (device, queue) = create_device_queue(&adapter).await;
|
||||
|
||||
let shader = create_shader(&device, ).await;
|
||||
let bind_group_layout = create_apply_transform_f32_bind_group_layout(&device).await;
|
||||
let pipeline_layout = create_pipeline_layout(&device, &bind_group_layout).await;
|
||||
let compute_pipeline = create_apply_transform_f32_compute_pipeline(&device, &pipeline_layout, &shader).await;
|
||||
|
||||
let transform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
contents: bytemuck::cast_slice(&[transform]),
|
||||
});
|
||||
|
||||
let variation_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
|
||||
contents: bytemuck::cast_slice(variations),
|
||||
});
|
||||
|
||||
glam::Vec2::new()
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn apply_linear_transform() {}
|
||||
}
|
11
crates/flare-shader/Cargo.toml
Normal file
11
crates/flare-shader/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "flare-shader"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib", "lib"]
|
||||
|
||||
[dependencies]
|
||||
flare-kernel = { path = "../flare-kernel" }
|
||||
spirv-std.workspace = true
|
21
crates/flare-shader/src/lib.rs
Normal file
21
crates/flare-shader/src/lib.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![no_std]
|
||||
use spirv_std::spirv;
|
||||
use spirv_std::glam::{UVec3, Vec2};
|
||||
use flare_kernel::{TransformSpec, VariationSpec};
|
||||
|
||||
#[spirv(compute(threads(1)))]
|
||||
pub fn apply_transform_f32(
|
||||
#[spirv(global_invocation_id)] _global_id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] transform: &TransformSpec,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] variations: &[VariationSpec],
|
||||
#[spirv(uniform, descriptor_set = 0, binding = 2)] point_in: &Vec2,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] point_out: &mut Vec2,
|
||||
) {
|
||||
let mut point = transform.coefs.transform_point2(*point_in);
|
||||
|
||||
for i in transform.variation_offset as usize..transform.variation_count as usize {
|
||||
point = variations[i].apply(point);
|
||||
}
|
||||
|
||||
*point_out = transform.post_coefs.transform_point2(point);
|
||||
}
|
3
rust-toolchain.toml
Normal file
3
rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2024-11-22"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
Reference in New Issue
Block a user