Check more carefully if DX11 maps are intercepted properly. Closes #3603

* Maps are recorded as open whenever we intercept them, usually only falling off
  for high traffic resources or direct maps like WRITE_NO_OVERWRITE.
* Unmaps can be successful any time as long as they're intercepted as reads (no-
  op) or write discard (since we just need to intercept these).
* Unmaps from other write types require a map during an active capture to ensure
  we properly set up shadow pointers.
This commit is contained in:
baldurk
2025-05-05 12:42:28 +01:00
parent 2288237723
commit 62be3340a5
2 changed files with 24 additions and 7 deletions
+2
View File
@@ -60,6 +60,8 @@ struct MapIntercept
D3D11_MAP MapType;
UINT MapFlags;
CaptureState state;
bool verifyWrite;
void CopyFromD3D();
+22 -7
View File
@@ -7593,6 +7593,7 @@ bool WrappedID3D11DeviceContext::Serialise_Map(SerialiserType &ser, ID3D11Resour
intercept.InitWrappedResource(resMap, Subresource, appMem);
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
intercept.state = m_State;
RDCASSERT(pMappedResource);
*pMappedResource = intercept.app;
@@ -7610,6 +7611,7 @@ bool WrappedID3D11DeviceContext::Serialise_Map(SerialiserType &ser, ID3D11Resour
intercept.SetD3D(mappedResource);
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
intercept.state = m_State;
if(intercept.verifyWrite)
{
@@ -7726,6 +7728,7 @@ HRESULT WrappedID3D11DeviceContext::Map(ID3D11Resource *pResource, UINT Subresou
MapIntercept intercept;
intercept.MapType = MapType;
intercept.MapFlags = MapFlags;
intercept.state = m_State;
m_OpenMaps[MappedResource(GetIDForDeviceChild(pResource), Subresource)] = intercept;
}
@@ -8068,13 +8071,25 @@ void WrappedID3D11DeviceContext::Unmap(ID3D11Resource *pResource, UINT Subresour
}
else if(IsCaptureMode(m_State))
{
if(it == m_OpenMaps.end() && IsActiveCapturing(m_State))
// verify that the map was intercepted in a way that will allow us to finish capturing it. Read
// maps we can allow since they're a no-op, and discard maps we only need 'basic' interception
// to ensure the user wrote into our buffer which is the case if we have them in our list. Other
// types of maps such as plain D3D11_MAP_WRITE and WRITE_NO_OVERWRITE require shadow buffers to
// detect changes and this will not have been initialised unless we began the map during an
// active frame capture.
if(IsActiveCapturing(m_State))
{
RDCWARN(
"Saw an Unmap that we didn't capture the corresponding Map for - this frame is "
"unsuccessful");
m_SuccessfulCapture = false;
m_FailureReason = CaptureFailed_UncappedUnmap;
if(it == m_OpenMaps.end() ||
(!IsActiveCapturing(it->second.state) && it->second.MapType != D3D11_MAP_WRITE_DISCARD &&
it->second.MapType != D3D11_MAP_READ))
{
RDCWARN(
"Saw an Unmap that we didn't capture the corresponding Map for - this frame is "
"unsuccessful");
m_SuccessfulCapture = false;
m_FailureReason = CaptureFailed_UncappedUnmap;
m_OpenMaps.erase(it);
}
}
if(it != m_OpenMaps.end())
@@ -8095,7 +8110,7 @@ void WrappedID3D11DeviceContext::Unmap(ID3D11Resource *pResource, UINT Subresour
m_ContextRecord->AddChunk(scope.Get());
}
else // IsIdleCapturing(m_State)
else // IsBackgroundCapturing(m_State)
{
D3D11ResourceRecord *record =
m_pDevice->GetResourceManager()->GetResourceRecord(GetIDForDeviceChild(pResource));