void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, InitialContentData data) { D3D12ResourceType type = IdentifyTypeByPtr(live); if(type == Resource_DescriptorHeap) { ID3D12DescriptorHeap *dstheap = (ID3D12DescriptorHeap *)live; ID3D12DescriptorHeap *srcheap = (ID3D12DescriptorHeap *)data.resource; if(srcheap) { // copy the whole heap m_Device->CopyDescriptorsSimple( srcheap->GetDesc().NumDescriptors, dstheap->GetCPUDescriptorHandleForHeapStart(), srcheap->GetCPUDescriptorHandleForHeapStart(), srcheap->GetDesc().Type); } } else if(type == Resource_Resource) { if(data.num == 1 && data.resource) { ID3D12Resource *copyDst = Unwrap((ID3D12Resource *)live); ID3D12Resource *copySrc = (ID3D12Resource *)data.resource; D3D12_HEAP_PROPERTIES heapProps = {}; copyDst->GetHeapProperties(&heapProps, NULL); // if destination is on the upload heap, it's impossible to copy via the device, // so we have to map both sides and CPU copy. if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD) { byte *src = NULL, *dst = NULL; HRESULT hr = S_OK; hr = copySrc->Map(0, NULL, (void **)&src); if(FAILED(hr)) { RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr); src = NULL; } if(copyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { hr = copyDst->Map(0, NULL, (void **)&dst); if(FAILED(hr)) { RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr); dst = NULL; } if(src && dst) { memcpy(dst, src, (size_t)copySrc->GetDesc().Width); } if(dst) copyDst->Unmap(0, NULL); } else { D3D12_RESOURCE_DESC desc = copyDst->GetDesc(); 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]; UINT *numrows = new UINT[numSubresources]; UINT64 *rowsizes = new UINT64[numSubresources]; m_Device->GetCopyableFootprints(&desc, 0, numSubresources, 0, layouts, numrows, rowsizes, NULL); for(UINT i = 0; i < numSubresources; i++) { hr = copyDst->Map(i, NULL, (void **)&dst); if(FAILED(hr)) { RDCERR("Doing CPU-side copy, couldn't map source: 0x%08x", hr); dst = NULL; } if(src && dst) { byte *bufPtr = src + layouts[i].Offset; byte *texPtr = dst; for(UINT d = 0; d < layouts[i].Footprint.Depth; d++) { for(UINT r = 0; r < numrows[i]; r++) { memcpy(bufPtr, texPtr, (size_t)rowsizes[i]); bufPtr += layouts[i].Footprint.RowPitch; texPtr += rowsizes[i]; } } } if(dst) copyDst->Unmap(0, NULL); } delete[] layouts; delete[] numrows; delete[] rowsizes; } if(src) copySrc->Unmap(0, NULL); } else { ID3D12GraphicsCommandList *list = Unwrap(m_Device->GetInitialStateList()); vector<D3D12_RESOURCE_BARRIER> barriers; const vector<D3D12_RESOURCE_STATES> &states = m_Device->GetSubresourceStates(GetResID(live)); barriers.reserve(states.size()); for(size_t i = 0; i < states.size(); i++) { if(states[i] & D3D12_RESOURCE_STATE_COPY_DEST) continue; D3D12_RESOURCE_BARRIER barrier; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Transition.pResource = copyDst; barrier.Transition.Subresource = (UINT)i; barrier.Transition.StateBefore = states[i]; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; barriers.push_back(barrier); } // transition to copy dest if(!barriers.empty()) list->ResourceBarrier((UINT)barriers.size(), &barriers[0]); if(copyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { list->CopyBufferRegion(copyDst, 0, copySrc, 0, copySrc->GetDesc().Width); } else { D3D12_RESOURCE_DESC desc = copyDst->GetDesc(); 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, NULL); for(UINT i = 0; i < numSubresources; i++) { D3D12_TEXTURE_COPY_LOCATION dst, src; dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; dst.pResource = copyDst; dst.SubresourceIndex = i; src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; src.pResource = copySrc; src.PlacedFootprint = layouts[i]; list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL); } delete[] layouts; } // transition back to whatever it was before 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]); #if ENABLED(SINGLE_FLUSH_VALIDATE) m_Device->CloseInitialStateList(); m_Device->ExecuteLists(); m_Device->FlushLists(true); #endif } } else { RDCERR("Unexpected num or NULL resource: %d, %p", data.num, data.resource); } } else { RDCERR("Unexpected type needing an initial state created: %d", type); } }