Fix D3D12 resource state transitions barriers

This commit is contained in:
Wojtek Figat
2021-06-08 14:12:31 +02:00
parent ab55c145f1
commit 9d9ecb3ba8
4 changed files with 78 additions and 56 deletions

View File

@@ -159,7 +159,7 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
if (ResourceStateDX12::IsTransitionNeeded(before, after))
{
AddTransitionBarrier(resource, before, after, D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES);
state.SetSubresourceState(subresourceIndex, after);
state.SetResourceState(after);
}
}
else
@@ -175,8 +175,8 @@ void GPUContextDX12::SetResourceState(ResourceOwnerDX12* resource, D3D12_RESOURC
}
}
ASSERT(state.CheckResourceState(after));
state.SetResourceState(after);
}
state.SetResourceState(after);
}
else
{
@@ -286,7 +286,7 @@ void GPUContextDX12::flushSRVs()
return;
// Bind all required slots and mark them as not dirty
_srMaskDirtyCompute &= ~srMask;
//_srMaskDirtyCompute &= ~srMask; // TODO: this causes visual artifacts sometimes, maybe use binary SR-dirty flag for all slots?
}
else
{
@@ -295,7 +295,7 @@ void GPUContextDX12::flushSRVs()
return;
// Bind all required slots and mark them as not dirty
_srMaskDirtyGraphics &= ~srMask;
//_srMaskDirtyGraphics &= ~srMask; // TODO: this causes visual artifacts sometimes, maybe use binary SR-dirty flag for all slots?
}
// Count SRVs required to be bind to the pipeline (the index of the most significant bit that's set)
@@ -309,7 +309,7 @@ void GPUContextDX12::flushSRVs()
{
const auto handle = _srHandles[i];
const auto dimensions = (D3D12_SRV_DIMENSION)header.SrDimensions[i];
if (handle != nullptr && dimensions)
if (srMask & (1 << i) && handle != nullptr && dimensions)
{
ASSERT(handle->SrvDimension == dimensions);
srcDescriptorRangeStarts[i] = handle->SRV();
@@ -360,7 +360,8 @@ void GPUContextDX12::flushRTVs()
if (_rtDepth)
{
depthBuffer = _rtDepth->DSV();
SetResourceState(_rtDepth->GetResourceOwner(), D3D12_RESOURCE_STATE_DEPTH_WRITE, _rtDepth->SubresourceIndex);
auto states = _rtDepth->ReadOnlyDepthView ? D3D12_RESOURCE_STATE_DEPTH_READ : D3D12_RESOURCE_STATE_DEPTH_WRITE;
SetResourceState(_rtDepth->GetResourceOwner(), states, _rtDepth->SubresourceIndex);
}
else
{
@@ -507,28 +508,33 @@ void GPUContextDX12::onDrawCall()
SetResourceState(_ibHandle, D3D12_RESOURCE_STATE_INDEX_BUFFER);
}
// If SRV resource is not binded to RTV then transition it to the whole state (GPU-BASED VALIDATION complains about it)
for (uint32 i = 0; i < GPU_MAX_SR_BINDED; i++)
if (_currentState)
{
const auto handle = _srHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
// If SRV resource is not binded to RTV then transition it to the whole state (GPU-BASED VALIDATION complains about it)
const uint32 srMask = _currentState->GetUsedSRsMask();
const uint32 srCount = Math::FloorLog2(srMask) + 1;
for (uint32 i = 0; i < srCount; i++)
{
const auto resourceOwner = handle->GetResourceOwner();
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
const auto handle = _srHandles[i];
if (srMask & (1 << i) && handle != nullptr && handle->GetResourceOwner())
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == resourceOwner)
const auto resourceOwner = handle->GetResourceOwner();
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
{
isRtv = true;
break;
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == resourceOwner)
{
isRtv = true;
break;
}
}
if (!isRtv)
{
D3D12_RESOURCE_STATES states = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
if (handle->IsDepthStencilResource())
states |= D3D12_RESOURCE_STATE_DEPTH_READ;
SetResourceState(handle->GetResourceOwner(), states);
}
}
if (!isRtv)
{
D3D12_RESOURCE_STATES states = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
if (handle->IsDepthStencilResource())
states |= D3D12_RESOURCE_STATE_DEPTH_READ;
SetResourceState(handle->GetResourceOwner(), states);
}
}
}
@@ -543,36 +549,39 @@ void GPUContextDX12::onDrawCall()
#if BUILD_DEBUG
// Additional verification of the state
for (int32 i = 0; i < _rtCount; i++)
if (_currentState)
{
const auto handle = _rtHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
for (int32 i = 0; i < _rtCount; i++)
{
const auto& state = handle->GetResourceOwner()->State;
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_RENDER_TARGET) != 0);
}
}
const uint32 srMask = _currentState->GetUsedSRsMask();
const uint32 srCount = Math::FloorLog2(srMask) + 1;
for (uint32 i = 0; i < srCount; i++)
{
const auto handle = _srHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
{
const auto& state = handle->GetResourceOwner()->State;
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
const auto handle = _rtHandles[i];
if (handle != nullptr && handle->GetResourceOwner())
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == handle->GetResourceOwner())
{
isRtv = true;
break;
}
const auto& state = handle->GetResourceOwner()->State;
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_RENDER_TARGET) != 0);
}
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) != 0);
if (!isRtv)
}
const uint32 srMask = _currentState->GetUsedSRsMask();
const uint32 srCount = Math::FloorLog2(srMask) + 1;
for (uint32 i = 0; i < srCount; i++)
{
const auto handle = _srHandles[i];
if (srMask & (1 << i) && handle != nullptr && handle->GetResourceOwner())
{
ASSERT(state.AreAllSubresourcesSame());
const auto& state = handle->GetResourceOwner()->State;
bool isRtv = false;
for (int32 j = 0; j < _rtCount; j++)
{
if (_rtHandles[j] && _rtHandles[j]->GetResourceOwner() == handle->GetResourceOwner())
{
isRtv = true;
break;
}
}
ASSERT((state.GetSubresourceState(handle->SubresourceIndex) & D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) != 0);
if (!isRtv)
{
ASSERT(state.AreAllSubresourcesSame());
}
}
}
}
@@ -1069,10 +1078,10 @@ void GPUContextDX12::ClearState()
void GPUContextDX12::FlushState()
{
// Flush
flushCBs();
flushSRVs();
flushRTVs();
flushUAVs();
//flushCBs();
//flushSRVs();
//flushRTVs();
//flushUAVs();
flushRBs();
//flushPS();
}