mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-25 07:56:33 +00:00
Add putting together an actual capture file. Give resources records
This commit is contained in:
@@ -89,7 +89,7 @@ class WrappedID3D12GraphicsCommandList : public RefCounter12<ID3D12GraphicsComma
|
||||
D3D12ResourceRecord *m_ListRecord;
|
||||
|
||||
Serialiser *m_pSerialiser;
|
||||
LogState m_State;
|
||||
LogState &m_State;
|
||||
|
||||
DummyID3D12DebugCommandList m_DummyDebug;
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12GraphicsCommandList);
|
||||
|
||||
WrappedID3D12GraphicsCommandList(ID3D12GraphicsCommandList *real, WrappedID3D12Device *device,
|
||||
Serialiser *serialiser);
|
||||
Serialiser *serialiser, LogState &state);
|
||||
virtual ~WrappedID3D12GraphicsCommandList();
|
||||
|
||||
Serialiser *GetSerialiser() { return m_pSerialiser; }
|
||||
|
||||
@@ -81,10 +81,18 @@ HRESULT WrappedID3D12GraphicsCommandList::Reset(ID3D12CommandAllocator *pAllocat
|
||||
// reset for new recording
|
||||
m_ListRecord->DeleteChunks();
|
||||
|
||||
// free parents
|
||||
m_ListRecord->FreeParents(GetResourceManager());
|
||||
|
||||
SCOPED_SERIALISE_CONTEXT(RESET_LIST);
|
||||
Serialise_Reset(pAllocator, pInitialState);
|
||||
|
||||
m_ListRecord->AddChunk(scope.Get());
|
||||
|
||||
// add allocator and initial state (if there is one) as parents
|
||||
m_ListRecord->AddParent(GetRecord(pAllocator));
|
||||
if(pInitialState)
|
||||
m_ListRecord->AddParent(GetRecord(pInitialState));
|
||||
}
|
||||
|
||||
return m_pReal->Reset(Unwrap(pAllocator), Unwrap(pInitialState));
|
||||
|
||||
@@ -76,7 +76,7 @@ class WrappedID3D12CommandQueue : public ID3D12CommandQueue,
|
||||
D3D12ResourceRecord *m_QueueRecord;
|
||||
|
||||
Serialiser *m_pSerialiser;
|
||||
LogState m_State;
|
||||
LogState &m_State;
|
||||
|
||||
DummyID3D12DebugCommandQueue m_DummyDebug;
|
||||
|
||||
@@ -86,12 +86,13 @@ public:
|
||||
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12CommandQueue);
|
||||
|
||||
WrappedID3D12CommandQueue(ID3D12CommandQueue *real, WrappedID3D12Device *device,
|
||||
Serialiser *serialiser);
|
||||
Serialiser *serialiser, LogState &state);
|
||||
virtual ~WrappedID3D12CommandQueue();
|
||||
|
||||
Serialiser *GetSerialiser() { return m_pSerialiser; }
|
||||
ResourceId GetResourceID() { return m_ResourceID; }
|
||||
ID3D12CommandQueue *GetReal() { return m_pReal; }
|
||||
D3D12ResourceRecord *GetRecord() { return m_QueueRecord; }
|
||||
WrappedID3D12Device *GetWrappedDevice() { return m_pDevice; }
|
||||
// interface for DXGI
|
||||
virtual IUnknown *GetRealIUnknown() { return GetReal(); }
|
||||
@@ -226,4 +227,10 @@ public:
|
||||
};
|
||||
|
||||
template <>
|
||||
ID3D12CommandQueue *Unwrap(ID3D12CommandQueue *obj);
|
||||
ID3D12CommandQueue *Unwrap(ID3D12CommandQueue *obj);
|
||||
|
||||
template <>
|
||||
ResourceId GetResID(ID3D12CommandQueue *obj);
|
||||
|
||||
template <>
|
||||
D3D12ResourceRecord *GetRecord(ID3D12CommandQueue *obj);
|
||||
@@ -73,6 +73,24 @@ ID3D12CommandQueue *Unwrap(ID3D12CommandQueue *obj)
|
||||
return ((WrappedID3D12CommandQueue *)obj)->GetReal();
|
||||
}
|
||||
|
||||
template <>
|
||||
ResourceId GetResID(ID3D12CommandQueue *obj)
|
||||
{
|
||||
if(obj == NULL)
|
||||
return ResourceId();
|
||||
|
||||
return ((WrappedID3D12CommandQueue *)obj)->GetResourceID();
|
||||
}
|
||||
|
||||
template <>
|
||||
D3D12ResourceRecord *GetRecord(ID3D12CommandQueue *obj)
|
||||
{
|
||||
if(obj == NULL)
|
||||
return NULL;
|
||||
|
||||
return ((WrappedID3D12CommandQueue *)obj)->GetRecord();
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE DummyID3D12DebugCommandQueue::AddRef()
|
||||
{
|
||||
m_pQueue->AddRef();
|
||||
@@ -99,8 +117,8 @@ ULONG STDMETHODCALLTYPE DummyID3D12DebugCommandList::Release()
|
||||
|
||||
WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
WrappedID3D12Device *device,
|
||||
Serialiser *serialiser)
|
||||
: RefCounter12(real), m_pDevice(device)
|
||||
Serialiser *serialiser, LogState &state)
|
||||
: RefCounter12(real), m_pDevice(device), m_State(state)
|
||||
{
|
||||
if(RenderDoc::Inst().GetCrashHandler())
|
||||
RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this,
|
||||
@@ -110,13 +128,11 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_State = READING;
|
||||
m_pSerialiser = serialiser;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSerialiser = new Serialiser(NULL, Serialiser::WRITING, true);
|
||||
m_State = WRITING_IDLE;
|
||||
|
||||
m_pSerialiser->SetDebugText(true);
|
||||
}
|
||||
@@ -134,8 +150,6 @@ WrappedID3D12CommandQueue::WrappedID3D12CommandQueue(ID3D12CommandQueue *real,
|
||||
m_QueueRecord->DataInSerialiser = false;
|
||||
m_QueueRecord->SpecialResource = true;
|
||||
m_QueueRecord->Length = 0;
|
||||
m_QueueRecord->NumSubResources = 0;
|
||||
m_QueueRecord->SubResources = NULL;
|
||||
m_QueueRecord->ignoreSerialise = true;
|
||||
}
|
||||
|
||||
@@ -189,8 +203,9 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12CommandQueue::QueryInterface(REFIID riid,
|
||||
|
||||
WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12GraphicsCommandList *real,
|
||||
WrappedID3D12Device *device,
|
||||
Serialiser *serialiser)
|
||||
: RefCounter12(real), m_pDevice(device)
|
||||
Serialiser *serialiser,
|
||||
LogState &state)
|
||||
: RefCounter12(real), m_pDevice(device), m_State(state)
|
||||
{
|
||||
if(RenderDoc::Inst().GetCrashHandler())
|
||||
RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(
|
||||
@@ -200,13 +215,11 @@ WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12Graphic
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_State = READING;
|
||||
m_pSerialiser = serialiser;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pSerialiser = new Serialiser(NULL, Serialiser::WRITING, true);
|
||||
m_State = WRITING_IDLE;
|
||||
|
||||
m_pSerialiser->SetDebugText(true);
|
||||
}
|
||||
@@ -224,8 +237,6 @@ WrappedID3D12GraphicsCommandList::WrappedID3D12GraphicsCommandList(ID3D12Graphic
|
||||
m_ListRecord->DataInSerialiser = false;
|
||||
m_ListRecord->SpecialResource = true;
|
||||
m_ListRecord->Length = 0;
|
||||
m_ListRecord->NumSubResources = 0;
|
||||
m_ListRecord->SubResources = NULL;
|
||||
m_ListRecord->ignoreSerialise = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,11 +185,15 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
|
||||
|
||||
m_TotalTime = m_AvgFrametime = m_MinFrametime = m_MaxFrametime = 0.0;
|
||||
|
||||
m_HeaderChunk = NULL;
|
||||
|
||||
if(RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_State = READING;
|
||||
m_pSerialiser = NULL;
|
||||
|
||||
m_FrameCaptureRecord = NULL;
|
||||
|
||||
ResourceIDGen::SetReplayResourceIDs();
|
||||
}
|
||||
else
|
||||
@@ -212,14 +216,19 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara
|
||||
|
||||
m_DeviceRecord = NULL;
|
||||
|
||||
m_Queue = NULL;
|
||||
|
||||
if(!RenderDoc::Inst().IsReplayApp())
|
||||
{
|
||||
m_DeviceRecord = GetResourceManager()->AddResourceRecord(m_ResourceID);
|
||||
m_DeviceRecord->DataInSerialiser = false;
|
||||
m_DeviceRecord->SpecialResource = true;
|
||||
m_DeviceRecord->Length = 0;
|
||||
m_DeviceRecord->NumSubResources = 0;
|
||||
m_DeviceRecord->SubResources = NULL;
|
||||
|
||||
m_FrameCaptureRecord = GetResourceManager()->AddResourceRecord(ResourceIDGen::GetNewUniqueID());
|
||||
m_FrameCaptureRecord->DataInSerialiser = false;
|
||||
m_FrameCaptureRecord->Length = 0;
|
||||
m_FrameCaptureRecord->SpecialResource = true;
|
||||
|
||||
RenderDoc::Inst().AddDeviceFrameCapturer((ID3D12Device *)this, this);
|
||||
}
|
||||
@@ -541,8 +550,6 @@ IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(WrappedIDXGISwapChain3 *swap,
|
||||
record->DataInSerialiser = false;
|
||||
record->SpecialResource = true;
|
||||
record->Length = 0;
|
||||
record->NumSubResources = 0;
|
||||
record->SubResources = NULL;
|
||||
|
||||
SCOPED_LOCK(m_D3DLock);
|
||||
|
||||
@@ -734,7 +741,7 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain3 *swap, UINT SyncInte
|
||||
if(!activeWindow)
|
||||
return S_OK;
|
||||
|
||||
RenderDoc::Inst().SetCurrentDriver(RDC_D3D11);
|
||||
RenderDoc::Inst().SetCurrentDriver(RDC_D3D12);
|
||||
|
||||
// kill any current capture that isn't application defined
|
||||
if(m_State == WRITING_CAPFRAME && !m_AppControlledCapture)
|
||||
@@ -750,10 +757,117 @@ HRESULT WrappedID3D12Device::Present(WrappedIDXGISwapChain3 *swap, UINT SyncInte
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool WrappedID3D12Device::Serialise_BeginCaptureFrame(bool applyInitialState)
|
||||
{
|
||||
if(m_State < WRITING && !applyInitialState)
|
||||
{
|
||||
m_pSerialiser->SkipCurrentChunk();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO save initial resources
|
||||
|
||||
if(applyInitialState)
|
||||
{
|
||||
// apply initial resources
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WrappedID3D12Device::Serialise_CaptureScope(uint64_t offset)
|
||||
{
|
||||
uint32_t FrameNumber = m_FrameCounter;
|
||||
m_pSerialiser->Serialise("FrameNumber", FrameNumber);
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
GetResourceManager()->Serialise_InitialContentsNeeded();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FrameRecord.frameInfo.fileOffset = offset;
|
||||
m_FrameRecord.frameInfo.firstEvent = 1;
|
||||
m_FrameRecord.frameInfo.frameNumber = FrameNumber;
|
||||
m_FrameRecord.frameInfo.immContextId = ResourceId();
|
||||
RDCEraseEl(m_FrameRecord.frameInfo.stats);
|
||||
|
||||
GetResourceManager()->CreateInitialContents();
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedID3D12Device::EndCaptureFrame(ID3D12Resource *presentImage)
|
||||
{
|
||||
SCOPED_SERIALISE_CONTEXT(CONTEXT_CAPTURE_FOOTER);
|
||||
|
||||
SERIALISE_ELEMENT(ResourceId, bbid, GetResID(presentImage));
|
||||
|
||||
bool HasCallstack = RenderDoc::Inst().GetCaptureOptions().CaptureCallstacks != 0;
|
||||
m_pSerialiser->Serialise("HasCallstack", HasCallstack);
|
||||
|
||||
if(HasCallstack)
|
||||
{
|
||||
Callstack::Stackwalk *call = Callstack::Collect();
|
||||
|
||||
RDCASSERT(call->NumLevels() < 0xff);
|
||||
|
||||
size_t numLevels = call->NumLevels();
|
||||
uint64_t *stack = (uint64_t *)call->GetAddrs();
|
||||
|
||||
m_pSerialiser->SerialisePODArray("callstack", stack, numLevels);
|
||||
|
||||
delete call;
|
||||
}
|
||||
|
||||
m_FrameCaptureRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
void WrappedID3D12Device::StartFrameCapture(void *dev, void *wnd)
|
||||
{
|
||||
if(m_State != WRITING_IDLE)
|
||||
return;
|
||||
|
||||
RenderDoc::Inst().SetCurrentDriver(RDC_D3D12);
|
||||
|
||||
m_AppControlledCapture = true;
|
||||
|
||||
m_FrameCounter = RDCMAX(1 + (uint32_t)m_CapturedFrames.size(), m_FrameCounter);
|
||||
|
||||
FetchFrameInfo frame;
|
||||
frame.frameNumber = m_FrameCounter + 1;
|
||||
frame.captureTime = Timing::GetUnixTimestamp();
|
||||
RDCEraseEl(frame.stats);
|
||||
m_CapturedFrames.push_back(frame);
|
||||
|
||||
GetResourceManager()->ClearReferencedResources();
|
||||
|
||||
GetResourceManager()->MarkResourceFrameReferenced(m_ResourceID, eFrameRef_Read);
|
||||
GetResourceManager()->MarkResourceFrameReferenced(GetResID(m_Queue), eFrameRef_Read);
|
||||
|
||||
// need to do all this atomically so that no other commands
|
||||
// will check to see if they need to markdirty or markpendingdirty
|
||||
// and go into the frame record.
|
||||
{
|
||||
SCOPED_LOCK(m_CapTransitionLock);
|
||||
GetResourceManager()->PrepareInitialContents();
|
||||
|
||||
RDCDEBUG("Attempting capture");
|
||||
m_FrameCaptureRecord->DeleteChunks();
|
||||
|
||||
{
|
||||
SCOPED_SERIALISE_CONTEXT(CONTEXT_CAPTURE_HEADER);
|
||||
|
||||
Serialise_BeginCaptureFrame(false);
|
||||
|
||||
// need to hold onto this as it must come right after the capture chunk,
|
||||
// before any command buffers
|
||||
m_HeaderChunk = scope.Get();
|
||||
}
|
||||
|
||||
m_State = WRITING_CAPFRAME;
|
||||
}
|
||||
|
||||
RDCLOG("Starting capture, frame %u", m_FrameCounter);
|
||||
}
|
||||
|
||||
bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
@@ -761,8 +875,173 @@ bool WrappedID3D12Device::EndFrameCapture(void *dev, void *wnd)
|
||||
if(m_State != WRITING_CAPFRAME)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
WrappedIDXGISwapChain3 *swap = NULL;
|
||||
|
||||
if(wnd)
|
||||
{
|
||||
for(auto it = m_SwapChains.begin(); it != m_SwapChains.end(); ++it)
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
it->first->GetDesc(&swapDesc);
|
||||
|
||||
if(swapDesc.OutputWindow == wnd)
|
||||
{
|
||||
swap = it->first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(swap == NULL)
|
||||
{
|
||||
RDCERR("Output window %p provided for frame capture corresponds with no known swap chain", wnd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RDCLOG("Finished capture, Frame %u", m_FrameCounter);
|
||||
|
||||
// TODO either get the swapchain associated with this window, or the last swapchain
|
||||
// to be presented.
|
||||
// Get the last buffer presented on that swapchain as backbuffer
|
||||
ID3D12Resource *backbuffer = NULL;
|
||||
|
||||
// transition back to IDLE atomically
|
||||
{
|
||||
SCOPED_LOCK(m_CapTransitionLock);
|
||||
EndCaptureFrame(backbuffer);
|
||||
|
||||
m_State = WRITING_IDLE;
|
||||
|
||||
// TOD wait for idle
|
||||
|
||||
// TODO free coherent map capture ref-data
|
||||
}
|
||||
|
||||
byte *thpixels = NULL;
|
||||
uint32_t thwidth = 0;
|
||||
uint32_t thheight = 0;
|
||||
|
||||
const uint32_t maxSize = 1024;
|
||||
|
||||
// gather backbuffer screenshot
|
||||
(void)maxSize;
|
||||
|
||||
byte *jpgbuf = NULL;
|
||||
int len = thwidth * thheight;
|
||||
|
||||
if(wnd && thpixels)
|
||||
{
|
||||
jpgbuf = new byte[len];
|
||||
|
||||
jpge::params p;
|
||||
|
||||
p.m_quality = 40;
|
||||
|
||||
bool success =
|
||||
jpge::compress_image_to_jpeg_file_in_memory(jpgbuf, len, thwidth, thheight, 3, thpixels, p);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
RDCERR("Failed to compress to jpg");
|
||||
SAFE_DELETE_ARRAY(jpgbuf);
|
||||
thwidth = 0;
|
||||
thheight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Serialiser *m_pFileSerialiser = RenderDoc::Inst().OpenWriteSerialiser(
|
||||
m_FrameCounter, &m_InitParams, jpgbuf, len, thwidth, thheight);
|
||||
|
||||
{
|
||||
SCOPED_SERIALISE_CONTEXT(DEVICE_INIT);
|
||||
|
||||
m_pFileSerialiser->Insert(scope.Get(true));
|
||||
}
|
||||
|
||||
RDCDEBUG("Inserting Resource Serialisers");
|
||||
|
||||
GetResourceManager()->InsertReferencedChunks(m_pFileSerialiser);
|
||||
|
||||
GetResourceManager()->InsertInitialContentsChunks(m_pFileSerialiser);
|
||||
|
||||
RDCDEBUG("Creating Capture Scope");
|
||||
|
||||
{
|
||||
SCOPED_SERIALISE_CONTEXT(CAPTURE_SCOPE);
|
||||
|
||||
Serialise_CaptureScope(0);
|
||||
|
||||
m_pFileSerialiser->Insert(scope.Get(true));
|
||||
|
||||
m_pFileSerialiser->Insert(m_HeaderChunk);
|
||||
}
|
||||
|
||||
// don't need to lock access to m_CmdListRecords as we are no longer
|
||||
// in capframe (the transition is thread-protected) so nothing will be
|
||||
// pushed to the vector
|
||||
|
||||
{
|
||||
RDCDEBUG("Flushing %u command buffer records to file serialiser",
|
||||
(uint32_t)m_CmdListRecords.size());
|
||||
|
||||
map<int32_t, Chunk *> recordlist;
|
||||
|
||||
// ensure all command buffer records within the frame evne if recorded before, but
|
||||
// otherwise order must be preserved (vs. queue submits and desc set updates)
|
||||
for(size_t i = 0; i < m_CmdListRecords.size(); i++)
|
||||
{
|
||||
/*
|
||||
SCOPED_SERIALISE_CONTEXT(BEGIN_CMD_LIST);
|
||||
Serialise_BeginCmdList(m_CmdListRecords[i]->GetResourceID());
|
||||
Chunk *beginCmdList = scope.Get();
|
||||
|
||||
*/
|
||||
|
||||
m_CmdListRecords[i]->Insert(recordlist);
|
||||
|
||||
RDCDEBUG("Adding %u chunks to file serialiser from command buffer %llu",
|
||||
(uint32_t)recordlist.size(), m_CmdListRecords[i]->GetResourceID());
|
||||
}
|
||||
|
||||
GetRecord(m_Queue)->Insert(recordlist);
|
||||
|
||||
m_FrameCaptureRecord->Insert(recordlist);
|
||||
|
||||
RDCDEBUG("Flushing %u chunks to file serialiser from context record",
|
||||
(uint32_t)recordlist.size());
|
||||
|
||||
for(auto it = recordlist.begin(); it != recordlist.end(); ++it)
|
||||
m_pFileSerialiser->Insert(it->second);
|
||||
|
||||
RDCDEBUG("Done");
|
||||
}
|
||||
|
||||
m_pFileSerialiser->FlushToDisk();
|
||||
|
||||
RenderDoc::Inst().SuccessfullyWrittenLog();
|
||||
|
||||
SAFE_DELETE(m_pFileSerialiser);
|
||||
SAFE_DELETE(m_HeaderChunk);
|
||||
|
||||
m_State = WRITING_IDLE;
|
||||
|
||||
// delete cmd buffers now - had to keep them alive until after serialiser flush.
|
||||
for(size_t i = 0; i < m_CmdListRecords.size(); i++)
|
||||
m_CmdListRecords[i]->Delete(GetResourceManager());
|
||||
|
||||
m_CmdListRecords.clear();
|
||||
|
||||
GetResourceManager()->MarkUnwrittenResources();
|
||||
|
||||
GetResourceManager()->ClearReferencedResources();
|
||||
|
||||
GetResourceManager()->FreeInitialContents();
|
||||
|
||||
GetResourceManager()->FlushPendingDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WrappedID3D12Device::Serialise_ReleaseResource(ID3D12DeviceChild *res)
|
||||
{
|
||||
return true;
|
||||
@@ -868,3 +1147,11 @@ void WrappedID3D12Device::SetResourceName(ID3D12DeviceChild *res, const char *na
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// need to create this dummy here so that we can record D3D12.
|
||||
ReplayCreateStatus D3D12_CreateReplayDevice(const char *logfile, IReplayDriver **driver)
|
||||
{
|
||||
return eReplayCreate_APIUnsupported;
|
||||
}
|
||||
|
||||
static DriverRegistration D3D12DriverRegistration(RDC_D3D12, "D3D12", &D3D12_CreateReplayDevice);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "common/wrapped_pool.h"
|
||||
#include "core/core.h"
|
||||
#include "driver/dxgi/dxgi_wrapped.h"
|
||||
#include "replay/replay_driver.h"
|
||||
#include "d3d12_common.h"
|
||||
#include "d3d12_manager.h"
|
||||
|
||||
@@ -214,6 +215,8 @@ class WrappedID3D12Device : public IFrameCapturer, public ID3DDevice, public ID3
|
||||
private:
|
||||
ID3D12Device *m_pDevice;
|
||||
|
||||
ID3D12CommandQueue *m_Queue;
|
||||
|
||||
D3D12ResourceManager *m_ResourceManager;
|
||||
DummyID3D12InfoQueue m_DummyInfoQueue;
|
||||
DummyID3D12DebugDevice m_DummyDebug;
|
||||
@@ -226,15 +229,18 @@ private:
|
||||
|
||||
uint32_t m_FrameCounter;
|
||||
vector<FetchFrameInfo> m_CapturedFrames;
|
||||
FetchFrameRecord m_FrameRecord;
|
||||
|
||||
PerformanceTimer m_FrameTimer;
|
||||
vector<double> m_FrameTimes;
|
||||
double m_TotalTime, m_AvgFrametime, m_MinFrametime, m_MaxFrametime;
|
||||
|
||||
Serialiser *m_pSerialiser;
|
||||
LogState m_State;
|
||||
bool m_AppControlledCapture;
|
||||
|
||||
Threading::CriticalSection m_CapTransitionLock;
|
||||
LogState m_State;
|
||||
|
||||
D3D12InitParams m_InitParams;
|
||||
ID3D12InfoQueue *m_pInfoQueue;
|
||||
|
||||
@@ -242,6 +248,18 @@ private:
|
||||
// protects wrapped resource creation and serialiser access
|
||||
Threading::CriticalSection m_D3DLock;
|
||||
|
||||
D3D12ResourceRecord *m_FrameCaptureRecord;
|
||||
Chunk *m_HeaderChunk;
|
||||
|
||||
// we record the command buffer records so we can insert them
|
||||
// individually, that means even if they were recorded locklessly
|
||||
// in parallel, on replay they are disjoint and it makes things
|
||||
// much easier to process (we will enforce/display ordering
|
||||
// by queue submit order anyway, so it's OK to lose the record
|
||||
// order).
|
||||
Threading::CriticalSection m_CmdListRecordsLock;
|
||||
vector<D3D12ResourceRecord *> m_CmdListRecords;
|
||||
|
||||
ResourceId m_ResourceID;
|
||||
D3D12ResourceRecord *m_DeviceRecord;
|
||||
|
||||
@@ -249,6 +267,10 @@ private:
|
||||
|
||||
UINT m_DescriptorIncrements[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
|
||||
|
||||
void Serialise_CaptureScope(uint64_t offset);
|
||||
bool Serialise_BeginCaptureFrame(bool applyInitialState);
|
||||
void EndCaptureFrame(ID3D12Resource *presentImage);
|
||||
|
||||
public:
|
||||
static const int AllocPoolCount = 4;
|
||||
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12Device, AllocPoolCount);
|
||||
|
||||
@@ -46,7 +46,7 @@ bool WrappedID3D12Device::Serialise_CreateCommandQueue(const D3D12_COMMAND_QUEUE
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = new WrappedID3D12CommandQueue(ret, this, m_pSerialiser);
|
||||
ret = new WrappedID3D12CommandQueue(ret, this, m_pSerialiser, m_State);
|
||||
|
||||
GetResourceManager()->AddLiveResource(Queue, ret);
|
||||
}
|
||||
@@ -71,7 +71,8 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *
|
||||
{
|
||||
SCOPED_LOCK(m_D3DLock);
|
||||
|
||||
WrappedID3D12CommandQueue *wrapped = new WrappedID3D12CommandQueue(real, this, m_pSerialiser);
|
||||
WrappedID3D12CommandQueue *wrapped =
|
||||
new WrappedID3D12CommandQueue(real, this, m_pSerialiser, m_State);
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
@@ -81,6 +82,11 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC *
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
if(m_Queue != NULL)
|
||||
RDCERR("Don't support multiple queues yet!");
|
||||
|
||||
m_Queue = (ID3D12CommandQueue *)wrapped;
|
||||
|
||||
*ppCommandQueue = (ID3D12CommandQueue *)wrapped;
|
||||
}
|
||||
|
||||
@@ -138,7 +144,11 @@ HRESULT WrappedID3D12Device::CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE type
|
||||
SCOPED_SERIALISE_CONTEXT(CREATE_COMMAND_ALLOCATOR);
|
||||
Serialise_CreateCommandAllocator(type, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppCommandAllocator = (ID3D12CommandAllocator *)wrapped;
|
||||
@@ -175,7 +185,7 @@ bool WrappedID3D12Device::Serialise_CreateCommandList(UINT nodeMask, D3D12_COMMA
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = new WrappedID3D12GraphicsCommandList(ret, this, m_pSerialiser);
|
||||
ret = new WrappedID3D12GraphicsCommandList(ret, this, m_pSerialiser, m_State);
|
||||
|
||||
GetResourceManager()->AddLiveResource(List, ret);
|
||||
}
|
||||
@@ -205,7 +215,7 @@ HRESULT WrappedID3D12Device::CreateCommandList(UINT nodeMask, D3D12_COMMAND_LIST
|
||||
SCOPED_LOCK(m_D3DLock);
|
||||
|
||||
WrappedID3D12GraphicsCommandList *wrapped =
|
||||
new WrappedID3D12GraphicsCommandList(real, this, m_pSerialiser);
|
||||
new WrappedID3D12GraphicsCommandList(real, this, m_pSerialiser, m_State);
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
@@ -213,7 +223,14 @@ HRESULT WrappedID3D12Device::CreateCommandList(UINT nodeMask, D3D12_COMMAND_LIST
|
||||
Serialise_CreateCommandList(nodeMask, type, pCommandAllocator, pInitialState, riid,
|
||||
(void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = wrapped->GetResourceRecord();
|
||||
|
||||
// we can add these parents - if the list is reset later, it will free all of its parents
|
||||
record->AddParent(GetRecord(pCommandAllocator));
|
||||
if(pInitialState)
|
||||
record->AddParent(GetRecord(pInitialState));
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppCommandList = (ID3D12GraphicsCommandList *)wrapped;
|
||||
@@ -276,7 +293,11 @@ HRESULT WrappedID3D12Device::CreateGraphicsPipelineState(const D3D12_GRAPHICS_PI
|
||||
SCOPED_SERIALISE_CONTEXT(CREATE_GRAPHICS_PIPE);
|
||||
Serialise_CreateGraphicsPipelineState(pDesc, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppPipelineState = (ID3D12PipelineState *)wrapped;
|
||||
@@ -336,7 +357,11 @@ HRESULT WrappedID3D12Device::CreateComputePipelineState(const D3D12_COMPUTE_PIPE
|
||||
SCOPED_SERIALISE_CONTEXT(CREATE_COMPUTE_PIPE);
|
||||
Serialise_CreateComputePipelineState(pDesc, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppPipelineState = (ID3D12PipelineState *)wrapped;
|
||||
@@ -396,7 +421,11 @@ HRESULT WrappedID3D12Device::CreateDescriptorHeap(const D3D12_DESCRIPTOR_HEAP_DE
|
||||
SCOPED_SERIALISE_CONTEXT(CREATE_DESCRIPTOR_HEAP);
|
||||
Serialise_CreateDescriptorHeap(pDescriptorHeapDesc, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppvHeap = (ID3D12DescriptorHeap *)wrapped;
|
||||
@@ -465,7 +494,11 @@ HRESULT WrappedID3D12Device::CreateRootSignature(UINT nodeMask, const void *pBlo
|
||||
Serialise_CreateRootSignature(nodeMask, pBlobWithRootSignature, blobLengthInBytes, riid,
|
||||
(void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppvRootSignature = (ID3D12RootSignature *)wrapped;
|
||||
@@ -602,7 +635,11 @@ HRESULT WrappedID3D12Device::CreateCommittedResource(const D3D12_HEAP_PROPERTIES
|
||||
InitialResourceState, pOptimizedClearValue, riidResource,
|
||||
(void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppvResource = (ID3D12Resource *)wrapped;
|
||||
@@ -686,7 +723,11 @@ HRESULT WrappedID3D12Device::CreateFence(UINT64 InitialValue, D3D12_FENCE_FLAGS
|
||||
SCOPED_SERIALISE_CONTEXT(CREATE_FENCE);
|
||||
Serialise_CreateFence(InitialValue, Flags, riid, (void **)&wrapped);
|
||||
|
||||
m_DeviceRecord->AddChunk(scope.Get());
|
||||
D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID());
|
||||
record->Length = 0;
|
||||
wrapped->SetResourceRecord(record);
|
||||
|
||||
record->AddChunk(scope.Get());
|
||||
}
|
||||
|
||||
*ppFence = (ID3D12Fence *)wrapped;
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
TrackedResource() { m_ID = ResourceIDGen::GetNewUniqueID(); }
|
||||
ResourceId GetResourceID() { return m_ID; }
|
||||
D3D12ResourceRecord *GetResourceRecord() { return m_pRecord; }
|
||||
void SetResourceRecord(D3D12ResourceRecord *record) { m_pRecord = record; }
|
||||
private:
|
||||
TrackedResource(const TrackedResource &);
|
||||
TrackedResource &operator=(const TrackedResource &);
|
||||
|
||||
Reference in New Issue
Block a user