diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 5f7e7bfb9..ae3ab209e 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -3141,6 +3141,14 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context) { GetResourceManager()->CreateInitialContents(ser); + if(initStateCurList) + { + CloseInitialStateList(); + + ExecuteLists(NULL, true); + FlushLists(); + } + SERIALISE_CHECK_READ_ERRORS(); } else if(system == SystemChunk::InitialContents) diff --git a/renderdoc/driver/d3d12/d3d12_initstate.cpp b/renderdoc/driver/d3d12/d3d12_initstate.cpp index 4470c969d..8930de198 100644 --- a/renderdoc/driver/d3d12/d3d12_initstate.cpp +++ b/renderdoc/driver/d3d12/d3d12_initstate.cpp @@ -790,7 +790,58 @@ void D3D12ResourceManager::Create_InitialState(ResourceId id, ID3D12DeviceChild { D3D12NOTIMP("Creating init states for resources"); - // not handling any missing states at the moment + ID3D12Resource *res = ((ID3D12Resource *)live); + + D3D12_RESOURCE_DESC resDesc = res->GetDesc(); + + D3D12_HEAP_PROPERTIES heapProps = {}; + res->GetHeapProperties(&heapProps, NULL); + + if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD) + { + // if destination is on the upload heap, it's impossible to copy via the device, + // so we have to CPU copy. To save time and make a more optimal copy, we just keep the data + // CPU-side + D3D12InitialContents initContents(D3D12InitialContents::Copy, Resource_Resource); + uint64_t size = RDCMAX(resDesc.Width, 64ULL); + initContents.srcData = AllocAlignedBuffer(size); + memset(initContents.srcData, 0, (size_t)size); + SetInitialContents(id, initContents); + } + else + { + // create a GPU-local copy of the resource + heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; + heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + heapProps.CreationNodeMask = 1; + heapProps.VisibleNodeMask = 1; + + resDesc.Alignment = 0; + resDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + ID3D12Resource *copy = NULL; + HRESULT hr = m_Device->CreateCommittedResource(&heapProps, D3D12_HEAP_FLAG_NONE, &resDesc, + D3D12_RESOURCE_STATE_COMMON, NULL, + __uuidof(ID3D12Resource), (void **)©); + if(FAILED(hr)) + { + RDCERR("Couldn't create initial state copy: %s", ToStr(hr).c_str()); + } + else + { + ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList()); + + copy->SetName(L"Create_InitialState blank"); + + list->CopyResource(Unwrap(copy), Unwrap(res)); + + D3D12InitialContents initContents(D3D12InitialContents::ForceCopy, type); + initContents.resourceType = Resource_Resource; + initContents.resource = copy; + SetInitialContents(id, initContents); + } + } } else { @@ -818,7 +869,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, } else if(type == Resource_Resource) { - if(data.tag == D3D12InitialContents::Copy) + if(data.tag == D3D12InitialContents::Copy || data.tag == D3D12InitialContents::ForceCopy) { ID3D12Resource *copyDst = Unwrap((ID3D12Resource *)live); @@ -961,9 +1012,10 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, list->CopyBufferRegion(copyDst, 0, Unwrap(copySrc), 0, RDCMIN(srcDesc.Width, dstDesc.Width)); } - else if(copyDst->GetDesc().SampleDesc.Count > 1) + else if(copyDst->GetDesc().SampleDesc.Count > 1 || data.tag == D3D12InitialContents::ForceCopy) { - // MSAA texture was pre-uploaded and decoded, just copy the texture + // MSAA texture was pre-uploaded and decoded, just copy the texture. + // Similarly for created initial states list->CopyResource(copyDst, Unwrap(copySrc)); } else diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 6fb13e796..ac1b6beae 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -539,6 +539,8 @@ struct D3D12InitialContents // this is only valid during capture - it indicates we didn't create a staging texture, we're // going to read directly from the resource (only valid for resources that are already READBACK) MapDirect, + // for created initial states we always have an identical resource + ForceCopy, }; D3D12InitialContents(D3D12Descriptor *d, uint32_t n) : tag(Copy),