Advertisement

D3D12: CopyTextureRegion mip-map

Started by January 04, 2018 08:24 AM
4 comments, last by VietNN 7 years, 1 month ago

Hi all,

I want to copy  just 1 mipmap level of a texture and I am doing like this:


void CopyTextureRegion(
  &CD3DX12_TEXTURE_COPY_LOCATION(pDstData, mipmapIndex),
  0, 0, 0,
  &CD3DX12_TEXTURE_COPY_LOCATION(pSrcData, pLayout),
  nullptr
);

- pDstData : is DEFAULT_HEAP, pSrcData is UPLOAD_HEAP(buffer size was get by GetCopyableFootprints from pDstData with highest miplevel), pLayout is D3D12_PLACED_SUBRESOURCE_FOOTPRINT

- I think the mipmapIndex will point the exact location data of Dest texture, but does it know where to get data location from Src texture because pLayout just contain info of this mipmap(Offset and Footprint).  (???)

- pLayout has a member name Offset, and I try to modify it but it(Offset) need 512 Alignment but real offset in Src texture does not.

So what I need to do to match the location of mip texture in Src Texture ?

@SoldierOfLight @galop1n

I'm not really following the question.

1. Did you create your upload buffer big enough for the top mip, or big enough for the entire mip chain?

2. Did you manually fill out the upload buffer layout, or was it populated by GetCopyableFootprints (ideally in a single call for the entire mip chain, but you could call it multiple times if you keep track of the starting offset)?

3. Where in the upload buffer did you write the data for the mip level you're trying to copy? At the start? Immediately after the previous one? Or at the offset provided for that mip level by GetCopyableFootprints?

Advertisement

Hi @SoldierOfLight

1. I created upload buffer big enough for entire mip as below code:


device->GetCopyableFootprints(&textureDesc, 0, textureDesc.MipLevels, 0, nullptr, nullptr, nullptr, &textureUploadBufferSize);
hr = m_device->GetId()->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(textureUploadBufferSize),
			D3D12_RESOURCE_STATE_GENERIC_READ,
			nullptr,
			IID_PPV_ARGS(&m_textureBufferUploadHeap));

2 & 3. At current, I fill data for each mip (mip by mip), step like this:

   - get data from 1 mip only

   - copy data to upload heap: offset for upload heap was got by:


GetCopyableFootprints(&textureDesc, 0, mipmapIndex, 0, nullptr, nullptr, nullptr, &offset)

     offset is total bytes from mip 0 to mipmapIndex - 1. Then I get data pointer by UploadHeap->Map() + offset. and start copy at this pointer.

   - copy mip data from UploadHeap to DefaultHeap by CopyTextureRegion: Here is the question come, I dont know how to match pointer to this mip on UploadHeap for copying. At #1 I tried to modify pLayout.Offset by offset value got by previous step but not success because it was not 512 Alignment

 

Right, the total size (which is what that last parameter is) doesn't need to be aligned to 512. You can just align your offset to the next 512 before writing.

Note that the intended usage pattern would involve not passing null for the pLayouts parameter, and having GetCopyableFootprints fill out offsets + layouts for all mips at the same time. You should also strongly consider using the UpdateSubresources helper in d3dx12.h, which encapsulates the layout retrieval, copying to the upload buffer, and issuing the CopyTextureRegion calls.

Thank you,

I did not know that GetCopyableFootprints  can fill out  offsets + layouts for all mips at the same time, by doing this pLayout.Offset will have value when NumSubresource > 1.

I did get pLayout for each mip by GetCopyableFootprints with FirstSubresource=mip_index and NumSubresource always = 1, so the pLayout.Offset just return 0.

Many thanks, @SoldierOfLight

This topic is closed to new replies.

Advertisement