GLSL f16mat4 Matrix Multiplication Restrictions
Using explicit half-precision floating-point matrices like
f16mat4 in GLSL offers substantial memory bandwidth and
throughput improvements on supported hardware, but it introduces strict
mathematical, architectural, and language-level limitations. This
article outlines the operational restrictions imposed on
f16mat4 matrix multiplication, focusing on explicit type
safety rules, dynamic range boundaries, intermediate accumulation
semantics, and driver-level requirements.
Extension and Target Requirements
To use f16mat4, the shader must explicitly enable the
float16 arithmetic extension:
#extension GL_EXT_shader_explicit_arithmetic_types_float16 : requireCompilation requires targeting an environment that supports explicit
16-bit floating-point capabilities, such as SPIR-V 1.0+ with the
Float16 capability enabled, alongside underlying GPU
architecture support for native 16-bit operations. If the hardware lacks
native FP16 execution units, the driver may emulate the operation using
standard 32-bit floats, nullifying potential performance gains.
Strict Type Matching and Disallowed Conversions
Explicit precision extensions in GLSL enforce strict type matching.
Matrix multiplication involving f16mat4 is subject to the
following rules:
- No Implicit Promotion: Multiplication between an
f16mat4and a standard 32-bitmat4,vec4, or scalarfloatis strictly invalid. Mixed-precision matrix multiplication causes a compile-time error. - Explicit Casting Required: Any interaction between
standard types and explicit half-precision types requires explicit
constructor casting (e.g., converting a
vec4tof16vec4before multiplying by anf16mat4). - Operand Shape Compatibility: Standard linear
algebra sizing rules apply strictly. You may multiply an
f16mat4by anotherf16mat4, anf16mat4by anf16vec4(column vector transformation), or anf16vec4by anf16mat4(row vector transformation).
Dynamic Range and Overflow Constraints
Half-precision floats follow the IEEE 754 binary16 format, which severely restricts the valid numerical range compared to single-precision:
- Range Limits: The maximum representable finite value is \(65504\), and the minimum positive normalized value is approximately \(6.10 \times 10^{-5}\).
- Premature Overflow: A \(4 \times 4\) matrix multiplication computes each entry as the dot product of four products: \(\sum_{i=0}^{3} A_{ik} B_{kj}\). If intermediate products exceed \(65504\), the value immediately overflows to infinity (\(\text{Inf}\)). This can occur even if the inputs appear moderate (for example, multiplying coordinates larger than \(\sim 128\) by a scale factor larger than \(\sim 512\)).
- Rapid Precision Loss: With only 10 bits of mantissa (yielding roughly 3.3 decimal digits of precision), repeated matrix transforms (such as hierarchical model transforms) compound rounding errors significantly faster than 32-bit operations.
Intermediate Accumulation Semantics
Under GL_EXT_shader_explicit_arithmetic_types_float16,
the specification does not mandate intermediate 32-bit accumulation for
dot products and matrix operations. Unless an implementation
specifically optimizes or targets a fused multiply-add path with
extended precision, both the intermediate multiplications and additions
occur in native 16-bit precision. Consequently, precision is truncated
at each addition step within the 4-component dot product, increasing
truncation bias.
Subnormal Flushing (FTZ)
Many GPU architectures operate on 16-bit floating-point values using Flush-to-Zero (FTZ) mode by default to maximize throughput:
- Numbers smaller than the minimum normalized value (\(2^{-14} \approx 6.10 \times 10^{-5}\)) are automatically flushed to zero.
- Denormalized inputs to an
f16mat4multiplication are often treated as zero before computation begins. - Fine-scale translation or minute rotation increments in a matrix
will collapse to zero, leading to visible stuttering or geometric
cracking if
f16mat4is used directly for world-space vertex positioning.
Memory Layout and Alignment Rules
When loading or storing f16mat4 matrices via Uniform
Buffer Objects (UBO) or Shader Storage Buffer Objects (SSBO):
- Under
std140, packing rules generally pad matrix columns up to standard base alignment boundaries, often requiring vector-equivalent padding. - Under
std430(orscalarlayout via extensions), anf16mat4is composed of four consecutivef16vec4columns, with each column aligned to 8 bytes (since eachfloat16_tis 2 bytes). Misaligned source memory will cause undefined behavior or invalid reads prior to the multiplication step.