Skip to content
Go back

Efficient Use of GPU Memory in Modern Games

· Updated:

slides video web

拙訳

メモリの種類(物理)

  • GPUメモリ:MEMORY_POOL_L1 (DX) / DEVICE_LOCAL (VK)
  • CPUメモリ:MEMORY_POOL_L0 (DX)

メモリの種類(論理)

  • GPUメモリ:DEFAULT (DX) / DEVICE_LOCAL (VK)
    • GPUから高速に直接アクセスできる
    • CPUから直接アクセスできない
    • GPUで頻繁に読み書きするもの(RTV/DSV/UAV)や1回書き込んだら何度も読み込むもの(変更しないIB/VB/Tex)に使う
  • CPUメモリ
    • CPU→GPU:UPLOAD (DX) / VISIBLE | COHERENT (VK)
      • CPUから直接アクセスでき、キャッシュされず、書き込みはまとめて行われる
        • 連続的な書き込みは高速🐰
        • 読み込みやトビトビな書き込みは低速🐢
      • CPUで書き込み、GPUにコピーされるものに使う
      • CPUで書き込み、GPUで直接読み出すものに使う
      • Pro tip: データの先頭は64Bに揃える
    • GPU→CPU:READBACK (DX) / VISIBLE | COHERENT | CACHED (VK)
      • CPUから直接アクセスでき、キャッシュされる
      • GPUで書き込み、CPUで読み込むものに使う

データのアップロード方法

  • 方法1:UPLOADにCPUで書き込み、DEFAULTにコピーしてからGPUで読み出す
  • 方法2:UPLOADにCPUで書き込み、そのままGPUで読み出す
    • バッファでは大丈夫
    • テクスチャではGPU固有の最適なフォーマットで格納したほうが良い
      • TEXTURE_LAYOUT_UNKNOWN (DX) / IMAGE_TILING_OPTIMAL (VK)
  • 方法3:BAR(Base Address Register)にCPUで書き込み、そのままGPUで読み出す
    • BARはGPU側にあるが、CPUで直接書アクセスでき、キャッシュされず、書き込みはまとめて行われる
    • Vulkanでは、LOCAL | VISIBLE | COHERENT
    • DirectXでは、現時点では確認する術はない

Resizable BAR (ReBAR)

  • 通常のBARは256MBで固定
  • ReBARを有効にするとVRAM全体にCPUでアクセスできるようになる
  • Vulkanでは、LOCAL | VISIBLEメモリが256MB以上かどうかで分かる
  • DirectXでは、現時点では直接使用する術はない
  • ReBARでもUPLOADと同様のTipsが有効
    • 連続的な書き込みが高速🐰
  • PCIe 4.0ならVRAMへの書き込みもCPUメモリと同等に高速なはず

パフォーマンスTips

  • 個々のバッファ/テクスチャにはオーバーヘッドが存在する
    • 大きなバッファ/テクスチャをいくつか用意してsub-allocateする
    • バッファ1つに有意義なデータが64KB以上あるとなお良い
  • 個々のSubmit/Executeやセマフォ/イベントによるキュー間同期にはオーバーヘッドが存在する
    • 並列処理でレイテンシーを隠蔽する
    • データを使うのと同じキューでコピーを行う、または、データを直接読み出してコピーを行わないようにする
  • Map/Unmapにはいくらかのオーバーヘッドが存在する
    • バッファをマップしたままにしておく
  • UPLOADリソースはVRAMに割り当てられることがあるので:
    • VRAMを取りすぎない、すなわち、UPLOADメモリを割り当てしすぎない
    • 生成時に「好ましいヒープ」が決められる、すなわち、VRAMに割り当てられる可能性を高めるために最重要リソースから割り当てを行う
    • “Residency”はヒープ全体で管理される、すなわち、巨大で重要なリソースを別個の割当で生成する(committed/dedicatedを使う)
  • コピーするのはどのキューが良い?
    • PCIeを介してUPLOADからコピーするときは、コピーキューのほうが若干早い🐰
    • コピー元がVRAMにあるときは、コピーキューのほうが何倍か遅い🐢🐢🐢
    • コピーキューを使うのは、レンダリングの裏で非同期に行う場合(テクスチャストリーミングとか)
    • グラフィクス/コンピュートキューを使うのは、結果が即座に欲しい場合(現フレームの動的データとか)
      • 非同期コンピュートが裏でのコピーに使えるかも?
    • UPLOADやBARを使ってコピーをしないことも一考すると良い
      • 少量のデータとか、一度しか読み出さないデータとか