2

directx 9 アプリケーションでディファード シェーディングを実装しています。私のディファード シェーディングの方法には、3 つのレンダー ターゲット ( color 、 position 、および normal ) が必要です。それはする必要があります:

  1. 「render」関数の開始時にデバイスにレンダー ターゲットを設定します
  2. 「rtパス」でデータを描画します
  3. デバイスからレンダー ターゲットを削除します (後続のパスでそれらの上に描画されないようにするため)。
  4. レンダー ターゲットを後続のパスのテクスチャとして設定し、エフェクトが「rt パス」で rt に「描画」されたデータを呼び出せるようにします...

この方法は問題なく機能しますが、パフォーマンスの問題が発生しています。それらを 2 つの関数呼び出しに絞り込みました。

IDirect3DTexture9::GetSurfaceLevel()
IDirect3DDevice9::SetRenderTarget()

レンダー ターゲットを設定するコードは次のとおりです。

IDirect3DDevice9 *pd3dDevice = CEffectManager::GetDevice();
IDirect3DTexture9 *pRT = CEffectManager::GetColorRT();
IDirect3DSurface9 *pSrf = NULL;

pRT->GetSurfaceLevel( 0, &pSrf );

pd3dDevice->SetRenderTarget( 0, pSrf );

PIX は、GetSurfaceLevel() への呼び出しの期間 (サイクル) が非常に高いことを示しています (期間 / 合計期間 * 1 / フレームレート)。合わせて 3 つの面を取得する必要があるため、持続時間が長すぎます。組み合わせたドローコールの 4 倍以上です...

レンダー ターゲットの作成中にサーフェスへのポインターを格納することにより、GetSurfaceLevel() の呼び出しをなくそうとしました...奇妙なことに、SetRenderTarget() 関数は同じ期間を想定していました (その期間がごくわずかである前に)。変更されたコードは次のとおりです。

IDirect3DDevice9 *pd3dDevice = CEffectManager::GetDevice();
IDirect3DSurface9 *pSrf = CEffectManager::GetColorSurface();

pd3dDevice->SetRenderTarget( 0, pSrf );

このパフォーマンスの問題を回避する方法はありますか? 2 番目の方法が最初の方法と同じくらい時間がかかるのはなぜですか? IDirect3DDevice9::SetRenderTarget() 内のプロセスに時間がかかるようです...パフォーマンスを向上させるために設定できるデバイスの状態はありますか?

更新: テストのパフォーマンスを向上させるために、次のコードを実装しました。

IDirect3DDevice9 *pd3dDevice = CEffectManager::GetDevice();
IDirect3DTexture9 *pRT = CEffectManager::GetColorRT();
IDirect3DSurface9 *pSRF = NULL;
IDirect3DQuery9 *pEvent = NULL;
LARG_INTEGER lnStart, lnStop, lnFrequency;

// create query
pd3dDevice->CreateQuery( D3DQUERYTYPE_EVENT, &pEvent );

// insert 'end' marker
pEvent->Issue( D3DISSUE_END );

// flush command buffer
while( S_FALSE == pEvent->GetData( NULL, 0, D3DGETDATA_FLUSH ) );

// get start time
QueryPerformanceCounter( &lnStart );

// api call
pRT->GetSurfaceLevel();

// insert 'end' marker
pEvent->Issue( D3DISSUE_END )

// flush the command buffer
while( S_FALSE == pEvent->GetData( NULL, 0, D3DGETDATA_FLUSH ) );

QueryPerformanceCounter( &lnStop );
QueryPerformanceFrequency( &lnFreq );

lnStop.QuadPart -= lnStart.QuadPart;
float fElapsedTime = ( float )lnStop.QuadPart / ( float )lnFreq.QuadPart;

fElapsedTime の平均測定値は 10 ~ 50 マイクロ秒 IDirect3DDevice9::SetRenderTarget() で同じテストを実行したところ、平均測定結果は 5 ~ 30 マイクロ秒でした...

このデータは、私が PIX から取得したものよりもはるかに優れています...思ったほどの遅延はないことを示唆していますが、遅延シェーディングを使用するとフレームレートが大幅に低下します...これが最も可能性の高いソースのようですパフォーマンスの低下について...デバイスに効果的にクエリを実行しましたか?

4

0 に答える 0