When serialising a clear, save view desc so we can recreate it if needed

* This is a bit convoluted so follow with me here...
* As an optimisation, when not capturing a frame we serialise clears as
  clears for resources and mark those resources as clean. This way if a
  resource is cleared, then used in the frame, we don't have to worry
  about fetching or storing its initial data - we just replay the clear
  once while initialising and we're done.
* The alternative here is to mark a resource dirty when it's cleared,
  and then we might have to read back and serialise a completely flat
  image - rather wasteful.
* The problem is that if the resource is referenced but its view isn't
  then the view will be trimmed from the capture and we don't have it
  around to actually perform the clear. This only started being a
  problem when views were tracked in their own separate records.
* We can't create a circular dependency from view -> resource -> view
  as that would create cycles and keep lots of things alive pointlessly.
  Instead we add serialisation of the resource & view descriptor so that
  we can recreate the view on demand if need be. This adds 32 bytes to
  each clear and since clears aren't hugely frequent it's not a big deal
This commit is contained in:
baldurk
2016-06-21 12:38:23 +02:00
parent 75b1baa2c9
commit 6c02222fd6
3 changed files with 218 additions and 28 deletions
+201 -18
View File
@@ -6255,6 +6255,31 @@ bool WrappedID3D11DeviceContext::Serialise_ClearRenderTargetView(
{
SERIALISE_ELEMENT(ResourceId, View, GetIDForResource(pRenderTargetView));
// at time of writing we don't support the 11.3 DESC1, but for the sake
// of not having to bump serialisation version later we'll serialise that
// version of the descriptor. We can just alias the memory because the only
// difference is some union members got larger.
union
{
D3D11_RENDER_TARGET_VIEW_DESC1 Desc1;
D3D11_RENDER_TARGET_VIEW_DESC Desc;
} ViewDesc;
ResourceId resID;
RDCEraseEl(ViewDesc.Desc1);
if(m_State >= WRITING)
{
pRenderTargetView->GetDesc(&ViewDesc.Desc);
resID = ((WrappedID3D11RenderTargetView *)pRenderTargetView)->GetResourceResID();
}
if(m_State >= WRITING || m_pDevice->GetLogVersion() >= 0x000009)
{
m_pSerialiser->Serialise("ViewDesc", ViewDesc.Desc1);
m_pSerialiser->Serialise("resID", resID);
}
float Color[4] = {0};
if(m_State >= WRITING)
@@ -6262,11 +6287,34 @@ bool WrappedID3D11DeviceContext::Serialise_ClearRenderTargetView(
m_pSerialiser->SerialisePODArray<4>("ColorRGBA", Color);
if(m_State <= EXECUTING && m_pDevice->GetResourceManager()->HasLiveResource(View))
if(m_State <= EXECUTING)
{
m_pRealContext->ClearRenderTargetView(
UNWRAP(WrappedID3D11RenderTargetView, m_pDevice->GetResourceManager()->GetLiveResource(View)),
Color);
if(m_pDevice->GetResourceManager()->HasLiveResource(View))
{
m_pRealContext->ClearRenderTargetView(
UNWRAP(WrappedID3D11RenderTargetView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
Color);
}
else if(m_pDevice->GetLogVersion() >= 0x000009)
{
// no live view, we have to create one ourselves to clear with.
if(m_pDevice->GetResourceManager()->HasLiveResource(resID))
{
ID3D11RenderTargetView *view = NULL;
m_pDevice->CreateRenderTargetView(
(ID3D11Resource *)m_pDevice->GetResourceManager()->GetLiveResource(resID),
&ViewDesc.Desc, &view);
m_pRealContext->ClearRenderTargetView(UNWRAP(WrappedID3D11RenderTargetView, view), Color);
SAFE_RELEASE(view);
}
}
else
{
RDCWARN(
"No view was found to perform clear - data might be wrong. "
"Re-capture with latest RenderDoc to solve this issue.");
}
}
const string desc = m_pSerialiser->GetDebugStr();
@@ -6381,6 +6429,31 @@ bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewUint(
{
SERIALISE_ELEMENT(ResourceId, View, GetIDForResource(pUnorderedAccessView));
// at time of writing we don't support the 11.3 DESC1, but for the sake
// of not having to bump serialisation version later we'll serialise that
// version of the descriptor. We can just alias the memory because the only
// difference is some union members got larger.
union
{
D3D11_UNORDERED_ACCESS_VIEW_DESC1 Desc1;
D3D11_UNORDERED_ACCESS_VIEW_DESC Desc;
} ViewDesc;
ResourceId resID;
RDCEraseEl(ViewDesc.Desc1);
if(m_State >= WRITING)
{
pUnorderedAccessView->GetDesc(&ViewDesc.Desc);
resID = ((WrappedID3D11UnorderedAccessView *)pUnorderedAccessView)->GetResourceResID();
}
if(m_State >= WRITING || m_pDevice->GetLogVersion() >= 0x000009)
{
m_pSerialiser->Serialise("ViewDesc", ViewDesc.Desc1);
m_pSerialiser->Serialise("resID", resID);
}
UINT Values[4] = {0};
if(m_State >= WRITING)
@@ -6388,12 +6461,35 @@ bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewUint(
m_pSerialiser->SerialisePODArray<4>("Values", Values);
if(m_State <= EXECUTING && m_pDevice->GetResourceManager()->HasLiveResource(View))
if(m_State <= EXECUTING)
{
m_pRealContext->ClearUnorderedAccessViewUint(
UNWRAP(WrappedID3D11UnorderedAccessView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
Values);
if(m_pDevice->GetResourceManager()->HasLiveResource(View))
{
m_pRealContext->ClearUnorderedAccessViewUint(
UNWRAP(WrappedID3D11UnorderedAccessView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
Values);
}
else if(m_pDevice->GetLogVersion() >= 0x000009)
{
// no live view, we have to create one ourselves to clear with.
if(m_pDevice->GetResourceManager()->HasLiveResource(resID))
{
ID3D11UnorderedAccessView *view = NULL;
m_pDevice->CreateUnorderedAccessView(
(ID3D11Resource *)m_pDevice->GetResourceManager()->GetLiveResource(resID),
&ViewDesc.Desc, &view);
m_pRealContext->ClearUnorderedAccessViewUint(UNWRAP(WrappedID3D11UnorderedAccessView, view),
Values);
SAFE_RELEASE(view);
}
}
else
{
RDCWARN(
"No view was found to perform clear - data might be wrong. "
"Re-capture with latest RenderDoc to solve this issue.");
}
}
const string desc = m_pSerialiser->GetDebugStr();
@@ -6500,6 +6596,31 @@ bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewFloat(
{
SERIALISE_ELEMENT(ResourceId, View, GetIDForResource(pUnorderedAccessView));
// at time of writing we don't support the 11.3 DESC1, but for the sake
// of not having to bump serialisation version later we'll serialise that
// version of the descriptor. We can just alias the memory because the only
// difference is some union members got larger.
union
{
D3D11_UNORDERED_ACCESS_VIEW_DESC1 Desc1;
D3D11_UNORDERED_ACCESS_VIEW_DESC Desc;
} ViewDesc;
ResourceId resID;
RDCEraseEl(ViewDesc.Desc1);
if(m_State >= WRITING)
{
pUnorderedAccessView->GetDesc(&ViewDesc.Desc);
resID = ((WrappedID3D11UnorderedAccessView *)pUnorderedAccessView)->GetResourceResID();
}
if(m_State >= WRITING || m_pDevice->GetLogVersion() >= 0x000009)
{
m_pSerialiser->Serialise("ViewDesc", ViewDesc.Desc1);
m_pSerialiser->Serialise("resID", resID);
}
FLOAT Values[4] = {0};
if(m_State >= WRITING)
@@ -6507,12 +6628,35 @@ bool WrappedID3D11DeviceContext::Serialise_ClearUnorderedAccessViewFloat(
m_pSerialiser->SerialisePODArray<4>("Values", Values);
if(m_State <= EXECUTING && m_pDevice->GetResourceManager()->HasLiveResource(View))
if(m_State <= EXECUTING)
{
m_pRealContext->ClearUnorderedAccessViewFloat(
UNWRAP(WrappedID3D11UnorderedAccessView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
Values);
if(m_pDevice->GetResourceManager()->HasLiveResource(View))
{
m_pRealContext->ClearUnorderedAccessViewFloat(
UNWRAP(WrappedID3D11UnorderedAccessView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
Values);
}
else if(m_pDevice->GetLogVersion() >= 0x000009)
{
// no live view, we have to create one ourselves to clear with.
if(m_pDevice->GetResourceManager()->HasLiveResource(resID))
{
ID3D11UnorderedAccessView *view = NULL;
m_pDevice->CreateUnorderedAccessView(
(ID3D11Resource *)m_pDevice->GetResourceManager()->GetLiveResource(resID),
&ViewDesc.Desc, &view);
m_pRealContext->ClearUnorderedAccessViewFloat(
UNWRAP(WrappedID3D11UnorderedAccessView, view), Values);
SAFE_RELEASE(view);
}
}
else
{
RDCWARN(
"No view was found to perform clear - data might be wrong. "
"Re-capture with latest RenderDoc to solve this issue.");
}
}
const string desc = m_pSerialiser->GetDebugStr();
@@ -6621,11 +6765,50 @@ bool WrappedID3D11DeviceContext::Serialise_ClearDepthStencilView(
SERIALISE_ELEMENT(float, Depth, Depth_);
SERIALISE_ELEMENT(uint8_t, Stencil, Stencil_);
if(m_State <= EXECUTING && m_pDevice->GetResourceManager()->HasLiveResource(View))
D3D11_DEPTH_STENCIL_VIEW_DESC ViewDesc = {};
ResourceId resID;
if(m_State >= WRITING)
{
m_pRealContext->ClearDepthStencilView(
UNWRAP(WrappedID3D11DepthStencilView, m_pDevice->GetResourceManager()->GetLiveResource(View)),
ClearFlags, Depth, Stencil);
pDepthStencilView->GetDesc(&ViewDesc);
resID = ((WrappedID3D11DepthStencilView *)pDepthStencilView)->GetResourceResID();
}
if(m_State >= WRITING || m_pDevice->GetLogVersion() >= 0x000009)
{
m_pSerialiser->Serialise("ViewDesc", ViewDesc);
m_pSerialiser->Serialise("resID", resID);
}
if(m_State <= EXECUTING)
{
if(m_pDevice->GetResourceManager()->HasLiveResource(View))
{
m_pRealContext->ClearDepthStencilView(
UNWRAP(WrappedID3D11DepthStencilView,
m_pDevice->GetResourceManager()->GetLiveResource(View)),
ClearFlags, Depth, Stencil);
}
else if(m_pDevice->GetLogVersion() >= 0x000009)
{
// no live view, we have to create one ourselves to clear with.
if(m_pDevice->GetResourceManager()->HasLiveResource(resID))
{
ID3D11DepthStencilView *view = NULL;
m_pDevice->CreateDepthStencilView(
(ID3D11Resource *)m_pDevice->GetResourceManager()->GetLiveResource(resID), &ViewDesc,
&view);
m_pRealContext->ClearDepthStencilView(UNWRAP(WrappedID3D11DepthStencilView, view),
ClearFlags, Depth, Stencil);
SAFE_RELEASE(view);
}
}
else
{
RDCWARN(
"No view was found to perform clear - data might be wrong. "
"Re-capture with latest RenderDoc to solve this issue.");
}
}
const string desc = m_pSerialiser->GetDebugStr();
+15 -8
View File
@@ -202,14 +202,21 @@ D3D11InitParams::D3D11InitParams()
// and set some defaults if necessary).
// Here we list which non-current versions we support, and what changed
const uint32_t D3D11InitParams::D3D11_OLD_VERSIONS[D3D11InitParams::D3D11_NUM_SUPPORTED_OLD_VERSIONS] = {
0x000004, // from 0x4 to 0x5, we added the stream-out hidden counters in the context's
// Serialise_BeginCaptureFrame
0x000005, // from 0x5 to 0x6, several new calls were made 'drawcalls', like Copy &
// GenerateMips, with serialised debug messages
0x000006, // from 0x6 to 0x7, we added some more padding in some buffer & texture chunks to
// get larger alignment than 16-byte
0x000007, // from 0x7 to 0x8, we changed the UAV arrays in the render state to be D3D11.1
// sized and separate CS array.
// from 0x4 to 0x5, we added the stream-out hidden counters in the context's
// Serialise_BeginCaptureFrame
0x000004,
// from 0x5 to 0x6, several new calls were made 'drawcalls', like Copy &
// GenerateMips, with serialised debug messages
0x000005,
// from 0x6 to 0x7, we added some more padding in some buffer & texture chunks to
// get larger alignment than 16-byte
0x000006,
// from 0x7 to 0x8, we changed the UAV arrays in the render state to be D3D11.1
// sized and separate CS array.
0x000007,
// from 0x8 to 0x9, we added the view creation details to clear calls in the device
// record so that we can still perform the clear even if the view wasn't referenced.
0x000008,
};
ReplayCreateStatus D3D11InitParams::Serialise()
+2 -2
View File
@@ -61,10 +61,10 @@ struct D3D11InitParams : public RDCInitParams
UINT NumFeatureLevels;
D3D_FEATURE_LEVEL FeatureLevels[16];
static const uint32_t D3D11_SERIALISE_VERSION = 0x0000008;
static const uint32_t D3D11_SERIALISE_VERSION = 0x0000009;
// backwards compatibility for old logs described at the declaration of this array
static const uint32_t D3D11_NUM_SUPPORTED_OLD_VERSIONS = 4;
static const uint32_t D3D11_NUM_SUPPORTED_OLD_VERSIONS = 5;
static const uint32_t D3D11_OLD_VERSIONS[D3D11_NUM_SUPPORTED_OLD_VERSIONS];
// version number internal to d3d11 stream