7

パン可能なタイル グラフィックを表示する WPF コントロール (FrameworkElement から継承) を作成しました。各タイルは 24bpp で 256x256 ピクセルです。OnRender をオーバーライドしました。そこで、新しいタイルを (BitmapFrame として) ロードし、drawingContext.DrawImage を使用してすべての可視タイルを描画します。

これで、レンダリング サイクルごとに数個以上の新しいタイルがある場合は常に、フレームレートが 60 fps からゼロに約 1 秒間低下します。これは、イメージの読み込み (ミリ秒単位で実行) や DrawImage (中間のレンダリング データ構造を埋めるだけなので、まったく時間がかからない) が原因ではありません。

私の推測では、レンダー スレッド自体が多数 (~20) の新しい BitmapSource インスタンス (つまり、まだキャッシュされていないインスタンス) を取得するたびにチョークします。それらを内部の DirectX 互換フォーマットに変換するのに多くの時間を費やしているか、キャッシュの問題である可能性があります。ビデオ RAM が不足することはありません。Perforator は 60MB 未満でピークを示し、私は 256MB を持っています。また、Perforator によると、すべてのレンダー ターゲットはハードウェア アクセラレーション対応であり、それもあり得ません。

どんな洞察もいただければ幸いです!

前もって感謝します

ダニエル

@RandomEngy:
BitmapScalingMode.LowQuality は問題を少し軽減しましたが、解決しませんでした。意図した解像度で既にタイルを読み込んでいます。また、最新のグラフィックス ドライバー (Nvidia) である必要はありません。
スケーリングにそれほど時間がかかることを知って、少し驚いています。私が理解した方法では、ビットマップ (サイズに関係なく) は Direct3D テクスチャとして読み込まれ、ハードウェア スケーリングされます。実際のところ、ビットマップが初めてレンダリングされると、それ以上フリーズすることなく回転とスケールを変更できます。

4

2 に答える 2

3

大量の画像だけではありません。大きな画像が 1 つあれば、それが読み込まれるまでレンダリングを停止するのに十分です。これは、画像のサイズが数千に達し始めると非常に顕著になる可能性があります。

おそらくレンダリング スレッドであることに同意します。テストを行ったところ、完全に事前にキャッシュされた BitmapImage を表示しようとしてこのレンダリングの遅延が発生している間、UI スレッドは引き続きメッセージを喜んでディスパッチしていました。

あなたが推測していたように、画像に対して何らかの変換または準備を行っているに違いありません。「レンダリング」することでアプリでこれを軽減しようとしましたが、画像を非表示にし、表示する必要があるときに表示します。ただし、とにかくレンダリングのフリーズが発生するため、これは理想的とは言えません。

(編集)

フォローアップ: MS WPF エイリアスについて議論した後、遅延の原因を突き止めました。私の Server 2008 マシンでは、新しい WDDM ドライバー モデルをサポートしない古いビデオ ドライバーと、画像のサイズ変更の遅延が原因でした。

ソース イメージのサイズが表示サイズと異なる場合、イメージが表示される前にレンダリング スレッドが遅延します。デフォルトでは、イメージは最高品質に設定されていますが、 を呼び出してレンダリングのスケーリング オプションを変更できますRenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality);。すると、画像表示前の不思議なフリーズがなくなりました。別の方法として、スケーリングによる品質の低下が気に入らない場合は、表示されるサイズに等しい DecodePixelWidth/Height で BitmapImage をロードすることです。その後、BitmapImage をバックグラウンド スレッドにロードすると、表示に遅延が発生することはありません。

于 2009-04-30T23:23:51.383 に答える
0

これらも試してください。

/* ivis is declared in XAML <Image x:Name="iVis" UseLayoutRounding="True" SnapsToDevicePixels="True" /> */

iVis.Stretch = Stretch.None;
RenderOptions.SetBitmapScalingMode(iVis, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetEdgeMode(iVis, EdgeMode.Aliased);
VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor;
iVis.Source = **** your bitmap source ****

大量の「A」チャネル カラーを使用するとパフォーマンスに問題が発生し、イメージがスケーリングしてレンダリングされるまで待つと、パフォーマンスが大幅に改善されました。

また、あなたが言ったように、タイル張りのグラフィックを使用していますか?

通常はTileBrushを使用して、単純に FrameworkElement の Brush として設定します。それらをアニメートしたり、新しいブラシを動的に追加したりする場合は、ブラシを生成して、手動でオブジェクトに適用することもできます。可能であれば、それらをフリーズしてください。また、VisualBitmapScalingMode はすべての Visual のプロパティです。

于 2010-02-26T14:50:17.450 に答える