エクスポート (0) 印刷
すべて展開
情報
要求されたトピックは次のとおりです。しかし、このトピックはこのライブラリには含まれていません。

Windows Phone 8 のタイル ベースのレンダリングの最適化

2014/06/18

対象: Windows Phone 8 および Windows Phone Silverlight 8.1 のみ

Windows Phone 8 デバイスは、タイル ベースのレンダリング アプローチを利用する GPU を使用します。このレンダリング アプローチでは、内部タイル キャッシュを利用することによって、他で必要になる外部メモリ トランザクションの多くを回避して、GPU のパフォーマンスを向上させ、消費電力を削減することを目指しています。概念としては、タイル ベースのレンダリングではレンダリング ターゲットをタイル キャッシュ サイズのピース、つまりタイルに分割し、レンダリング ターゲットに対するレンダリング コマンドを、各ファイルに 1 回ずつ、複数回実行する必要があります。タイル ベース GPU のドライバーは高性能で、特定のタイルでレンダリングする必要がある頂点を特定し、必要に応じて三角形や線分をクリッピングし、"ビニング" プロセスを使用します。ただし、レンダリング ターゲットが複数または複雑であるアプリケーションのシナリオで、タイル ベースのレンダリングを最適化することはドライバーにとってより難しくなります。これは主に、アプリケーションが現在のレンダリング ターゲットからのタイルの処理をいつ終了したかが、ドライバーには必ずしも明確ではないからです。既定では、新しいレンダリング ターゲットのタイルに移動すると、ドライバーはタイルの内容を保持します。つまり、新しいタイルを読み込む前に、タイルをメモリに保存するので、潜在的に不必要なメモリのオーバーヘッドが発生します。

タイル ベースの GPU のタイル キャッシュ アーキテクチャは、キャッシュ内のグラフィック メモリのトランザクションを非常に効率的に処理するように最適化されています。たとえば、タイル ベースの GPU ではアルファ ブレンドを事実上自由にデザインできます。一方、従来の GPU では、外部グラフィック メモリとの間で必要な読み取り、変更、書き込みトランザクションに関連する追加のオーバーヘッドが発生します。同様に、マルチサンプル アンチエイリアシング (MSAA) のレンダリング ターゲットは、従来の GPU と比べた場合、タイル ベースの GPU では、最適化されたタイル キャッシュ アーキテクチャによってオーバーヘッドが大幅に減少します。

Direct3D11 (D3D 11) には、不必要なタイル関連のメモリ トランザクションを回避するためのヒントを、アプリケーションが GPU ドライバーに提供できるようにする API が含まれています。以下のセクションでは、一般的なアプリケーション シナリオおよびタイル ベースのレンダリングのコンテキストでの、既存および新規の D3D 11.1 GPU ヒンティング API について説明します。

一般的に、複数のレンダリング ターゲットを使用するアプリケーションでは、特定のシーンで 1 つのレンダリング ターゲットの処理を完了してから次のターゲットの処理に移行することによって、不必要なタイルの解決と関連するパフォーマンスのペナルティを回避します。たとえば、現在のフレームのバックバッファーをレンダリングするときにサンプリングされるテクスチャを生成する、1 つまたは複数のオフスクリーン レンダリング ターゲットを使用するアプリケーションでは、各テクスチャのレンダリングを完了してからバックバッファーをレンダリングする必要があります。

複数のテクスチャ レイヤーの合成に関連するアプリケーション シナリオでは、"インクリメンタル レンダリング" を回避するために、インクリメンタル マージを回避する必要があります。インクリメンタル レンダリングによって、大量の外部メモリ トランザクションによってパフォーマンスを不必要に低下させ、不必要な D3D11 呼び出しを発生させます。たとえば、マージを遅延させる代わりに、4 つのテクスチャ レイヤーをインクリメンタルにマージした場合の影響を考えてみます。

望ましい方法

非効率的な方法

  1. レンダー ターゲット A を設定、A をクリア、A に描画

  2. レンダー ターゲット B を設定、B をクリア、B に描画

  3. レンダー ターゲット C を設定、C をクリア、C に描画

  4. レンダリング ターゲット D を設定し、D をクリアし、A、B、および C を使用して D まで描画する

このメソッドは、4 回の呼び出しによってレンダー ターゲットを設定する結果になります。

  1. レンダー ターゲット A を設定、A をクリア、A に描画

  2. レンダリング ターゲット D を設定し、D をクリアし、A から D まで描画する

  3. レンダー ターゲット B を設定、B をクリア、B に描画

  4. レンダリング ターゲット D を設定し、B から D まで描画する

  5. レンダー ターゲット C を設定、C をクリア、C に描画

  6. レンダリング ターゲット D を設定し、C から D まで描画する

このメソッドは、6 回の呼び出しによってレンダー ターゲットを設定する結果になります。

前に示した望ましい方法では、各レンダリング ターゲットに切り替えた直後に Clear が呼び出されています。これによって、特定のレンダリング ターゲットについて "インクリメンタル レンダリング" が不要であること (つまり、レンダリングの前に各レンダリング ターゲットのタイルを読み取る必要がないこと) が GPU ドライバーに通知されます。次のセクションの Clear に代わる方法も参照してください。非効率的な例では、OMSetRenderTarget の呼び出しが増えることに加えて、レンダリング ターゲット D のタイルを複数回メモリに読み込むことも必要です。

既存のレンダリング ターゲット リソースの各ピクセルを置換する必要がない、つまりそれ以降のレンダリング操作が不要であることが、あらかじめアプリケーションでわかっているシナリオに対応するために、GPU ドライバーにこれを通知できる、2 つの新しい "Discard" メソッドが D3D 11.1 に追加されました。以前にこのようなシナリオに対応する場合、アプリケーションには 2 つの方法がありました。

  1. クリアせずにシーンを描画する方法。この方法は、タイル ベースの GPU ではコストが高くなります。GPU は描画の前に各タイルを復元する、つまり各タイルをタイル キャッシュに読み込むひつようがあるからです。アプリケーションが以前の内容を使用しない場合、この復元が不必要で大きなオーバーヘッドになることは明らかです。

  2. 描画の前にクリアする方法。この方法では、ドライバーはタイルの復元を回避できますが、クリア コマンドを実行するには、レンダリング ターゲットの書き込み操作が必要です。以前の内容がアプリケーションによって使用されない場合、この操作も不必要になります。

新しい D3D 11.1 の Discard メソッドは、次の表に示されているように、より効率的な 3 番目のオプションをアプリケーションに提供します。

ID3D11DeviceContext1::DiscardResource

リソースの現在の内容およびすべてのビューが定義されなくなり、以降のレンダリング パスで保持しておく必要がないことを GPU ドライバーに通知します。

ID3D11DeviceContext1::DiscardView

基本的に DiscardResource と同じ操作ですが、スコープが特定のレンダリング ターゲットのビューに限定されます。

アプリケーションがレンダリング ターゲットのリソースまたはビューで Discard を呼び出すと、その後に Draw 呼び出しが続き、各ピクセルが更新されることが想定されています。Discard の後のレンダリング ターゲットの内容は未定義であるため、アプリケーションでその上にアルファ ブレンドを行ったり、部分的に覆われたシェイプだけを描画したりすることはできません。

シーンの途中で ID3D11DeviceContext::Flush を呼び出すと、タイルのリゾルブが途中になり、不必要なタイルの読み込みが行われる可能性があります。詳細については、「ID3D11DeviceContext::Flush」のリファレンス トピックの「解説」を参照してください。

特定のシーンで、レンダリング ターゲットの限られた部分だけが更新されることがアプリでわかっている場合は、ID3D11DeviceContext::RSSetScissorRects メソッドを使用して、どのタイルを処理する必要がないかを GPU ドライバーがあらかじめ判断できるようにしてください。

表示:
© 2015 Microsoft