What Is the Difference Between std140 and std430?

In GLSL (OpenGL Shading Language), std140 and std430 are standard memory layout qualifiers that define how data structures are aligned and padded in GPU memory buffers. While std140 enforces strict 16-byte alignment rules across arrays and structures for Uniform Buffer Objects (UBOs), std430 provides a tighter, more cache-friendly layout designed specifically for Shader Storage Buffer Objects (SSBOs). Understanding the differences between these two layouts is essential for ensuring that host application memory (such as C++ structs) matches the layout expected by GPU shaders without corrupting data or introducing unnecessary padding.

Buffer Compatibility

The primary functional difference between the two memory layouts lies in where they can be legally used:

  • std140: Introduced in OpenGL 3.1, std140 is the standard layout for Uniform Buffer Objects (UBOs). It can also be applied to Shader Storage Buffer Objects (SSBOs), ensuring backward compatibility and cross-buffer layout consistency.
  • std430: Introduced in OpenGL 4.3 alongside SSBOs, std430 is valid only for SSBOs. It cannot be used for standard Uniform Buffer Objects.

Alignment and Padding Rules

Both layouts align fundamental types like float, int, vec2, and vec4 to multiples of their natural size (e.g., a float aligns to 4 bytes, a vec2 to 8 bytes, and a vec4 to 16 bytes). The major divergence occurs when handling arrays and nested structures.

Arrays and Array Elements

  • std140: Every element in an array is rounded up to the size of a vec4 (16 bytes), regardless of the actual data type. For example, an array of scalars like float values[4] consumes 64 bytes in std140 because each float is padded to 16 bytes (equivalent to a 16-byte stride).
  • std430: Array elements retain their natural base alignment. A float values[4] array in std430 occupies 16 contiguous bytes (4 bytes per element), and a vec2 coords[4] array occupies 32 bytes (8 bytes per element).

Structures and Nested Types

  • std140: The base alignment of a struct is rounded up to a multiple of 16 bytes (vec4 size). Any array of structs will also have its stride padded to a multiple of 16 bytes.
  • std430: A struct's alignment is determined solely by the largest base alignment of any of its member variables. If a struct contains only float and vec2 members, its alignment remains 8 bytes rather than being forced to 16 bytes.

Comparison Summary

Feature std140 std430
Supported Buffers Uniform Buffer Objects (UBOs), SSBOs Shader Storage Buffer Objects (SSBOs) only
Scalar Array Stride Padded to 16 bytes per element Natural alignment (4 bytes for float/int)
Vector Array Stride Always rounded up to 16 bytes Matches vector size (vec2 = 8 bytes, vec4 = 16 bytes)
Struct Alignment Always rounded up to a multiple of 16 bytes Largest member's natural alignment
Memory Efficiency Lower (higher padding overhead) Higher (compact packing)

Practical Host-Side Matching

When setting up data on the CPU in languages like C or C++, matching std430 is generally simpler because standard C++ struct packing rules closely resemble std430 natural alignment. In contrast, mapping data for a std140 buffer often requires explicit manual padding or alignment attributes (such as alignas(16)) to account for forced 16-byte boundaries on array elements and nested structs.