次の方法で共有


コンポジション スワップチェーン プログラミング ガイド

コンポジション スワップチェーン API は DXGI スワップチェーンのスピリチュアルな後継であり、アプリケーションがコンテンツをレンダリングして画面に表示できるようにします。 DXGI スワップチェーンでこの API を使用するには、いくつかの利点があります。 スワップチェーンの状態に関してよりきめ細かな制御がアプリケーションに与えられ、スワップチェーンの使用方法に関しては、より自由に制御できます。 さらに、この API は、正確な present タイミングに関するより優れたストーリーを提供します。

プレゼンテーションとは

プレゼンテーション は、描画操作の結果を画面上に表示する概念です。 プレゼンテーションの 1 つのインスタンスである present は、画面上の 1 つのバッファーに描画操作の結果を表示する要求です。 presentには、画面上に表示する方法を説明する追加の属性を含めることができます。 この API では、presentは ターゲット時刻 を持つこともできます。これは、present を表示する必要がある理想的な時刻を表すシステム相対タイムスタンプ (割り込み時間) です。 アプリケーションでは、これを使用して、コンテンツが画面に表示される速度をより正確に制御したり、システム内の他のイベント (オーディオ トラックなど) とプレゼンテーションを同期したりできます。

プレゼンテーションの中心にあるのは同期です。 つまり、描画操作は通常、CPU ではなく GPU によって実行され、最初に操作を発行した CPU の非同期タイムラインで実行されます。 プレゼンテーションは GPU に送信される操作であり、バッファーが画面に表示される前に、以前に発行された描画操作が完了していることを確認します。

通常、アプリケーションは時間の経過に伴って多数のpresentを発行し、presentを発行するときに複数のテクスチャを選択します。 アプリケーションでは、この API が提供する同期メカニズムを使用して、バッファーを描画して提示した後、そのバッファーが表示され、その後、後続の存在から新しいバッファーに置き換えられるまで、そのバッファーに再度描画しないようにする必要があります。 それ以外の場合、アプリケーションが最初に表示することを意図したバッファーの内容は、その存在が画面に表示されるときに上書きされる可能性があります。

プレゼンテーション モード - コンポジション、マルチプレーン オーバーレイ、および独立フリップ

アプリケーションによって提示されるバッファーは、いくつかの異なる方法でシステムによって表示できます。

最も簡単な方法 (既定値) は、存在が DWM に送信され、DWM が提示されたバッファーに基づいてフレームをレンダリングすることです。 つまり、DWM がディスプレイに送信するバックバッファーへのプレゼンテーション バッファーのコピー (またはより正確には 3D レンダリング) があります。 この存在を表示する方法は、Composition と呼ばれます。

present を表示するよりパフォーマンスの高いモードは、プレゼンテーション バッファーをハードウェアに直接スキャンし、発生するコピーを排除することです。 存在を表示するこの方法は、 ダイレクト スキャンアウト と呼ばれます。 presentを処理する場合、DWM は、 マルチプレーン オーバーレイ プレーン (または略して MPO 平面) にバッファーを割り当てるか、バッファーをハードウェアに直接反転 (ダイレクト フリップと呼ばれます) することで、プレゼンテーション バッファーから直接スキャンするようにハードウェアをプログラムすることを決定できます。

presentを表示するさらにパフォーマンスの高い方法は、presentをグラフィックス カーネルによって直接表示し、DWM を完全にバイパスすることです。 このプレゼンテーション方法は、 独立したフリップ (iflip) と呼ばれます。 マルチプレーン オーバーレイと iflip の両方の パフォーマンスを最大限に 高めるには、DXGI フリップ モデルを使用します

コンポジションは最も簡単にサポートされますが、効率も最も低いです。 サーフェスは、直接スキャンアウトまたは iflip の対象となるために特別に割り当てる必要があります。この種類の特別な割り当てには、コンポジション スワップチェーンよりも厳密なシステム要件があります。 WDDM 3.0 以降のハードウェアでのみ使用できます。 その結果、アプリケーションは、コンポジションのみのプレゼンテーションに対する API サポートと、直接スキャンアウトまたは iflip の対象となるプレゼンテーションに対してクエリを実行できます。

Note

サーフェスでこれらのより最適化されたプレゼンテーション モードを自動的に利用できるようにするには、サーフェスを GPU で直接表示可能なものとして割り当てる必要があります。 Direct3D 11 サーフェスの場合は、サーフェスを表示可能なものとして割り当てる必要があります。 表示可能なものとして割り当てられていないサーフェスも、画面上のシステム コンポジターで合成できますが、独立フリップ モードの利点は得られません。

プレゼンテーション ファクトリ、チェック機能、プレゼンテーション マネージャー

コンポジション スワップチェーン API からアプリケーションが使用する最初のオブジェクトは、 プレゼンテーション ファクトリ です。 プレゼンテーション ファクトリは、アプリケーションによって作成され、アプリケーションが作成する呼び出しに渡す Direct3D デバイスにバインドされます。そのため、そのデバイスに関連付けられているビデオ アダプターとのアフィニティがあります。

プレゼンテーション ファクトリは、現在のシステムとグラフィックス デバイスがコンポジション スワップチェーン API を使用できるかどうかをチェックするメソッドを公開します。 IPresentationFactory::IsPresentationSupported などの機能メソッドを使用して、システム サポートチェックできます。 機能メソッドが API のシステム サポートを示している場合は、プレゼンテーション ファクトリを使用して プレゼンテーション マネージャーを作成できます。 このプレゼンテーション マネージャーは、プレゼンテーション機能を実行するために使用するオブジェクトであり、その作成に使用されたプレゼンテーション ファクトリと同じ Direct3D デバイスとビデオ アダプターにバインドされます。

現在、コンポジション スワップチェーン API を使用するためのシステム要件は、WDDM (Windows デバイス ドライバー モデル) 2.0 と Windows 11 (ビルド 10.0.22000.194) 以降をサポートする GPU ドライバーです。 コンポジション スワップチェーン API を最もパフォーマンスの高い方法 (ダイレクト スキャンアウトと独立フリップ、または iflip) で使用するには、WDDM 3.0 をサポートする GPU ドライバーが必要です。

システムがコンポジション スワップチェーン API を使用できない場合、アプリケーションには、DXGI スワップチェーンなどの古いメソッドを使用してプレゼンテーションを処理するための別のコードパスが必要です。

プレゼンテーション バッファーを登録して表示する

プレゼンテーション マネージャーは、プレゼンテーションできるバッファーを追跡します。 Direct3D テクスチャを表示するには、アプリケーションでまず Direct3D でそのテクスチャを作成してから、プレゼンテーション マネージャーに登録する必要があります。 テクスチャがプレゼンテーション マネージャーに登録されている場合、テクスチャは プレゼンテーション バッファー と呼ばれ、その時点からそのプレゼンテーション マネージャーによって画面に表示されます。 アプリケーションでは、必要に応じてプレゼンテーション バッファーを追加および削除できますが、1 つのプレゼンテーション マネージャー (現在は 31) に追加できるプレゼンテーション バッファーの最大数があります。 これらのプレゼンテーション バッファーは、個々のプレゼンテーション バッファーが表示されるときに有効になるさまざまなサイズと形式の場合もあります。

テクスチャは、任意の数のプレゼンテーション マネージャーに登録できます。ただし、ほとんどの場合、これは通常の使用とは見なされず、アプリケーションが管理を担当する複雑な同期シナリオが発生します。

表示するコンテンツの定義

一般に、存在するバッファーは、 ビジュアル ツリー内のコンテンツに関連付ける必要があります。 そのため、アプリケーションの 問題が発生したときに、表示されるバッファーがビジュアル ツリー内のどこに表示されるかが明確になるように、一種の バインディング を定義する必要があります。 このバインド の プレゼンテーション コンテンツと呼びます。

表示されるコンテンツは、多くの形式をとることができます。 アプリケーションでは、表示する 1 つのバッファーを提示したい場合や、ステレオ コンテンツに左右の両方の目のバッファーを表示したい場合があります。 この API の初期バージョンでは、1 つのバッファーを画面に表示するためのサポートが提供されます。

プレゼンテーション サーフェイス を、一度に 1 つのバッファーが表示されるプレゼンテーション コンテンツの形式として定義します。 プレゼンテーション サーフェイスは、ビジュアル ツリー内のコンテンツとして設定でき、一度に 1 つのプレゼンテーション バッファーを画面上に表示できます。 プレゼンテーション マネージャーが表示すると、1 つ以上のプレゼンテーション サーフェイスによって表示されるバッファーがアトミックに更新されます。

プレゼンテーション マネージャを使用して、特定の コンポジション サーフェス ハンドルに対して 1 つ以上のプレゼンテーション サーフェスを作成できます。 各コンポジション サーフェス ハンドルは、ビジュアル ツリー内の 1 つ以上のビジュアルにバインドして (Windows.UI.CompositionDirectComposition API のドキュメントで概説されている戦略によって)、関連するプレゼンテーション サーフェイスとそのビジュアル ツリーに表示される場所との関係を定義できます。 アプリケーションは、システムに送信され、次の present 操作で実行される 1 つ以上のプレゼンテーション サーフェイスを更新できます。

プレゼンテーション マネージャーは、任意の数のプレゼンテーション サーフェイスに任意のプレゼンテーション バッファーを表示できることに注意してください。 制限事項はありません。 ただし、発行したバッファーと、プレゼンテーション 画面で表示されている間に新しい描画をそのバッファーに発行しないようにするには、アプリケーションが追跡する必要があります。

プレゼンテーション 画面にプロパティを適用する

プレゼンテーション サーフェイスに表示するバッファーを指定するだけでなく、プレゼンテーションサーフェイスに対して他のさまざまなプロパティを指定することもできます。 これには、アルファ モードと色空間、ソース テクスチャの変換とレイアウト方法、保護されたコンテンツの表示または読み戻しの制限など、ソース テクスチャのサンプリング方法を定義するプロパティが含まれます。 これらはすべて、アプリケーションによって変更できるプレゼンテーション サーフェイス上のプロパティ セッター メソッドとして公開され、バッファーの更新と同様に、アプリケーションの存在が行われるときに有効になります。

表示面に表示する

アプリケーションでプレゼンテーション サーフェイスを作成し、プレゼンテーション バッファーを登録し、プレゼンテーション中に問題が発生する更新を指定したら、プレゼンテーションを行ってこれらのプロパティを適用できます。 アプリケーションは、プレゼンテーション マネージャーを通じてプレゼンテーションを発行します。 その存在がシステムによって処理されると、すべての更新がアトミックに適用されます。 さらに、アプリケーションでは、present の他のプロパティ (理想的な時間 ( present ターゲット時間) など) や、その他のまれなプロパティ (目的のコンテンツ レートなど) を指定することもできます。これは、システムでカスタム更新モードを有効にするために使用できます。 プレゼンテーションは特定の時刻にスケジュールできるため、アプリケーションは事前に複数のプレゼンテーションを発行できます。 これらのプレゼントは、スケジュールされた時間に達すると 1 つずつ処理されます。

プレゼンテーションの同期

アプリケーションは、バッファーにレンダリングされ、問題が発生するときに、レンダリング先のバッファーを選択する必要があります。これにより、他の未処理の以前のpresent の存在によって参照されていないバッファーが選択されます。これにより、意図したバッファー コンテンツが上書きされる可能性があります。 さらに、スキャンアウト ハードウェアでプレゼンテーション サーフェイスによって現在表示されているバッファーへのレンダリングをアプリケーションで問題が発生した場合、Direct3D では フロント バッファーレンダリング が禁止されているため、レンダリングが無期限にストールする可能性があります。

コンポジション スワップチェーン API には、アプリケーションが提示したバッファーの適切な同期を実行するためのいくつかの異なるメカニズムが用意されています。

バッファーを参照する 未処理のプレゼンテーションがなく、現在、システムによって表示されていない場合、バッファーは 使用可能 であると言われます。 それ以外の場合は使用できません。 API は、バッファーが使用可能かどうかを示す各プレゼンテーション バッファーのイベントを提供します。 これは、アプリケーションで使用する最も簡単な同期方法です。 バッファーに描画して表示する前に、アプリケーションで 使用可能な イベントが通知されることを確認できます。 特定のバッファーに対して 使用可能な イベントは、API のプレゼンテーション サーフェイスにバインドされた時点で符号なしになり、present が廃止されるまでずっと符号なしのままです。

第 2 に、プレゼンテーション マネージャーは、プレゼンテーションが完了したアプリケーションと通信するために、1 つの present 廃止フェンス を追跡します。 フェンスの値は、次のライフサイクル セクションで説明するように、 ライフサイクル廃止 フェーズを開始した最後の present 識別子に対応します。 プレゼンテーションがこのフェーズに入ると、後続のプレゼンテーションに置き換えられたバッファーを再利用できることを想定しても安全です。

この同期方法はより高度ですが、ワークフローの調整をより詳細に制御でき、現在の present キューの深さに関するシステムの状態に関してより有益です。 present のライフサイクルの概要については、以下のセクションを参照してください。

present のライフサイクル

プレゼンテーション マネージャーの present は、 present キュー の一部としてシステムにキューに入れられます。 システム プロセスはキューに登録された順序で表示されます。 さらに、各プレゼンテーションには、一意の (プレゼンテーション マネージャーに対して) present 識別子が関連付けられています。これは、present に割り当てられた増分値であり、最初のプレゼンテーションの場合は 1 から始まり、後続の存在ごとに 1 ずつインクリメントされます。 この present 識別子は、同期プリミティブやプレゼンテーション統計など、API のさまざまな部分で、その特定の存在を参照するために使用されます。

ここで説明するように、アプリケーションの問題が特定のライフサイクルに従っていることを示します。

アプリケーションは、present の一部として行われる変更を設定すると、プレゼンテーション マネージャーを使用して実際に現在を発行します。 この時点で、プレゼントは 保留中 と言われます。

保留中になると、プレゼンテーション マネージャーの present キューにプレゼンテーションが配置され、2 つのいずれかが発生するまでそのキューが維持されます。

  • presentは、 取り消されます。 プレゼンテーション マネージャーを使用すると、以前に発行された present をアプリケーションで取り消すことができます。 この場合、present は 取り消される と言われ、すぐに 廃止されます。 この遷移では、キャンセルされた present に関連するバッファー使用可能なイベントが更新されますが、以前に表示された present (キャンセルされたプレゼントの前) は表示されたままであるため、present 廃止フェンスは信号を送信されません。 このため、アプリケーションで preesnt 廃止フェンスを使用して、キャンセルされた present を特定することはできません。 代わりに、キャンセルされた各 present に対して返される present の状態統計からこれを学習する必要があります。 アプリケーションでは、バッファーの 使用可能な イベントを使用して、キャンセル後に存在する使用可能なバッファーを見つけることをお勧めします。 その present が表示されると、前の present が廃止プロセスを開始し、present 廃止フェンスを更新します。
  • 取り消されない場合、present は 最終的に処理の 準備 が整います。 準備を整えるためには、2 つの主要な条件を満たす必要があります。
    • present が呼び出される前に Direct3D コンテキストに発行されたすべての描画作業を完了する必要があります。 これにより、アプリケーションの描画が完了する前にバッファーが表示されないようにします。
    • present ターゲット時間が指定されている場合、present を表示できると予想される現在のシステム相対時間は、アプリケーションが present に適用した要求されたターゲット時間を満たします。

システムは、画面上に表示する present を見つけると、表示の 準備完了 した最後の present を選択します。。 複数の 準備が完了 した present がある場合、最新のもの(つまり、最大の present 識別子を持つ present)以外はすべて スキップされ、すぐに 廃止 に入ります。 この時点でバッファの 使用可能 イベントが通知されますが、スキップされた present が 表示 状態から移行しないため、present 廃止フェンスには通知されません。

表示 準備が完了 したプレゼンテーションを選択すると、システムはそれを画面上に表示するための作業を開始します。 これは、DWM フレームの一部としてバッファーをレンダリングし、そのフレームが画面上に表示されるようにハードウェアに要求することを意味する場合や、iflip の場合にハードウェアをスキャンアウトするためにバッファーを直接送信することを意味する場合があります。 この処理が行われると、present は キューに入れられます。 大まかに言えば、これは表示される途中であることを意味します。

ハードウェアが present の表示に近付くと、その present は 表示されている と言われます。 その後の present が入って置き換えられるまで、画面に表示され続けます。

後続の present がキューに入ると、ハードウェアが最終的に現在の present の表示を停止することがわかります。 この時点で、その preesnt は 廃止中 と言われます。

その後の present が表示されると、現在のpresent は 廃止されていると言われます。

プレゼンテーション マネージャーは、 present 廃止フェンス を公開します。これは、present が 廃止 状態になると、各 present の present 識別子にシグナリングされます。 このシグナルは、以前の存在を破損することなく、その存在に関連付けられているバッファーにレンダリング作業を発行することが安全になったことをアプリケーションに示します。 アプリケーションがpresent 廃止 状態でレンダリング作業を発行した場合、レンダリング処理は、present が 廃止 状態に入るまでキューに入れられ、その時点で実行されます。 present が 廃止 された後にレンダリング作業が発行された場合は、すぐに実行されます。

この状態変化の図を次に示します。

present のライフサイクル

バッファー、サーフェス、および present の図

プレゼンテーション マネージャー、プレゼンテーション バッファー、プレゼンテーション サーフェイス、プレゼンテーション、および更新に関連する図を次に示します。

バッファー、サーフェス、および present の図

この図は、2 つのプレゼンテーション サーフェスと 3 つのプレゼンテーション バッファーを持つプレゼンテーション マネージャーを示しています。このバッファーには、これまでに発行されたプレゼンテーションが 2 つあり、サーフェス 1 に最初に表示されたバッファー 1、サーフェス 2 にバッファー 2 が表示されています。 第2の present 更新サーフェス 2 は、プレゼンテーションバッファ 3 を示し、サーフェス 1 の結合を変更していません。 Present 2 が表示されると、サーフェス 1 にバッファー 1 が表示され、サーフェス 2 にバッファー 3 が表示されます。これは、プレゼンテーション マネージャーのオブジェクトの現在の状態で確認できます。 キューに存在する各キューは、システムで処理されるときに有効になります。

Note

Present 2 はサーフェス 1 のバッファーを変更しなかったため、サーフェス 1 は前の present のバッファー 1 に結合したままでした。 この意味で、present 2 のバッファ 1 には「暗黙の」参照が存在します。これは、present 2 が表示された後もサーフェス 1 がバッファ 1 にバインドされたままになるためです。

ビジュアル ツリーへのプレゼンテーション サーフェイスの追加

プレゼンテーション サーフェスは、コンポジション ビジュアル ツリーの一部として存在するコンテンツです。 各プレゼンテーション サーフェスは、 コンポジション サーフェス ハンドル にバインドされます。 Windows.UI.Composition では、既存のコンポジション サーフェス ハンドル用にサーフェス ブラシを作成し、スプライト ビジュアルにバインドできます。 DirectComposition では、コンポジション サーフェスを既存のコンポジション サーフェス ハンドルから作成し、コンテンツとしてビジュアルにバインドできます。 詳細については、各 API のそれぞれのドキュメントを参照してください。

この API を使用するように構築された Windows Media Foundation などの API は、プレゼンテーション サーフェスに事前にバインドされるコンポジション サーフェス ハンドルを公開します。 アプリケーションでは、独自のコンポジション サーフェス ハンドルを作成して、その後プレゼンテーション サーフェスにバインドし、 DCompositionCreateSurfaceHandle を呼び出してビジュアル ツリーに追加することもできます。

プレゼンテーションの統計情報の読み取り

コンポジション スワップチェーン API は、特定の 存在がどのように処理されたかに関するさまざまな情報を記述するプレゼンテーション統計を公開します。 一般に、この情報では、DWM フレームでプレゼンテーション サーフェスがどのように使用されたか、表示された時点、表示されたかどうかなどが記述される場合があります。

さまざまな種類のプレゼンテーション統計情報があり、将来のバージョンの API で拡張できるように設計されています。 アプリケーションでは、プレゼンテーション マネージャーを使用して登録し、関心のある種類の統計情報を受け取ります。 その後、これらの統計がプレゼンテーション・マネージャーの 統計キュー に プッシュされます。 プレゼンテーション マネージャーは、 統計情報の使用可能なイベント をアプリケーションに公開します。これは、統計キューに読み取り可能な統計項目がある場合を示すイベント ハンドルです。 その場合、アプリケーションはキューから最初の統計項目をデキューし、読み取って処理することができます。 プレゼンテーション マネージャーは、アプリケーションが現在キューにあるすべての統計情報を読み取ったときに、使用可能な統計イベントをリセットします。 通常、アプリケーションは、使用可能な統計イベントがリセットされるまで、ループ内の統計を読み取って処理します。 アプリケーションでは、 present の発行に使用するのと同じ作業ループでこの統計キューを処理するのが一般的です。 推奨される使用パターンは、キューがオーバーフローしないように、新しい present の発行よりも処理統計に優先順位を付けます。

キューには追跡する統計の最大数があり、これは 512 から 1024 の統計の順序になります。 通常の場合、最大キューの深さは約 5 秒分の統計情報を格納するのに十分です。 統計キューがいっぱいになり、さらに多くの統計が報告される場合、ポリシーは、最も古い統計がインベントリから削除され、スペースを作成することです。