Skip to content
Open
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
182 commits
Select commit Hold shift + click to select a range
f2b51c1
MVP type layout 2
chronicl May 22, 2025
4b7e4a4
Add gpu_repr(uniform) to layout example
chronicl May 22, 2025
2a9a4ed
Add GpuStore: GpuAligned back
chronicl May 22, 2025
4619d60
Cleanup type layout Vertex
chronicl May 22, 2025
fb24c94
Fix example
chronicl May 22, 2025
8222864
Rebase
chronicl May 23, 2025
8420a3c
Small import change
chronicl May 23, 2025
6ce7e49
Fix example name
chronicl May 23, 2025
c5b9088
PackedVector to ir type conversion
chronicl May 23, 2025
bdcf157
Remove alignment rounding duplication
chronicl May 23, 2025
f3690d0
Add byte_size and align for LayoutableType
chronicl May 23, 2025
e255e1b
Make default use_color false
chronicl May 23, 2025
3f1dcf7
Decouple gpu_layout from GpuLayout
chronicl May 23, 2025
e19e85b
Move Display impl of ScalarType
chronicl May 23, 2025
e2f41cd
Make TryFrom<Layoutabletype> for StoreType fallible started
chronicl May 24, 2025
1aecb7e
Make ContainsPackedVecError simple
chronicl May 24, 2025
38b535e
Test LayoutableType -> StoreType conversion
chronicl May 24, 2025
f49aa5b
Make align of all types 1 when Repr::Packed
chronicl May 24, 2025
1d3aadc
Fix shame::Struct layout trait impls
chronicl May 24, 2025
ea6f659
Move LayoutCalculator
chronicl May 24, 2025
c4456f2
Split TypeLayout<Repr> into TypeLayout and GpuTypeLayout<Repr>
chronicl May 26, 2025
b11e5a3
Fix FieldLayout construction from LayoutableType
chronicl May 26, 2025
c22bfa7
Change GpuLayout impl of PackedVec
chronicl May 26, 2025
6dc9776
Change gpu_layout
chronicl May 26, 2025
3d8ddb4
Fix FieldLayout runtime sized array construction
chronicl May 26, 2025
02dd2c5
Cleanup and FieldOffsets redone
chronicl May 26, 2025
23af34a
Fix repr_c_struct_layout
chronicl May 27, 2025
6c3d170
Some comment cleanup
chronicl May 29, 2025
a9abd26
.
Jun 28, 2025
77f7b40
.
Jun 28, 2025
cba751c
.
Jun 28, 2025
0dc1ed8
.
Jun 28, 2025
3b5a7d6
Make ReprCField.alignment a U32PowerOf2
Jun 29, 2025
db74edb
Cleanup repr_c_struct_layout
Jun 29, 2025
6c9da5f
GpuRepr clarification documented
Jun 29, 2025
673c007
.
Jun 29, 2025
603a213
.
Jun 29, 2025
8c2adb3
.
Jun 29, 2025
6276218
.
Jun 29, 2025
e6b32b8
.
Jun 29, 2025
85f82cb
.
Jun 29, 2025
4517791
.
Jun 29, 2025
443d7a4
.
Jun 29, 2025
8eeaf46
.
Jun 29, 2025
244ae45
.
Jun 29, 2025
f09ea4c
.
Jun 29, 2025
33cb347
.
Jun 29, 2025
ee4c23d
.
Jun 29, 2025
0f90123
.
Jun 29, 2025
622fe48
.
Jun 29, 2025
43afa0f
.
Jun 29, 2025
86d4530
.
Jun 29, 2025
8c8be8d
.
Jun 29, 2025
26b658f
.
Jun 29, 2025
c115a7d
.
Jun 29, 2025
9bd22b0
.
Jun 29, 2025
a7ecc38
.
Jun 29, 2025
0fdc397
.
Jun 29, 2025
b644315
.
Jun 29, 2025
c8ade95
.
Jun 29, 2025
1ecb223
.
Jun 29, 2025
7d5426d
.
Jun 29, 2025
41ae4a6
.
Jun 29, 2025
b9bae54
.
Jun 29, 2025
ba5e534
.
Jun 29, 2025
4ce2fdc
.
Jun 29, 2025
6d15f81
.
Jun 29, 2025
d3c039a
.
Jun 29, 2025
863078d
.
Jun 29, 2025
1f0844b
.
Jun 29, 2025
bc3770a
detailed duplicate field fame check moved to ir::SizedStruct
Jun 29, 2025
1250b70
.
Jun 29, 2025
857f026
.
Jun 29, 2025
77811ee
.
Jun 29, 2025
7c9cee0
.
Jun 29, 2025
90fccad
.
Jun 29, 2025
ea1d2f1
.
Jun 29, 2025
401116c
.
Jun 29, 2025
c9181ac
.
Jun 30, 2025
8ef3f04
.
Jun 30, 2025
cd8c5c0
.
Jun 30, 2025
98fbad5
.
Jun 30, 2025
9c3c9a1
.
Jun 30, 2025
5d6d7f6
.
Jun 30, 2025
880bb13
.
Jun 30, 2025
ff439a9
.
Jun 30, 2025
0577202
.
Jun 30, 2025
54a2abd
.
Jun 30, 2025
2afb911
.
Jun 30, 2025
a1ca4a3
.
Jun 30, 2025
213f70b
.
Jun 30, 2025
1fd0957
.
Jun 30, 2025
ffcb834
.
Jun 30, 2025
002d58a
.
Jun 30, 2025
92ae245
.
Jun 30, 2025
660036c
.
Jun 30, 2025
3db727d
.
Jun 30, 2025
16f1fda
api_showcase glam comment fix
RayMarch Jun 30, 2025
2e99da1
`GpuTypeLayout` comment adjustment
RayMarch Jun 30, 2025
78e3d09
`LayoutableConversionError` edit
RayMarch Jun 30, 2025
0ebfac6
make `Vector` layout depend on repr
RayMarch Jun 30, 2025
766562a
.
Jul 3, 2025
9dda47c
.
Jul 4, 2025
74b9105
merge LayoutableType with Layoutable
Jul 4, 2025
9916bd0
.
Jul 4, 2025
c597929
.
Jul 4, 2025
5136b45
.
Jul 4, 2025
86e2440
.
Jul 4, 2025
3e63802
.
Jul 4, 2025
09356ea
.
Jul 4, 2025
c9353ba
.
Jul 4, 2025
f02a993
.
Jul 4, 2025
08ec712
.
Jul 4, 2025
4cc7b47
.
Jul 4, 2025
16db762
.
Jul 4, 2025
a1c4ac6
.
Jul 4, 2025
91e1e2f
.
Jul 4, 2025
a732486
.
Jul 4, 2025
1b48501
.
Jul 4, 2025
1bcda70
.
Jul 4, 2025
590cd00
.
Jul 4, 2025
8ad86f4
.
Jul 4, 2025
d628f76
.
Jul 4, 2025
1dbe3ad
.
Jul 4, 2025
074a206
Fix array stride for uniform layout rules
Jul 4, 2025
79938ca
Fix array stride for uniform layout rules
Jul 4, 2025
ad4a86a
Move type layout example into GpuTypeLayout docs
Jul 4, 2025
fd23627
.
Jul 4, 2025
bffd8b5
Add unit tests to align_size.rs layout calculations
Jul 6, 2025
a35b602
Move adjust_struct_alignment_for_repr into LayoutCalculator
Jul 6, 2025
ddf6379
Add unit tests for TypeLayout::new_layout_for
Jul 6, 2025
5372cd5
cleanup align size tests
chronicl Jul 8, 2025
8f561e0
Make clippy happy
chronicl Jul 8, 2025
255fb80
Rename LayoutCalculator -> StructLayoutCalculator
chronicl Jul 11, 2025
defb6fa
Make Repr::Packed ignore custom_min_align attributes and catch simult…
chronicl Jul 11, 2025
737522c
.
chronicl Jul 19, 2025
49692f5
New TypeLayoutCompatibleWith<AddressSpace> type and layout comparison…
chronicl Jul 21, 2025
27e89f7
layout comparison / mismatch errors improved
chronicl Jul 22, 2025
1610c20
layout mismatch cleanup and some comments
chronicl Jul 23, 2025
f256447
improve layout mismatch error, rename Repr::Storage -> Repr::Wgsl
chronicl Jul 23, 2025
68f81a8
rename LayoutableType -> TypeLayoutRecipe, layoutable -> recipe
chronicl Jul 23, 2025
519b662
cleanup
chronicl Jul 23, 2025
23981f2
layout mismatch cleanup
chronicl Jul 23, 2025
8b36dd4
layout mismatch test prints
chronicl Jul 23, 2025
4480b93
TypeLayoutCompatibleWith tests started
chronicl Jul 23, 2025
4460799
TypeLayoutCompatibleWith done
chronicl Jul 26, 2025
b78cba8
disable print in tests
chronicl Jul 26, 2025
96e16cd
new layout mismatch test
chronicl Jul 26, 2025
d154c34
remove unused to_string methods
chronicl Jul 26, 2025
d1a2eec
rearange method
chronicl Jul 26, 2025
c272489
more tests and docs
chronicl Jul 26, 2025
beffd64
comment improved
chronicl Jul 27, 2025
291cc26
Replace compatible_with::AddressSpace with existing BufferAddressSpace
chronicl Aug 4, 2025
ab5182d
making `U32PowerOf2` part of public api
RayMarch Oct 18, 2025
c492a1f
rust 1.90.0 fix
RayMarch Oct 18, 2025
b35b8f3
added `rust_layout_with_shame_semantics` helper
RayMarch Oct 18, 2025
cd7c16d
fix warnings
RayMarch Oct 18, 2025
fb3137c
preparing changes to `TypeLayout`s size/align mutation api
RayMarch Oct 19, 2025
8d9c9de
changes to `TypeLayout`'s size/align mutation api part 1
RayMarch Oct 19, 2025
6968f7e
changes to `TypeLayout`'s size/align mutation api part 2
RayMarch Oct 19, 2025
5440609
added panic that we need to resolve later
RayMarch Oct 19, 2025
7ff81fc
replace `unreachable!()` in error display
RayMarch Jan 5, 2026
d7a320c
rename `LayoutInfo` -> `LayoutInfoFlags`
RayMarch Jan 5, 2026
77bb06a
#[track_caller] for cpu_layout and gpu_layout
RayMarch Jan 5, 2026
61aa3dc
make `TypeLayout`'s `Debug` impl use `Display` formatting
RayMarch Jan 6, 2026
de6fb93
fixed CpuLayout mismatch error
RayMarch Jan 6, 2026
5b46ef0
changed stride docs
RayMarch Jan 7, 2026
2249b52
minor changes
RayMarch Jan 7, 2026
49ab78f
change duplicate field name error display
RayMarch Jan 7, 2026
f020d73
made layout::ScalarType part of the public interface
RayMarch Jan 7, 2026
a6287c7
adjust duplicate struct field name display
RayMarch Jan 8, 2026
14cf916
change `TopLevelMismatch` error messages
RayMarch Jan 8, 2026
c878874
switching left/right in error message
RayMarch Jan 8, 2026
40f2cdd
rewrote `StructMismatch::FieldLayout` message
RayMarch Jan 8, 2026
7fac545
change `BufferAddressSpaceEnum` `Display` impl
RayMarch Jan 8, 2026
523a64a
adjust comment
RayMarch Jan 8, 2026
69b429d
added cpu stride from size identity function for clarity
RayMarch Jan 8, 2026
2f95a65
change stride_check argument
RayMarch Jan 8, 2026
a82a571
added `Repr` arg to `get_attribs_and_stride`
RayMarch Jan 8, 2026
830077a
make `cpu_type_name_and_layout` for `PackedVec` be `None`
RayMarch Jan 8, 2026
e1bede7
changed `NoXYZ` trait implementor note
RayMarch Jan 8, 2026
9e071c7
impl `From<StructureFieldNamesMustBeUnique>`
RayMarch Jan 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 18 additions & 17 deletions examples/api_showcase/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#![allow(unused, clippy::no_effect)]
use shame::gpu_layout;
use shame as sm;
use shame::prelude::*;
use shame::aliases::*;

#[rustfmt::skip]
fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::EncodingErrors> {

// start a pipeline encoding with the default settings.
// (in the `shame_wgpu` examples, this is wrapped by the `Gpu` object)
//
// compared to earlier versions of `shame`, pipeline
//
// compared to earlier versions of `shame`, pipeline
// encoding is no longer based on a closure, but based on a
// RAII guard `sm::EncodingGuard<...>` instead.
// That way you can use the `?` operator for your own
Expand Down Expand Up @@ -60,7 +61,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
// only supported in vertex buffers, not storage/uniform buffers.
// This is reflected in the traits that are derived for `MyVertexFormat`.
//
// note: vertex layouts support #[gpu_repr(packed)] to prevent padding
// note: vertex layouts support #[gpu_repr(packed)] to prevent padding
// between fields of a struct, which often happens with 3 dimensional vectors
#[derive(sm::GpuLayout)]
struct MyVertexFormat {
Expand All @@ -76,7 +77,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
// import storage or uniform buffers via the `group0` iterator
//
// these iterators exist so that you can abstract them away in your own
// api-specific layer that suits your needs such that you can represent
// api-specific layer that suits your needs such that you can represent
// bind groups as types.
//
// `Transforms` is checked for compatibility with `TransformsOnCpu` here.
Expand All @@ -85,7 +86,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
// (once rusts const-generics are more powerful this may be moved to compile-time)
let xforms_sto: sm::Buffer<Transforms, sm::mem::Storage> = group0.next();
let xforms_uni: sm::Buffer<Transforms, sm::mem::Uniform> = group0.next();

// conditional code generation based on pipeline parameter
if some_param > 0 {
// if not further specified, defaults to `sm::mem::Storage`
Expand All @@ -99,7 +100,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
let my_vec3 = sm::vec!(1.0, 2.0, 3.0);
let my_vec4 = sm::vec!(my_vec3, 0.0); // component concatenation, like usual in shaders
let my_vec4 = my_vec3.extend(0.0); // or like this

let my_normal = sm::vec!(1.0, 1.0, 0.0).normalize();
let rgb = my_normal.remap(-1.0..=1.0, 0.0..=1.0); // remap linear ranges (instead of " * 0.5 + 0.5")

Expand All @@ -117,7 +118,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
let k = alpha.rsub1().sqrt().rsub1(); // same as above

// iterate over components of vec
let sum: f32x1 = my_vec4.into_iter().map(|x| x * x).sum();
let sum: f32x1 = my_vec4.into_iter().map(|x| x * x).sum();

let linear = xform.resize() as f32x3x3; // generic matrix resize
let linear = linear * sm::mat::id(); // generic identity matrix
Expand Down Expand Up @@ -162,8 +163,8 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
my_vec.y.set(3.0);

// rusts `if/while/for` means conditional code generation and loop-unrolling,
//
// therefore shader control flow uses closures.
//
// therefore shader control flow uses closures.
// The api is designed after rusts `bool::then` and the likes:

let rust_bool = true;
Expand All @@ -172,12 +173,12 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc

let shame_bool = true.to_gpu();
// condition appears in the shader as `if true { k = 1 }`
// (the `move` keyword is required for safety,
// (the `move` keyword is required for safety,
// but can be turned off via a shame crate-feature)
shame_bool.then(move || k.set(1));

// a variety of different shader-loop functions also exist

// for loop doesn't appear in the shader, only `k = 1; k = 2; k = 3; ...`
for i in 0..=10 {
k.set(i)
Expand All @@ -202,7 +203,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc

// clipping planes
let primitive = primitive.clip(mirror_distances);

// use `rasterize`, `rasterize_multisample` or `rasterize_supersample`.
// Rasterization gives access to the fragment-stage api via `frag`
let frag = primitive.rasterize(sm::Accuracy::Relaxed);
Expand All @@ -225,7 +226,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
// individual partial derivatives are accessible as fields.
duv.dx;
duv.dy;

// `fwidth` was renamed to `dxy_manhattan` because "width" is misleading
frag.quad.dxy_manhattan(uv, sm::GradPrecision::Coarse);

Expand Down Expand Up @@ -270,7 +271,7 @@ fn make_pipeline(some_param: u32) -> Result<sm::results::RenderPipeline, sm::Enc
// `shame` makes it impossible to use these features if they don't apply to the situation.

// this causes a compiler error, because Rg8Unorm has no alpha channel:
// targets.next::<tfmt::Rg8Unorm>().set_with_alpha_to_coverage(rg);
// targets.next::<tfmt::Rg8Unorm>().set_with_alpha_to_coverage(rg);

// finish the encoding and obtain the pipeline setup info + shader code.
encoder.finish()
Expand Down Expand Up @@ -486,13 +487,13 @@ struct Mat2([[f32; 2]; 2]);
// tell `shame` about the layout semantics of your cpu types
// Mat2::layout() == sm::f32x2x2::layout()
impl sm::CpuLayout for Mat2 {
fn cpu_layout() -> sm::TypeLayout { sm::f32x2x2::gpu_layout() }
fn cpu_layout() -> sm::TypeLayout { gpu_layout::<sm::f32x2x2>() }
}

#[repr(C, align(16))]
struct Mat4([[f32; 4]; 4]);
impl sm::CpuLayout for Mat4 {
fn cpu_layout() -> sm::TypeLayout { sm::f32x4x4::gpu_layout() }
fn cpu_layout() -> sm::TypeLayout { gpu_layout::<sm::f32x4x4>() }
}

// using "duck-traiting" allows you to define layouts for foreign cpu-types,
Expand Down
8 changes: 4 additions & 4 deletions examples/hello_triangles/src/util/shame_glam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! implement `shame::CpuLayout` for some glam types.

use shame as sm;
use shame::{self as sm, gpu_layout};
use sm::GpuLayout;

/// circumventing the orphan rule by defining our own trait.
Expand All @@ -14,14 +14,14 @@ pub trait CpuLayoutExt {

// glam::Vec4 matches sm::f32x4 in size and alignment
impl CpuLayoutExt for glam::Vec4 {
fn cpu_layout() -> sm::TypeLayout { sm::f32x4::gpu_layout() }
fn cpu_layout() -> sm::TypeLayout { gpu_layout::<sm::f32x4>() }
}

// glam::Vec2 only matches sm::f32x2 if it has 8 byte alignment
impl CpuLayoutExt for glam::Vec2 {
fn cpu_layout() -> sm::TypeLayout {
if align_of::<Self>() == 8 {
sm::f32x2::gpu_layout()
gpu_layout::<sm::f32x2>()
} else {
panic!("glam needs to use the `cuda` crate feature for Vec2 to be 8 byte aligned");
}
Expand All @@ -30,5 +30,5 @@ impl CpuLayoutExt for glam::Vec2 {

// glam::Mat4 matches sm::f32x4x4 in size and alignment
impl CpuLayoutExt for glam::Mat4 {
fn cpu_layout() -> sm::TypeLayout { sm::f32x4x4::gpu_layout() }
fn cpu_layout() -> sm::TypeLayout { gpu_layout::<sm::f32x4x4>() }
}
14 changes: 6 additions & 8 deletions examples/shame_wgpu/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn sample_type(st: sm::TextureSampleUsageType) -> wgpu::TextureSampleType {
}
}

/// converts `tf` into a `wgpu::TextureFormat` if supported.
/// converts `tf` into a `wgpu::TextureFormat` if supported.
/// If `tf` is `ExtraTextureFormats::SurfaceFormat`, then the provided `surface_format` argument
/// is returned if it is `Some`. Otherwise an error is returned.
#[rustfmt::skip]
Expand Down Expand Up @@ -194,7 +194,7 @@ pub fn texture_format(tf: &dyn sm::TextureFormatId, surface_format: Option<wgpu:
SmTf::EacR11Snorm => wgpu::TextureFormat::EacR11Snorm,
SmTf::EacRg11Unorm => wgpu::TextureFormat::EacRg11Unorm,
SmTf::EacRg11Snorm => wgpu::TextureFormat::EacRg11Snorm,
SmTf::Astc { block, channel } => wgpu::TextureFormat::Astc {
SmTf::Astc { block, channel } => wgpu::TextureFormat::Astc {
block: match block {
SmASTCb::B4x4 => wgpu::AstcBlock::B4x4,
SmASTCb::B5x4 => wgpu::AstcBlock::B5x4,
Expand All @@ -210,12 +210,12 @@ pub fn texture_format(tf: &dyn sm::TextureFormatId, surface_format: Option<wgpu:
SmASTCb::B10x10 => wgpu::AstcBlock::B10x10,
SmASTCb::B12x10 => wgpu::AstcBlock::B12x10,
SmASTCb::B12x12 => wgpu::AstcBlock::B12x12,
},
},
channel: match channel {
SmASTCc::Unorm => wgpu::AstcChannel::Unorm,
SmASTCc::UnormSrgb => wgpu::AstcChannel::UnormSrgb,
SmASTCc::Hdr => wgpu::AstcChannel::Hdr,
}
}
},
};
Ok(wtf)
Expand Down Expand Up @@ -449,7 +449,7 @@ fn color_writes(write_mask: smr::ChannelWrites) -> wgpu::ColorWrites {

#[rustfmt::skip]
fn vertex_format(format: smr::VertexAttribFormat) -> Result<wgpu::VertexFormat, ShameToWgpuError> {
use smr::ScalarType as S;
use shame::any::layout::ScalarType as S;
use smr::Len as L;
use wgpu::VertexFormat as W;
let unsupported = Err(ShameToWgpuError::UnsupportedVertexAttribFormat(format));
Expand Down Expand Up @@ -479,10 +479,8 @@ fn vertex_format(format: smr::VertexAttribFormat) -> Result<wgpu::VertexFormat,
(S::I32, L::X2) => W::Sint32x2,
(S::I32, L::X3) => W::Sint32x3,
(S::I32, L::X4) => W::Sint32x4,

(S::Bool, _) => return unsupported,
},

smr::VertexAttribFormat::Coarse(p) => {
use smr::PackedScalarType as PS;
use smr::PackedFloat as Norm;
Expand Down
7 changes: 7 additions & 0 deletions examples/type_layout/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "type_layout"
version = "0.1.0"
edition = "2024"

[dependencies]
shame = { path = "../../shame/" }
57 changes: 57 additions & 0 deletions examples/type_layout/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#![allow(dead_code, unused)]
//! Demonstration of the TypeLayout and TypeLayout Builder API.

use layout::{repr, Repr, SizedStruct};
use shame::{
any::{
self,
layout::{
self, FieldOptions, LayoutableSized, Len, RuntimeSizedArrayField, ScalarType, SizedField, SizedType,
UnsizedStruct, Vector, GpuTypeLayout,
},
U32PowerOf2,
},
boolx1, f32x1, f32x2, f32x3, f32x4, gpu_layout, Array, GpuLayout, GpuSized, TypeLayout, VertexAttribute,
VertexLayout,
};

fn main() {
// We'll start by replicating this struct using `any::layout` types.
#[derive(GpuLayout)]
struct Vertex {
position: f32x3,
normal: f32x3,
uv: f32x2,
}

// SizedStruct::new immediately takes the first field of the struct, because
// structs need to have at least one field.
let sized_struct = SizedStruct::new("Vertex", "position", f32x3::layoutable_type_sized())
.extend("normal", f32x3::layoutable_type_sized())
.extend("uv", f32x1::layoutable_type_sized());

let storage = GpuTypeLayout::<repr::Storage>::new(sized_struct.clone());
let packed = GpuTypeLayout::<repr::Packed>::new(sized_struct);
assert_ne!(storage.layout(), packed.layout());

// Does not exist:
// let uniform = GpuTypeLayout::<repr::Uniform>::new(sized_struct.clone());

// However we can try to upgrade a GpuTypeLayout::<repr::Storage>
let uniform = GpuTypeLayout::<repr::Uniform>::try_from(storage.clone()).unwrap();

// Which if it succeeds, guarantees:
assert_eq!(storage.layout(), uniform.layout());

// // Let's end on a pretty error message
let mut sized_struct = SizedStruct::new("D", "a", f32x2::layoutable_type_sized())
// This has align of 4 for storage and align of 16 for uniform.
.extend("b", Array::<f32x1, shame::Size<1>>::layoutable_type_sized());

let storage = GpuTypeLayout::<repr::Storage>::new(sized_struct.clone());
let uniform_result = GpuTypeLayout::<repr::Uniform>::try_from(storage.clone());
match uniform_result {
Err(e) => println!("This error is a showcase:\n{}", e),
Ok(u_layout) => println!("It unexpectedly worked, ohh no."),
}
}
38 changes: 29 additions & 9 deletions shame/src/common/po2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ pub enum U32PowerOf2 {
_2147483648,
}

impl From<U32PowerOf2> for u32 {
impl U32PowerOf2 {
/// Returns the corresponding u32.
#[rustfmt::skip]
fn from(value: U32PowerOf2) -> Self {
match value {
pub const fn as_u32(self) -> u32 {
match self {
U32PowerOf2::_1 => 1_u32 ,
U32PowerOf2::_2 => 2_u32 ,
U32PowerOf2::_4 => 4_u32 ,
Expand Down Expand Up @@ -76,6 +77,18 @@ impl From<U32PowerOf2> for u32 {
U32PowerOf2::_2147483648 => 2147483648_u32,
}
}

/// Returns the corresponding u64.
pub const fn as_u64(self) -> u64 { self.as_u32() as u64 }
}

impl From<U32PowerOf2> for u32 {
fn from(value: U32PowerOf2) -> Self { value.as_u32() }
}

impl U32PowerOf2 {
/// Returns the maximum between `self` and `other`.
pub const fn max(self, other: Self) -> Self { if self as u32 > other as u32 { self } else { other } }
}

#[derive(Debug)]
Expand All @@ -89,11 +102,10 @@ impl Display for NotAU32PowerOf2 {

impl std::error::Error for NotAU32PowerOf2 {}

impl TryFrom<u32> for U32PowerOf2 {
type Error = NotAU32PowerOf2;

fn try_from(value: u32) -> Result<Self, Self::Error> {
Ok(match value {
impl U32PowerOf2 {
/// Tries to convert a u32 to U32PowerOf2.
pub const fn try_from_u32(value: u32) -> Option<Self> {
Some(match value {
1 => U32PowerOf2::_1,
2 => U32PowerOf2::_2,
4 => U32PowerOf2::_4,
Expand Down Expand Up @@ -126,11 +138,19 @@ impl TryFrom<u32> for U32PowerOf2 {
536870912 => U32PowerOf2::_536870912,
1073741824 => U32PowerOf2::_1073741824,
2147483648 => U32PowerOf2::_2147483648,
n => return Err(NotAU32PowerOf2(n)),
n => return None,
})
}
}

impl TryFrom<u32> for U32PowerOf2 {
type Error = NotAU32PowerOf2;

fn try_from(value: u32) -> Result<Self, Self::Error> {
U32PowerOf2::try_from_u32(value).ok_or(NotAU32PowerOf2(value))
}
}

impl From<U32PowerOf2> for u64 {
fn from(value: U32PowerOf2) -> Self { u32::from(value) as u64 }
}
12 changes: 10 additions & 2 deletions shame/src/common/proc_macro_reexports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ pub use crate::frontend::rust_types::struct_::BufferFields;
pub use crate::frontend::rust_types::struct_::SizedFields;
pub use crate::frontend::rust_types::type_layout::FieldLayout;
pub use crate::frontend::rust_types::type_layout::FieldLayoutWithOffset;
pub use crate::frontend::rust_types::type_layout::layoutable::FieldOptions;
pub use crate::frontend::rust_types::type_layout::StructLayout;
pub use crate::frontend::rust_types::type_layout::StructLayoutError;
pub use crate::frontend::rust_types::type_layout::Repr;
pub use crate::frontend::rust_types::type_layout::repr;
pub use crate::frontend::rust_types::type_layout::TypeLayout;
pub use crate::frontend::rust_types::type_layout::TypeLayoutRules;
pub use crate::frontend::rust_types::type_layout::TypeLayoutSemantics;
pub use crate::frontend::rust_types::type_traits::BindingArgs;
pub use crate::frontend::rust_types::type_traits::GpuAligned;
Expand All @@ -40,6 +41,13 @@ pub use crate::frontend::rust_types::type_traits::NoBools;
pub use crate::frontend::rust_types::type_traits::NoHandles;
pub use crate::frontend::rust_types::type_traits::VertexAttribute;
pub use crate::frontend::rust_types::type_traits::GpuLayoutField;
pub use crate::frontend::rust_types::type_layout::layoutable::SizedStruct;
pub use crate::frontend::rust_types::type_layout::layoutable::Layoutable;
pub use crate::frontend::rust_types::type_layout::layoutable::LayoutableSized;
pub use crate::frontend::rust_types::type_layout::layoutable::LayoutableType;
pub use crate::frontend::rust_types::type_layout::layoutable::SizedType;
pub use crate::frontend::rust_types::type_layout::layoutable::SizedOrArray;
pub use crate::frontend::rust_types::type_layout::layoutable::builder::StructFromPartsError;
pub use crate::frontend::rust_types::AsAny;
pub use crate::frontend::rust_types::GpuType;
#[allow(missing_docs)]
Expand Down
Loading