Allow D3D12 Implicit State Transitions

When transitioning from the COMMON state, an explicit ResourceBarrier
call is unnecessary and can be handled implicitly by the driver. This
acts as an optimization because no synchronization waits are required
when transitioning from the COMMON state.

Bug: dawn:167
Change-Id: Ifd45236dc51c339de8b9945e6f4e2a00934f3676
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/7920
Commit-Queue: Brandon Jones <brandon1.jones@intel.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Brandon Jones 2019-06-14 15:14:12 +00:00 committed by Commit Bot service account
parent e0a2ae8a0b
commit d1b4b5cba5
3 changed files with 48 additions and 2 deletions

View File

@ -130,6 +130,30 @@ namespace dawn_native { namespace d3d12 {
D3D12_RESOURCE_STATES lastState = D3D12BufferUsage(mLastUsage);
D3D12_RESOURCE_STATES newState = D3D12BufferUsage(newUsage);
// The COMMON state represents a state where no write operations can be pending, which makes
// it possible to transition to some states without synchronizaton (i.e. without an explicit
// ResourceBarrier call). This can be to 1) a single write state, or 2) multiple read
// states.
//
// Destination states used in Dawn that qualify for implicit transition for a buffer:
// COPY_SOURCE, VERTEX_AND_CONSTANT_BUFFER, INDEX_BUFFER, COPY_DEST, UNORDERED_ACCESS
// https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#implicit-state-transitions
{
static constexpr D3D12_RESOURCE_STATES kD3D12BufferReadOnlyStates =
D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER |
D3D12_RESOURCE_STATE_INDEX_BUFFER;
if (lastState == D3D12_RESOURCE_STATE_COMMON) {
bool singleWriteState = ((newState == D3D12_RESOURCE_STATE_COPY_DEST) ||
(newState == D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
bool readOnlyState = newState == (newState & kD3D12BufferReadOnlyStates);
if (singleWriteState ^ readOnlyState) {
return false;
}
}
}
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier->Transition.pResource = mResource.Get();

View File

@ -436,8 +436,8 @@ namespace dawn_native { namespace d3d12 {
if (ToBackend(usages.buffers[i])
->CreateD3D12ResourceBarrierIfNeeded(&barrier, usages.bufferUsages[i])) {
barriers.push_back(barrier);
ToBackend(usages.buffers[i])->SetUsage(usages.bufferUsages[i]);
}
ToBackend(usages.buffers[i])->SetUsage(usages.bufferUsages[i]);
}
for (size_t i = 0; i < usages.textures.size(); ++i) {
@ -445,8 +445,8 @@ namespace dawn_native { namespace d3d12 {
if (ToBackend(usages.textures[i])
->CreateD3D12ResourceBarrierIfNeeded(&barrier, usages.textureUsages[i])) {
barriers.push_back(barrier);
ToBackend(usages.textures[i])->SetUsage(usages.textureUsages[i]);
}
ToBackend(usages.textures[i])->SetUsage(usages.textureUsages[i]);
}
if (barriers.size()) {

View File

@ -186,6 +186,28 @@ namespace dawn_native { namespace d3d12 {
return false;
}
// The COMMON state represents a state where no write operations can be pending, and where
// all pixels are uncompressed. This makes it possible to transition to some states without
// synchronization (i.e. without an explicit ResourceBarrier call). This can be to 1) a
// single write state, or 2) multiple read states.
//
// Destination states that qualify for an implicit transition for a non-simulataneous-access
// texture: NON_PIXEL_SHADER_RESOURCE, PIXEL_SHADER_RESOURCE, COPY_SRC, COPY_DEST
// https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#implicit-state-transitions
{
static constexpr D3D12_RESOURCE_STATES kD3D12TextureReadOnlyStates =
D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
if (mLastState == D3D12_RESOURCE_STATE_COMMON) {
bool singleWriteState = (newState == D3D12_RESOURCE_STATE_COPY_DEST);
bool readOnlyState = newState == (newState & kD3D12TextureReadOnlyStates);
if (singleWriteState ^ readOnlyState) {
return false;
}
}
}
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier->Transition.pResource = mResourcePtr;