diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index c238fdbbb..550ffddd7 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -2100,9 +2100,17 @@ bool WrappedID3D12Device::Serialise_BeginCaptureFrame(SerialiserType &ser) { rdcarray barriers; + if(IsReplayingAndReading() && IsLoading(m_State)) + { + m_InitialResourceStates = m_ResourceStates; + } + + std::map initialStates; + { SCOPED_LOCK(m_ResourceStatesLock); // not needed on replay, but harmless also - GetResourceManager()->SerialiseResourceStates(ser, barriers, m_ResourceStates); + GetResourceManager()->SerialiseResourceStates(ser, barriers, m_ResourceStates, + m_InitialResourceStates); } SERIALISE_CHECK_READ_ERRORS(); diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index 5481625d2..473ab971a 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -683,6 +683,11 @@ private: std::map m_ResourceStates; Threading::CriticalSection m_ResourceStatesLock; + // used on replay only. Contains the initial resource states before any barriers - this allows us + // to reset any resources to their proper initial state if they were created mid-frame, since for + // those we won't have recorded their state at the start of the frame capture. + std::map m_InitialResourceStates; + std::set m_Cubemaps; // only valid on replay diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index c40851601..a5db452c0 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -682,14 +682,17 @@ void D3D12ResourceManager::ApplyBarriers(rdcarray &barri } template -void D3D12ResourceManager::SerialiseResourceStates(SerialiserType &ser, - rdcarray &barriers, - std::map &states) +void D3D12ResourceManager::SerialiseResourceStates( + SerialiserType &ser, rdcarray &barriers, + std::map &states, + const std::map &initialStates) { SERIALISE_ELEMENT_LOCAL(NumMems, (uint32_t)states.size()); auto srcit = states.begin(); + std::unordered_set processed; + for(uint32_t i = 0; i < NumMems; i++) { SERIALISE_ELEMENT_LOCAL(Resource, srcit->first).TypedAs("ID3D12Resource *"_lit); @@ -701,6 +704,8 @@ void D3D12ResourceManager::SerialiseResourceStates(SerialiserType &ser, if(IsReplayingAndReading() && liveid != ResourceId()) { + processed.insert(liveid); + for(size_t m = 0; m < States.size(); m++) { if(states[liveid][m] != States[m]) @@ -722,15 +727,48 @@ void D3D12ResourceManager::SerialiseResourceStates(SerialiserType &ser, srcit++; } + // for any resources that didn't have a recorded state, use the initialStates we're given and + // restore them if needed + if(IsReplayingAndReading()) + { + for(auto it = initialStates.begin(); it != initialStates.end(); ++it) + { + // ignore internal resources, we only care about restoring states for captured resources + if(GetOriginalID(it->first) == it->first) + continue; + + if(processed.find(it->first) == processed.end()) + { + for(size_t m = 0; m < it->second.size(); m++) + { + if(states[it->first][m] != it->second[m]) + { + D3D12_RESOURCE_BARRIER b; + b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + b.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + b.Transition.pResource = (ID3D12Resource *)GetCurrentResource(it->first); + b.Transition.Subresource = (UINT)m; + b.Transition.StateBefore = states[it->first][m]; + b.Transition.StateAfter = it->second[m]; + + barriers.push_back(b); + } + } + } + } + } + ApplyBarriers(barriers, states); } template void D3D12ResourceManager::SerialiseResourceStates( ReadSerialiser &ser, rdcarray &barriers, - std::map &states); + std::map &states, + const std::map &initialStates); template void D3D12ResourceManager::SerialiseResourceStates( WriteSerialiser &ser, rdcarray &barriers, - std::map &states); + std::map &states, + const std::map &initialStates); void D3D12ResourceManager::SetInternalResource(ID3D12DeviceChild *res) { diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index d0b888632..ba7116292 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -652,7 +652,8 @@ public: template void SerialiseResourceStates(SerialiserType &ser, rdcarray &barriers, - std::map &states); + std::map &states, + const std::map &initialStates); template bool Serialise_InitialState(SerialiserType &ser, ResourceId id, D3D12ResourceRecord *record,