Why Divergent UVs Cause Texture Cache Misses in GLSL
Sampling large, mipmapped textures using divergent UV coordinates in GLSL leads to severe texture cache misses primarily due to broken spatial locality across parallel execution threads and chaotic level-of-detail (LOD) calculations. When neighboring threads in a GPU warp or wavefront request texels from distant coordinates or different mipmap levels, the hardware's fixed-size texture cache cannot satisfy the disparate memory requests simultaneously. This article examines the architectural and mathematical reasons why UV divergence degrades texture sampling performance and explains the mechanisms that trigger these cache misses.
GPU SIMT Execution and Texture Cache Design
Modern GPUs process fragment shaders using Single Instruction, Multiple Threads (SIMT) grouped into units called warps (NVIDIA) or wavefronts (AMD), typically consisting of 32 to 64 threads. The hardware texture cache is optimized under the assumption of high spatial locality: neighboring fragment threads covering a 2x2 quad on screen are expected to sample texels that reside physically close to one another in GPU memory.
When adjacent threads access texels that reside in the same memory cache line, a single fetch satisfies multiple threads. However, divergent UV coordinates break this model. If neighboring threads sample distant UV coordinates, each thread requests a distinct, non-contiguous block of texel data, saturating the L1 and L2 texture caches and forcing the GPU to fetch data from high-latency global VRAM.
Implicit Derivatives and Mipmap Calculation
When invoking the standard texture() function in GLSL,
the GPU automatically selects a mipmap level based on implicit
screen-space derivatives:
vec2 dx = dFdx(uv);
vec2 dy = dFdy(uv);The hardware evaluates UV differences across adjacent fragments in 2x2 pixel quads. The magnitude of these derivatives determines the level-of-detail (\(\lambda\)):
\[\lambda = \log_2(\max(\|\frac{\partial uv}{\partial x}\|, \|\frac{\partial uv}{\partial y}\|))\]
UV divergence directly undermines this calculation:
- Derivative Spikes: Sharp, discontinuous changes in UVs between adjacent pixels generate massive derivative values. This causes the sampler to select a much lower resolution (coarser) mip level than intended.
- Intra-Warp LOD Divergence: Threads within the same warp can calculate wildly different LOD values. While thread A might sample from mip level 0, adjacent thread B may sample from mip level 5. This forces the texture unit to fetch from completely different memory offsets corresponding to separate mip allocations, multiplying cache thrashing.
The Impact of Large Texture Dimensions
As texture resolution increases (such as 4K or 8K textures), the
physical memory stride between normalized UV coordinates widens. A
normalized UV shift of 0.01 spans far more texels—and
consequently more distinct memory pages—in an 8192×8192 texture than in
a 512×512 texture.
Consequently, even modest UV divergence across neighboring threads on high-resolution textures triggers memory fetches that fall completely outside the local texture cache line (typically 64 or 128 bytes). The working set of requested texels rapidly exceeds cache capacity, evicting newly loaded lines before neighboring operations can reuse them.
Mitigating Divergence-Induced Misses
To resolve cache bottlenecks caused by divergent texture lookups, developers rely on specialized GLSL sampling methods:
Explicit Derivatives (
textureGrad): Manually passing continuous analytical derivatives prevents the hardware from computing erratic mip levels across discontinuous geometry (such as UV seams or cube map edges):vec4 color = textureGrad(u_Texture, uv, continuousDx, continuousDy);Explicit LOD Selection (
textureLod): Forcing a fixed or procedurally smoothed LOD bypasses implicit derivative logic entirely, ensuring threads in a warp access predictable mip levels:vec4 color = textureLod(u_Texture, uv, targetMipLevel);Minimizing Fragment Divergence: Sorting or restructuring draw calls and geometric data ensures that fragments mapped to adjacent screen pixels maintain coherent texture coordinate flows.