GLSL dvec3 vs vec3 ALU Throughput Impact

Switching from single-precision vec3 to double-precision dvec3 in desktop OpenGL Shading Language (GLSL) causes a severe reduction in Arithmetic Logic Unit (ALU) throughput. Desktop GPUs are fundamentally optimized for 32-bit floating-point math, meaning double-precision operations execute on dedicated, highly restricted hardware paths. This article explains how the FP64 execution bottleneck, register pressure, and pipeline stalls combine to reduce compute efficiency when using dvec3.

Hardware FP64-to-FP32 Execution Ratios

The primary factor limiting dvec3 throughput is the physical ratio of 64-bit floating-point (FP64) cores to 32-bit floating-point (FP32) cores on desktop GPUs. Consumer-grade architectures heavily deprioritize FP64 hardware to maximize silicon space for graphics and AI workloads:

  • NVIDIA GeForce (Ampere, Ada Lovelace): Typically features an FP64-to-FP32 throughput ratio of 1:64.
  • AMD Radeon (RDNA 2, RDNA 3): Typically features an FP64-to-FP32 throughput ratio of 1:16 or 1:32.

When processing a vec3, the GPU's primary vector or scalar execution units handle three 32-bit operations at full clock rate. When replacing it with a dvec3, the hardware must dispatch three 64-bit operations to the scarce FP64 units. On an NVIDIA GPU with a 1:64 ratio, the ALU throughput for these operations drops by a factor of 64, turning lightweight vector math into a massive computational bottleneck.

Register Allocation and Occupancy

Each component of a dvec3 requires 64 bits of storage, requiring 192 bits (24 bytes) in total, compared to 96 bits (12 bytes) for a vec3. In low-level GPU machine code, hardware registers are almost universally organized into 32-bit slots. Consequently, storing a single dvec3 requires six 32-bit physical registers instead of three.

This increased register demand leads to two performance degradations:

  1. Reduced Warp/Wavefront Occupancy: GPUs rely on having a high number of active warps (NVIDIA) or wavefronts (AMD) scheduled on a Streaming Multiprocessor (SM) or Compute Unit (CU) to hide memory and arithmetic latencies. As per-thread register usage doubles, fewer threads can run concurrently.
  2. Register Spilling: If the shader is already complex, the extra register load introduced by dvec3 variables increases the likelihood of spilling registers to local scratch memory (VRAM/L1 cache), drastically degrading throughput.

Instruction Latency and Pipeline Serialization

Double-precision ALUs often operate with longer instruction latencies than their single-precision counterparts. Because fewer FP64 execution units exist per hardware block, multiple threads in a warp cannot execute FP64 operations in parallel as easily as FP32 operations.

Instead, the hardware must serialize the execution across fewer execution units over multiple clock cycles. This leads to:

  • Increased issue-to-read latency for dependent instructions.
  • Stalled execution pipelines when alternating between single- and double-precision math, as execution units wait for instruction schedulers to clear the FP64 pipeline.

Vector Packing and Special Function Units

Desktop GPUs utilize scalar SIMT (Single Instruction, Multiple Threads) architectures. A vec3 splits cleanly into three independent scalar 32-bit instructions (e.g., ADD, MUL, FMA). Similarly, a dvec3 splits into three 64-bit instructions.

However, transcendentals and special functions (such as sin(), cos(), normalize(), or inversesqrt()) do not have native 64-bit Special Function Unit (SFU) hardware on desktop chips. While a normalize(vec3) uses fast reciprocal square root hardware, a normalize(dvec3) is expanded by the driver into a complex multi-instruction software emulation sequence using basic FP64 arithmetic, resulting in an order-of-magnitude throughput penalty.

Alternatives for Performance-Critical Shaders

Unless native double precision is strictly required for numerical stability (such as large-scale planetary coordinate systems), dvec3 should be avoided in performance-critical desktop GLSL code. Common alternatives include:

  • Camera-Relative Rendering: Subtracting the camera position on the CPU and passing relative offsets to the shader as standard vec3 values to eliminate precision jitter without FP64 cost.
  • Emulated Double Precision (DSFUN32): Representing 64-bit values as pairs of two 32-bit floats (float-float arithmetic). While this takes roughly 10 to 20 FP32 operations per math function, it is frequently faster on consumer GPUs than native FP64 hardware executing at a 1:64 rate.