Skip to content

Commit

Permalink
extract u8,i8,u16,i16 in shaders as u32,i32
Browse files Browse the repository at this point in the history
  • Loading branch information
schell committed Dec 5, 2023
1 parent ddf06a3 commit 57579de
Show file tree
Hide file tree
Showing 11 changed files with 621 additions and 132 deletions.
39 changes: 32 additions & 7 deletions crates/renderling-shader/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use crate::slab::Slabbed;

#[repr(C)]
pub struct Array<T> {
// u32 offset in the slab
index: u32,
// number of `T` elements in the array
len: u32,
_phantom: PhantomData<T>,
}
Expand All @@ -25,11 +27,15 @@ impl<T> Copy for Array<T> {}

impl<T> core::fmt::Debug for Array<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Array")
.field("index", &self.index)
.field("len", &self.len)
.field("_phantom", &self._phantom)
.finish()
f.debug_struct(if self.is_null() {
"Array (null)"
} else {
"Array"
})
.field("index", &self.index)
.field("len", &self.len)
.field("_phantom", &self._phantom)
.finish()
}
}

Expand Down Expand Up @@ -75,7 +81,7 @@ impl<T: Slabbed> Default for Array<T> {
}
}

impl<T: Slabbed> Array<T> {
impl<T> Array<T> {
pub fn new(index: u32, len: u32) -> Self {
Self {
index,
Expand All @@ -92,11 +98,18 @@ impl<T: Slabbed> Array<T> {
self.len == 0
}

pub fn is_null(&self) -> bool {
self.index == u32::MAX
}

pub fn contains_index(&self, index: usize) -> bool {
index >= self.index as usize && index < (self.index + self.len) as usize
}

pub fn at(&self, index: usize) -> Id<T> {
pub fn at(&self, index: usize) -> Id<T>
where
T: Slabbed,
{
if index >= self.len() {
Id::NONE
} else {
Expand All @@ -107,4 +120,16 @@ impl<T: Slabbed> Array<T> {
pub fn starting_index(&self) -> usize {
self.index as usize
}

/// Convert this array into a `u32` array.
pub fn into_u32_array(self) -> Array<u32>
where
T: Slabbed,
{
Array {
index: self.index,
len: self.len * T::slab_size() as u32,
_phantom: PhantomData,
}
}
}
127 changes: 127 additions & 0 deletions crates/renderling-shader/src/bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,72 @@ pub const U16_0_BITS: (u32, u32) = bits(0..=15);
/// The shift/mask range for the second 16 bits of a u32.
pub const U16_1_BITS: (u32, u32) = bits(16..=31);

/// Extract the "nth" 8 bits of the u32 at the given index in the slab.
///
/// Returns the extracted value, the index of the next component and the index
/// of the next u32 in the slab.
pub fn extract_u8(
// component index, eg 0 for the first 8 bits, 1 for the second 8 bits, etc
n: u32,
// index of the u32 in the slab
u32_index: usize,
// slab of u32s
slab: &[u32],
) -> (u32, u32, usize) {
match n {
0 => (extract(slab[u32_index], U8_0_BITS), 1, u32_index),
1 => (extract(slab[u32_index], U8_1_BITS), 2, u32_index),
2 => (extract(slab[u32_index], U8_2_BITS), 3, u32_index),
_ => (extract(slab[u32_index], U8_3_BITS), 0, u32_index + 1),
}
}

/// Extract the "nth" 8 bits of the u32 at the given index in the slab.
///
/// Returns the extracted value, the index of the next component and the index
/// of the next u32 in the slab.
pub fn extract_i8(
// component index, eg 0 for the first 8 bits, 1 for the second 8 bits, etc
n: u32,
// index of the u32 in the slab
u32_index: usize,
// slab of u32s
slab: &[u32],
) -> (i32, u32, usize) {
let (value, n, u32_index) = extract_u8(n, u32_index, slab);
let value: i32 = (value as i32 & 0xFF) - ((value as i32 & 0x80) << 1);
(value, n, u32_index)
}

/// Extract the "nth" 16 bits of the u32 at the given index in the slab.
pub fn extract_u16(
// component index, eg 0 for the first 16 bits, 1 for the second 16 bits, etc
n: u32,
// index of the u32 in the slab
u32_index: usize,
// slab of u32s
slab: &[u32],
) -> (u32, u32, usize) {
match n {
0 => (extract(slab[u32_index], U16_0_BITS), 1, u32_index),
_ => (extract(slab[u32_index], U16_1_BITS), 0, u32_index + 1),
}
}

/// Extract the "nth" 16 bits of the u32 at the given index in the slab.
pub fn extract_i16(
// component index, eg 0 for the first 16 bits, 1 for the second 16 bits, etc
n: u32,
// index of the u32 in the slab
u32_index: usize,
// slab of u32s
slab: &[u32],
) -> (i32, u32, usize) {
let (value, n, u32_index) = extract_u16(n, u32_index, slab);
let value: i32 = (value as i32 & 0xFFFF) - ((value as i32 & 0x8000) << 1);
(value, n, u32_index)
}

#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -96,4 +162,65 @@ mod test {
assert_eq!(super::extract(bits, super::U8_2_BITS), 4);
assert_eq!(super::extract(bits, super::U8_3_BITS), 3);
}

#[test]
fn extract_u8_sanity() {
let u8_slab = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 0u8, 0u8];
let u32_slab: &[u32] = bytemuck::cast_slice(&u8_slab);
let index = 0;
let n = 0;
let (a, n, index) = extract_u8(n, index, u32_slab);
let (b, n, index) = extract_u8(n, index, u32_slab);
let (c, n, index) = extract_u8(n, index, u32_slab);
let (d, n, index) = extract_u8(n, index, u32_slab);
let (e, n, index) = extract_u8(n, index, u32_slab);
let (f, _, _) = extract_u8(n, index, u32_slab);
assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]);
}

#[test]
fn extract_i8_sanity() {
let i8_slab = [0i8, -1i8, -2i8, -3i8, 4i8, 5i8, 0i8, 0i8];
let u32_slab: &[u32] = bytemuck::cast_slice(&i8_slab);
let index = 0;
let n = 0;
let (a, n, index) = extract_i8(n, index, u32_slab);
let (b, n, index) = extract_i8(n, index, u32_slab);
let (c, n, index) = extract_i8(n, index, u32_slab);
let (d, n, index) = extract_i8(n, index, u32_slab);
let (e, n, index) = extract_i8(n, index, u32_slab);
let (f, _, _) = extract_i8(n, index, u32_slab);
assert_eq!([0, -1, -2, -3, 4, 5], [a, b, c, d, e, f]);
}

#[test]
fn extract_u16_sanity() {
let u16_slab = [0u16, 1u16, 2u16, 3u16, 4u16, 5u16];
let u32_slab: &[u32] = bytemuck::cast_slice(&u16_slab);
let index = 0;
let n = 0;
let (a, n, index) = extract_u16(n, index, u32_slab);
let (b, n, index) = extract_u16(n, index, u32_slab);
let (c, n, index) = extract_u16(n, index, u32_slab);
let (d, n, index) = extract_u16(n, index, u32_slab);
let (e, n, index) = extract_u16(n, index, u32_slab);
let (f, _, _) = extract_u16(n, index, u32_slab);
assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]);
}

#[test]
fn extract_i16_sanity() {
let i16_slab = [0i16, -1i16, -2i16, -3i16, 4i16, 5i16, -12345i16, 0i16];
let u32_slab: &[u32] = bytemuck::cast_slice(&i16_slab);
let index = 0;
let n = 0;
let (a, n, index) = extract_i16(n, index, u32_slab);
let (b, n, index) = extract_i16(n, index, u32_slab);
let (c, n, index) = extract_i16(n, index, u32_slab);
let (d, n, index) = extract_i16(n, index, u32_slab);
let (e, n, index) = extract_i16(n, index, u32_slab);
let (f, n, index) = extract_i16(n, index, u32_slab);
let (g, _, _) = extract_i16(n, index, u32_slab);
assert_eq!([0, -1, -2, -3, 4, 5, -12345], [a, b, c, d, e, f, g]);
}
}
Loading

0 comments on commit 57579de

Please sign in to comment.