UMA の最適化: CPU アクセス可能テクスチャと標準スウィズル
ユニバーサル メモリ アーキテクチャ (UMA) GPU は、効率の点で独立型 (ディスクリート) GPU よりも有利です。特にモバイル デバイスに合わせて最適化するときです。 GPU が UMA である場合にリソースを CPU アクセス可能にすると、CPU と GPU の間で発生するコピーの量を削減できます。 UMA 設計のすべてのリソースをアプリケーションで無条件に CPU アクセス可能にすることはお勧めできませんが、適切なリソースを CPU アクセス可能にすると効率向上の機会が得られます。 ディスクリート GPU とは異なり、CPU は、GPU からアクセス可能なすべてのリソースへのポインターを持つことが技術的に可能です。
CPU アクセス可能テクスチャの概要
CPU アクセス可能テクスチャ (グラフィックス パイプライン内の) は、UMA アーキテクチャの機能の 1 つです。この機能によって、CPU からテクスチャの読み取りと書き込みのアクセスが可能になります。 より一般的なディスクリート GPU では、CPU はグラフィックス パイプライン内のテクスチャにアクセスできません。
テクスチャに関しては一般的に、ディスクリート GPU にも対応するよう設計することが推奨されます。このようにするには一般的に、「バッファーを使用したテクスチャ データのアップロード」で説明するプロセスが必要になります。その要約を次に示します。
- 大部分のテクスチャについては CPU アクセスを一切許可しない。
- テクスチャ レイアウトをD3D12_TEXTURE_LAYOUT_UNKNOWNに設定します。
- CopyTextureRegion を使用してテクスチャを GPU にアップロードする。
ただし、状況によっては、CPU と GPU が同じデータに対してやりとりする頻度が高くなるため、テクスチャをマッピングすると、電力を節約することや、特定のアダプターまたはアーキテクチャ上の特定の設計を高速化することに役立つ可能性があります。 アプリケーションでは、このような状況を検出して、最適化によって不要なコピーをなくす必要があります。 これに該当する場合に最適なパフォーマンスを得るには、次のことを考慮します。
D3D12_FEATURE_DATA_ARCHITECTURE::UMA が TRUE の場合にのみ、マッピング テクスチャのパフォーマンスを向上させます。 このようにするときは、CacheCoherentUMA に注意を払って、どの CPU キャッシュ プロパティをヒープに対して選択するかを判断します。
テクスチャに対する CPU アクセスを活用することは、バッファーの場合よりも複雑です。 GPU の最も効率的なテクスチャ レイアウトがrow_majorされることはほとんどありません。 実際、一部の GPU では、テクスチャ データをコピーするときにrow_majorテクスチャのみをサポートできます。
UMA GPU は一般的に、単純な最適化によってレベルロード時間を短縮できるはずです。 アプリケーションでは、UMA を認識した後に、最適化として最初の CopyTextureRegion (GPU によって変更されることのないテクスチャをメモリに入れておくため) を除去することができます。 D3D12_HEAP_TYPE_DEFAULTを使用してヒープ内にテクスチャを作成し、テクスチャ データをマーシャリングする代わりに、アプリケーションで WriteToSubresource を 使用して、実際のテクスチャ レイアウトを理解しないようにすることができます。
D3D12 では、D3D12_TEXTURE_LAYOUT_UNKNOWNで作成され、CPU アクセスなしで作成されたテクスチャは、頻繁な GPU レンダリングとサンプリングに最も効率的です。 パフォーマンス テストでは、これらのテクスチャを CPU アクセスを使用するD3D12_TEXTURE_LAYOUT_UNKNOWNと比較し、CPU アクセスを使用してD3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLEし、アダプター間のサポートをD3D12_TEXTURE_LAYOUT_ROW_MAJORする必要があります。
CPU アクセスでD3D12_TEXTURE_LAYOUT_UNKNOWNを使用すると、 WriteToSubresource、 ReadFromSubresource、 Map (ポインターへのアプリケーション アクセスを除外)、および マップ解除の各メソッドが有効になります。GPU アクセスの効率を犠牲にすることができます。
CPU アクセスでD3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLEを使用すると、 WriteToSubresource、 ReadFromSubresource、 Map (アプリケーションへの有効なポインターを返す)、および マップ解除が有効になります。 また、CPU アクセスを使用して GPU アクセスの効率をD3D12_TEXTURE_LAYOUT_UNKNOWN以上に犠牲にすることもできます。
標準スウィズルの概要
D3D12 (および D3D11.3) では、標準の多次元データ レイアウトが導入されています。 この目的は、複数の処理ユニットが同じデータの操作を行うときに、複数のレイアウト間でのデータのコピーやデータのスウィズルを不要にすることです。 レイアウトが標準化されていれば、ネットワーク効果による効率の向上が可能になると共に、特定のパターンを想定することによってアルゴリズムのショートカットが可能になります。
テクスチャ レイアウトの詳細については、「 D3D12_TEXTURE_LAYOUT」を参照してください。
ただし、この標準スウィズルはハードウェアの機能の 1 つであるため、すべての GPU でサポートされるとはかぎりません。
スウィズルの背景情報については、Z 階数曲線の説明を参照してください。
API
D3D11.3 とは異なり、D3D12 では既定でテクスチャ マッピングがサポートされているため、 D3D12_FEATURE_DATA_D3D12_OPTIONSに対してクエリを実行する必要はありません。 ただし、D3D12 では標準のスワイズルが常にサポートされているわけではありません。この機能は、CheckFeatureSupport を呼び出して、D3D12_FEATURE_DATA_D3D12_OPTIONSの StandardSwizzle64KBSupported フィールドを確認してクエリを実行する必要があります。
テクスチャ マッピングを参照する API は次のとおりです。
列挙型
- D3D12_TEXTURE_LAYOUT : 既定のテクスチャのスワイズル パターンを制御し、CPU アクセス可能なテクスチャでマップのサポートを有効にします。
構造体
- D3D12_RESOURCE_DESC : テクスチャなどのリソースを記述します。これは広く使用されている構造です。
- D3D12_HEAP_DESC : ヒープについて説明します。
メソッド
- ID3D12Device::CreateCommittedResource : 単一のリソースとバッキング ヒープを適切なサイズとアラインメントで作成します。
- ID3D12Device::CreateHeap : バッファーまたはテクスチャ用のヒープを作成します。
- ID3D12Device::CreatePlacedResource : 特定のヒープ内に配置されるリソースを作成します。通常は、リソース作成用のメソッドとして CreateHeap よりも高速です。
- ID3D12Device::CreateReservedResource : 予約されているがコミットもヒープへの配置もまだ行われていないリソースを作成します。
- ID3D12CommandQueue::UpdateTileMappings : タイル リソース内のタイル位置とリソース ヒープ内のメモリ位置とのマッピングを更新します。
- ID3D12Resource::Map : リソース内の指定されたデータへのポインターを取得し、そのサブリソースへの GPU アクセスを拒否します。
- ID3D12Resource::GetDesc : リソースのプロパティを取得します。
- ID3D12Heap::GetDesc : ヒープのプロパティを取得します。
- ReadFromSubresource : Map を使用してマッピングされたテクスチャからデータをコピーします。
- WriteToSubresource : Map を使用してマッピングされたテクスチャにデータをコピーします。
リソースと親ヒープには、アラインメントに関して次の要件があります。
- マルチサンプル テクスチャのD3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4 MB)。
- 単一のサンプル テクスチャとバッファーのD3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT (64 KB)。
- 線形サブリソースのコピーは、D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512 バイト) に配置し、行ピッチをD3D12_TEXTURE_DATA_PITCH_ALIGNMENT (256 バイト) に揃える必要があります。
- 定数バッファー ビューは、D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT (256 バイト) に揃える必要があります。
64 KB よりも小さいテクスチャは、CreateCommittedResource を介して処理する必要があります。
動的テクスチャ (フレームごとに変わるテクスチャ) の場合は、CPU がアップロード ヒープに線形書き込みした後に GPU コピー操作が行われます。
一般的に、動的リソースを作成するには、大きいバッファーをアップロード ヒープ内に作成します (「バッファー内のサブ割り当て」を参照)。 ステージング リソースを作成するには、大きいバッファーをリードバック ヒープ内に作成します。 既定の静的リソースを作成するには、隣接リソースを既定のヒープ内に作成します。 既定のエイリアス リソースを作成するには、重複するリソースを既定のヒープ内に作成します。
WriteToSubresource と ReadFromSubresource を使用すると、テクスチャ データを行優先レイアウトと未定義リソース レイアウトとの間で再配置することができます。 この操作は同期的であるため、アプリケーションは CPU スケジューリングを念頭に置く必要があります。 アプリケーションではいつでも、コピー処理を小さな領域に分割することや、この操作を別のタスクで行うようにスケジュールすることができます。 MSAA リソースや深度ステンシル リソースのリソース レイアウトが不透明の場合は、このような CPU コピー操作ではサポートされず、エラーとなります。 フォーマットの要素サイズが 2 のべき乗でない場合も、サポートされていないためエラーとなります。 メモリ不足のリターン コードが発生する可能性があります。
関連トピック