Skip to content

Enhanced barriers and barrier builders.#97

Merged
crud89 merged 19 commits intomainfrom
enhanced-barriers
Apr 12, 2023
Merged

Enhanced barriers and barrier builders.#97
crud89 merged 19 commits intomainfrom
enhanced-barriers

Conversation

@crud89
Copy link
Copy Markdown
Owner

@crud89 crud89 commented Apr 6, 2023

Describe the pull request

This PR changes the barrier interface to make them more flexible to use. This is enabled by the enhanced barrier for DirectX 12, provided by the Agility SDK introduced in #95.

Barriers have been completely re-worked and now support more granular control over synchronization. The old ResourceState has been removed and got replaced by three new enumerations:

  • PipelineStage is a flag set that controls the pipeline stages to block.
  • ResourceAccess is a flag set that controls the access mode to allow/deny.
  • ImageLayout defines the different possible layouts for textures.

Note that the combinations of those enumerations in a barrier are not arbitrary, but follow rules. When debugging barriers, it is advised to use validation layers to ensure conformity for the target backend(s).

A barrier is always initialized with one or more PipelineStages to wait for and to continue with. The builder interface makes this easier to read:

// Ex.: Wait for compute stage to finish until continuing with a fragment stage.
device->buildBarrier().waitFor(PipelineStage::Compute).toContinueWith(PipelineStage::Fragment);

A barrier in LiteFX is a actually a set of multiple barriers in the individual backends, which share common wait/continue stages. Apart from that, it can contain any number and combination of the following three barrier types:

  • Global Barriers block all memory accesses for a certain ResourceAccess, until another ResourceAccess has finished. If possible, you should always block individual resources, since this may introduce unnecessary stalls. A global barrier is inserted by calling wait on the barrier object or using blockAccessTo without any resource on the builder interface.
  • Buffer Barriers block access to a certain buffer. The kind of accesses to block, as well the kind of accesses to wait for are configured using the ResourceAccess properties. Note that there's an overload, that takes a sub-resource (i.e. an element index in an array buffer). However, due to API support, this is reserved and effectively also blocks the whole buffer.
  • Iamge Barriers are used in a similar fashion to buffer layouts, but also to transition individual sub-resources or the whole image into another layout. Layout changes are tracked on the image, but it is also possible to specify any different ImageLayout in the input. This supports scenarios, where external synchronization appears or implicit layout changes are happening, that cannot be tracked. Apart from that, you should avoid those overloads.

Image or buffer barriers are inserted by calling any of the transition overloads on the barrier or the respective blockAccessTo on the builder. Note that a barrier without a wait or transition instruction will no-op and is not submitted to a command buffer.

Here's a more complete example of a barrier built through the new builder interface:

auto barrier = device.buildBarrier()
    // Insert a global barrier.
    .waitFor(PipelineStage::Compute)
        .toContinueWith(PipelineStage::Fragment)
    // Insert a buffer barrier.
    .blockAccessTo(buffer, ResourceAccess::ShaderRead)
        .untilFinishedWith(ResourceAccess::ShaderReadWrite)
    // Insert an image barrier.
    .blockAccessTo(image, ResourceAccess::ShaderRead)
        .subresource(0, 1).transitionLayout(ImageLayout::ShaderResource)
        .whenFinishedWith(ResourceAccess::ShaderReadWrite);

Related issues

Known issues

When not using multi-sampling, the renderer draws directly into the swap chain back buffer. In the DirectX 12 back-end, this causes the transition barrier from RenderTarget to Present layout to raise an validation error about an invalid legacy resource state. The error is described in detail in this repository. Since I do believe that this is a false-positive and all barriers are now using the enhanced barrier feature, this error is explicitly suppressed in the info queue as a (hopefully temporary) workaround.

@crud89 crud89 added Priority: High A high priority issue. Type: Requirement Vulkan πŸŒ‹ The issue involves the Vulkan backend. DX12 ❎ The issue involves the DX12 backend. labels Apr 6, 2023
@crud89 crud89 added this to the Alpha #04 milestone Apr 6, 2023
@crud89 crud89 self-assigned this Apr 6, 2023
@crud89 crud89 marked this pull request as ready for review April 12, 2023 08:55
@crud89 crud89 merged commit b2facd5 into main Apr 12, 2023
@crud89 crud89 deleted the enhanced-barriers branch April 12, 2023 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DX12 ❎ The issue involves the DX12 backend. Priority: High A high priority issue. Vulkan πŸŒ‹ The issue involves the Vulkan backend.

Projects

Status: v0.4.1

Development

Successfully merging this pull request may close these issues.

Enhance barrier interface. Add a builder interface for barriers.

1 participant