I want to get cpu-readable buffer from D3D12 texture (dimension is D3D12_RESOURCE_DIMENSION_TEXTURE2D which can not directly accessed by cpu). So I tried to copy the texture to an intermediate texture with a readback heap type.
Here is the code:
ID3D12Resource* newTex;
hr = GetD3D12Device()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(GetRequiredIntermediateSize(texture, 0, 1)),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&newTex));
if (hr < 0) {
return;
}
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
srcLocation.pResource = texture;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
dstLocation.pResource = newTex;
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
commandList_->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, nullptr);
void* pData;
hr = newTex->Map(0, nullptr, &pData);
if (hr < 0) {
return;
}
Here is the error log:
D3D12 ERROR: ID3D12CommandList::CopyTextureRegion: D3D12_SUBRESOURCE_FOOTPRINT::Format is not supported at the current feature level with the dimensionality implied by the D3D12_SUBRESOURCE_FOOTPRINT::Height and D3D12_SUBRESOURCE_FOOTPRINT::Depth. Format = UNKNOWN, Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D, Height = 0, Depth = 0, and FeatureLevel is D3D_FEATURE_LEVEL_12_2.
What am i missing? Or Is it practical to get the texture to a cpu-readable buffer?
Well you didn't fill PlacedFootprint
member of your destination D3D12_TEXTURE_COPY_LOCATION
and SubresourceIndex
of your source D3D12_TEXTURE_COPY_LOCATION
:
D3D12_TEXTURE_COPY_LOCATION dst_texture;
dst_texture.pResource = newTex;
dst_texture.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
dst_texture.PlacedFootprint.Offset = 0;
dst_texture.PlacedFootprint.Footprint.Width = textureWidth;
dst_texture.PlacedFootprint.Footprint.Height = textureHeight;
dst_texture.PlacedFootprint.Footprint.Depth = 1;
dst_texture.PlacedFootprint.Footprint.Format = textureFormat;
dst_texture.PlacedFootprint.Footprint.RowPitch = textureRowPitch; //depends on your texture format stride and texture width
D3D12_TEXTURE_COPY_LOCATION src_texture;
src_texture.pResource = texture;
src_texture.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src_texture.SubresourceIndex = 0;
commandList_->CopyTextureRegion(&dst_texture, 0, 0, 0, &src_texture, nullptr);