Texture Fetch Survey
This document surveys how texture fetch instructions are modeled in modern GPU APIs and how they are executed in practice on mainstream desktop and mobile GPUs.
Scope:
- OpenGL/GLSL, Vulkan/SPIR-V, Direct3D/HLSL, Metal
- Hardware behavior on NVIDIA, AMD, Intel, Apple (high-level, public information)
- Shader execution model (SIMT/SIMD waves/warps), divergence, and latency hiding
1) Are texture instructions sync, async, queued, mailboxed?
Short answer:
- In shader languages, texture fetches are exposed as regular expressions/instructions that return values in program order.
- In hardware, they are typically issued into texture/memory pipelines and serviced asynchronously relative to ALU progress, while preserving each lane's data dependencies.
- They are not generally exposed as user-visible "mailbox" primitives in graphics shaders, but internally they behave like queued requests with scoreboarding.
Practical model:
- A wave/warp executes ALU until it reaches a texture op.
- The texture op issues one or more requests (after address/filter setup).
- The wave may stall on dependent use of that result.
- The scheduler runs other ready waves to hide the latency.
- When data returns, the original wave becomes runnable again.
So texture fetches are best described as:
- Program-order synchronous from the shader author's perspective
- Internally pipelined, queued, and latency-hidden by wave scheduling
2) Texture instruction families and parameters
2.1 Common semantic families
| Family | Typical API forms | Coordinate domain | Filtering | LOD source |
|---|---|---|---|---|
| Implicit sample | GLSL texture, HLSL Sample, SPIR-V OpImageSampleImplicitLod |
Normalized (except rect/buffer forms) | Sampler-controlled | Hardware derivatives (mostly fragment) |
| Explicit LOD | GLSL textureLod, HLSL SampleLevel, SPIR-V OpImageSampleExplicitLod |
Normalized | Sampler-controlled | Shader-provided |
| Explicit gradients | GLSL textureGrad, HLSL SampleGrad, SPIR-V explicit grad image sample |
Normalized | Sampler-controlled | Shader-provided ddx/ddy |
| Texel fetch (unfiltered) | GLSL texelFetch, HLSL Load, SPIR-V OpImageFetch |
Integer texel space | None (point fetch) | Explicit mip / sample index |
| Gather | GLSL textureGather, HLSL Gather*, SPIR-V gather ops |
Normalized | Gather semantics (usually one channel x4 taps) | Implicit or explicit forms |
| Depth compare sample | Shadow samplers / comparison samplers | Normalized | Compare + filter behavior | Implicit/explicit variants |
2.2 Parameter types typically involved
| Parameter | Meaning | Notes |
|---|---|---|
Coordinates (x, y, z, uvw) |
Texture location | Usually normalized for sampled textures; integer for fetch/load forms |
| Array layer index | Selects texture array slice | Typically final coordinate component or separate parameter depending on API form |
| LOD / mip level | Chooses mip | Fractional values can blend between mips |
| Bias | Mip bias adjustment | Added to implicit LOD path |
Gradients (dPdx, dPdy) |
Explicit footprint derivatives | Commonly used when implicit derivatives are invalid/undesired |
| Offset | Constant texel offset | Often must be compile-time/static immediate in many forms |
| Sample index (MSAA) | Chooses sample in multisampled texture | Used in texel-fetch/load style MSAA access |
| Compare value | For depth comparison sampling | Used with shadow/compare samplers |
| Sampler state | Filter, address modes, anisotropy, LOD clamps, compare mode | Separate object in D3D/Vulkan/Metal-style binding models |
3) Coordinate systems: normalized vs pixel/texel
Normalized sampling:
- Coordinates in [0,1] range (subject to addressing mode)
- Used by regular filtered sample ops
- Better matches material/shading UV workflows
Integer texel-space access:
- Coordinates in pixel/texel units
- Used by
texelFetch/Loadstyle ops - Deterministic element addressing, no filtering
- Common in G-buffer, lookup tables, compute-like shader paths
Mipmap / sample addressing:
- Mip level explicit in fetch/load forms
- Implicit from derivatives in classic fragment sampling
- MSAA sample index explicit in fetch forms
4) Vendor-level execution tendencies (high level)
Important: APIs are largely cross-vendor; differences are mostly in scheduling, caches, compiler lowering, and throughput/latency behavior.
NVIDIA (warp model)
- Warp-based SIMT execution with deep latency hiding via many resident warps.
- Strong texture hardware with mature filtering and caching paths.
- Divergent texture coordinates typically expand memory footprint and reduce cache locality.
- Benefits from coherent UVs and minimized dependent texture chains.
AMD (wavefront model, wave32/wave64 variants)
- Wave scheduling and occupancy are central to hiding texture latency.
- Register/LDS pressure can reduce occupancy and reduce ability to hide memory waits.
- Divergent fetches can increase cache pressure and reduce effective throughput.
- Tooling often exposes occupancy and memory wait behavior explicitly.
Intel (EU/subslice model)
- Similar principles: thread-level parallelism, scoreboarded memory ops, cache hierarchy sensitivity.
- Compiler behavior and memory coalescing patterns can strongly affect texture-heavy shaders.
- Coherent access and reduced divergence improve utilization.
Apple (tile-based GPU architecture)
- Tile-based deferred rendering impacts where bandwidth is spent and what stays on-chip.
- Sampler state and filtering controls are explicit; normalized coordinates are standard for sampled paths.
- Texture-heavy passes are sensitive to tile memory behavior, format choice, and pass structure.
What differs most across vendors in practice
- Optimal occupancy point (more is not always better)
- Cache hierarchy behavior and line/tile organization details
- Cost profile of dependent reads, gather patterns, and anisotropic filtering
- Compiler lowering of high-level sampling sequences
5) Advantages and disadvantages of differing approaches
Implicit LOD sampling
Advantages:
- Simple shader code
- Good default mip choice in fragment shaders
- High quality for standard surface shading
Disadvantages:
- Less control
- Derivative-dependent behavior can be problematic in some control-flow patterns
Explicit LOD sampling
Advantages:
- Deterministic mip choice
- Useful in vertex/compute-like sampling and custom effects
Disadvantages:
- Easy to choose suboptimal mip (aliasing/blur)
- Can reduce hardware's automatic filtering quality decisions
Explicit gradient sampling
Advantages:
- Full footprint control
- Correctness when implicit derivatives are invalid/unavailable
Disadvantages:
- More parameters and complexity
- Bad gradients can hurt both quality and performance
Texel fetch/load (integer, unfiltered)
Advantages:
- Exact data access (no filter ambiguity)
- Strong fit for data textures, LUTs, screen-space indexed reads
Disadvantages:
- No filtering convenience
- Manual handling needed for interpolation-like behavior
Gather instructions
Advantages:
- Efficient neighborhood/channel gathering for some kernels
- Useful for PCF-like and custom filter logic
Disadvantages:
- Can increase bandwidth pressure if overused
- Benefit depends on hardware path and kernel shape
6) Divergent fetches inside one shader across many pixels/cores
When a wave/warp executes a texture op:
- If lanes access nearby coordinates, requests can be cache-friendly.
- If lanes diverge (random UVs/layers/mips), requests spread out and cache reuse drops.
- Hardware still executes under one control stream but may internally serialize or replay parts of work depending on architecture and operation.
Typical consequences of high divergence:
- More cache misses and longer average memory latency
- More outstanding requests needed to sustain throughput
- Lower effective sampling throughput per cycle
- Greater reliance on occupancy to hide stalls
How GPUs cope:
- Queue many in-flight requests
- Switch to other ready waves while waiting
- Use multi-level caches and specialized texture caches
- Track dependencies with scoreboards so ALU can proceed where possible
7) Vertex vs fragment texture fetch usage
Vertex shader texture usage
Common patterns:
- Displacement maps
- Skinning/animation lookup textures
- Lookup tables for procedural geometry
Characteristics:
- Fewer invocations than fragments for typical scenes
- Often explicit LOD usage (or no derivatives)
- Access patterns can be less spatially coherent than rasterized fragments, depending on mesh order
- Latency can matter but total fetch volume is usually lower than fragment stage in classic forward/deferred shading
Fragment shader texture usage
Common patterns:
- Base color, normal, roughness/metalness, AO, emissive, shadow maps
- G-buffer reads in deferred passes
- Post-processing chains
Characteristics:
- Very high invocation count
- Heavy reliance on implicit derivatives for mip selection
- Texture bandwidth/cache behavior often dominates pass cost
- Coherence of UVs and screen locality heavily influence performance
Summary comparison
| Aspect | Vertex | Fragment |
|---|---|---|
| Invocation volume | Lower | Much higher |
| Typical sampling mode | Explicit LOD / selective sample | Implicit LOD dominant |
| Bandwidth pressure | Usually moderate | Often high to extreme |
| Derivatives availability role | Limited/less central | Central for mip choice |
| Performance limiter tendency | ALU + occasional memory | Frequently texture/memory-bound |
8) API-level notes you can rely on
- OpenGL/GLSL distinguishes filtered sampling (
texture*) from exact texel access (texelFetch*). - HLSL similarly separates
Sample*family fromLoadand provides explicit LOD/gradient variants. - Metal sampler descriptors expose normalized coordinates, addressing/filtering, LOD clamps, anisotropy, compare mode, and related controls.
- Vulkan/SPIR-V models these as explicit image operations (
OpImageSample*,OpImageFetch, gather variants), with selected operands carrying LOD/grad/offset information.
9) Practical guidance
- Prefer coherent UVs and coherent control flow whenever possible.
- Use implicit LOD in standard fragment shading unless you have a clear reason not to.
- Use explicit LOD/grad in specialized passes (virtual texturing, custom filters, vertex/compute-like sampling).
- Keep an eye on occupancy and register pressure in texture-heavy shaders.
- Profile per vendor architecture; compiler and cache behavior can shift optimal choices.
10) Caveats
- Vendor implementation details are partly proprietary; this survey describes widely observed behavior and documented API semantics, not exact private microarchitecture.
- The best approach is workload-dependent: the same change can help one GPU and hurt another.
- "Async" here means hardware pipeline/scheduler overlap behavior, not a user-visible future/promise API in shader code.