Handle UpdateSubresource workaround needed on software command lists

This commit is contained in:
baldurk
2016-06-17 20:03:25 +02:00
parent 623e5681c2
commit a26a5c0665
4 changed files with 147 additions and 5 deletions
+9
View File
@@ -111,6 +111,15 @@ WrappedID3D11DeviceContext::WrappedID3D11DeviceContext(WrappedID3D11Device *real
const bool debugSerialiser = true;
#endif
m_NeedUpdateSubWorkaround = false;
{
D3D11_FEATURE_DATA_THREADING caps = {FALSE, FALSE};
hr = m_pDevice->CheckFeatureSupport(D3D11_FEATURE_THREADING, &caps, sizeof(caps));
if(SUCCEEDED(hr) && !caps.DriverCommandLists)
m_NeedUpdateSubWorkaround = true;
}
if(RenderDoc::Inst().IsReplayApp())
{
m_State = READING;
+2
View File
@@ -188,6 +188,8 @@ private:
ID3D11DeviceContext2 *m_pRealContext2;
bool m_NeedUpdateSubWorkaround;
set<D3D11ResourceRecord *> m_DeferredRecords;
map<ResourceId, int> m_MapResourceRecordAllocs;
+78 -3
View File
@@ -147,11 +147,63 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource1(ID3D11Resource *pD
if(m_State == READING)
RecordUpdateStats(DestResource, SourceDataLength, true);
if(flags == 0)
if(flags == ~0U)
{
byte *adjustedData = SourceData;
if(pBox && m_NeedUpdateSubWorkaround && GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
RDCWARN("oops!");
// apply the workaround for the data we're about to pass
D3D11_BOX alignedBox = *pBox;
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
if(WrappedID3D11Texture1D::IsAlloc(DestResource))
{
D3D11_TEXTURE1D_DESC desc;
((WrappedID3D11Texture1D *)DestResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture2D::IsAlloc(DestResource))
{
D3D11_TEXTURE2D_DESC desc;
((WrappedID3D11Texture2D *)DestResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture3D::IsAlloc(DestResource))
{
D3D11_TEXTURE3D_DESC desc;
((WrappedID3D11Texture3D *)DestResource)->GetDesc(&desc);
fmt = desc.Format;
}
else
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(DestResource));
}
// convert from pixels to blocks
if(IsBlockFormat(fmt))
{
alignedBox.left /= 4;
alignedBox.right /= 4;
alignedBox.top /= 4;
alignedBox.bottom /= 4;
}
// if we couldn't get a format it's a buffer, so work in bytes
if(fmt != DXGI_FORMAT_UNKNOWN)
adjustedData = adjustedData - (alignedBox.front * SourceDepthPitch) -
(alignedBox.top * SourceRowPitch) -
(alignedBox.left * GetByteSize(1, 1, 1, fmt, 0));
else
adjustedData = adjustedData - alignedBox.left;
}
m_pRealContext->UpdateSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, pBox,
SourceData, SourceRowPitch, SourceDepthPitch);
adjustedData, SourceRowPitch, SourceDepthPitch);
}
else
{
@@ -161,6 +213,16 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource1(ID3D11Resource *pD
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, pBox,
SourceData, SourceRowPitch, SourceDepthPitch, flags);
}
else if(flags == 0)
{
// if flags is 0 UpdateSubresource1 behaves identically to UpdateSubresource
// according to the docs. The only case is the deferred context bug workaround
// isn't needed, but this wasn't properly handled before, and now this ambiguity
// is resolved by passing ~0U as the flags to indicate a 'real' call to UpdateSubresource
m_pRealContext->UpdateSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, pBox,
SourceData, SourceRowPitch, SourceDepthPitch);
}
else
{
RDCERR("Replaying a D3D11.1 context without D3D11.1 available");
@@ -246,7 +308,7 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource1(ID3D11Resource *pD
RecordUpdateStats(DestResource,
SourceRowPitch * subHeight + SourceDepthPitch * subWidth * subHeight, true);
if(flags == 0)
if(flags == ~0U)
{
m_pRealContext->UpdateSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, NULL,
@@ -260,9 +322,22 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource1(ID3D11Resource *pD
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, NULL,
bufData, SourceRowPitch, SourceDepthPitch, flags);
}
else if(flags == 0)
{
// if flags is 0 UpdateSubresource1 behaves identically to UpdateSubresource
// according to the docs. The only case is the deferred context bug workaround
// isn't needed, but this wasn't properly handled before, and now this ambiguity
// is resolved by passing ~0U as the flags to indicate a 'real' call to UpdateSubresource
m_pRealContext->UpdateSubresource(
m_pDevice->GetResourceManager()->UnwrapResource(DestResource), DestSubresource, NULL,
bufData, SourceRowPitch, SourceDepthPitch);
}
else
{
RDCERR("Replaying a D3D11.1 context without D3D11.1 available");
m_pDevice->AddDebugMessage(
eDbgCategory_Portability, eDbgSeverity_High, eDbgSoruce_UnsupportedConfiguration,
"Replaying a call to UpdateSubresource1() without D3D11.1 available");
}
}
}
+58 -2
View File
@@ -5628,8 +5628,10 @@ bool WrappedID3D11DeviceContext::Serialise_UpdateSubresource(ID3D11Resource *pDs
const void *pSrcData, UINT SrcRowPitch,
UINT SrcDepthPitch)
{
// pass ~0U as the flags to indicate this came for UpdateSubresource, so we know to apply
// deferred context workarounds or not
return Serialise_UpdateSubresource1(pDstResource, DstSubresource, pDstBox, pSrcData, SrcRowPitch,
SrcDepthPitch, 0);
SrcDepthPitch, ~0U);
}
void WrappedID3D11DeviceContext::UpdateSubresource(ID3D11Resource *pDstResource, UINT DstSubresource,
@@ -5640,6 +5642,57 @@ void WrappedID3D11DeviceContext::UpdateSubresource(ID3D11Resource *pDstResource,
m_EmptyCommandList = false;
const void *pOrigSrcData = pSrcData;
if(pDstBox && m_NeedUpdateSubWorkaround && GetType() == D3D11_DEVICE_CONTEXT_DEFERRED)
{
// we need to apply the *inverse* of the workaround, which matches the broken D3D behaviour
// so that we end up pointing at the expected data.
D3D11_BOX alignedBox = *pDstBox;
DXGI_FORMAT fmt = DXGI_FORMAT_UNKNOWN;
if(WrappedID3D11Texture1D::IsAlloc(pDstResource))
{
D3D11_TEXTURE1D_DESC desc;
((WrappedID3D11Texture1D *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture2D::IsAlloc(pDstResource))
{
D3D11_TEXTURE2D_DESC desc;
((WrappedID3D11Texture2D *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else if(WrappedID3D11Texture3D::IsAlloc(pDstResource))
{
D3D11_TEXTURE3D_DESC desc;
((WrappedID3D11Texture3D *)pDstResource)->GetDesc(&desc);
fmt = desc.Format;
}
else
{
RDCASSERT(WrappedID3D11Buffer::IsAlloc(pDstResource));
}
// convert from pixels to blocks
if(IsBlockFormat(fmt))
{
alignedBox.left /= 4;
alignedBox.right /= 4;
alignedBox.top /= 4;
alignedBox.bottom /= 4;
}
// if we couldn't get a format it's a buffer, so work in bytes
if(fmt != DXGI_FORMAT_UNKNOWN)
pSrcData = ((const BYTE *)pSrcData) + (alignedBox.front * SrcDepthPitch) +
(alignedBox.top * SrcRowPitch) + (alignedBox.left * GetByteSize(1, 1, 1, fmt, 0));
else
pSrcData = ((const BYTE *)pSrcData) + (alignedBox.left);
}
if(m_State == WRITING_CAPFRAME)
{
SCOPED_SERIALISE_CONTEXT(UPDATE_SUBRESOURCE);
@@ -5842,8 +5895,11 @@ void WrappedID3D11DeviceContext::UpdateSubresource(ID3D11Resource *pDstResource,
}
}
// pass pOrigSrcData here because any workarounds etc need to be preserved as if we were never
// in the way intercepting things.
m_pRealContext->UpdateSubresource(m_pDevice->GetResourceManager()->UnwrapResource(pDstResource),
DstSubresource, pDstBox, pSrcData, SrcRowPitch, SrcDepthPitch);
DstSubresource, pDstBox, pOrigSrcData, SrcRowPitch,
SrcDepthPitch);
}
bool WrappedID3D11DeviceContext::Serialise_CopyStructureCount(ID3D11Buffer *pDstBuffer,