mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-24 08:21:35 +00:00
Track resource states for initial states, apply barriers while recording
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user