HRESULT WrappedID3D12Device::CreateDescriptorHeap(const D3D12_DESCRIPTOR_HEAP_DESC *pDescriptorHeapDesc, REFIID riid, void **ppvHeap) { if(ppvHeap == NULL) return m_pDevice->CreateDescriptorHeap(pDescriptorHeapDesc, riid, NULL); if(riid != __uuidof(ID3D12DescriptorHeap)) return E_NOINTERFACE; ID3D12DescriptorHeap *real = NULL; HRESULT ret = m_pDevice->CreateDescriptorHeap(pDescriptorHeapDesc, riid, (void **)&real); if(SUCCEEDED(ret)) { SCOPED_LOCK(m_D3DLock); WrappedID3D12DescriptorHeap *wrapped = new WrappedID3D12DescriptorHeap(real, this, *pDescriptorHeapDesc); if(m_State >= WRITING) { SCOPED_SERIALISE_CONTEXT(CREATE_DESCRIPTOR_HEAP); Serialise_CreateDescriptorHeap(pDescriptorHeapDesc, riid, (void **)&wrapped); D3D12ResourceRecord *record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID()); record->type = Resource_DescriptorHeap; record->Length = 0; wrapped->SetResourceRecord(record); record->AddChunk(scope.Get()); { SCOPED_LOCK(m_CapTransitionLock); if(m_State != WRITING_CAPFRAME) GetResourceManager()->MarkDirtyResource(wrapped->GetResourceID()); else GetResourceManager()->MarkPendingDirty(wrapped->GetResourceID()); } } else { GetResourceManager()->AddLiveResource(wrapped->GetResourceID(), wrapped); } *ppvHeap = (ID3D12DescriptorHeap *)wrapped; } return ret; }
bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) { ResourceId id = GetResID(res); D3D12ResourceType type = IdentifyTypeByPtr(res); if(type == Resource_DescriptorHeap) { WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)res; UINT numElems = heap->GetDesc().NumDescriptors; D3D12Descriptor *descs = (D3D12Descriptor *)Serialiser::AllocAlignedBuffer(sizeof(D3D12Descriptor) * numElems); memcpy(descs, heap->GetDescriptors(), sizeof(D3D12Descriptor) * numElems); SetInitialContents(heap->GetResourceID(), D3D12ResourceManager::InitialContentData(NULL, numElems, (byte *)descs)); return true; } else if(type == Resource_Resource) { WrappedID3D12Resource *r = (WrappedID3D12Resource *)res; ID3D12Pageable *pageable = r; bool nonresident = false; if(!r->Resident()) nonresident = true; D3D12_RESOURCE_DESC desc = r->GetDesc(); if(desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D && desc.SampleDesc.Count > 1) { D3D12NOTIMP("Multisampled initial contents"); SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(NULL, 2, NULL)); return true; } else if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { D3D12_HEAP_PROPERTIES heapProps; r->GetHeapProperties(&heapProps, NULL); if(heapProps.Type == D3D12_HEAP_TYPE_READBACK) { // already on readback heap, just mark that we can map it directly and continue SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(NULL, 1, NULL)); return true; } 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; desc.Flags = D3D12_RESOURCE_FLAG_NONE; 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(nonresident) m_Device->MakeResident(1, &pageable); if(SUCCEEDED(hr)) { ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList()); list->CopyResource(copyDst, r->GetReal()); } else { RDCERR("Couldn't create readback buffer: 0x%08x", hr); } if(nonresident) { m_Device->CloseInitialStateList(); m_Device->ExecuteLists(); m_Device->FlushLists(); m_Device->Evict(1, &pageable); } SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL)); return true; } else { 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; D3D12_RESOURCE_DESC bufDesc; bufDesc.Alignment = 0; bufDesc.DepthOrArraySize = 1; bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; bufDesc.Flags = D3D12_RESOURCE_FLAG_NONE; bufDesc.Format = DXGI_FORMAT_UNKNOWN; bufDesc.Height = 1; bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; bufDesc.MipLevels = 1; bufDesc.SampleDesc.Count = 1; bufDesc.SampleDesc.Quality = 0; bufDesc.Width = 1; UINT numSubresources = desc.MipLevels; if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D) numSubresources *= desc.DepthOrArraySize; D3D12_PLACED_SUBRESOURCE_FOOTPRINT *layouts = new D3D12_PLACED_SUBRESOURCE_FOOTPRINT[numSubresources]; m_Device->GetCopyableFootprints(&desc, 0, numSubresources, 0, layouts, NULL, NULL, &bufDesc.Width); ID3D12Resource *copyDst = NULL; HRESULT hr = m_Device->GetReal()->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &bufDesc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, __uuidof(ID3D12Resource), (void **)©Dst); if(nonresident) m_Device->MakeResident(1, &pageable); if(SUCCEEDED(hr)) { ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList()); vector<D3D12_RESOURCE_BARRIER> barriers; const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(r)); barriers.reserve(states.size()); for(size_t i = 0; i < states.size(); i++) { if(states[i] & D3D12_RESOURCE_STATE_COPY_SOURCE) continue; D3D12_RESOURCE_BARRIER barrier; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Transition.pResource = r->GetReal(); barrier.Transition.Subresource = (UINT)i; barrier.Transition.StateBefore = states[i]; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; barriers.push_back(barrier); } // transition to copy dest if(!barriers.empty()) list->ResourceBarrier((UINT)barriers.size(), &barriers[0]); for(UINT i = 0; i < numSubresources; i++) { D3D12_TEXTURE_COPY_LOCATION dst, src; src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; src.pResource = r->GetReal(); src.SubresourceIndex = i; dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; dst.pResource = copyDst; dst.PlacedFootprint = layouts[i]; list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL); } // transition back for(size_t i = 0; i < barriers.size(); i++) std::swap(barriers[i].Transition.StateBefore, barriers[i].Transition.StateAfter); if(!barriers.empty()) list->ResourceBarrier((UINT)barriers.size(), &barriers[0]); } else { RDCERR("Couldn't create readback buffer: 0x%08x", hr); } if(nonresident) { m_Device->CloseInitialStateList(); m_Device->ExecuteLists(); m_Device->FlushLists(); m_Device->Evict(1, &pageable); } SAFE_DELETE_ARRAY(layouts); SetInitialContents(GetResID(r), D3D12ResourceManager::InitialContentData(copyDst, 0, NULL)); return true; } } else { RDCERR("Unexpected type needing an initial state prepared: %d", type); } return false; }