DirectX 12 Enhanced Barriers in Agility SDK
Enhanced barriers in the DirectX 12 Agility SDK provide a modernized,
fine-grained synchronization model designed to replace the original,
coarse-grained resource barrier system. By decoupling execution
synchronization, cache flushes, and texture layout transitions, enhanced
barriers give developers precise control over GPU hardware, reducing
unnecessary pipeline stalls and improving memory efficiency. This
article details the architectural shift from legacy
D3D12_RESOURCE_BARRIER structures to the new buffer,
texture, and global barrier models.
Limitations of Legacy Resource Barriers
The original DirectX 12 barrier system relied on the
D3D12_RESOURCE_BARRIER structure, which grouped all
synchronization into three broad categories: Transition, Aliasing, and
Unordered Access View (UAV) barriers.
While functional, this legacy system had significant drawbacks:
- Coupled Semantics: Resource states
(
D3D12_RESOURCE_STATES) combined execution synchronization (which pipeline stages must finish), memory visibility (which caches must be flushed or invalidated), and layout transitions (decompression or tiling formats) into a single bitfield flag. - Redundant Operations: Combining multiple read or write states often forced the GPU driver to insert overly conservative pipeline stalls and redundant cache flushes to ensure safety.
- Subresource Overhead: Transitioning mip levels or array slices individually required separate barrier structures for each subresource, bloating the command stream and increasing CPU overhead.
The Architecture of Enhanced Barriers
Enhanced barriers eliminate the unified
D3D12_RESOURCE_STATES bitmask. Instead, synchronization is
split into three distinct, explicit components:
- Synchronization Scope
(
D3D12_BARRIER_SYNC): Specifies the exact GPU pipeline stages that must complete before the barrier can be passed (SyncBefore), and the stages that must wait until the barrier completes (SyncAfter). - Access Scope (
D3D12_BARRIER_ACCESS): Defines the specific CPU/GPU memory access and cache visibility requirements before (AccessBefore) and after (AccessAfter) the barrier. - Layout (
D3D12_BARRIER_LAYOUT): Dictates the hardware data compression and tiling format for texture resources, completely separated from memory access types.
How Enhanced Barriers Replace Legacy Structures
Instead of using
ID3D12GraphicsCommandList::ResourceBarrier, developers
submit enhanced barriers using
ID3D12GraphicsCommandList7::Barrier. This API accepts an
array of barrier groups (D3D12_BARRIER_GROUP), which
categorize synchronization into three dedicated structures.
1. Global Barriers
(D3D12_GLOBAL_BARRIER)
Legacy UAV barriers (D3D12_RESOURCE_BARRIER_TYPE_UAV)
were tied to specific resources, even though UAV synchronization often
applies globally across multiple dispatches.
The D3D12_GLOBAL_BARRIER replaces this by controlling
pipeline synchronization and memory access across the entire GPU without
referencing any individual resource pointer. It ensures that preceding
writes (like compute shader UAV writes) are visible to subsequent reads
across any stage, matching hardware-level cache flushes much closer than
the legacy model.
2. Buffer Barriers
(D3D12_BUFFER_BARRIER)
Buffers do not possess complex layouts or compression states; they
are simple linear allocations. The D3D12_BUFFER_BARRIER
structure explicitly reflects this by eliminating layout flags entirely.
It only defines:
- The resource pointer.
SyncBeforeandSyncAfterstages.AccessBeforeandAccessAfterstates.- Byte offset and size, allowing sub-allocation tracking.
This removes the overhead of treating buffers like textures within the driver, preventing unnecessary compression checks.
3. Texture Barriers
(D3D12_TEXTURE_BARRIER)
Texture transitions were the primary source of inefficiencies in
legacy barriers. D3D12_TEXTURE_BARRIER directly replaces
D3D12_RESOURCE_TRANSITION_BARRIER with major
improvements:
- Explicit Layout Transitions: Controls formats such as render targets, depth-stencil writes, or shader-readable states independently of cache invalidation.
- Native Range Support: A single structure can target
a contiguous range of subresources (mip slices, array slices, or planes)
using a
D3D12_BARRIER_SUBRESOURCE_RANGE, removing the need to issue loops of individual transition barriers. - Discard Flags: Includes flags like
D3D12_TEXTURE_BARRIER_FLAG_DISCARD, allowing the GPU to drop existing subresource data during transitions, bypassing redundant memory copies or decompressive resolves.
Key Advantages
By transitioning to enhanced barriers in the Agility SDK, applications gain:
- Lower Driver Overhead: Drivers spend less time inferring hardware intentions from overloaded bitmasks.
- Reduced Stalls: Finer control over pipeline stages avoids full pipeline flushes when only specific shader stages need coordination.
- Optimized Cache Use: Caches are only flushed and invalidated when the access masks explicitly demand it, improving overall memory bandwidth utilization.