Skip to content

Commit

Permalink
chore/remove bytemuck from renderling shader (#70)
Browse files Browse the repository at this point in the history
* parted out slab into slabcrab

* parted out slab into crabslab

* parted out slab into crabslab

* Update README.md

* readme

* WIP part out crabslab, remove non-slab shaders, remove bloom (to be reimplemented later)

* WIP

* img-diff takes into account pixel threshold and image threshold

* fixed problems with the skybox after slabbing

* fixed tests to use explicit linear transfer where appropriate
  • Loading branch information
schell authored Jan 3, 2024
1 parent db34533 commit 504f537
Show file tree
Hide file tree
Showing 86 changed files with 2,368 additions and 3,807 deletions.
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ members = [
"crates/renderling",
"crates/renderling-shader",
"crates/renderling-gpui",
"crates/renderling-derive",
"crates/crabslab",
"crates/crabslab-derive",
]

exclude = ["./shaders"]

resolver = "2"

[workspace.dependencies]
async-channel = "1.8"
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.2"
glam = { version = "0.24.2", default-features = false }
snafu = "0.7"
winit = { version = "0.27" }
wgpu = { version = "0.17" }
2 changes: 1 addition & 1 deletion DEVLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Debugging rabbit hole:
* Maybe print out the brightness texture and make sure it's populated?
* Losing steam here, especially since bloom needs to be re-done as "physically based".

TODO: Part out the
### Physically Based Bloom

## Thu Dec 21, 2023

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "renderling-derive"
name = "crabslab-derive"
version = "0.1.0"
edition = "2021"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn get_params(input: &DeriveInput) -> syn::Result<Params> {
_ => {
return Err(syn::Error::new(
name.span(),
"deriving Slabbed only supports structs".to_string(),
"deriving SlabItem only supports structs".to_string(),
))
}
};
Expand All @@ -41,7 +41,7 @@ fn get_params(input: &DeriveInput) -> syn::Result<Params> {
.map(|field| {
let ty = &field.ty;
quote! {
<#ty as renderling_shader::slab::Slabbed>::slab_size()
<#ty as crabslab::SlabItem>::slab_size()
}
})
.collect();
Expand Down Expand Up @@ -69,7 +69,7 @@ fn get_params(input: &DeriveInput) -> syn::Result<Params> {
})
}

#[proc_macro_derive(Slabbed)]
#[proc_macro_derive(SlabItem)]
pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input: DeriveInput = syn::parse_macro_input!(input);
let name = &input.ident;
Expand All @@ -88,8 +88,7 @@ pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStre
/// Adds a `CanFetch<'lt>` bound on each of the system data types.
fn constrain_system_data_types(clause: &mut WhereClause, tys: &[Type]) {
for ty in tys.iter() {
let where_predicate: WherePredicate =
syn::parse_quote!(#ty : renderling_shader::slab::Slabbed);
let where_predicate: WherePredicate = syn::parse_quote!(#ty : crabslab::SlabItem);
clause.predicates.push(where_predicate);
}
}
Expand Down Expand Up @@ -129,9 +128,9 @@ pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStre
FieldName::Ident(field) => Ident::new(&format!("offset_of_{}", field), field.span()),
};
offsets.push(quote! {
pub fn #ident() -> renderling_shader::id::Offset<#ty> {
renderling_shader::id::Offset::new(
#(<#offset_tys as renderling_shader::slab::Slabbed>::slab_size()+)*
pub fn #ident() -> crabslab::Offset<#ty> {
crabslab::Offset::new(
#(<#offset_tys as crabslab::SlabItem>::slab_size()+)*
0
)
}
Expand All @@ -147,7 +146,7 @@ pub fn derive_from_slab(input: proc_macro::TokenStream) -> proc_macro::TokenStre
}

#[automatically_derived]
impl #impl_generics renderling_shader::slab::Slabbed for #name #ty_generics #where_clause
impl #impl_generics crabslab::SlabItem for #name #ty_generics #where_clause
{
fn slab_size() -> usize {
#(#sizes)+*
Expand Down
33 changes: 33 additions & 0 deletions crates/crabslab/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "crabslab"
version = "0.1.0"
edition = "2021"
description = "Slab allocator focused on GPU compute (rust-gpu)"
repository = "https://github.com/schell/renderling"
license = "MIT OR Apache-2.0"
keywords = ["game", "graphics", "shader", "rendering"]
categories = ["rendering", "game-development", "graphics"]
readme = "README.md"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["wgpu", "glam", "futures-lite"]
futures-lite = ["dep:futures-lite"]
glam = ["dep:glam"]
wgpu = ["dep:wgpu", "dep:bytemuck", "dep:snafu", "dep:async-channel", "dep:log"]

[dependencies]
async-channel = {workspace=true, optional=true}
bytemuck = {workspace=true, optional=true}
futures-lite = {workspace=true, optional=true}
log = {workspace=true, optional=true}
crabslab-derive = { version = "0.1.0", path = "../crabslab-derive" }
snafu = {workspace=true, optional=true}
wgpu = {workspace=true, optional=true}

[target.'cfg(not(target_arch = "spirv"))'.dependencies]
glam = { workspace = true, features = ["std"], optional = true }

[target.'cfg(target_arch = "spirv")'.dependencies]
glam = { version = "0.24.2", default-features = false, features = ["libm"], optional = true }
34 changes: 34 additions & 0 deletions crates/crabslab/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<div align="center">
<img src="crabslab.png" alt="slabcraft for crabs" width="512" />
</div>

## what
`crabslab` is a slab implementation focused on marshalling data from CPUs to GPUs.

## why
### Opinion
Working with shaders is much easier using a slab.

### rust-gpu
This crate was made to work with [`rust-gpu`](https://github.com/EmbarkStudios/rust-gpu/).
Specifically, using this crate it is possible to pack your types into a buffer on the CPU
and then read your types from the slab on the GPU (in Rust).

### Other no-std platforms
Even though this crate was written with `rust-gpu` in mind, it should work in other `no-std`
contexts.

## how
`crabslab` includes:
* a few traits:
- `Slab`
- `GrowableSlab`
- `SlabItem`
* a derive macro for `SlabItem`
* a few structs for working with various slabs
- `Id`
- `Array`
- `Offset`
* a helper struct `CpuSlab`
* a feature-gated helper for using slabs with `wgpu` - `WgpuBuffer`
- [example](src/wgpu_slab.rs#L344)
Binary file added crates/crabslab/crabslab.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
//! A slab-allocated array.
use core::marker::PhantomData;

use crate::id::Id;
use crate::slab::Slabbed;
use crate::{id::Id, slab::SlabItem};

#[derive(Clone, Copy)]
pub struct ArrayIter<T> {
array: Array<T>,
index: usize,
}

impl<T: Slabbed> Iterator for ArrayIter<T> {
impl<T: SlabItem> Iterator for ArrayIter<T> {
type Item = Id<T>;

fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -24,6 +23,7 @@ impl<T: Slabbed> Iterator for ArrayIter<T> {
}
}

/// A pointer to contiguous `T` elements in a slab.
#[repr(C)]
pub struct Array<T> {
// u32 offset in the slab
Expand Down Expand Up @@ -59,9 +59,12 @@ impl<T> From<Id<T>> for Array<T> {
impl<T> core::fmt::Debug for Array<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_null() {
f.write_fmt(format_args!("Array<{}>(null)", core::any::type_name::<T>()))
f.write_fmt(core::format_args!(
"Array<{}>(null)",
core::any::type_name::<T>()
))
} else {
f.write_fmt(format_args!(
f.write_fmt(core::format_args!(
"Array<{}>({}, {})",
core::any::type_name::<T>(),
self.index,
Expand All @@ -77,7 +80,7 @@ impl<T> PartialEq for Array<T> {
}
}

impl<T: Slabbed> Slabbed for Array<T> {
impl<T: SlabItem> SlabItem for Array<T> {
fn slab_size() -> usize {
2
}
Expand All @@ -103,7 +106,7 @@ impl<T: Slabbed> Slabbed for Array<T> {
}
}

impl<T: Slabbed> Default for Array<T> {
impl<T: SlabItem> Default for Array<T> {
fn default() -> Self {
Self {
index: u32::MAX,
Expand Down Expand Up @@ -140,7 +143,7 @@ impl<T> Array<T> {

pub fn at(&self, index: usize) -> Id<T>
where
T: Slabbed,
T: SlabItem,
{
if index >= self.len() {
Id::NONE
Expand All @@ -163,7 +166,7 @@ impl<T> Array<T> {
/// Convert this array into a `u32` array.
pub fn into_u32_array(self) -> Array<u32>
where
T: Slabbed,
T: SlabItem,
{
Array {
index: self.index,
Expand All @@ -176,7 +179,7 @@ impl<T> Array<T> {
/// Return the slice of the slab that this array represents.
pub fn sub_slab<'a>(&'a self, slab: &'a [u32]) -> &[u32]
where
T: Slabbed,
T: SlabItem,
{
let arr = self.into_u32_array();
&slab[arr.index as usize..(arr.index + arr.len) as usize]
Expand Down
35 changes: 23 additions & 12 deletions crates/renderling-shader/src/id.rs → crates/crabslab/src/id.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! Typed identifiers that can also be used as indices.
use core::marker::PhantomData;

use crate::{self as renderling_shader, slab::Slabbed};
use crate::{self as crabslab, slab::SlabItem};

pub const ID_NONE: u32 = u32::MAX;

/// An identifier.
/// An identifier that can be used to read or write a type from/into the slab.
#[repr(transparent)]
#[derive(bytemuck::Pod, bytemuck::Zeroable, Slabbed)]
#[derive(SlabItem)]
pub struct Id<T>(pub(crate) u32, PhantomData<T>);

impl<T> PartialOrd for Id<T> {
Expand Down Expand Up @@ -72,9 +72,12 @@ impl<T> Default for Id<T> {
impl<T> core::fmt::Debug for Id<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if self.is_none() {
f.write_fmt(format_args!("Id<{}>(null)", &core::any::type_name::<T>(),))
f.write_fmt(core::format_args!(
"Id<{}>(null)",
&core::any::type_name::<T>(),
))
} else {
f.write_fmt(format_args!(
f.write_fmt(core::format_args!(
"Id<{}>({})",
&core::any::type_name::<T>(),
&self.0
Expand Down Expand Up @@ -143,12 +146,12 @@ impl<T> Id<T> {

/// The offset of a field relative a parent's `Id`.
///
/// Offset functions are automatically derived for `Slabbed` structs.
/// Offset functions are automatically derived for `SlabItem` structs.
///
/// ```rust
/// use renderling_shader::{id::{Id, Offset}, slab::{Slab, Slabbed}};
/// use crabslab::{Id, Offset, Slab, SlabItem};
///
/// #[derive(Debug, Default, PartialEq, Slabbed)]
/// #[derive(Debug, Default, PartialEq, SlabItem)]
/// pub struct Parent {
/// pub child_a: u32,
/// pub child_b: u32,
Expand All @@ -157,7 +160,10 @@ impl<T> Id<T> {
/// let mut slab = [0u32; 10];
///
/// let parent_id = Id::new(3);
/// let parent = Parent{ child_a: 0, child_b: 1 };
/// let parent = Parent {
/// child_a: 0,
/// child_b: 1,
/// };
/// slab.write(parent_id, &parent);
/// assert_eq!(parent, slab.read(parent_id));
///
Expand Down Expand Up @@ -203,15 +209,20 @@ impl<T> Offset<T> {

#[cfg(test)]
mod test {
use crate::stage::GpuEntity;

use super::*;

#[derive(SlabItem)]
struct MyEntity {
name: u32,
age: f32,
destiny: [u32; 3],
}

#[test]
fn id_size() {
assert_eq!(
std::mem::size_of::<u32>(),
std::mem::size_of::<Id<GpuEntity>>(),
std::mem::size_of::<Id<MyEntity>>(),
"id is not u32"
);
}
Expand Down
18 changes: 18 additions & 0 deletions crates/crabslab/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![cfg_attr(target_arch = "spirv", no_std)]
//! Creating and crafting a tasty slab of memory.
mod array;
pub use array::*;

mod id;
pub use id::*;

mod slab;
pub use slab::*;

#[cfg(feature = "wgpu")]
mod wgpu_slab;
#[cfg(feature = "wgpu")]
pub use wgpu_slab::*;

pub use crabslab_derive::SlabItem;
Loading

0 comments on commit 504f537

Please sign in to comment.