Skip to content

Commit

Permalink
rebase of rust SIMD culling (native loding broken)
Browse files Browse the repository at this point in the history
  • Loading branch information
burgerindividual committed Feb 24, 2024
1 parent 435a6bd commit e673218
Show file tree
Hide file tree
Showing 40 changed files with 3,455 additions and 33 deletions.
2 changes: 2 additions & 0 deletions native/core/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-Ctarget-cpu=x86-64-v3"]
2 changes: 2 additions & 0 deletions native/core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
**/*.rs.bk
90 changes: 90 additions & 0 deletions native/core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions native/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[package]
name = "sodium_core"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[profile.dev]
opt-level = 0
panic = "abort"
lto = "thin"
debug-assertions = true

[profile.test]
inherits = "dev"

[profile.release]
panic = "abort"
debug = true
lto = "fat"

[profile.asm]
inherits = "release"
lto = "off"

[profile.production]
inherits = "release"
lto = "fat"
debug = false
strip = "debuginfo"

[dependencies]
# Using these dependencies directly gives us access to setting features.
core_simd = { git = "https://github.com/rust-lang/portable-simd.git", features = [
"all_lane_counts",
] }
std_float = { git = "https://github.com/rust-lang/portable-simd.git" }
sodium_proc_macros = { path = "../proc_macros" }
derive_more = { version = "1.0.0-beta.6", default_features = false, features = [
"add",
"add_assign",
"mul",
"mul_assign",
] }
7 changes: 7 additions & 0 deletions native/core/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
imports_granularity = "Module"
group_imports = "StdExternalCrate"
use_field_init_shorthand = true
use_try_shorthand = true
wrap_comments = true
comment_width = 100
max_width = 100
192 changes: 192 additions & 0 deletions native/core/src/collections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
use alloc::boxed::Box;
use core::mem::MaybeUninit;
use core::ptr::{self, addr_of_mut};

use crate::mem::InitDefaultInPlace;
use crate::unwrap_debug;

pub struct ArrayDeque<T, const CAPACITY: usize> {
head: usize,
tail: usize,
elements: [MaybeUninit<T>; CAPACITY],
}

impl<T, const CAPACITY: usize> ArrayDeque<T, CAPACITY> {
pub fn push(&mut self, value: T) {
self.set_tail_element(value);

self.tail += 1;
}

pub fn push_conditionally(&mut self, value: T, cond: bool) {
self.set_tail_element(value);

self.tail += if cond { 1 } else { 0 };
}

fn set_tail_element(&mut self, value: T) {
unsafe {
*unwrap_debug!(self.elements.get_mut(self.tail)) = MaybeUninit::new(value);
}
}

pub fn pop(&mut self) -> Option<&T> {
if self.is_empty() {
return None;
}

// the unchecked unwrap should be fine, because if we read past the array, it
// would've already been a problem when we pushed an element past the
// array.
let value =
unsafe { MaybeUninit::assume_init_ref(unwrap_debug!(self.elements.get(self.head))) };
self.head += 1;

Some(value)
}

pub fn reset(&mut self) {
// TODO: should we drop everything between head and tail?
self.head = 0;
self.tail = 0;
}

pub fn is_empty(&self) -> bool {
self.head == self.tail
}
}

impl<T, const CAPACITY: usize> Default for ArrayDeque<T, CAPACITY> {
fn default() -> Self {
Self {
head: 0,
tail: 0,
elements: unsafe { MaybeUninit::<[MaybeUninit<T>; CAPACITY]>::uninit().assume_init() },
}
}
}

impl<T, const CAPACITY: usize> InitDefaultInPlace for *mut ArrayDeque<T, CAPACITY> {
fn init_default_in_place(self) {
unsafe {
addr_of_mut!((*self).head).write(0);
addr_of_mut!((*self).tail).write(0);
// skip initialization of data array because the contents don't
// matter
}
}
}

#[repr(C)]
pub struct CVec<T> {
count: u32,
data: *mut T,
}

impl<T> CVec<T> {
pub fn from_boxed_slice(data: Box<[T]>) -> Self {
CVec {
count: data.len().try_into().expect("len is not a valid u32"),
data: if data.len() == 0 {
ptr::null_mut()
} else {
Box::leak(data).as_mut_ptr()
},
}
}
}

// TODO: validate that the capacity is smaller than u32::MAX
#[repr(C)]
pub struct CInlineVec<T, const CAPACITY: usize> {
count: u32,
data: [MaybeUninit<T>; CAPACITY],
}

impl<T, const CAPACITY: usize> CInlineVec<T, CAPACITY> {
pub fn push(&mut self, value: T) {
self.set_top_element(value);
self.count += 1;
}

pub fn push_conditionally(&mut self, value: T, cond: bool) {
self.set_top_element(value);
self.count += if cond { 1 } else { 0 };
}

fn set_top_element(&mut self, value: T) {
unsafe {
*unwrap_debug!(self.data.get_mut(self.count as usize)) = MaybeUninit::new(value);
}
}

pub fn clear(&mut self) {
for i in 0..self.count as usize {
unsafe {
unwrap_debug!(self.data.get_mut(i)).assume_init_drop();
}
}

self.count = 0;
}

pub fn is_empty(&self) -> bool {
self.count == 0
}

pub fn element_count(&self) -> u32 {
self.count
}

/// # Safety
/// The vec must not be empty before calling this function.
pub fn pop(&mut self) -> T {
self.count -= 1;
unsafe { unwrap_debug!(self.data.get(self.count as usize)).assume_init_read() }
}

pub fn get_slice(&self) -> &[T] {
// SAFETY: count shouldn't ever be able to be incremented past LEN, and the
// contents should be initialized
unsafe {
MaybeUninit::slice_assume_init_ref(unwrap_debug!(self.data.get(0..self.count as usize)))
}
}

pub fn get_slice_mut(&mut self) -> &mut [T] {
// SAFETY: count shouldn't ever be able to be incremented past LEN, and the
// contents should be initialized
unsafe {
MaybeUninit::slice_assume_init_mut(unwrap_debug!(self
.data
.get_mut(0..self.count as usize)))
}
}
}

impl<T, const CAPACITY: usize> Default for CInlineVec<T, CAPACITY> {
fn default() -> Self {
Self {
data: unsafe { MaybeUninit::<[MaybeUninit<T>; CAPACITY]>::uninit().assume_init() },
count: 0,
}
}
}

impl<T, const CAPACITY: usize> InitDefaultInPlace for *mut CInlineVec<T, CAPACITY> {
fn init_default_in_place(self) {
unsafe {
addr_of_mut!((*self).count).write(0);
// skip initialization of data array because the contents don't
// matter
}
}
}

impl<T: Copy, const CAPACITY: usize> Clone for CInlineVec<T, CAPACITY> {
fn clone(&self) -> Self {
*self
}
}

impl<T: Copy, const CAPACITY: usize> Copy for CInlineVec<T, CAPACITY> {}
Loading

0 comments on commit e673218

Please sign in to comment.