What is WGSL Memory Alignment?
When writing shaders in WebGPU Shading Language (WGSL), data passed from the CPU (JavaScript/C++) to the GPU must follow strict structural layouts in memory. This is called memory alignment.
The GPU's memory controller expects variables to begin at specific byte offsets based on their type. If you violate these rules, the GPU will read the wrong bytes, causing corrupted graphics, broken physics, or outright crashes in your WebGPU application.
The 16-Byte Chunk Rule & Data Types
Variables within a WGSL struct have specific alignment requirements:
f32,i32,u32: 4 bytes size, 4-byte alignment (can start at offsets 0, 4, 8, 12).vec2<f32>: 8 bytes size, 8-byte alignment (can start at offsets 0, 8, 16).vec3<f32>: 12 bytes size, 16-byte alignment (can ONLY start at offsets 0, 16, 32). This is a common trap!vec4<f32>: 16 bytes size, 16-byte alignment.mat4x4<f32>: 64 bytes size, 16-byte alignment.array<T, N>: Stride is generally aligned to 16 bytes when used inside uniform buffers (even for arrays of floats).
Uniform Buffers vs Storage Buffers
WebGPU defines two main buffer types which influence padding rules:
- Uniform Buffers: Highly optimized, read-only memory. Because of hardware requirements, WGSL strictly mandates that the total size of a Uniform struct must be a multiple of 16 bytes. If it isn't, empty padding is forced at the very end of the struct.
- Storage Buffers: Larger, more flexible read/write buffers. They do not require the entire struct to be a multiple of 16 bytes at the end, though the internal variables still obey their standard alignment rules.
Wasted Padding (The Red Bytes)
Because a vec3 requires a 16-byte alignment, if you place a vec3 immediately after an f32 (which takes up bytes 0-3), the vec3 cannot start at byte 4. It MUST jump to byte 16.
This forces the compiler to insert 12 bytes of empty padding (bytes 4-15). In this visualizer, padding is highlighted in red dashed lines. Wasted padding consumes precious GPU bandwidth and makes your uniform buffers artificially large.
Best Practices for Struct Packing
To achieve 0% wasted padding, data scientists and graphics engineers use struct packing strategies. You can use the Auto-Pack Optimizer in this tool to automatically do this for you.
- Largest to Smallest: Always declare your largest variables (matrices,
vec4) at the top of the struct, and the smallest (f32) at the bottom. This prevents large variables from getting "stuck" behind smaller ones and creating gaps. - Fill the Gaps: If you have a
vec3, it leaves 4 bytes of empty space at the end of its 16-byte chunk. Place a singlef32immediately after thevec3to perfectly pack the 16-byte block.