次の方法で共有


割り当ての使用状況の追跡

割り当てリストが表示されなくなったため、ビデオ メモリ マネージャー (VidMm) は、特定のコマンド バッファーで参照されている割り当てを表示できなくなりました。 その結果、VidMm は割り当ての使用状況を追跡し、関連する同期を処理する位置にありません。 この責任は、ユーザー モード ドライバー (UMD) に該当するようになりました。 特に、UMD は、割り当てと名前変更への直接 CPU アクセスに関して同期を処理する必要があります。

VidMm は、呼び出し元のスレッドとパフォーマンスに対して非ブロッキングの両方を行う安全な方法で、割り当て破棄を非同期的に延期します。 そのため、UMD は割り当て破棄を延期する必要があることを懸念する必要はありません。 VidMm は、割り当て破棄要求を受信すると、破棄要求の前にキューに入れたコマンドが、破棄される割り当てにアクセスする可能性があることを既定で想定します。 これにより、VidMm は、キューに登録されたコマンドが完了するまで破棄操作を延期します。 UMD は、保留中のコマンドが破棄される割り当てにアクセスできないことを認識している場合は、Deallocate2 またはDestroyAllocation2 を呼び出すときに AssumeNotInUse フラグを設定することで、待機せずに要求を処理するように VidMm に指示できます。

Lock2

UMD は、直接 CPU アクセスに関して適切な同期を処理する役割を担います。 特に、UMD は次の場合に必要です。

  1. 非上書きおよび破棄ロック セマンティクスをサポートします。これは、UMD が独自の名前変更スキームを実装する必要があることを意味します。

  2. 同期を必要とするマップ操作の場合 (つまり、上記の非上書きまたは破棄ではありません)。

    • 現在ビジー状態の割り当てにアクセスしようとして、ロック操作が呼び出し元スレッドをブロックしないように呼び出し元が要求した場合は、WasStillDrawing を返します (D3D11_MAP_FLAG_DO_NOT_WAIT)。
    • あるいは、D3D11_MAP_FLAG_DO_NOT_WAIT フラグが設定されていない場合は、割り当てが CPU アクセスに使用できるようになるまで待ちます。 UMD は、非ポーリング待機を実装する必要があります。 UMD では、新しいコンテキスト監視メカニズムが使用されます。

現時点では、UMD は引き続き LockCb/UnlockCb を呼び出して、CPU アクセスの割り当てを設定するように VidMm に要求する必要があります。 ほとんどの場合、UMD は割り当てをその有効期間全体にわたってマップしたままにできます。 ただし、今後、LockCbUnlockCb は廃止され、新しい Lock2Cb 呼び出しと Unlock2Cb 呼び出しが優先されます。 これらの新しいコールバックの目的は、新しいクリーン実装に新しい引数とフラグのセットを提供することです。

スイズリング範囲は、WDDM バージョン 2 から削除されます。 Lock2Cb に基づく実装に移行する際に、ドライバー開発者は、LockCb への呼び出しからスイズリング範囲への依存関係を削除する必要があります。

Lock2Cb は、割り当てに対する仮想アドレスを取得するための簡単な方法として公開されます。 割り当ての種類と現在常駐している現在のセグメントに基づいて、いくつかの制限があります。

ドライバーは、セグメントが CpuVisible フラグを介して CPU にアクセスできるかどうかを示します。これは、DXGK_SEGMENTDESCRIPTOR 構造体の Flags メンバーにあります。

CPU アクセス可能な割り当ての場合:

  • キャッシュされた CPU アクセス可能割り当ては、アパーチャ セグメント内に存在するか、ロックするために常駐していない必要があります。 グラフィックス処理装置 (GPU) 上の CPU とメモリ セグメントの間のキャッシュの一貫性を保証することはできません。
  • 完全に CPU アクセス可能なメモリ セグメント (サイズ変更可能な BAR を使用してサイズ変更) にある CPU アクセス可能な割り当ては、ロック可能であり、仮想アドレスを返すことが保証されます。 このシナリオでは、特別な制限は必要ありません。
  • CPU アクセスできないメモリ セグメント内にある CPU アクセス可能な割り当て (CpuHostAperture へのアクセスの有無にかかわらず) は、さまざまな理由で CPU 仮想アドレスにマップできない可能性があります。 CpuHostAperture の空き領域が不足しているか、割り当てでアパーチャ セグメントが指定されていない場合は、仮想アドレスを取得できません。 このため、CPU アクセス不可のメモリ セグメント内のすべての CPU アクセス可能割り当てには、サポートされているセグメント セットにアパーチャ セグメントが含まれている必要があります。 この要件により、VidMm がシステム メモリ内に割り当てを配置し、仮想アドレスを提供できることが保証されます。
  • システム メモリ内に既に配置されている (またはアパーチャ セグメントにマップされている) CPU アクセス可能な割り当ては、確実に動作することが保証されます。

CPU にアクセス不可能な割り当ての場合:

  • CPU アクセス可能な割り当ては、GPU フレーム バッファーを直接指し示すことができないセクション オブジェクトによってサポートされます。 CPU にアクセスできない割り当てをロックするには、割り当てでサポートされているセグメント セット内のアパーチャ セグメントがサポートされているか、既にシステム メモリ内に存在している必要があります (デバイスに常駐することはできません)。

割り当てがデバイス上に存在しないが、アパーチャ セグメントをサポートしていない間に割り当てが正常にロックされた場合、割り当てはロックの期間中、メモリ セグメントにコミットすることはできません。

現在、Lock2 にはフラグが含まれており、Reserved フラグ ビットはすべて 0 である必要があります。

CpuHostAperture

BAR のサイズ変更が失敗したときに CPU にアクセスできないメモリ セグメントによるロックをより適切にサポートするために、PCI アパーチャに CpuHostAperture が用意されています。 CpuHostAperture はページ ベースのマネージャーとして動作し、DxgkDdiMapCpuHostAperture デバイス ドライバー インターフェイス (DDI) 関数を使用してビデオ メモリの領域に直接マップできます。 その後、VidMm は仮想アドレス空間の範囲を CpuHostAperture の連続しない範囲に直接マップし、CpuHostAperture をビデオ メモリにマップします。スイズリング範囲は必要はありません。

CPU がアクセスできないメモリ セグメント内で CPU が参照できるロック可能なメモリの最大量は、CpuHostAperture のサイズに制限されます。 CpuHostAperture を DirectX グラフィックス カーネルに公開する方法の詳細については、「CPU ホスト アパーチャ」を参照してください。

I/O コヒーレンシー

現在の x86/x64 では、GPU がキャッシュ可能なシステム メモリ サーフェイスに対して読み取りまたは書き込みを行い、CPU との一貫性を維持するために、すべての GPU で PCIe 経由の I/O コヒーレンシーをサポートする必要があります。 サーフェスが GPU の観点からキャッシュ コヒーレントとしてマップされている場合、GPU はサーフェスにアクセスするときに CPU キャッシュをスヌーピングする必要があります。 通常、この形式の一貫性は、一部のステージング サーフェスなど、CPU が読み取る必要があるリソースに使用されます。

一部の Arm プラットフォームでは、I/O コヒーレンシーはハードウェアで直接サポートされていません。 これらのプラットフォームでは、CPU キャッシュ階層を手動で無効にすることで、I/O コヒーレンシーをエミュレートする必要があります。 VidMm では、GPU からの割り当て (割り当てリストの読み取り/書き込み操作) と CPU (マップ操作、読み取り/書き込み) に対する操作を追跡することによって行われます。 VidMm は、キャッシュに次のいずれかが含まれている可能性が判断されると、キャッシュの無効化を生成します。

  • 書き戻す必要があるデータ (CPU 書き込み、GPU 読み取り)
  • 無効にする必要がある古いデータ (GPU 書き込み、CPU 読み取り)。

I/O コヒーレンシーのないプラットフォームでは、割り当てに対する CPU と GPU のアクセスを追跡するのは、UMD の責任となります。 グラフィックス カーネルは、UMD がキャッシュ可能な割り当てに関連付けられている仮想アドレス範囲を書き戻して無効にするために使用できる新しい Invalidate Cache DDI を公開します。 I/O コヒーレンシーをサポートしていないプラットフォームでは、CPU 書き込み後、GPU 読み取り前、および書き込み後と CPU 読み取り前に、UMD でこの関数を呼び出す必要があります。 後者は、最初は直感的でないように見えるかもしれません。 しかし、CPU は GPU の書き込み前にデータをメモリに投機的に読み取る可能性があるため、CPU が RAM からデータを確実に再読み取りするには、すべての CPU キャッシュを無効にする必要があります。