Track resource states for initial states, apply barriers while recording

This commit is contained in:
baldurk
2016-07-10 18:09:43 +02:00
parent 3a3c2abd8a
commit e1fcde1d71
8 changed files with 172 additions and 2 deletions
@@ -92,6 +92,8 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::ExecuteCommandLists(
// TODO apply barriers from command list to current resource state tracking
m_pDevice->ApplyBarriers(record->bakedCommands->cmdInfo->barriers);
// need to lock the whole section of code, not just the check on
// m_State, as we also need to make sure we don't check the state,
// start marking dirty resources then while we're doing so the
+18
View File
@@ -45,6 +45,24 @@ enum D3D12ComponentMapping
{
};
UINT GetNumSubresources(const D3D12_RESOURCE_DESC *desc)
{
switch(desc->Dimension)
{
default:
case D3D12_RESOURCE_DIMENSION_UNKNOWN:
RDCERR("Unexpected resource dimension! %d", desc->Dimension);
break;
case D3D12_RESOURCE_DIMENSION_BUFFER: return 1;
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
return RDCMAX((UINT16)1, desc->DepthOrArraySize) * RDCMAX((UINT16)1, desc->MipLevels);
case D3D12_RESOURCE_DIMENSION_TEXTURE3D: return RDCMAX((UINT16)1, desc->MipLevels);
}
return 1;
}
string ToStrHelper<false, D3D12ComponentMapping>::Get(const D3D12ComponentMapping &el)
{
string ret;
+2
View File
@@ -37,6 +37,8 @@
// debugbreak.
#define D3D12NOTIMP(...) RDCDEBUG("D3D12 not implemented - " __VA_ARGS__)
UINT GetNumSubresources(const D3D12_RESOURCE_DESC *desc);
class WrappedID3D12Device;
template <typename RealType>
+34 -2
View File
@@ -462,6 +462,12 @@ void WrappedID3D12Device::FirstFrame(WrappedIDXGISwapChain3 *swap)
}
}
void WrappedID3D12Device::ApplyBarriers(vector<D3D12_RESOURCE_BARRIER> &barriers)
{
SCOPED_LOCK(m_ResourceStatesLock);
GetResourceManager()->ApplyBarriers(barriers, m_ResourceStates);
}
void WrappedID3D12Device::ReleaseSwapchainResources(WrappedIDXGISwapChain3 *swap)
{
if(swap)
@@ -502,9 +508,10 @@ bool WrappedID3D12Device::Serialise_WrapSwapchainBuffer(WrappedIDXGISwapChain3 *
// the original type will be stored in the texture below
Descriptor.Format = GetTypelessFormat(Descriptor.Format);
// create fake texture
HRESULT hr = E_INVALIDARG;
// TODO create fake backbuffer texture
if(FAILED(hr))
{
RDCERR("Failed to create fake back buffer, HRESULT: 0x%08x", hr);
@@ -517,6 +524,10 @@ bool WrappedID3D12Device::Serialise_WrapSwapchainBuffer(WrappedIDXGISwapChain3 *
fakeBB->SetName(L"Swap Chain Buffer");
GetResourceManager()->AddLiveResource(TexID, fakeBB);
SubresourceStateVector &states = m_ResourceStates[wrapped->GetResourceID()];
states.resize(1, D3D12_RESOURCE_STATE_PRESENT);
}
}
@@ -561,6 +572,13 @@ IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(WrappedIDXGISwapChain3 *swap,
Serialise_WrapSwapchainBuffer(swap, swapDesc, buffer, pRes);
record->AddChunk(scope.Get());
{
SCOPED_LOCK(m_ResourceStatesLock);
SubresourceStateVector &states = m_ResourceStates[id];
states.resize(1, D3D12_RESOURCE_STATE_PRESENT);
}
}
if(buffer == 0 && m_State >= WRITING)
@@ -785,11 +803,18 @@ bool WrappedID3D12Device::Serialise_BeginCaptureFrame(bool applyInitialState)
return true;
}
// TODO save initial resource states
vector<D3D12_RESOURCE_BARRIER> barriers;
{
SCOPED_LOCK(m_ResourceStatesLock); // not needed on replay, but harmless also
GetResourceManager()->SerialiseResourceStates(barriers, m_ResourceStates);
}
if(applyInitialState)
{
// apply initial resource states
for(size_t i = 0; i < barriers.size(); i++)
barriers[i].Transition.pResource = Unwrap(barriers[i].Transition.pResource);
}
return true;
@@ -1068,6 +1093,13 @@ bool WrappedID3D12Device::Serialise_ReleaseResource(ID3D12DeviceChild *res)
void WrappedID3D12Device::ReleaseResource(ID3D12DeviceChild *res)
{
D3D12NOTIMP("ReleaseResource");
ResourceId id = GetResID(res);
{
SCOPED_LOCK(m_ResourceStatesLock);
m_ResourceStates.erase(id);
}
}
bool WrappedID3D12Device::Serialise_SetShaderDebugPath(ID3D12DeviceChild *res, const char *p)
+7
View File
@@ -256,6 +256,11 @@ private:
ResourceId m_ResourceID;
D3D12ResourceRecord *m_DeviceRecord;
// used both on capture and replay side to track resource states. Only locked
// in capture
map<ResourceId, SubresourceStateVector> m_ResourceStates;
Threading::CriticalSection m_ResourceStatesLock;
struct SwapPresentInfo
{
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[8];
@@ -297,6 +302,8 @@ public:
void ReleaseSwapchainResources(IDXGISwapChain *swap, IUnknown **backbuffers, int numBackbuffers);
void FirstFrame(WrappedIDXGISwapChain3 *swap);
void ApplyBarriers(vector<D3D12_RESOURCE_BARRIER> &barriers);
void StartFrameCapture(void *dev, void *wnd);
bool EndFrameCapture(void *dev, void *wnd);
@@ -604,6 +604,9 @@ bool WrappedID3D12Device::Serialise_CreateCommittedResource(
ret = new WrappedID3D12Resource(ret, this);
GetResourceManager()->AddLiveResource(Res, ret);
SubresourceStateVector &states = m_ResourceStates[GetResID(ret)];
states.resize(GetNumSubresources(&desc), state);
}
}
@@ -659,6 +662,13 @@ HRESULT WrappedID3D12Device::CreateCommittedResource(const D3D12_HEAP_PROPERTIES
}
}
{
SCOPED_LOCK(m_ResourceStatesLock);
SubresourceStateVector &states = m_ResourceStates[wrapped->GetResourceID()];
states.resize(GetNumSubresources(pResourceDesc), InitialResourceState);
}
*ppvResource = (ID3D12Resource *)wrapped;
}
+91
View File
@@ -131,6 +131,97 @@ D3D12_CPU_DESCRIPTOR_HANDLE FromPortableHandle(D3D12ResourceManager *manager, Po
return D3D12_CPU_DESCRIPTOR_HANDLE();
}
// debugging logging for barriers
#if 1
#define BARRIER_DBG RDCLOG
#define BARRIER_ASSERT RDCASSERTMSG
#else
#define BARRIER_DBG(...)
#define BARRIER_ASSERT(...)
#endif
void D3D12ResourceManager::ApplyBarriers(vector<D3D12_RESOURCE_BARRIER> &barriers,
map<ResourceId, SubresourceStateVector> &states)
{
for(size_t b = 0; b < barriers.size(); b++)
{
D3D12_RESOURCE_TRANSITION_BARRIER &trans = barriers[b].Transition;
ResourceId id = GetResID(trans.pResource);
SubresourceStateVector &st = states[id];
// skip non-transitions, or begin-halves of transitions
if(barriers[b].Type != D3D12_RESOURCE_BARRIER_TYPE_TRANSITION ||
(barriers[b].Flags & D3D12_RESOURCE_BARRIER_FLAG_BEGIN_ONLY))
continue;
if(trans.Subresource == D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
{
for(size_t i = 0; i < st.size(); i++)
{
BARRIER_ASSERT("Mismatching before state", st[i] == trans.StateBefore, st[i],
trans.StateBefore, i);
st[i] = trans.StateAfter;
}
}
else
{
BARRIER_ASSERT("Mismatching before state", st[trans.Subresource] == trans.StateBefore,
st[trans.Subresource], trans.StateBefore, trans.Subresource);
st[trans.Subresource] = trans.StateAfter;
}
}
}
void D3D12ResourceManager::SerialiseResourceStates(vector<D3D12_RESOURCE_BARRIER> &barriers,
map<ResourceId, SubresourceStateVector> &states)
{
SERIALISE_ELEMENT(uint32_t, NumMems, (uint32_t)states.size());
auto srcit = states.begin();
for(uint32_t i = 0; i < NumMems; i++)
{
SERIALISE_ELEMENT(ResourceId, id, srcit->first);
SERIALISE_ELEMENT(uint32_t, NumStates, (uint32_t)srcit->second.size());
ResourceId liveid;
if(m_State < WRITING && HasLiveResource(id))
liveid = GetLiveID(id);
for(uint32_t m = 0; m < NumStates; m++)
{
SERIALISE_ELEMENT(D3D12_RESOURCE_STATES, state, srcit->second[m]);
if(m_State < WRITING && liveid != ResourceId() && srcit != states.end())
{
D3D12_RESOURCE_BARRIER b;
b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
b.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
b.Transition.pResource = (ID3D12Resource *)GetCurrentResource(liveid);
b.Transition.Subresource = m;
b.Transition.StateBefore = states[liveid][m];
b.Transition.StateAfter = state;
barriers.push_back(b);
}
}
if(m_State >= WRITING)
srcit++;
}
// erase any do-nothing barriers
for(auto it = barriers.begin(); it != barriers.end();)
{
if(it->Transition.StateBefore == it->Transition.StateAfter)
it = barriers.erase(it);
else
++it;
}
ApplyBarriers(barriers, states);
}
bool D3D12ResourceManager::SerialisableResource(ResourceId id, D3D12ResourceRecord *record)
{
if(record->SpecialResource)
+8
View File
@@ -274,6 +274,8 @@ struct D3D12ResourceRecord : public ResourceRecord
CmdListRecordingInfo *cmdInfo;
};
typedef vector<D3D12_RESOURCE_STATES> SubresourceStateVector;
class D3D12ResourceManager
: public ResourceManager<ID3D12DeviceChild *, ID3D12DeviceChild *, D3D12ResourceRecord>
{
@@ -289,6 +291,12 @@ public:
return (T *)GetLiveResource(id);
}
void ApplyBarriers(vector<D3D12_RESOURCE_BARRIER> &barriers,
map<ResourceId, SubresourceStateVector> &states);
void SerialiseResourceStates(vector<D3D12_RESOURCE_BARRIER> &barriers,
map<ResourceId, SubresourceStateVector> &states);
private:
bool SerialisableResource(ResourceId id, D3D12ResourceRecord *record);
ResourceId GetID(ID3D12DeviceChild *res);