summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-12-23 06:56:19 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-12-23 06:56:19 +0000
commitd80f5d9b2d769fd0513ae0e026d8a56b5d56a1fe (patch)
treef4c2d1959618a7e69c23a3819dce15431034d68d /Graphics
parentAdded clamp() function to math lib (diff)
downloadDiligentCore-d80f5d9b2d769fd0513ae0e026d8a56b5d56a1fe.tar.gz
DiligentCore-d80f5d9b2d769fd0513ae0e026d8a56b5d56a1fe.zip
Implemented split barriers (closed https://github.com/DiligentGraphics/DiligentCore/issues/43).
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.h15
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h51
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp8
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandContext.cpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp12
5 files changed, 100 insertions, 21 deletions
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.h b/Graphics/GraphicsEngine/include/DeviceContextBase.h
index 959eafae..51420d83 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.h
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.h
@@ -934,12 +934,13 @@ void DeviceContextBase<BaseInterface,ImplementationTraits> ::
{
DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer members of StateTransitionDesc must not be null");
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
+ RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN;
if (Barrier.pTexture)
{
const auto& TexDesc = Barrier.pTexture->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, true), "Invlaid new state specified for texture '", TexDesc.Name, "'");
- auto OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pTexture->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of texture '", TexDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
DEV_CHECK_ERR(VerifyResourceStates(OldState, true), "Invlaid old state specified for texture '", TexDesc.Name, "'");
@@ -968,10 +969,20 @@ void DeviceContextBase<BaseInterface,ImplementationTraits> ::
{
const auto& BuffDesc = Barrier.pBuffer->GetDesc();
DEV_CHECK_ERR(VerifyResourceStates(Barrier.NewState, false), "Invlaid new state specified for buffer '", BuffDesc.Name, "'");
- auto OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState();
+ OldState = Barrier.OldState != RESOURCE_STATE_UNKNOWN ? Barrier.OldState : Barrier.pBuffer->GetState();
DEV_CHECK_ERR(OldState != RESOURCE_STATE_UNKNOWN, "The state of buffer '", BuffDesc.Name, "' is unknown to the engine and is not explicitly specified in the barrier");
DEV_CHECK_ERR(VerifyResourceStates(OldState, false), "Invlaid old state specified for buffer '", BuffDesc.Name, "'");
}
+
+ if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
+ {
+ DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "For UAV barriers, transition type must be STATE_TRANSITION_TYPE_IMMEDIATE");
+ }
+
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ DEV_CHECK_ERR(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
+ }
}
template<typename BaseInterface, typename ImplementationTraits>
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index d515b2a1..1e605009 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -1659,6 +1659,24 @@ namespace Diligent
RESOURCE_STATE_COPY_SOURCE
};
+ /// State transition barrier type
+ enum STATE_TRANSITION_TYPE : Uint8
+ {
+ /// Perform state transition immediately.
+ STATE_TRANSITION_TYPE_IMMEDIATE = 0,
+
+ /// Begin split barrier. This mode only has effect in Direct3D12 backend, and corresponds to
+ /// [D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY](https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_resource_barrier_flags)
+ /// flag. See https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#split-barriers.
+ /// In other backends, begin-split barriers are ignored.
+ STATE_TRANSITION_TYPE_BEGIN,
+
+ /// End split barrier. This mode only has effect in Direct3D12 backend, and corresponds to
+ /// [D3D12_RESOURCE_BARRIER_FLAG_END_ONLY](https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ne-d3d12-d3d12_resource_barrier_flags)
+ /// flag. See https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#split-barriers.
+ /// In other backends, this mode is similar to STATE_TRANSITION_TYPE_IMMEDIATE.
+ STATE_TRANSITION_TYPE_END
+ };
/// Resource state transition barrier description
struct StateTransitionDesc
@@ -1693,25 +1711,31 @@ namespace Diligent
/// Resource state after transition.
RESOURCE_STATE NewState = RESOURCE_STATE_UNKNOWN;
+ /// State transition type, see Diligent::STATE_TRANSITION_TYPE.
+
+ /// \note When issuing UAV barrier (i.e. OldState and NewState equal RESOURCE_STATE_UNORDERED_ACCESS),
+ /// TransitionType must be STATE_TRANSITION_TYPE_IMMEDIATE.
+ STATE_TRANSITION_TYPE TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE;
+
/// If set to true, the internal resource state will be set to NewState and the engine
- /// will be able to take the resource state management. In this case it is the
+ /// will be able to take over the resource state management. In this case it is the
/// responsibility of the application to make sure that all subresources are indeed in
/// designated state.
- /// If set to false, internal resource state will be set to RESOURCE_STATE_UNKNOWN, and the
- /// engine will not manage or check the resource state in all further operations until the
- /// state is set to a known value.
+ /// If set to false, internal resource state will be unchanged.
+ /// \note When TransitionType is STATE_TRANSITION_TYPE_BEGIN, this member must be false.
bool UpdateResourceState = false;
StateTransitionDesc(){}
- StateTransitionDesc(ITexture* _pTexture,
- RESOURCE_STATE _OldState,
- RESOURCE_STATE _NewState,
- Uint32 _FirstMipLevel = 0,
- Uint32 _MipLevelsCount = RemainingMipLevels,
- Uint32 _FirstArraySlice = 0,
- Uint32 _ArraySliceCount = RemainingArraySlices,
- bool _UpdateState = false) :
+ StateTransitionDesc(ITexture* _pTexture,
+ RESOURCE_STATE _OldState,
+ RESOURCE_STATE _NewState,
+ Uint32 _FirstMipLevel = 0,
+ Uint32 _MipLevelsCount = RemainingMipLevels,
+ Uint32 _FirstArraySlice = 0,
+ Uint32 _ArraySliceCount = RemainingArraySlices,
+ STATE_TRANSITION_TYPE _TransitionType = STATE_TRANSITION_TYPE_IMMEDIATE,
+ bool _UpdateState = false) :
pTexture (_pTexture),
FirstMipLevel (_FirstMipLevel),
MipLevelsCount (_MipLevelsCount),
@@ -1719,6 +1743,7 @@ namespace Diligent
ArraySliceCount (_ArraySliceCount),
OldState (_OldState),
NewState (_NewState),
+ TransitionType (_TransitionType),
UpdateResourceState (_UpdateState)
{}
@@ -1726,7 +1751,7 @@ namespace Diligent
RESOURCE_STATE _OldState,
RESOURCE_STATE _NewState,
bool _UpdateState) :
- StateTransitionDesc(_pTexture, _OldState, _NewState, 0, RemainingMipLevels, 0, RemainingArraySlices, _UpdateState)
+ StateTransitionDesc(_pTexture, _OldState, _NewState, 0, RemainingMipLevels, 0, RemainingArraySlices, STATE_TRANSITION_TYPE_IMMEDIATE, _UpdateState)
{}
StateTransitionDesc(IBuffer* _pBuffer,
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index e04686a9..8ee4090b 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -1871,6 +1871,14 @@ namespace Diligent
DEV_CHECK_ERR((Barrier.pTexture != nullptr) ^ (Barrier.pBuffer != nullptr), "Exactly one of pTexture or pBuffer must not be null");
DEV_CHECK_ERR(Barrier.NewState != RESOURCE_STATE_UNKNOWN, "New resource state can't be unknown");
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ // Skip begin-split barriers
+ VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
+ continue;
+ }
+ VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
+
if (Barrier.pTexture)
{
auto* pTextureD3D11Impl = ValidatedCast<TextureBaseD3D11>(Barrier.pTexture);
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
index 71859d23..a007a01f 100644
--- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
@@ -120,6 +120,24 @@ void CommandContext::InsertUAVBarrier(ID3D12Resource* pd3d12Resource)
BarrierDesc.UAV.pResource = pd3d12Resource;
}
+static D3D12_RESOURCE_BARRIER_FLAGS TransitionTypeToD3D12ResourceBarrierFlag(STATE_TRANSITION_TYPE TransitionType)
+{
+ switch(TransitionType)
+ {
+ case STATE_TRANSITION_TYPE_IMMEDIATE:
+ return D3D12_RESOURCE_BARRIER_FLAG_NONE;
+
+ case STATE_TRANSITION_TYPE_BEGIN:
+ return D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY;
+
+ case STATE_TRANSITION_TYPE_END:
+ return D3D12_RESOURCE_BARRIER_FLAG_END_ONLY;
+
+ default:
+ UNEXPECTED("Unexpected state transition type");
+ return D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ }
+}
void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
{
@@ -175,8 +193,8 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
NewState = static_cast<RESOURCE_STATE>(OldState | NewState);
D3D12_RESOURCE_BARRIER BarrierDesc;
- BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
- BarrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ BarrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ BarrierDesc.Flags = TransitionTypeToD3D12ResourceBarrierFlag(Barrier.TransitionType);
BarrierDesc.Transition.pResource = pd3d12Resource;
BarrierDesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
BarrierDesc.Transition.StateBefore = ResourceStateFlagsToD3D12ResourceStates(OldState);
@@ -217,13 +235,21 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
if (pTextureD3D12Impl)
{
- pTextureD3D12Impl->SetState(Barrier.UpdateResourceState ? NewState : RESOURCE_STATE_UNKNOWN);
+ VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END), "Texture state can't be updated in begin-split barrier");
+ if (Barrier.UpdateResourceState)
+ {
+ pTextureD3D12Impl->SetState(NewState);
+ }
}
else
{
VERIFY_EXPR(pBufferD3D12Impl);
- pBufferD3D12Impl->SetState(Barrier.UpdateResourceState ? NewState : RESOURCE_STATE_UNKNOWN);
+ VERIFY(!Barrier.UpdateResourceState || (Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END), "Buffer state can't be updated in begin-split barrier");
+ if (Barrier.UpdateResourceState)
+ {
+ pBufferD3D12Impl->SetState(NewState);
+ }
if (pBufferD3D12Impl->GetDesc().Usage == USAGE_DYNAMIC && (pBufferD3D12Impl->GetDesc().BindFlags & (BIND_SHADER_RESOURCE|BIND_UNORDERED_ACCESS)) == 0)
VERIFY(pBufferD3D12Impl->GetState() == RESOURCE_STATE_GENERIC_READ, "Dynamic buffers without SRV/UAV bind flag are expected to never transition from RESOURCE_STATE_GENERIC_READ state");
@@ -232,6 +258,7 @@ void CommandContext::TransitionResource(const StateTransitionDesc& Barrier)
if (OldState == RESOURCE_STATE_UNORDERED_ACCESS && Barrier.NewState == RESOURCE_STATE_UNORDERED_ACCESS)
{
+ DEV_CHECK_ERR(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE, "UAV barriers must not be split");
InsertUAVBarrier(pd3d12Resource);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 856d20ca..b34daae6 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -1859,7 +1859,6 @@ namespace Diligent
void DeviceContextVkImpl::TransitionBufferState(BufferVkImpl& BufferVk, RESOURCE_STATE OldState, RESOURCE_STATE NewState, bool UpdateBufferState)
{
- EnsureVkCmdBuffer();
if (OldState == RESOURCE_STATE_UNKNOWN)
{
if (BufferVk.IsInKnownState())
@@ -1889,6 +1888,7 @@ namespace Diligent
DEV_CHECK_ERR(BufferVk.m_VulkanBuffer != VK_NULL_HANDLE, "Cannot transition suballocated buffer");
VERIFY_EXPR(BufferVk.GetDynamicOffset(m_ContextId, this) == 0);
+ EnsureVkCmdBuffer();
auto vkBuff = BufferVk.GetVkBuffer();
auto OldAccessFlags = ResourceStateFlagsToVkAccessFlags(OldState);
auto NewAccessFlags = ResourceStateFlagsToVkAccessFlags(NewState);
@@ -1936,7 +1936,7 @@ namespace Diligent
void DeviceContextVkImpl::TransitionResourceStates(Uint32 BarrierCount, StateTransitionDesc* pResourceBarriers)
{
- if(BarrierCount == 0)
+ if (BarrierCount == 0)
return;
EnsureVkCmdBuffer();
@@ -1947,6 +1947,14 @@ namespace Diligent
#ifdef DEVELOPMENT
DvpVerifyStateTransitionDesc(Barrier);
#endif
+ if (Barrier.TransitionType == STATE_TRANSITION_TYPE_BEGIN)
+ {
+ // Skip begin-split barriers
+ VERIFY(!Barrier.UpdateResourceState, "Resource state can't be updated in begin-split barrier");
+ continue;
+ }
+ VERIFY(Barrier.TransitionType == STATE_TRANSITION_TYPE_IMMEDIATE || Barrier.TransitionType == STATE_TRANSITION_TYPE_END, "Unexpected barrier type");
+
if (Barrier.pTexture)
{
auto* pTextureVkImpl = ValidatedCast<TextureVkImpl>(Barrier.pTexture);