### Write affine transform to uniform buffer in Rust Source: https://github.com/teoxoy/encase/blob/main/README.md Demonstrates creating a ShaderType struct representing a 2D affine transformation and serializing it into a UniformBuffer. The example shows how to prepare data for GPU transfer by converting it to a byte buffer with proper memory layout. ```rust use encase::{ShaderType, UniformBuffer}; #[derive(ShaderType)] struct AffineTransform2D { matrix: test_impl::Mat2x2f, translate: test_impl::Vec2f, } let transform = AffineTransform2D { matrix: test_impl::Mat2x2f::IDENTITY, translate: test_impl::Vec2f::ZERO, }; let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&transform).unwrap(); let byte_buffer = buffer.into_inner(); // write byte_buffer to GPU assert_eq!(&byte_buffer, &[0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0]); ``` -------------------------------- ### Write multiple data types to dynamic storage buffer with alignment in Rust Source: https://github.com/teoxoy/encase/blob/main/README.md Shows how to use DynamicStorageBuffer to write multiple different data types with custom alignment. This example demonstrates writing arrays, vectors, and vector types while maintaining specified byte alignment between each write. ```rust use encase::{ShaderType, DynamicStorageBuffer}; let mut byte_buffer: Vec = Vec::new(); let mut buffer = DynamicStorageBuffer::new_with_alignment(&mut byte_buffer, 64); let offsets = [ buffer.write(&[5.; 10]).unwrap(), buffer.write(&vec![3u32; 20]).unwrap(), buffer.write(&test_impl::Vec3f::ONE).unwrap(), ]; // write byte_buffer to GPU assert_eq!(offsets, [0, 64, 192]); ``` -------------------------------- ### Write and read storage buffer with runtime-sized arrays in Rust Source: https://github.com/teoxoy/encase/blob/main/README.md Demonstrates using StorageBuffer to serialize and deserialize a struct containing a runtime-sized array with an ArrayLength field. The example shows how to modify buffer data on the GPU side and read it back with updated array lengths. ```rust use encase::{ShaderType, ArrayLength, StorageBuffer}; #[derive(ShaderType)] struct Positions { length: ArrayLength, #[shader(size(runtime))] positions: Vec } let mut positions = Positions { length: ArrayLength, positions: Vec::from([ test_impl::Vec2f::from([4.5, 3.4]), test_impl::Vec2f::from([1.5, 7.4]), test_impl::Vec2f::from([4.3, 1.9]), ]) }; let mut byte_buffer: Vec = Vec::new(); let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.write(&positions).unwrap(); // write byte_buffer to GPU // change length on GPU side byte_buffer[0] = 2; // read byte_buffer from GPU let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.read(&mut positions).unwrap(); assert_eq!(positions.positions.len(), 2); ``` -------------------------------- ### StorageBuffer content_of Helper Method in Rust Source: https://context7.com/teoxoy/encase/llms.txt Convenience method to convert ShaderType instances directly to bytes without manually managing buffer creation and writing. Provides a one-liner alternative to explicit buffer initialization and serialization for GPU buffer uploads. ```rust use encase::{ShaderType, StorageBuffer}; #[derive(ShaderType)] struct LightData { position: test_impl::Vec3f, intensity: f32, color: test_impl::Vec3f, } let light = LightData { position: test_impl::Vec3f::from([10.0, 5.0, 0.0]), intensity: 100.0, color: test_impl::Vec3f::from([1.0, 0.9, 0.8]), }; // One-liner to get bytes let bytes: Vec = StorageBuffer::content_of(&light).unwrap(); // Equivalent to: // let mut buffer = StorageBuffer::new(Vec::::new()); // buffer.write(&light).unwrap(); // let bytes = buffer.into_inner(); // bytes ready for GPU buffer upload assert!(bytes.len() >= 28); // Minimum size with padding ``` -------------------------------- ### impl_matrix! Macro for Custom Matrix Types in Rust Source: https://context7.com/teoxoy/encase/llms.txt Demonstrates the use of the `impl_matrix!` macro to implement `ShaderType` for custom matrix types. It ensures correct column-major layout and padding required for WGSL. ```rust use encase::{impl_matrix, ShaderType, UniformBuffer}; // Custom 3x3 matrix type (3 columns, 3 rows) #[derive(Clone, Copy)] struct MyMat3x3f { cols: [[f32; 3]; 3] // column-major } impl AsRef<[[f32; 3]; 3]> for MyMat3x3f { fn as_ref(&self) -> &[[f32; 3]; 3] { &self.cols } } impl AsMut<[[f32; 3]; 3]> for MyMat3x3f { fn as_mut(&mut self) -> &mut [[f32; 3]; 3] { &mut self.cols } } impl From<[[f32; 3]; 3]> for MyMat3x3f { fn from(cols: [[f32; 3]; 3]) -> Self { MyMat3x3f { cols } } } // Implement ShaderType: 3 columns, 3 rows impl_matrix!(3, 3, MyMat3x3f; using AsRef AsMut From); // Identity matrix let identity = MyMat3x3f { cols: [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], ] }; let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&identity).unwrap(); // Automatically handles column padding for proper WGSL layout ``` -------------------------------- ### Write to Uninitialized Memory Buffers in Rust Source: https://context7.com/teoxoy/encase/llms.txt Allocate and write directly to uninitialized memory buffers using MaybeUninit for performance-critical scenarios, avoiding redundant initialization overhead. This snippet demonstrates buffer creation with alignment, multi-type writing, and safe conversion to initialized Vec for GPU transfer. ```rust use std::mem::MaybeUninit; use encase::DynamicStorageBuffer; // Allocate uninitialized buffer let mut uninit_buffer: Vec> = Vec::new(); // Write to uninitialized memory directly let mut buffer = DynamicStorageBuffer::new_with_alignment(&mut uninit_buffer, 64); let offsets = [ buffer.write(&[5.0; 10]).unwrap(), buffer.write(&vec![3u32; 20]).unwrap(), buffer.write(&test_impl::Vec3f::ONE).unwrap(), ]; // SAFETY: Vec and Vec> share the same layout // and all written regions have been initialized let byte_buffer: Vec = unsafe { Vec::from_raw_parts( uninit_buffer.as_mut_ptr().cast(), uninit_buffer.len(), uninit_buffer.capacity() ) }; std::mem::forget(uninit_buffer); // byte_buffer contains initialized data ready for GPU assert_eq!(offsets, [0, 64, 192]); ``` -------------------------------- ### ShaderType Attributes for WGSL Layout Control in Rust Source: https://context7.com/teoxoy/encase/llms.txt Illustrates how `#[derive(ShaderType)]` and `#[shader(...)]` attributes control memory layout for WGSL uniform buffer compatibility. It shows how to enforce alignment and size constraints to prevent layout errors. ```rust use encase::{ShaderType, UniformBuffer}; // Without alignment attribute - would fail uniform compatibility // #[derive(ShaderType)] // struct Invalid { // a: f32, // b: S, // Error: offset must be at least 16 // } #[derive(ShaderType)] struct S { x: f32, } // Fixed with explicit alignment #[derive(ShaderType)] struct Valid { a: f32, #[shader(align(16))] // Increase alignment to 16 bytes b: S, } // Or fixed with size attribute #[derive(ShaderType)] struct AlsoValid { #[shader(size(16))] // Increase size of field to 16 bytes a: f32, b: S, } // Both structs are now uniform buffer compatible Valid::assert_uniform_compat(); AlsoValid::assert_uniform_compat(); let data = Valid { a: 1.0, b: S { x: 2.0 } }; let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&data).unwrap(); ``` -------------------------------- ### impl_vector! Macro for Custom Vector Types in Rust Source: https://context7.com/teoxoy/encase/llms.txt Shows how to use the `impl_vector!` macro to automatically implement `ShaderType` for custom vector types from external libraries. This ensures compatibility with GPU buffers by handling layout and alignment. ```rust use encase::{impl_vector, ShaderType, StorageBuffer, vector::VectorScalar}; // Custom vector type from your math library #[derive(Clone, Copy)] struct MyVec3f { data: [f32; 3] } impl AsRef<[f32; 3]> for MyVec3f { fn as_ref(&self) -> &[f32; 3] { &self.data } } impl AsMut<[f32; 3]> for MyVec3f { fn as_mut(&mut self) -> &mut [f32; 3] { &mut self.data } } impl From<[f32; 3]> for MyVec3f { fn from(data: [f32; 3]) -> Self { MyVec3f { data } } } // Implement ShaderType with automatic trait derivation impl_vector!(3, MyVec3f; using AsRef AsMut From); // Now usable in GPU buffers let my_vec = MyVec3f { data: [1.0, 2.0, 3.0] }; let mut buffer = StorageBuffer::new(Vec::::new()); buffer.write(&my_vec).unwrap(); let bytes = buffer.into_inner(); assert_eq!(bytes.len(), 12); // 3 * 4 bytes with proper alignment ``` -------------------------------- ### Uniform Buffer Compile-Time Compatibility Checking in Rust Source: https://context7.com/teoxoy/encase/llms.txt Validate types at compile-time to ensure they meet uniform address space restrictions and layout constraints before GPU usage. The assert_uniform_compat() method checks for invalid patterns like runtime-sized arrays and stride requirements, preventing runtime GPU errors. ```rust use encase::ShaderType; // Runtime-sized arrays are NOT uniform compatible // >::assert_uniform_compat(); // Panics! // Arrays with stride < 16 bytes are NOT uniform compatible // <[f32; 2]>::assert_uniform_compat(); // Panics! (stride = 4) // Arrays with stride >= 16 bytes ARE uniform compatible <[test_impl::Vec4f; 2]>::assert_uniform_compat(); // OK (stride = 16) #[derive(ShaderType)] struct GoodUniform { value1: test_impl::Vec4f, value2: test_impl::Mat4x4f, array: [test_impl::Vec4f; 8], } // Check at compile time (will panic if invalid) GoodUniform::assert_uniform_compat(); // Use with UniformBuffer - automatically validates use encase::UniformBuffer; let data = GoodUniform { value1: test_impl::Vec4f::ONE, value2: test_impl::Mat4x4f::IDENTITY, array: [test_impl::Vec4f::ZERO; 8], }; let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&data).unwrap(); // Automatically calls assert_uniform_compat ``` -------------------------------- ### StorageBuffer Read/Write for WGSL in Rust Source: https://context7.com/teoxoy/encase/llms.txt Enables reading and writing data with WGSL storage buffer layout, including support for runtime-sized arrays. It handles data serialization and deserialization to/from a byte buffer, allowing modification of array lengths on the GPU side. ```rust use encase::{ShaderType, ArrayLength, StorageBuffer}; #[derive(ShaderType)] struct Positions { length: ArrayLength, #[shader(size(runtime))] positions: Vec } let mut positions = Positions { length: ArrayLength, positions: Vec::from([ test_impl::Vec2f::from([4.5, 3.4]), test_impl::Vec2f::from([1.5, 7.4]), test_impl::Vec2f::from([4.3, 1.9]), ]) }; // Write to buffer let mut byte_buffer: Vec = Vec::new(); let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.write(&positions).unwrap(); // Simulate GPU-side length modification byte_buffer[0] = 2; // Read back with modified length let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.read(&mut positions).unwrap(); assert_eq!(positions.positions.len(), 2); ``` -------------------------------- ### DynamicUniformBuffer Offset Management in Rust Source: https://context7.com/teoxoy/encase/llms.txt Demonstrates how to use DynamicUniformBuffer to read data from specific aligned offsets within a byte buffer. This is useful for simulating GPU buffer reads where data is not necessarily at the beginning of the buffer. ```rust use encase::DynamicUniformBuffer; // Simulate reading from GPU buffer let byte_buffer = [1u8; 256 + 8]; let mut buffer = DynamicUniformBuffer::new(&byte_buffer); // Set offset to read from specific location (must be aligned) buffer.set_offset(256); // Create instance by reading from buffer at offset let vector: test_impl::Vec2i = buffer.create().unwrap(); assert_eq!(vector, test_impl::Vec2i::from([16843009, 16843009])); ``` -------------------------------- ### impl_rts_array! Macro for Runtime-Sized Arrays in Rust Source: https://context7.com/teoxoy/encase/llms.txt Explains how to use the `impl_rts_array!` macro to implement `ShaderType` for custom runtime-sized array types, making them compatible with WGSL's runtime-sized arrays, typically used as the last member in storage buffer structs. ```rust use encase::{impl_rts_array, ShaderType, StorageBuffer, CalculateSizeFor}; use std::collections::VecDeque; // VecDeque already has impl_rts_array implementation, but here's how it works: // impl_rts_array!(VecDeque; using len truncate); #[derive(ShaderType)] struct ParticleSystem { #[shader(size(runtime))] particles: VecDeque } let mut system = ParticleSystem { particles: VecDeque::from([ test_impl::Vec4f::from([1.0, 2.0, 3.0, 4.0]), test_impl::Vec4f::from([5.0, 6.0, 7.0, 8.0]), ]) }; // Calculate size for specific element count let size = >::calculate_size_for(10); let mut byte_buffer = Vec::new(); let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.write(&system).unwrap(); // Read back buffer.read(&mut system).unwrap(); assert_eq!(system.particles.len(), 2); ``` -------------------------------- ### UniformBuffer Write Operations in Rust Source: https://context7.com/teoxoy/encase/llms.txt Wraps a byte buffer to facilitate writing data with automatic WGSL uniform address space compatibility and alignment. Supports custom structs derived with ShaderType, writing them into a Vec buffer for GPU upload. ```rust use encase::{ShaderType, UniformBuffer}; #[derive(ShaderType)] struct CameraData { view_matrix: test_impl::Mat4x4f, projection_matrix: test_impl::Mat4x4f, position: test_impl::Vec3f, } let camera = CameraData { view_matrix: test_impl::Mat4x4f::IDENTITY, projection_matrix: test_impl::Mat4x4f::IDENTITY, position: test_impl::Vec3f::from([10.0, 5.0, 0.0]), }; // Write to Vec buffer let mut byte_buffer = Vec::new(); let mut buffer = UniformBuffer::new(&mut byte_buffer); buffer.write(&camera).unwrap(); // byte_buffer now contains properly aligned data for GPU uniform buffer // You can now upload byte_buffer to GPU via wgpu/WebGPU APIs ``` -------------------------------- ### Derive ShaderType for Structs in Rust Source: https://context7.com/teoxoy/encase/llms.txt Automatically implements WGSL-compatible buffer traits for Rust structs, handling alignment and size. Accepts struct instances and writes them to a UniformBuffer, outputting raw bytes for GPU upload. ```rust use encase::{ShaderType, UniformBuffer}; // Simple struct with automatic layout #[derive(ShaderType)] struct AffineTransform2D { matrix: test_impl::Mat2x2f, translate: test_impl::Vec2f, } // Create instance and write to buffer let transform = AffineTransform2D { matrix: test_impl::Mat2x2f::IDENTITY, translate: test_impl::Vec2f::ZERO, }; let mut buffer = UniformBuffer::new(Vec::::new()); buffer.write(&transform).unwrap(); let byte_buffer = buffer.into_inner(); // Resulting bytes ready for GPU upload assert_eq!(&byte_buffer, &[ 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0 ]); ``` -------------------------------- ### DynamicStorageBuffer with Alignment in Rust Source: https://context7.com/teoxoy/encase/llms.txt Allows writing multiple data types to a single buffer with configurable dynamic offsets and alignment, suitable for dynamic uniform/storage buffer arrays. It returns the byte offset for each written element, ensuring proper alignment for GPU dynamic indexing. ```rust use encase::DynamicStorageBuffer; let mut byte_buffer: Vec = Vec::new(); // Create with 64-byte alignment (common for dynamic offsets) let mut buffer = DynamicStorageBuffer::new_with_alignment(&mut byte_buffer, 64); // Write multiple data types, returns offset for each write let offsets = [ buffer.write(&[5.0_f32; 10]).unwrap(), buffer.write(&vec![3u32; 20]).unwrap(), buffer.write(&test_impl::Vec3f::ONE).unwrap(), ]; // Offsets are properly aligned for GPU dynamic indexing assert_eq!(offsets, [0, 64, 192]); // byte_buffer now contains all data at aligned offsets // Use offsets with wgpu's dynamic offset binding ``` -------------------------------- ### ArrayLength Helper Type for Runtime-Sized Arrays in Rust Source: https://context7.com/teoxoy/encase/llms.txt Use ArrayLength to explicitly store and manage the length of runtime-sized arrays, solving issues with WGSL's arrayLength() function that may return incorrect values due to padding or capacity. The helper automatically sets array length during serialization and controls element count during deserialization. ```rust use encase::{ShaderType, ArrayLength, StorageBuffer}; #[derive(ShaderType)] struct Particles { length: ArrayLength, // Explicit length field active_count: u32, // Additional metadata #[shader(size(runtime))] positions: Vec } let mut particles = Particles { length: ArrayLength, // Automatically set on write active_count: 3, positions: vec![ test_impl::Vec4f::from([1.0, 2.0, 3.0, 1.0]), test_impl::Vec4f::from([4.0, 5.0, 6.0, 1.0]), test_impl::Vec4f::from([7.0, 8.0, 9.0, 1.0]), ] }; let mut byte_buffer = Vec::new(); let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.write(&particles).unwrap(); // Length is written as u32 to buffer (value: 3) // WGSL shader can read this as: let len = particles.length; // On read, ArrayLength controls how many elements are read let mut buffer = StorageBuffer::new(&mut byte_buffer); buffer.read(&mut particles).unwrap(); assert_eq!(particles.positions.len(), 3); ``` -------------------------------- ### Write to uninitialized memory buffer in Rust Source: https://github.com/teoxoy/encase/blob/main/README.md Demonstrates writing to a Vec> buffer instead of pre-allocated memory, then safely converting it to a Vec using unsafe code. This technique avoids unnecessary zero-initialization overhead when preparing GPU data. ```rust use std::mem::MaybeUninit; use encase::{ShaderType, DynamicStorageBuffer}; let mut uninit_buffer: Vec> = Vec::new(); let mut buffer = DynamicStorageBuffer::new_with_alignment(&mut uninit_buffer, 64); let offsets = [ buffer.write(&[5.; 10]).unwrap(), buffer.write(&vec![3u32; 20]).unwrap(), buffer.write(&test_impl::Vec3f::ONE).unwrap(), ]; // SAFETY: Vec and Vec> share the same layout. let byte_buffer: Vec = unsafe { Vec::from_raw_parts( uninit_buffer.as_mut_ptr().cast(), uninit_buffer.len(), uninit_buffer.capacity() ) }; std::mem::forget(uninit_buffer); // write byte_buffer to GPU assert_eq!(offsets, [0, 64, 192]); ``` -------------------------------- ### Read vector from dynamic uniform buffer at offset in Rust Source: https://github.com/teoxoy/encase/blob/main/README.md Shows how to read a specific data type from a DynamicUniformBuffer at a given offset. This is useful when multiple data structures are packed into a single buffer and you need to access them individually. ```rust use encase::DynamicUniformBuffer; // read byte_buffer from GPU let byte_buffer = [1u8; 256 + 8]; let mut buffer = DynamicUniformBuffer::new(&byte_buffer); buffer.set_offset(256); let vector: test_impl::Vec2i = buffer.create().unwrap(); assert_eq!(vector, test_impl::Vec2i::from([16843009, 16843009])); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.