AVIF Shader Decoding Memory Alignment Rules

Decoding AVIF (AV1 Image File Format) images for use in graphics shaders requires strict adherence to memory alignment constraints across both CPU staging and GPU execution pipelines. Because AVIF relies on the AV1 video codec—often outputting YUV color spaces at 8-bit, 10-bit, or 12-bit depths—the decoded data must be correctly aligned to satisfy SIMD CPU decoding, driver transfer thresholds, and GPU hardware sampling architectures. Failing to align memory properly causes visual shearing, illegal memory access crashes, or costly fallback paths in graphics APIs such as Vulkan, DirectX 12, Metal, and WebGPU.

CPU Decoder SIMD Alignment

Before image data reaches a shader, CPU-based AV1 decoders (such as dav1d or libgav1) unpack the compressed bitstream. Modern decoders rely heavily on SIMD instructions (SSE4.1, AVX2, AVX-512, and ARM NEON).

  • Heap Allocation Boundaries: Decoder working buffers and target planar buffers must be aligned to at least 16-byte (SSE/NEON), 32-byte (AVX2), or 64-byte (AVX-512) boundaries.
  • Stride Padding: Each decoded scanline (stride/pitch) must be padded to a multiple of 16, 32, or 64 bytes, rather than tightly fitting the pixel width. Unaligned memory access in AV1 motion compensation and loop restoration filters degrades decoding throughput or triggers segmentation faults.

Staging Buffer to Texture Transfer Alignment

When transferring decoded AVIF pixel buffers from CPU host memory to GPU device memory, graphics APIs impose hardware-level pitch and offset restrictions.

  • Row Pitch (Stride) Alignment: Graphics APIs require the memory offset between consecutive rows of a staging buffer to match hardware boundaries. For example, Direct3D 12 and WebGPU mandate that the row pitch (bytesPerRow) must be an integer multiple of 256 bytes (D3D12_TEXTURE_DATA_PITCH_ALIGNMENT). Vulkan requires implementations to satisfy VkPhysicalDeviceLimits::optimalBufferCopyRowPitchAlignment.
  • Buffer Offset Alignment: The base address offset where the image or plane starts within a staging buffer must satisfy the API’s base alignment constraint (typically a multiple of 512 bytes in D3D12 or governed by optimalBufferCopyOffsetAlignment in Vulkan).

Pixel Format and Chroma Plane Alignment

AVIF natively encodes content using discrete Y, U, and V chroma planes, commonly in YUV 4:2:0, 4:2:2, or 4:4:4 sampling formats.

  • High Bit-Depth (10-bit and 12-bit): AV1 natively represents 10-bit and 12-bit components in 16-bit (short) scalar containers. Each channel element must align on a 2-byte boundary. When binding raw multi-channel textures (such as R16_UNORM), rows must remain word-aligned.
  • Chroma Subsampling Dimensions: For 4:2:0 subsampled images, the UV planes are half the width and height of the Y plane. If odd image dimensions are decoded, chroma plane memory allocation and pitch must round up to the nearest even dimension or SIMD chunk boundary to prevent out-of-bounds reading during shader sampling.

Shader Storage and Uniform Buffer Alignment (SSBO / UBO)

If the AVIF data is passed to compute shaders for custom debanding, color-space conversion, or direct software-rasterized decoding, shader memory layout rules apply:

  • std140 Layout (Uniform Buffers): Scalar elements and vectors align based on their size, rounded up to powers of two. A vec3 or vec4 requires 16-byte alignment. Array elements are rounded up to 16 bytes.
  • std430 Layout (Compute Storage Buffers): Tighter alignment than std140, but arrays of structures still require members to align to their naturally declared sizes (e.g., 4 bytes for 32-bit floats, 8 bytes for 64-bit vectors, 16 bytes for 4-component vectors).
  • Texel Buffers: When using buffer views (texelBuffer), the starting address must align to minTexelBufferOffsetAlignment in Vulkan or equivalent hardware limits.

Custom YUV-to-RGB Compute Shader Alignment

When converting multi-planar AVIF images to RGB within a compute shader:

  • Compute workgroups typically execute in 8x8 or 16x16 pixel blocks.
  • Shared memory (groupshared / shared) allocations for caching YUV values must be mapped to 4-byte or 16-byte bank-conflict-free boundaries to ensure coalesced reads across shader threads.
  • If planar data is kept separate and sampled via planar textures, bind each plane with individual linear strides matching the power-of-two boundaries designated by the target platform.