Skip to content

Commit

Permalink
feat: slab tutorial examples (#60)
Browse files Browse the repository at this point in the history
* feat: slab tutorial examples

* remove example-debugging from workspace

* github workflow ensure shaders are checked in

* skip testing for now
  • Loading branch information
schell authored Dec 1, 2023
1 parent 6c052fc commit fb63d72
Show file tree
Hide file tree
Showing 40 changed files with 2,191 additions and 259 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ on: [push]
name: push

jobs:
renderling-build:
renderling-build-shaders:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- run: cd shaders && cargo run --release && cd .. && cargo build
- run: |
# ensure the shader binaries were properly checked in
rm -rf crates/renderling/src/linkage/*.spv
cd shaders && cargo run --release && cd ..
git diff --exit-code --no-ext-diff crates/renderling/src/linkage
#renderling-test:
# runs-on: [ubuntu-latest, gpu]
Expand Down
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ resolver = "2"

[workspace.dependencies]
bytemuck = { version = "1.13.0", features = ["derive"] }
futures-lite = "1.13"
gltf = { git = 'https://github.com/gltf-rs/gltf.git', features = ["KHR_lights_punctual", "KHR_materials_unlit", "KHR_materials_emissive_strength", "extras"] }
image = "^0.24"
log = "^0.4"
glam = "^0.24"
winit = { version = "^0.27" }
wgpu = { version = "^0.17" }
image = "0.24"
log = "0.4"
glam = "0.24.2"
winit = { version = "0.27" }
wgpu = { version = "0.17" }
2 changes: 2 additions & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Just pro-cons on tech choices and little things I don't want to forget whil impl
* it's Rust
- using cargo and Rust module system
- expressions!
- type checking!
- editor tooling!

## cons / limititions

Expand Down
2 changes: 1 addition & 1 deletion crates/example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ renderling-gpui = { path = "../renderling-gpui" }
anyhow = "^1.0"
clap = { version = "^4.3", features = ["derive"] }
env_logger = "0.10.0"
futures-lite = "^1.13"
futures-lite = {workspace=true}
icosahedron = "^0.1"
instant = "^0.1"
loading-bytes = { path = "../loading-bytes" }
Expand Down
4 changes: 2 additions & 2 deletions crates/renderling-shader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ default = []
[dependencies]
bytemuck = { workspace = true }
renderling-derive = { version = "0.1.0", path = "../renderling-derive" }
spirv-std = "^0.9"
spirv-std = "0.9"

[target.'cfg(not(target_arch = "spirv"))'.dependencies]
glam = { workspace = true, features = ["bytemuck"] }
Expand All @@ -21,7 +21,7 @@ glam = { workspace = true, features = ["bytemuck"] }
glam = { workspace = true, features = ["debug-glam-assert", "bytemuck"] }

[target.'cfg(target_arch = "spirv")'.dependencies]
glam = { version = "^0.24", default-features = false, features = ["libm", "bytemuck"] }
glam = { version = "0.24.2", default-features = false, features = ["libm", "bytemuck"] }

[dev-dependencies]
image = { workspace = true }
Expand Down
19 changes: 4 additions & 15 deletions crates/renderling-shader/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl<T: Slabbed> Slabbed for Array<T> {
}

fn read_slab(&mut self, index: usize, slab: &[u32]) -> usize {
if index + Self::slab_size() >= slab.len() {
if index + Self::slab_size() > slab.len() {
index
} else {
let index = self.index.read_slab(index, slab);
Expand All @@ -44,7 +44,7 @@ impl<T: Slabbed> Slabbed for Array<T> {
}

fn write_slab(&self, index: usize, slab: &mut [u32]) -> usize {
if index + Self::slab_size() >= slab.len() {
if index + Self::slab_size() > slab.len() {
index
} else {
let index = self.index.write_slab(index, slab);
Expand Down Expand Up @@ -72,6 +72,7 @@ impl<T: Slabbed> Array<T> {
_phantom: PhantomData,
}
}

pub fn len(&self) -> usize {
self.len as usize
}
Expand All @@ -88,19 +89,7 @@ impl<T: Slabbed> Array<T> {
if index >= self.len() {
Id::NONE
} else {
Id::new(self.index + index as u32)
Id::new(self.index + (T::slab_size() * index) as u32)
}
}
}

impl<T: Slabbed> Array<T> {
fn slab_size() -> usize {
2
}

pub fn read(&self, item: &mut T, item_index: usize, slab: &[u32]) {
let size = T::slab_size();
let start = self.index as usize + size * item_index;
let _ = item.read_slab(start, slab);
}
}
15 changes: 10 additions & 5 deletions crates/renderling-shader/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ impl<T> Default for Id<T> {
}
}

#[cfg(not(target_arch = "spirv"))]
impl<T> std::fmt::Debug for Id<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple(&format!("Id<{}>", std::any::type_name::<T>()))
.field(&self.0)
impl<T> core::fmt::Debug for Id<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Id")
.field("type", &core::any::type_name::<T>())
.field("index", &self.0)
.finish()
}
}
Expand Down Expand Up @@ -122,6 +122,11 @@ impl<T> Id<T> {
self.0 as usize
}

/// The raw u32 value of this id.
pub fn inner(&self) -> u32 {
self.0
}

pub fn is_none(&self) -> bool {
*self == Id::NONE
}
Expand Down
13 changes: 5 additions & 8 deletions crates/renderling-shader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

use core::ops::Mul;

use glam::{Vec4Swizzles, Vec3, Quat};
use spirv_std::num_traits::Zero;
use glam::{Quat, Vec3, Vec4Swizzles};
#[cfg(target_arch = "spirv")]
use spirv_std::num_traits::Float;
use spirv_std::num_traits::Zero;

pub mod array;
pub mod bits;
Expand All @@ -16,10 +16,11 @@ pub mod debug;
pub mod id;
pub mod math;
pub mod pbr;
pub mod stage;
pub mod skybox;
pub mod slab;
pub mod stage;
pub mod tonemapping;
pub mod tutorial;
pub mod ui;

/// Additional methods for vector types.
Expand Down Expand Up @@ -138,11 +139,7 @@ impl IsMatrix for glam::Mat4 {
return srt_id();
}

let det_sign = if det >= 0.0 {
1.0
} else {
-1.0
};
let det_sign = if det >= 0.0 { 1.0 } else { -1.0 };

let scale = glam::Vec3::new(
self.x_axis.length() * det_sign,
Expand Down
116 changes: 108 additions & 8 deletions crates/renderling-shader/src/slab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,6 @@ impl<T: Slabbed, const N: usize> Slabbed for [T; N] {

impl Slabbed for glam::Mat4 {
fn read_slab(&mut self, index: usize, slab: &[u32]) -> usize {
if slab.len() < index + 16 {
return index;
}
let Self {
x_axis,
y_axis,
Expand Down Expand Up @@ -218,11 +215,10 @@ impl Slabbed for glam::Vec4 {
if slab.len() < index + 4 {
return index;
}
let Self { x, y, z, w } = self;
let index = x.read_slab(index, slab);
let index = y.read_slab(index, slab);
let index = z.read_slab(index, slab);
w.read_slab(index, slab)
let index = self.x.read_slab(index, slab);
let index = self.y.read_slab(index, slab);
let index = self.z.read_slab(index, slab);
self.w.read_slab(index, slab)
}

fn write_slab(&self, index: usize, slab: &mut [u32]) -> usize {
Expand Down Expand Up @@ -357,9 +353,27 @@ impl<T: core::any::Any> Slabbed for PhantomData<T> {
}

pub trait Slab {
/// Return the number of u32 elements in the slab.
fn len(&self) -> usize;

/// Returns whether the slab may contain the value with the given id.
fn contains<T: Slabbed>(&self, id: Id<T>) -> bool {
id.index() + T::slab_size() <= self.len()
}

/// Read the type from the slab using the Id as the index.
fn read<T: Slabbed + Default>(&self, id: Id<T>) -> T;

#[cfg(not(target_arch = "spirv"))]
fn read_vec<T: Slabbed + Default>(&self, array: crate::array::Array<T>) -> Vec<T> {
let mut vec = Vec::with_capacity(array.len());
for i in 0..array.len() {
let id = array.at(i);
vec.push(self.read(id));
}
vec
}

/// Write the type into the slab at the index.
///
/// Return the next index, or the same index if writing would overlap the slab.
Expand All @@ -372,6 +386,10 @@ pub trait Slab {
}

impl Slab for [u32] {
fn len(&self) -> usize {
self.len()
}

fn read<T: Slabbed + Default>(&self, id: Id<T>) -> T {
let mut t = T::default();
let _ = t.read_slab(id.index(), self);
Expand All @@ -391,8 +409,31 @@ impl Slab for [u32] {
}
}

#[cfg(not(target_arch = "spirv"))]
impl Slab for Vec<u32> {
fn len(&self) -> usize {
self.len()
}

fn read<T: Slabbed + Default>(&self, id: Id<T>) -> T {
self.as_slice().read(id)
}

fn write<T: Slabbed + Default>(&mut self, t: &T, index: usize) -> usize {
self.as_mut_slice().write(t, index)
}

fn write_slice<T: Slabbed + Default>(&mut self, t: &[T], index: usize) -> usize {
self.as_mut_slice().write_slice(t, index)
}
}

#[cfg(test)]
mod test {
use glam::Vec4;

use crate::{array::Array, stage::Vertex};

use super::*;

#[test]
Expand All @@ -402,5 +443,64 @@ mod test {
slab.write(&666, 1);
let t = slab.read(Id::<[u32; 2]>::new(0));
assert_eq!([42, 666], t);
let t: Vec<u32> = slab.read_vec(Array::new(0, 2));
assert_eq!([42, 666], t[..]);
slab.write_slice(&[1, 2, 3, 4], 2);
let t: Vec<u32> = slab.read_vec(Array::new(2, 4));
assert_eq!([1, 2, 3, 4], t[..]);
slab.write_slice(&[[1.0, 2.0, 3.0, 4.0], [5.5, 6.5, 7.5, 8.5]], 0);

let arr = Array::<[f32; 4]>::new(0, 2);
assert_eq!(Id::new(0), arr.at(0));
assert_eq!(Id::new(4), arr.at(1));
assert_eq!([1.0, 2.0, 3.0, 4.0], slab.read(arr.at(0)));
assert_eq!([5.5, 6.5, 7.5, 8.5], slab.read(arr.at(1)));

let geometry = vec![
Vertex {
position: Vec4::new(0.5, -0.5, 0.0, 1.0),
color: Vec4::new(1.0, 0.0, 0.0, 1.0),
..Default::default()
},
Vertex {
position: Vec4::new(0.0, 0.5, 0.0, 1.0),
color: Vec4::new(0.0, 1.0, 0.0, 1.0),
..Default::default()
},
Vertex {
position: Vec4::new(-0.5, -0.5, 0.0, 1.0),
color: Vec4::new(0.0, 0.0, 1.0, 1.0),
..Default::default()
},
Vertex {
position: Vec4::new(-1.0, 1.0, 0.0, 1.0),
color: Vec4::new(1.0, 0.0, 0.0, 1.0),
..Default::default()
},
Vertex {
position: Vec4::new(-1.0, 0.0, 0.0, 1.0),
color: Vec4::new(0.0, 1.0, 0.0, 1.0),
..Default::default()
},
Vertex {
position: Vec4::new(0.0, 1.0, 0.0, 1.0),
color: Vec4::new(0.0, 0.0, 1.0, 1.0),
..Default::default()
},
];
let geometry_slab_size = Vertex::slab_size() * geometry.len();
let mut slab = vec![0u32; geometry_slab_size + Array::<Vertex>::slab_size()];
let index = 0usize;
let vertices = Array::<Vertex>::new(index as u32, geometry.len() as u32);
let index = slab.write_slice(&geometry, index);
assert_eq!(geometry_slab_size, index);
let vertices_id = Id::<Array<Vertex>>::from(index);
let index = slab.write(&vertices, index);
assert_eq!(geometry_slab_size + Array::<Vertex>::slab_size(), index);
assert_eq!(Vertex::slab_size() * 6, vertices_id.index());
assert!(slab.contains(vertices_id),);

let array = slab.read(vertices_id);
assert_eq!(vertices, array);
}
}
Loading

0 comments on commit fb63d72

Please sign in to comment.