How GLSL packDouble2x32 Combines Two 32-Bit uints
This article provides an overview of how the GLSL built-in function
packDouble2x32 packs a two-component 32-bit unsigned
integer vector into a single 64-bit double-precision floating-point
number. It details the bit-level arrangement prescribed by the OpenGL
Shading Language specification, the specific placement of the least and
most significant bits, and how the underlying 64-bit sequence is
reinterpreted according to the IEEE 754 standard without undergoing
mathematical type conversion.
The packDouble2x32 function accepts a single parameter
of type uvec2 (a vector of two 32-bit unsigned integers)
and returns a single double. Its primary purpose is to
reconstruct a 64-bit representation that may have been split across
32-bit registers or buffers, common in graphics pipelines where memory
buses or certain stages are optimized around 32-bit words.
Under the GLSL specification, the packing operation treats the input
vector's components as raw bitfields rather than performing an
arithmetic conversion. The first component, v[0] (or
v.x), provides the 32 least significant bits (bits 0
through 31) of the resulting 64-bit value. The second component,
v[1] (or v.y), provides the 32 most
significant bits (bits 32 through 63). Conceptually, this operation
aligns with the bitwise expression
(uint64(v[1]) << 32) | uint64(v[0]).
Once these two 32-bit patterns are concatenated into a contiguous
64-bit word, the GPU reinterprets the resulting bit sequence directly as
an IEEE 754 double-precision floating-point value. In this format, bit
63 serves as the sign bit, bits 62 through 52 form the 11-bit biased
exponent, and bits 51 through 0 represent the 52-bit fractional
significand (mantissa). Because v.y supplies bits 32 to 63,
it dictates the sign, exponent, and the upper 20 bits of the mantissa,
while v.x supplies the remaining lower 32 bits of the
mantissa.
Because packDouble2x32 is a bitwise reinterpretation
(equivalent to a bit-cast), the values inside v.x and
v.y do not represent the whole and fractional parts of a
decimal number. If the combined 64-bit pattern matches special IEEE 754
encodings, the returned double will evaluate directly to
those values, such as subnormal numbers, positive or negative infinity,
or NaN (Not-a-Number). The inverse of this operation is handled by
unpackDouble2x32, which extracts a double back
into its constituent low and high 32-bit unsigned integers.