2015-01-12 45 views
5

私はSharpDXプロジェクトを完了しています。それは相互作用のためにKinectを使用します。このため、私のプロジェクトでは、KinectリージョンとKinectUserViewerオブジェクトの両方でWPFを使用しています。これまでのところ、SharpDXはすべての面で優れていましたが、direct3Dを頻繁に使用するプログラムの特定の部分に到達すると、ちらつきが始まります。これは、明らかに、D3Dimage(MainWindow.xamlのSharpDXElementによって利用される)が「WPFでの効率的なD3Dレンダリングに根本的に壊れて不適切」であるという事実に関連しています。[1]私のWPF要素を保持し、direct3Dで点滅しない方法はありますか?SharpDXElementの代替が必要です。 sharpDX WPFフリッカーの回避策

+0

あなたには、いくつかの関連するコードを示していただけますか?このような質問に答えるときに、あなたがどこにいるのかを見ることは大いに役立ちます。 – rfornal

+0

これは15000行以上のコードを持っています。関連するコードを見つけるのは難しいです。これは、描画ループと更新ループに対してtoolkit.gameクラスを使用します。私は主にスプライトバッチを使用していますが、その部分は問題の部分を含めてxnaとdirect3Dの両方を使用しています。あなたが助けると思う部分がありますか? – Asor

+0

あなたのリンクを見てみましたが、あなたの見積もりの​​文脈を見ると、Windowsフォームを使った限定的な回避策についても言及しました。回避策を理解していれば、D3DImageの置き換え領域にはWindowsフォームが基本的にホストされます。そのエリアのみがXAML要素を使用できないと考えています。それはあなたのために働くだろうか?または、回避策の性質について何か不足していますか? –

答えて

5

Flickeringは、D3DImageがフレームをフロントバッファにコピーしようとする前にGPUがフレームのレンダリングを完了していないことを示します。これは、WPFではフレームをレンダリングするためにスワップチェーンに提示する標準的なメカニズムを使用しないため、WPFで簡単に発生する可能性があります。 - 私は、そのファイルにDevice.Flush()が表示されていないが、私はそれは、呼び出し元のコードであることを疑う

// rendering code 
Device.Flush(); // or equivalent, depending on Direct3D version used 
D3DImage.Lock(); 
D3DImage.AddDirtyRect(...); 
D3DImage.Unlock(); 

SharpDXElement.InvalidateRender続い少なくともパターンです:その代わり、ほとんどのコードは、次のようなものを使用しています。

問題はDevice.Flush()が同期していないことです。軽いGPUロード(GPUがロック/アンロックコードが終了する前に終了する)ではうまく動作しますが、重いロードの場合、レンダリングが完了していないことが多く、少なくとも一部のフレームでは空白フレームになります。これはちらつきとして表示されます。

オープンソースに関する素晴らしい点は、コードを変更できることです。この問題を検証し、(ハック場合)簡単なソリューションを提供し、GPUにもう少し時間を与えてみてくださいするには:

D3DImage.Lock(); 
Thread.Sleep(2); // 2ms 
D3DImage.AddDirtyRect(...); 
D3DImage.Unlock(); 

それはあなたのちらつきを軽減または排除した場合、これはあなたの問題です。少なくともDirect3D 10または11の場合、より徹底的な解決策はuse query events as described in this questionです。

Windowsフォームを使用する際の問題は、WPFの空白の問題(WPFアイテムが子ウィンドウの上に描画されないこと)で終わることです。 Airspace issues can be fixedですが、SharpDXElementを編集するよりもはるかに複雑です。

1

私は同じ問題を抱えていましたが、DeviceCreationFlags.SingleThreadedが私を助けました。

2

問題はロック機構ではありません。通常、画像を表示するにはPresentを使用します。 Presentは、すべての描画が完了するまで待機します。 D3DImageではPresent()メソッドを使用していません。プレゼンテーションの代わりに、ロックしてDirtyRectを追加し、D3DImageのロックを解除します。

レンダリングはasynchroneで行われるため、ロックを解除するときには描画操作が準備できていない可能性があります。これがフリッカー効果を引き起こしています。場合によっては半分のアイテムが表示されることがあります。貧弱な解決策(私がテストした)はロックを解除する前に小さな遅延を追加しています。それは少し助けましたが、それはすてきな解決策ではありませんでした。それはひどかった!

ソリューション:私は何か他のものを継続し

。私はMSAA (アンチエイリアス)でexpirimentingしていた、私が直面した最初の問題は、 MSAAはdx11/dx9共有テクスチャでは実行できませんので、新しいテクスチャ(dx11)にレンダリングし、dx9共有テクスチャへのコピーを作成することにしました。私はテーブルの上で頭を叩きました。なぜなら、それはアンチエイリアスされ、フリッキングフリーだったからです!

コピーアクションは、すべての図面が準備されるまで待っています(もちろん)ので、これで描画が完了します。だから、

、テクスチャのコピーを作成:(_dx11BackpageTexture共有質感と_dx11RenderTextureは、MSAAのDX11のテクスチャである)は、レンダリングの準備ができるまで待ちますと、コピーが作成されます

DXDevice11.Device.ImmediateContext.ResolveSubresource(
    _dx11RenderTexture, 0, _dx11BackpageTexture, 0, ColorFormat); 

を。

これは、私はちらつきを処分した方法です....

+0

ブリリアント。これを試してみよう。何年もDX11/DX9のちらつきに悩まされてきたので、さまざまなハッキング/回避策を試みました... –

関連する問題