ユーザ用ツール

サイト用ツール


d3d:d3d12:texture

Texture の転送

転送手順の概要

Buffer, Texture の転送もアプリケーション側で管理する必要があります。

GPU 側の VRAM を直接 Map することはできません。 一旦 Map 可能な Buffer (D3D12_HEAP_TYPE_UPLOAD) に書き込み、GPU の Copy 命令で転送を行います。

  1. Texture 用の Resource 作成 (D3D12_HEAP_TYPE_DEFAULT, D3D12_RESOURCE_STATE_COPY_DEST)
  2. 転送用 Buffer の Resource を作成 (D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ)
  3. レイアウト取得 ( GetCopyableFootprints() )
  4. レイアウトに従い、転送するピクセルデータを Buffer に書き込む
  5. 転送用 CommandList を作成
  6. CommandList に CopyTextureRegion() 等の転送コマンドを格納
  7. 転送に使う CommandList/Queue が描画用と共用なら ResourceBarrier が必要。D3D12_RESOURCE_STATE_COPY_DEST → D3D12_RESOURCE_STATE_GENERIC_READ
  8. 転送用の CommandQueue で CommandList を実行
  9. CommandQueue に転送完了 Fence (Sginal) を挿入
  10. Fence で転送完了を確認。完了後は Upload 用の Buffer と CommandList を Release できる。

Texture 用 Resource 作成。

ID3D12Resource* iTexture= nullptr;
 
D3D12_RESOURCE_DESC  desc;
memset( &desc, 0, sizeof(desc) );
desc.Dimension= D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Width= 512;
desc.Height= 512;
desc.DepthOrArraySize= 1;
desc.MipLevels= 1;
desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count= 1;
 
D3D12_HEAP_PROPERTIES  heap;
memset( &heap, 0, sizeof(heap) );
heap.Type= D3D12_HEAP_TYPE_DEFAULT;
 
iD3DDevice->CreateCommitedResource( &heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&iTexture) );

Footprint 取得。

D3D12_PLACED_SUBRESOURCE_FOOTPRINT  footprint;
UINT64  total_bytes= 0;
iD3DDevice->GetCopyableFootprints( &desc, 0, 1, 0, &footprint, nullptr, nullptr, &total_bytes );

Upload 用 Buffer 作成

D3D12_RESOURCE_DESC  desc;
memset( &desc, 0, sizeof(desc) );
desc.Dimension= D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Width= total_bytes;
desc.Height= 1;
desc.DepthOrArraySize= 1;
desc.MipLevels= 1;
desc.SamleDesc.Count= 1;
desc.Layout= D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
 
D3D12_HEAP_PROPERTIES  heap;
memset( &heap, 0, sizeof(heap) );
heap.Type= D3D12_HEAP_TYPE_UPLOAD;
 
ID3D12Resource*  iUploadBuffer= nullptr;
iD3DDevice->CreateCommittedResource( &heap, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&iUploadBuffer) );

Upload Buffer への書き込み。

void*  ptr= nullptr;
iUploadBuffer->Map( 0, nullptr, &ptr );
memcpy( reinterpret_cast<unsigned char*>(ptr) + footprint.Offset, pixel_data, pixel_data_size );

Copy コマンド作成

D3D12_TEXTURE_COPY_LOCATION  dest;
memset( &dest, 0, sizeof(dest) );
dest.pResource= iTexture;
dest.Type= D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dest.SubresourceIndex= 0;
 
D3D12_TEXTURE_COPY_LOCATION  src;
memset( &src, 0, sizeof(src) );
src.pResource= iUploadBuffer;
src.Type= D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.PlacedFootprint= footprint;
 
ID3D12GraphicsCommandList*  iCommandList= GetCurrentCommandList();
iCommandList->CopyTextureRegion( &dest, 0, 0, 0, &src, nullptr );

ResourceBarrier 挿入

D3D12_RESOURCE_BARRIER  barrier;
memset( &barrier, 0, sizeof(barrier) );
barrier.Type= D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Transition.pResource= iTexture;
barrier.Transition.Subresource= D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore= D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.StateAfter= D3D12_RESOURCE_STATE_GENERIC_READ;
 
iCommandList->ResourceBarrier( 1, &barrier );

Command 実行

iCommandList->Close();
ID3D12CommandList*  list[]= { iCommandList };
iCommandQueue->ExecuteCommandLists( 1, list );
 
FenceCount++;
iCommandQueue->Signal( iUploadFence, FenceCount );

ResourceView の作成

D3D12_SHADER_RESOURCE_VIEW_DESC  desc;
memset( &desc, 0, sizeof(desc) );
desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
desc.ViewDimension= D3D12_SRV_DIMENSION_TEXTURE2D;
desc.Shader4ComponentMapping= D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
desc.Texture2D.MipLevels= 1;
 
D3D12_CPU_DESCRIPTOR_HANDLE  cpu_handle= iDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
iD3DDevice->CreateShaderResourceView( iTexture, &desc, cpu_handle );
d3d/d3d12/texture.txt · 最終更新: 2015/09/20 20:45 by oga