diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 7ff93e65e..b45ee58f2 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -187,6 +187,12 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara m_HeaderChunk = NULL; + m_Alloc = NULL; + m_List = NULL; + m_GPUSyncFence = NULL; + m_GPUSyncHandle = NULL; + m_GPUSyncCounter = 0; + if(RenderDoc::Inst().IsReplayApp()) { m_State = READING; @@ -282,6 +288,8 @@ WrappedID3D12Device::~WrappedID3D12Device() { RenderDoc::Inst().RemoveDeviceFrameCapturer((ID3D12Device *)this); + DestroyInternalResources(); + if(m_DeviceRecord) { RDCASSERT(m_DeviceRecord->GetRefCount() == 1); @@ -1198,6 +1206,38 @@ void WrappedID3D12Device::SetResourceName(ID3D12DeviceChild *res, const char *na } } +void WrappedID3D12Device::CreateInternalResources() +{ + m_pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), (void **)&m_Alloc); + m_pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_Alloc, NULL, + __uuidof(ID3D12GraphicsCommandList), (void **)&m_List); + m_pDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void **)&m_GPUSyncFence); + m_GPUSyncHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL); + + m_GPUSyncCounter = 0; +} + +void WrappedID3D12Device::DestroyInternalResources() +{ + if(m_GPUSyncHandle == NULL) + return; + + SAFE_RELEASE(m_Alloc); + SAFE_RELEASE(m_List); + SAFE_RELEASE(m_GPUSyncFence); + CloseHandle(m_GPUSyncHandle); +} + +void WrappedID3D12Device::GPUSync() +{ + m_GPUSyncCounter++; + + m_Queue->GetReal()->Signal(m_GPUSyncFence, m_GPUSyncCounter); + m_GPUSyncFence->SetEventOnCompletion(m_GPUSyncCounter, m_GPUSyncHandle); + WaitForSingleObject(m_GPUSyncHandle, 2000); +} + // need to create this dummy here so that we can record D3D12. ReplayCreateStatus D3D12_CreateReplayDevice(const char *logfile, IReplayDriver **driver) { diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index 5ec7e02fa..c84c0e666 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -219,6 +219,15 @@ private: WrappedID3D12CommandQueue *m_Queue; + ID3D12CommandAllocator *m_Alloc; + ID3D12GraphicsCommandList *m_List; + ID3D12Fence *m_GPUSyncFence; + HANDLE m_GPUSyncHandle; + UINT64 m_GPUSyncCounter; + + void CreateInternalResources(); + void DestroyInternalResources(); + D3D12ResourceManager *m_ResourceManager; DummyID3D12InfoQueue m_DummyInfoQueue; DummyID3D12DebugDevice m_DummyDebug; @@ -302,6 +311,10 @@ public: void ReleaseSwapchainResources(IDXGISwapChain *swap, IUnknown **backbuffers, int numBackbuffers); void FirstFrame(WrappedIDXGISwapChain3 *swap); + WrappedID3D12CommandQueue *GetQueue() { return m_Queue; } + ID3D12CommandAllocator *GetAlloc() { return m_Alloc; } + ID3D12GraphicsCommandList *GetList() { return m_List; } + void GPUSync(); void ApplyBarriers(vector &barriers); void StartFrameCapture(void *dev, void *wnd); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index ee3532de2..15c75294a 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -49,6 +49,16 @@ bool WrappedID3D12Device::Serialise_CreateCommandQueue(const D3D12_COMMAND_QUEUE ret = new WrappedID3D12CommandQueue(ret, this, m_pSerialiser, m_State); GetResourceManager()->AddLiveResource(Queue, ret); + + if(Descriptor.Type == D3D12_COMMAND_LIST_TYPE_DIRECT) + { + if(m_Queue != NULL) + RDCERR("Don't support multiple direct queues yet!"); + + m_Queue = (WrappedID3D12CommandQueue *)ret; + + CreateInternalResources(); + } } } @@ -82,10 +92,15 @@ HRESULT WrappedID3D12Device::CreateCommandQueue(const D3D12_COMMAND_QUEUE_DESC * m_DeviceRecord->AddChunk(scope.Get()); } - if(m_Queue != NULL) - RDCERR("Don't support multiple queues yet!"); + if(pDesc->Type == D3D12_COMMAND_LIST_TYPE_DIRECT) + { + if(m_Queue != NULL) + RDCERR("Don't support multiple queues yet!"); - m_Queue = wrapped; + m_Queue = wrapped; + + CreateInternalResources(); + } *ppCommandQueue = (ID3D12CommandQueue *)wrapped; } diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index 78df5f5e9..93bd70ab8 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -23,6 +23,7 @@ ******************************************************************************/ #include "d3d12_manager.h" +#include "d3d12_command_queue.h" #include "d3d12_device.h" #include "d3d12_resources.h" @@ -279,7 +280,39 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) D3D12_RESOURCE_DESC desc = r->GetDesc(); - (void)desc; + if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + D3D12_HEAP_PROPERTIES heapProps; + heapProps.Type = D3D12_HEAP_TYPE_READBACK; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + ID3D12Resource *copyDst = NULL; + HRESULT hr = m_Device->GetReal()->CreateCommittedResource( + &heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, + __uuidof(ID3D12Resource), (void **)©Dst); + + if(SUCCEEDED(hr)) + { + m_Device->GetList()->Reset(m_Device->GetAlloc(), NULL); + + m_Device->GetList()->CopyResource(copyDst, Unwrap(r)); + + m_Device->GetList()->Close(); + + ID3D12CommandList *list = (ID3D12CommandList *)m_Device->GetList(); + m_Device->GetQueue()->GetReal()->ExecuteCommandLists(1, &list); + } + else + { + RDCERR("Couldn't create readback buffer: 0x%08x", hr); + } + + SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL)); + return true; + } D3D12NOTIMP("resource init states"); return true; @@ -315,7 +348,40 @@ bool D3D12ResourceManager::Serialise_InitialState(ResourceId resid, ID3D12Device D3D12_RESOURCE_DESC desc = r->GetDesc(); - (void)desc; + m_pSerialiser->Serialise("Dimension", desc.Dimension); + + if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + m_Device->GPUSync(); + + ID3D12Resource *copySrc = (ID3D12Resource *)initContents.resource; + + byte dummy[4] = {}; + byte *ptr = NULL; + uint64_t size = 0; + + HRESULT hr = E_NOINTERFACE; + + if(copySrc) + { + copySrc->Map(0, NULL, (void **)&ptr); + size = copySrc->GetDesc().Width; + } + + if(FAILED(hr) || ptr == NULL) + { + size = 4; + ptr = dummy; + } + + m_pSerialiser->Serialise("NumBytes", size); + m_pSerialiser->SerialiseBuffer("BufferData", ptr, size); + + if(SUCCEEDED(hr) && ptr) + copySrc->Unmap(0, NULL); + + return true; + } D3D12NOTIMP("resource init states"); return true; @@ -375,6 +441,53 @@ bool D3D12ResourceManager::Serialise_InitialState(ResourceId resid, ID3D12Device } else if(type == Resource_Resource) { + D3D12_RESOURCE_DIMENSION Dimension; + m_pSerialiser->Serialise("Dimension", Dimension); + + if(Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + uint64_t size = 0; + byte *ptr = NULL; + + m_pSerialiser->Serialise("NumBytes", size); + m_pSerialiser->SerialiseBuffer("BufferData", ptr, size); + + D3D12_HEAP_PROPERTIES heapProps; + heapProps.Type = D3D12_HEAP_TYPE_UPLOAD; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + D3D12_RESOURCE_DESC desc; + desc.Alignment = 0; + desc.DepthOrArraySize = 1; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.Height = 1; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.MipLevels = 1; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Width = size; + + ID3D12Resource *copySrc = NULL; + HRESULT hr = m_Device->GetReal()->CreateCommittedResource( + &heapProps, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, + __uuidof(ID3D12Resource), (void **)©Src); + + if(FAILED(hr)) + { + RDCERR("Couldn't create upload buffer: 0x%08x", hr); + return false; + } + + SetInitialContents(id, D3D12ResourceManager::InitialContentData(copySrc, 1, NULL)); + + return true; + } + D3D12NOTIMP("resource init states"); return true; } @@ -401,6 +514,8 @@ void D3D12ResourceManager::Create_InitialState(ResourceId id, ID3D12DeviceChild else if(type == Resource_Resource) { D3D12NOTIMP("resource init states"); + + // not handling any missing states at the moment } else { @@ -427,7 +542,25 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, InitialCo } else if(type == Resource_Resource) { - D3D12NOTIMP("resource init states"); + if(data.num == 1 && data.resource) + { + // buffer + m_Device->GetList()->Reset(m_Device->GetAlloc(), NULL); + + ID3D12Resource *copyDst = Unwrap((ID3D12Resource *)live); + ID3D12Resource *copySrc = (ID3D12Resource *)data.resource; + + m_Device->GetList()->CopyResource(copyDst, copySrc); + + m_Device->GetList()->Close(); + + ID3D12CommandList *list = (ID3D12CommandList *)m_Device->GetList(); + m_Device->GetQueue()->GetReal()->ExecuteCommandLists(1, &list); + } + else + { + D3D12NOTIMP("resource init states"); + } } else {