Skip to content

Commit

Permalink
make wgsl_type const
Browse files Browse the repository at this point in the history
  • Loading branch information
victorvde committed Jul 26, 2023
1 parent b0b65dd commit 25851af
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 32 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "encase"
version = "0.6.1"
edition = "2021"
rust-version = "1.63"
rust-version = "1.64"

license = "MIT-0"
readme = "./README.md"
Expand Down
6 changes: 2 additions & 4 deletions derive/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl FieldData {
fn wgsl_type(&self, root: &Path) -> TokenStream {
let ty = &self.field.ty;
quote! {
<#ty as #root::ShaderType>::wgsl_type()
<#ty as #root::ShaderType>::WGSL_TYPE
}
}

Expand Down Expand Up @@ -636,9 +636,7 @@ pub fn derive_shader_type(input: DeriveInput, root: &Path) -> TokenStream {
#root::SizeValue::new(Self::METADATA.alignment().round_up(offset)).0
}

fn wgsl_type() -> ::std::string::String {
::std::string::ToString::to_string(#name_string)
}
const WGSL_TYPE: &'static ::core::primitive::str = #name_string;
}

impl #impl_generics #root::WriteInto for #name #ty_generics
Expand Down
99 changes: 99 additions & 0 deletions src/const_str.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Const string implementation for WGSL_TYPE and WGSL_STRUCT
// Used instead of crates like const_str because of E0401 when trying to use them in traits
// See also https://old.reddit.com/r/rust/comments/sv119a/concat_static_str_at_compile_time/

// Must be constant to avoid running into E0401. Should only affect compilation.
const BUFFER_SIZE: usize = 8192;

pub struct ConstStr {
data: [u8; BUFFER_SIZE],
len: usize,
}

impl ConstStr {
pub const fn new() -> ConstStr {
ConstStr {
data: [0u8; BUFFER_SIZE],
len: 0,
}
}

pub const fn str(mut self, s: &str) -> Self {
let b = s.as_bytes();
let mut index = 0;
while index < b.len() {
self.data[self.len] = b[index];
self.len += 1;
index += 1;
}

self
}

pub const fn u64(mut self, x: u64) -> Self {
let mut x2 = x;
let mut l = 0;
loop {
l += 1;
x2 /= 10;
if x2 == 0 {
break;
}
}
let mut x3 = x;
let mut index = 0;
loop {
self.data[self.len + l - 1 - index] = (x3 % 10) as u8 + '0' as u8;
index += 1;
x3 /= 10;
if x3 == 0 {
break;
}
}
self.len += l;

self
}

pub const fn as_str<'a>(&'a self) -> &'a str {
// SAFETY: safe because this is only used in const, and should be correct by construction
unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.data.as_ptr(), self.len)) }
}
}

mod test {
use super::ConstStr;

trait Name {
const NAME: &'static str;
}

trait Prefix: Name {}

trait Root: Name {}

struct Kilo;

impl Prefix for Kilo {}

struct Meter;

impl Root for Meter {}

impl Name for Kilo {
const NAME: &'static str = "kilo";
}

impl Name for Meter {
const NAME: &'static str = "meter";
}

impl<P: Prefix, R: Root> Name for (P, R) {
const NAME: &'static str = ConstStr::new().str(P::NAME).str(R::NAME).u64(1234567).as_str();
}

#[test]
fn test_trait() {
assert_eq!(<(Kilo, Meter)>::NAME, "kilometer1234567");
}
}
10 changes: 5 additions & 5 deletions src/core/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ pub trait ShaderType {
#[doc(hidden)]
const METADATA: Metadata<Self::ExtraMetadata>;

/// The [WGSL type name](https://www.w3.org/TR/WGSL/#types) for the implementing Rust type.
///
/// Note that for structs, this is just the name of the struct. See also [`WgslStruct`].
const WGSL_TYPE: &'static str;

/// Represents the minimum size of `Self` (equivalent to [GPUBufferBindingLayout.minBindingSize](https://gpuweb.github.io/gpuweb/#dom-gpubufferbindinglayout-minbindingsize))
///
/// For [WGSL fixed-footprint types](https://gpuweb.github.io/gpuweb/wgsl/#fixed-footprint-types)
Expand Down Expand Up @@ -86,11 +91,6 @@ pub trait ShaderType {
#[doc(hidden)]
const UNIFORM_COMPAT_ASSERT: fn() = || {};

/// Returns the [WGSL type name](https://www.w3.org/TR/WGSL/#types) for the implementing Rust type.
///
/// Note that for structs, this is just the name of the struct. See also [`WgslStruct`].
fn wgsl_type() -> String;

/// Asserts that `Self` meets the requirements of the
/// [uniform address space restrictions on stored values](https://gpuweb.github.io/gpuweb/wgsl/#address-spaces-uniform) and the
/// [uniform address space layout constraints](https://gpuweb.github.io/gpuweb/wgsl/#address-space-layout-constraints)
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ pub use encase_derive::ShaderType;
mod utils;
mod core;
mod types;
mod const_str;

mod impls;

Expand Down Expand Up @@ -165,4 +166,5 @@ pub mod private {
pub use super::ShaderSize;
pub use super::ShaderType;
pub use const_panic::concat_assert;
pub use super::const_str::ConstStr;
}
5 changes: 2 additions & 3 deletions src/types/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::core::{
BufferMut, BufferRef, CreateFrom, Metadata, ReadFrom, Reader, ShaderSize, ShaderType,
SizeValue, WriteInto, Writer,
};
use crate::const_str::ConstStr;

pub struct ArrayMetadata {
pub stride: SizeValue,
Expand Down Expand Up @@ -56,9 +57,7 @@ impl<T: ShaderType + ShaderSize, const N: usize> ShaderType for [T; N] {
])
};

fn wgsl_type() -> String {
format!("array<{},{}>", T::wgsl_type(), N)
}
const WGSL_TYPE: &'static ::core::primitive::str = ConstStr::new().str("array<").str(T::WGSL_TYPE).str(",").u64(N as u64).str(">").as_str();
}

impl<T: ShaderSize, const N: usize> ShaderSize for [T; N] {}
Expand Down
4 changes: 1 addition & 3 deletions src/types/matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,7 @@ macro_rules! impl_matrix_inner {
}
};

fn wgsl_type() -> ::std::string::String {
::std::format!("mat{}x{}<{}>", $c, $r, <$el_ty as $crate::private::ShaderType>::wgsl_type())
}
const WGSL_TYPE: &'static ::core::primitive::str = $crate::private::ConstStr::new().str("mat").u64($c).str("x").u64($r).str("<").str(<$el_ty as $crate::private::ShaderType>::WGSL_TYPE).str(">").as_str();
}

impl<$($generics)*> $crate::private::ShaderSize for $type
Expand Down
8 changes: 2 additions & 6 deletions src/types/runtime_sized_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ pub struct ArrayLength;
impl ShaderType for ArrayLength {
type ExtraMetadata = ();
const METADATA: Metadata<Self::ExtraMetadata> = Metadata::from_alignment_and_size(4, 4);
fn wgsl_type() -> String {
"u32".to_string()
}
const WGSL_TYPE: &'static str = "u32";
}

impl ShaderSize for ArrayLength {}
Expand Down Expand Up @@ -155,9 +153,7 @@ macro_rules! impl_rts_array_inner {
.0
}

fn wgsl_type() -> ::std::string::String {
::std::format!("array<{}>", <T as $crate::private::ShaderType>::wgsl_type())
}
const WGSL_TYPE: &'static ::core::primitive::str = $crate::private::ConstStr::new().str("array<").str(<T as $crate::private::ShaderType>::WGSL_TYPE).str(">").as_str();
}

impl<$($generics)*> $crate::private::RuntimeSizedArray for $type
Expand Down
4 changes: 1 addition & 3 deletions src/types/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ macro_rules! impl_basic_traits {
impl ShaderType for $type {
type ExtraMetadata = ();
const METADATA: Metadata<Self::ExtraMetadata> = Metadata::from_alignment_and_size(4, 4);
fn wgsl_type() -> String {
$wgsl.to_string()
}
const WGSL_TYPE: &'static str = $wgsl;
}

impl ShaderSize for $type {}
Expand Down
4 changes: 1 addition & 3 deletions src/types/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ macro_rules! impl_vector_inner {
}
};

fn wgsl_type() -> ::std::string::String {
::std::format!("vec{}<{}>", $n, <$el_ty as $crate::private::ShaderType>::wgsl_type())
}
const WGSL_TYPE: &'static ::core::primitive::str = $crate::private::ConstStr::new().str("vec").u64($n).str("<").str(<$el_ty as $crate::private::ShaderType>::WGSL_TYPE).str(">").as_str();
}

impl<$($generics)*> $crate::private::ShaderSize for $type
Expand Down
4 changes: 1 addition & 3 deletions src/types/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ macro_rules! impl_wrapper_inner {
<T as $crate::private::ShaderType>::size(&self$($get_ref)*)
}

fn wgsl_type() -> ::std::string::String {
<T as $crate::private::ShaderType>::wgsl_type()
}
const WGSL_TYPE: &'static ::core::primitive::str = <T as $crate::private::ShaderType>::WGSL_TYPE;
}
impl<$($generics)*> $crate::private::ShaderSize for $type
where
Expand Down
2 changes: 1 addition & 1 deletion tests/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn all_types() {

#[test]
fn wgsl_struct() {
assert_eq!(A::wgsl_type(), "A");
assert_eq!(A::WGSL_TYPE, "A");
assert_eq!(
A::wgsl_struct(),
"struct A {
Expand Down

0 comments on commit 25851af

Please sign in to comment.