D3D12 Enhanced Barriers Preview
Good news for developers frustrated by confusing and inefficient D3D12 resource barriers, Enhanced Barriers are coming soon to D3D12, and are available now for experimental preview. Enhanced Barriers are a new set of D3D12 API’s that give developers independent control over GPU work synchronization, texture layout transitions, and cache flushing (“resource memory access”). Enhanced barriers replace resource state barriers with more expressive barrier types. Enhanced barriers offer less latency, support for concurrent read and write (including same-resource copy), diverse aliasing topologies, and better concurrency.
Although enhanced barriers are by no means “simpler” than legacy resource barriers, they are far less ambiguous, and therefore actually easier for developers to understand and reason about. The original resource barriers design was intended to abstract the nuance around cache flushing, hazard tracking, and texture layout using the concept of a “resource state”. However, this over-simplification caused as much harm as good in many ways. For one, developers are often forced to use expensive barriers when a less expensive (or even no) barrier should be allowed. For another, resource barriers are often incapable of fully expressing hardware-supported scenarios, such as concurrent read and write on a single resource or indicating resource state during aliasing transitions. And finally, developers must still understand the inner complexities behind resource states, such as state promotion and decay rules, “simple” vs “advanced” aliasing models, in order to use barriers effectively.
There are three types of Enhance Barriers: Buffer, Texture, and Global. All barriers control GPU work synchronization and read or write access types before and after the barrier. In addition, Texture Barriers manage layout of texture subresources. Conveniently, subresource selection can be expressed as a range of mip, array, and plane slices, in addition to the familiar one-or-all option used by legacy resource barriers. Buffer Barriers and Global Barriers control only synchronization and resource access and have no impact on resource layout (buffers don’t have a layout). Global Barriers affect all cached memory, and so they can be expensive and should only be used when a more scoped barrier is insufficient.
Resource state promotion and decay are a major source of developer confusion. Fortunately, enhanced barriers do not include such implicit state transitions. At the start of any command list execution, all resources initially have “common” access, meaning any resource may be accessed without a barrier so long as the access type is compatible with the current layout and create-time constraints (e.g. D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, etc). Since buffers have no layout, any buffer access type is allowed, again within the limits of create-time constraints. The only stateful attribute of a resource is texture layout. A texture subresource can only be in one layout at a time, and transitioning layout always requires a barrier.
All write operations must be finished and flushed using a barrier before any subsequent dependent access in the same ExecuteCommandLists scope. This is done by specifying before/after synchronization scopes and before/after access types in a barrier, as well as any before/after texture layout changes if required.
Frequently, developers want to write to one region of a buffer/subresource, while concurrently reading from a different region the same buffer/subresource. Unfortunately, legacy resource barrier rules prevent placing a resource in both read and write states at the same time. This is a necessary limitation imposed by the state model rather than by any hardware constraints. Fortunately, enhanced barriers do allow concurrent read and write access to the same subresource, including same-resource copy.
Managing aliased resources with legacy D3D12 barriers is difficult or impossible to handle efficiently. In many (most?) cases, developers simply use NULL/NULL aliasing barriers (akin to a sync-and-flush-everything barrier). Even then, the state of the affected resources may be ambiguous, requiring additional barriers to establish known states (which itself is a dubious act given the resource data may be ‘garbage’). In addition, Clear, Discard, or Copy operations are needed if aliased textures are to be used as render target or depth-stencil resources. Resource aliasing with enhanced barriers is much more direct. For example, finish and flush any work on ‘deactivating’ resources and declare a layout on any ‘activating’ textures, with the option to perform a full-texture Discard as part of the barrier. There are a variety of ways to accomplish aliasing transitions depending on whether data-sharing requirements or alignment of aliased resources. No matter what, there is a set of barriers to efficiently accomplish just about any aliasing scenario supported by hardware… or use a great big sync-and-flush-everything global barrier (the “kitchen sync”?) if simplicity is preferred.
Apps can use both legacy resource barriers and enhanced barriers simultaneously, with the limitation that a resource switching between these is first placed in RESOURCE_STATE_COMMON or BARRIER_LAYOUT_COMMON/BARRIER_ACCESS_COMMON. For the most part, the debug layer continues to validate legacy resource state for all resources that were last assigned a legacy state. However, GPU-Based Validation (GBV) cannot reasonably validate both legacy state and enhanced barriers state, so GBV always performs enhanced barrier validation when the underlying hardware supports enhanced barriers, reporting equivalent enhance barrier state for resources using a legacy barrier state. This means that some GBV errors may report layout or access bits errors on a resource that was transitioned using a legacy state. Not ideal, but over time this is expected to become less of an issue as developers switch to enhanced barriers. And yes, there is an option to force GBV to use legacy state validation. Note, GBV is not ship-ready in the initial enhanced barriers preview.
A preview Direct3D Agility SDK NuGet package with enhanced barriers is available here. Since this is a developer preview, the target machine must be in developer mode to use this SDK. Drivers with Enhanced Barriers support are currently under development, and we’ll share more information once these drivers are ready. In the meantime, the latest developer insider builds of Windows 11 supports enhanced barriers in the Microsoft Basic Display Adapter (a.k.a. WARP). For more on developer insider builds see here.