Why glTF bufferView byteStride Must Be a Multiple of 4
In the glTF 2.0 specification, bufferView.byteStride
defines the stride in bytes between consecutive vertex attributes and
must strictly be a multiple of 4 (between 4 and 252 bytes). This
constraint exists primarily to enforce GPU memory alignment, ensure
compatibility with WebGL and OpenGL ES constraints, prevent hardware
performance penalties or crashes on mobile architectures, and enable
efficient zero-copy loading directly into graphics memory.
GPU Memory Alignment and Bus Architecture
Modern graphics processing units (GPUs) and CPUs access memory in
discrete chunks, typically 32-bit (4-byte), 64-bit, or 128-bit words.
When vertex attributes are packed into an interleaved buffer, unaligned
reads force the memory controller to perform multiple memory accesses to
fetch a single attribute value. By requiring byteStride to
be a multiple of 4, the glTF specification guarantees that attributes
within the buffer remain aligned to at least a 32-bit boundary across
sequential elements, maintaining maximum memory throughput across all
hardware architectures.
WebGL and OpenGL ES Requirements
glTF was designed from the ground up as a transmission format for the
web, closely aligning with WebGL and OpenGL ES standards. The graphics
command glVertexAttribPointer handles the vertex stride
parameter. In OpenGL ES and WebGL implementations—especially those
running on ARM-based mobile devices—providing a non-4-byte-aligned
offset or stride can lead to GL_INVALID_OPERATION errors,
software-emulated fallbacks, or hardware memory alignment faults. The
glTF format avoids these platform-specific failures by enforcing the
lowest common denominator required by standard WebGL
implementations.
Zero-Copy Loading
A core architectural goal of glTF is fast asset delivery with minimal
CPU overhead. When a 3D model is downloaded, the runtime should ideally
map the binary buffer directly to the GPU without needing to inspect,
repack, or shift individual byte arrays. If arbitrary strides (such as 3
or 5 bytes) were allowed, runtimes would need to allocate new memory and
repack the vertex buffers on the CPU before uploading them to VRAM.
Enforcing 4-byte increments guarantees that raw glTF binary buffers
(.bin or embedded base64) can be uploaded directly to GPU
buffer objects as-is.
Component Type Compatibility
Vertex attributes commonly use 32-bit floating-point numbers
(FLOAT), 16-bit integers
(SHORT/UNSIGNED_SHORT), or 8-bit integers
(BYTE/UNSIGNED_BYTE). While single 8-bit or
16-bit values do not naturally occupy 4 bytes, attributes are typically
grouped as vectors (e.g., a 4-component byte vector VEC4
for vertex colors occupies 4 bytes) or padded to match 4-byte
boundaries. Requiring byteStride to be a multiple of 4
ensures that common 32-bit scalar and vector components never shift out
of alignment over the course of iterating through thousands of
vertices.