Skip to content

Commit 0108d78

Browse files
committed
WIP part out crabslab, remove non-slab shaders, remove bloom (to be reimplemented later)
1 parent ac64a57 commit 0108d78

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+541
-2542
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ futures-lite = "1.13"
2121
gltf = { git = 'https://github.com/gltf-rs/gltf.git', features = ["KHR_lights_punctual", "KHR_materials_unlit", "KHR_materials_emissive_strength", "extras"] }
2222
image = "0.24"
2323
log = "0.4"
24-
glam = "0.24.2"
24+
glam = { version = "0.24.2", default-features = false }
2525
snafu = "0.7"
2626
winit = { version = "0.27" }
2727
wgpu = { version = "0.17" }

crates/crabslab/Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,22 @@ readme = "README.md"
1212
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1313

1414
[features]
15-
default = ["wgpu", "glam", "dep:futures-lite"]
15+
default = ["wgpu", "glam", "futures-lite"]
16+
futures-lite = ["dep:futures-lite"]
1617
glam = ["dep:glam"]
1718
wgpu = ["dep:wgpu", "dep:bytemuck", "dep:snafu", "dep:async-channel", "dep:log"]
1819

1920
[dependencies]
2021
async-channel = {workspace=true, optional=true}
2122
bytemuck = {workspace=true, optional=true}
2223
futures-lite = {workspace=true, optional=true}
23-
glam = {workspace=true, optional=true}
2424
log = {workspace=true, optional=true}
2525
crabslab-derive = { version = "0.1.0", path = "../crabslab-derive" }
2626
snafu = {workspace=true, optional=true}
2727
wgpu = {workspace=true, optional=true}
28+
29+
[target.'cfg(not(target_arch = "spirv"))'.dependencies]
30+
glam = { workspace = true, features = ["std"], optional = true }
31+
32+
[target.'cfg(target_arch = "spirv")'.dependencies]
33+
glam = { version = "0.24.2", default-features = false, features = ["libm"], optional = true }

crates/crabslab/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@
99
### Opinion
1010
Working with shaders is much easier using a slab.
1111

12+
### rust-gpu
13+
This crate was made to work with [`rust-gpu`](https://github.com/EmbarkStudios/rust-gpu/).
14+
Specifically, using this crate it is possible to pack your types into a buffer on the CPU
15+
and then read your types from the slab on the GPU (in Rust).
16+
17+
### Other no-std platforms
18+
Even though this crate was written with `rust-gpu` in mind, it should work in other `no-std`
19+
contexts.
20+
1221
## how
1322
`crabslab` includes:
1423
* a few traits:

crates/crabslab/src/array.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! A slab-allocated array.
22
use core::marker::PhantomData;
33

4-
use crate::id::Id;
5-
use crate::slab::SlabItem;
4+
use crate::{id::Id, slab::SlabItem};
65

76
#[derive(Clone, Copy)]
87
pub struct ArrayIter<T> {
@@ -60,9 +59,12 @@ impl<T> From<Id<T>> for Array<T> {
6059
impl<T> core::fmt::Debug for Array<T> {
6160
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6261
if self.is_null() {
63-
f.write_fmt(format_args!("Array<{}>(null)", core::any::type_name::<T>()))
62+
f.write_fmt(core::format_args!(
63+
"Array<{}>(null)",
64+
core::any::type_name::<T>()
65+
))
6466
} else {
65-
f.write_fmt(format_args!(
67+
f.write_fmt(core::format_args!(
6668
"Array<{}>({}, {})",
6769
core::any::type_name::<T>(),
6870
self.index,

crates/crabslab/src/id.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ impl<T> Default for Id<T> {
7272
impl<T> core::fmt::Debug for Id<T> {
7373
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
7474
if self.is_none() {
75-
f.write_fmt(format_args!("Id<{}>(null)", &core::any::type_name::<T>(),))
75+
f.write_fmt(core::format_args!(
76+
"Id<{}>(null)",
77+
&core::any::type_name::<T>(),
78+
))
7679
} else {
77-
f.write_fmt(format_args!(
80+
f.write_fmt(core::format_args!(
7881
"Id<{}>({})",
7982
&core::any::type_name::<T>(),
8083
&self.0

crates/crabslab/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![cfg_attr(target_arch = "spirv", no_std)]
12
//! Creating and crafting a tasty slab of memory.
23
34
mod array;

crates/crabslab/src/slab.rs

Lines changed: 69 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Slab traits.
2-
use core::marker::PhantomData;
2+
use core::{default::Default, marker::PhantomData};
33
pub use crabslab_derive::SlabItem;
44

55
use crate::{array::Array, id::Id};
@@ -457,73 +457,12 @@ pub trait GrowableSlab: Slab {
457457
///
458458
/// Returns the previous length.
459459
fn increment_len(&mut self, n: usize) -> usize;
460-
}
461-
462-
/// A wrapper around a `GrowableSlab` that provides convenience methods for
463-
/// working with CPU-side slabs.
464-
///
465-
/// Working with slabs on the CPU is much more convenient because the underlying
466-
/// buffer `B` is often a growable type, like `Vec<u32>`. This wrapper provides
467-
/// methods for appending to the end of the buffer with automatic resizing and
468-
/// for preallocating space for elements that will be written later.
469-
pub struct CpuSlab<B> {
470-
slab: B,
471-
}
472-
473-
impl<B> AsRef<B> for CpuSlab<B> {
474-
fn as_ref(&self) -> &B {
475-
&self.slab
476-
}
477-
}
478-
479-
impl<B> AsMut<B> for CpuSlab<B> {
480-
fn as_mut(&mut self) -> &mut B {
481-
&mut self.slab
482-
}
483-
}
484-
485-
impl<B: Slab> Slab for CpuSlab<B> {
486-
fn len(&self) -> usize {
487-
self.slab.len()
488-
}
489-
490-
fn read<T: SlabItem + Default>(&self, id: Id<T>) -> T {
491-
self.slab.read(id)
492-
}
493-
494-
fn write_indexed<T: SlabItem>(&mut self, t: &T, index: usize) -> usize {
495-
self.slab.write_indexed(t, index)
496-
}
497-
498-
fn write_indexed_slice<T: SlabItem>(&mut self, t: &[T], index: usize) -> usize {
499-
self.slab.write_indexed_slice(t, index)
500-
}
501-
}
502460

503-
impl<B: GrowableSlab> GrowableSlab for CpuSlab<B> {
504-
fn capacity(&self) -> usize {
505-
self.slab.capacity()
506-
}
507-
508-
fn reserve_capacity(&mut self, capacity: usize) {
509-
self.slab.reserve_capacity(capacity);
510-
}
511-
512-
fn increment_len(&mut self, n: usize) -> usize {
513-
self.slab.increment_len(n)
514-
}
515-
}
516-
517-
impl<B: GrowableSlab> CpuSlab<B> {
518-
/// Create a new `SlabBuffer` with the given slab.
519-
pub fn new(slab: B) -> Self {
520-
Self { slab }
521-
}
522461

523462
/// Expands the slab to fit the given number of `T`s, if necessary.
524463
fn maybe_expand_to_fit<T: SlabItem>(&mut self, len: usize) {
525464
let size = T::slab_size();
526-
let capacity = self.slab.capacity();
465+
let capacity = self.capacity();
527466
//log::trace!(
528467
// "append_slice: {size} * {ts_len} + {len} ({}) >= {capacity}",
529468
// size * ts_len + len
@@ -545,7 +484,7 @@ impl<B: GrowableSlab> CpuSlab<B> {
545484
///
546485
/// NOTE: This changes the next available buffer index and may change the
547486
/// buffer capacity.
548-
pub fn allocate<T: SlabItem>(&mut self) -> Id<T> {
487+
fn allocate<T: SlabItem>(&mut self) -> Id<T> {
549488
self.maybe_expand_to_fit::<T>(1);
550489
let index = self.increment_len(T::slab_size());
551490
Id::from(index)
@@ -558,7 +497,7 @@ impl<B: GrowableSlab> CpuSlab<B> {
558497
/// written later with [`Self::write_array`].
559498
///
560499
/// NOTE: This changes the length of the buffer and may change the capacity.
561-
pub fn allocate_array<T: SlabItem>(&mut self, len: usize) -> Array<T> {
500+
fn allocate_array<T: SlabItem>(&mut self, len: usize) -> Array<T> {
562501
if len == 0 {
563502
return Array::default();
564503
}
@@ -570,25 +509,87 @@ impl<B: GrowableSlab> CpuSlab<B> {
570509
/// Append to the end of the buffer.
571510
///
572511
/// Returns the `Id` of the written element.
573-
pub fn append<T: SlabItem + Default>(&mut self, t: &T) -> Id<T> {
512+
fn append<T: SlabItem + Default>(&mut self, t: &T) -> Id<T> {
574513
let id = self.allocate::<T>();
575514
// IGNORED: safe because we just allocated the id
576-
let _ = self.slab.write(id, t);
515+
let _ = self.write(id, t);
577516
id
578517
}
579518

580519
/// Append a slice to the end of the buffer, resizing if necessary
581520
/// and returning a slabbed array.
582521
///
583522
/// Returns the `Array` of the written elements.
584-
pub fn append_array<T: SlabItem + Default>(&mut self, ts: &[T]) -> Array<T> {
523+
fn append_array<T: SlabItem + Default>(&mut self, ts: &[T]) -> Array<T> {
585524
let array = self.allocate_array::<T>(ts.len());
586525
// IGNORED: safe because we just allocated the array
587526
let _ = self.write_array(array, ts);
588527
array
589528
}
590529
}
591530

531+
/// A wrapper around a `GrowableSlab` that provides convenience methods for
532+
/// working with CPU-side slabs.
533+
///
534+
/// Working with slabs on the CPU is much more convenient because the underlying
535+
/// buffer `B` is often a growable type, like `Vec<u32>`. This wrapper provides
536+
/// methods for appending to the end of the buffer with automatic resizing and
537+
/// for preallocating space for elements that will be written later.
538+
pub struct CpuSlab<B> {
539+
slab: B,
540+
}
541+
542+
impl<B> AsRef<B> for CpuSlab<B> {
543+
fn as_ref(&self) -> &B {
544+
&self.slab
545+
}
546+
}
547+
548+
impl<B> AsMut<B> for CpuSlab<B> {
549+
fn as_mut(&mut self) -> &mut B {
550+
&mut self.slab
551+
}
552+
}
553+
554+
impl<B: Slab> Slab for CpuSlab<B> {
555+
fn len(&self) -> usize {
556+
self.slab.len()
557+
}
558+
559+
fn read<T: SlabItem + Default>(&self, id: Id<T>) -> T {
560+
self.slab.read(id)
561+
}
562+
563+
fn write_indexed<T: SlabItem>(&mut self, t: &T, index: usize) -> usize {
564+
self.slab.write_indexed(t, index)
565+
}
566+
567+
fn write_indexed_slice<T: SlabItem>(&mut self, t: &[T], index: usize) -> usize {
568+
self.slab.write_indexed_slice(t, index)
569+
}
570+
}
571+
572+
impl<B: GrowableSlab> GrowableSlab for CpuSlab<B> {
573+
fn capacity(&self) -> usize {
574+
self.slab.capacity()
575+
}
576+
577+
fn reserve_capacity(&mut self, capacity: usize) {
578+
self.slab.reserve_capacity(capacity);
579+
}
580+
581+
fn increment_len(&mut self, n: usize) -> usize {
582+
self.slab.increment_len(n)
583+
}
584+
}
585+
586+
impl<B: GrowableSlab> CpuSlab<B> {
587+
/// Create a new `SlabBuffer` with the given slab.
588+
pub fn new(slab: B) -> Self {
589+
Self { slab }
590+
}
591+
}
592+
592593
#[cfg(not(target_arch = "spirv"))]
593594
impl GrowableSlab for Vec<u32> {
594595
fn capacity(&self) -> usize {

crates/crabslab/src/wgpu_slab.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! CPU side of slab storage using `wgpu`.
22
use std::{
33
ops::Deref,
4-
sync::{atomic::AtomicUsize, Arc, RwLock},
4+
sync::{atomic::AtomicUsize, Arc},
55
};
66

77
use crate::{GrowableSlab, Id, Slab, SlabItem};
@@ -56,19 +56,16 @@ pub fn print_slab(slab: &[u32], starting_index: usize) {
5656
}
5757

5858
/// A slab buffer used by the stage to store heterogeneous objects.
59-
///
60-
/// A clone of a buffer is a reference to the same buffer.
61-
#[derive(Clone)]
6259
pub struct WgpuBuffer {
63-
pub(crate) buffer: Arc<RwLock<wgpu::Buffer>>,
60+
pub(crate) buffer: wgpu::Buffer,
6461
device: Arc<wgpu::Device>,
6562
queue: Arc<wgpu::Queue>,
6663
// The number of u32 elements currently stored in the buffer.
6764
//
6865
// This is the next index to write into.
69-
len: Arc<AtomicUsize>,
66+
len: AtomicUsize,
7067
// The total number of u32 elements that can be stored in the buffer.
71-
capacity: Arc<AtomicUsize>,
68+
capacity: AtomicUsize,
7269
}
7370

7471
impl Slab for WgpuBuffer {
@@ -103,8 +100,7 @@ impl Slab for WgpuBuffer {
103100
.device
104101
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
105102
self.queue.write_buffer(
106-
// UNWRAP: if we can't lock we want to panic
107-
&self.buffer.read().unwrap(),
103+
&self.buffer,
108104
byte_offset as u64,
109105
bytemuck::cast_slice(bytes.as_slice()),
110106
);
@@ -137,8 +133,7 @@ impl Slab for WgpuBuffer {
137133
let _ = u32_data.write_indexed_slice(t, 0);
138134
let byte_offset = index * std::mem::size_of::<u32>();
139135
self.queue.write_buffer(
140-
// UNWRAP: if we can't lock we want to panic
141-
&self.buffer.read().unwrap(),
136+
&self.buffer,
142137
byte_offset as u64,
143138
bytemuck::cast_slice(&u32_data),
144139
);
@@ -161,21 +156,20 @@ impl GrowableSlab for WgpuBuffer {
161156
if new_capacity > capacity {
162157
log::trace!("resizing buffer from {capacity} to {new_capacity}");
163158
let len = self.len();
164-
let mut buffer = self.buffer.write().unwrap();
165-
let new_buffer = Self::new_buffer(&self.device, new_capacity, buffer.usage());
159+
let new_buffer = Self::new_buffer(&self.device, new_capacity, self.buffer.usage());
166160
let mut encoder = self
167161
.device
168162
.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
169163
// UNWRAP: if we can't lock we want to panic
170164
encoder.copy_buffer_to_buffer(
171-
&buffer,
165+
&self.buffer,
172166
0,
173167
&new_buffer,
174168
0,
175169
(len * std::mem::size_of::<u32>()) as u64,
176170
);
177171
self.queue.submit(std::iter::once(encoder.finish()));
178-
*buffer = new_buffer;
172+
self.buffer = new_buffer;
179173
self.capacity
180174
.store(new_capacity, std::sync::atomic::Ordering::Relaxed);
181175
}
@@ -222,7 +216,7 @@ impl WgpuBuffer {
222216
let device = device.into();
223217
let queue = queue.into();
224218
Self {
225-
buffer: RwLock::new(Self::new_buffer(&device, capacity, usage)).into(),
219+
buffer: Self::new_buffer(&device, capacity, usage),
226220
len: AtomicUsize::new(0).into(),
227221
capacity: AtomicUsize::new(capacity).into(),
228222
device,
@@ -256,8 +250,7 @@ impl WgpuBuffer {
256250
output_buffer_size:{output_buffer_size}",
257251
);
258252
encoder.copy_buffer_to_buffer(
259-
// UNWRAP: if we can't lock we want to panic
260-
&self.buffer.read().unwrap(),
253+
&self.buffer,
261254
byte_offset as u64,
262255
&output_buffer,
263256
0,
@@ -285,9 +278,8 @@ impl WgpuBuffer {
285278
}
286279

287280
/// Get the underlying buffer.
288-
pub fn get_buffer(&self) -> impl Deref<Target = wgpu::Buffer> + '_ {
289-
// UNWRAP: if we can't lock we want to panic
290-
self.buffer.read().unwrap()
281+
pub fn get_buffer(&self) -> &wgpu::Buffer {
282+
&self.buffer
291283
}
292284
}
293285

0 commit comments

Comments
 (0)