2010/1/18 月曜日

【地味な研究シリーズ】SilverlightのWriteableBitmapの高速化。

カテゴリー: 代表飯島エントリ, 地味な研究, 技術情報, 社長コラム — shinji-i @ 18:16:27

皆様こんにちわ。
ふむふむソフト代表取締役の飯島です。

ひさびさに地味な研究結果を発表したいと思います。
今回はSilverlight3から搭載されたWriteableBitmapについてです。

WriteableBitmapとは簡単にいえば「書き換え可能なビットマップ」です。
WPFには以前から搭載されていたようですが、Silverlightにも3から搭載されました。

さて、このクラスを使うメリットは「ピクセルを直に触れる」ことにあります。
本来であれば、XAMLの高度な描画メソッドを使ってバリバリ描画していくのがSilverlightのあるべき姿なんでしょうが、ピクセルが触れるとなれば黙っていられないのがVGA(DOS)時代のPCゲームにヤラレちゃってた人間の性なのです。
私の場合、DirectDrawはもちろん、WinGの時からそうだったのですから仕方がありません。

話を戻しましょう。
このSilverlight3のWriteableBitmapは、ピクセルがint型の配列になっています(pixelsメンバ)。
(この時点でVGAの13hモードのVRAMを思いだして胸が熱くなります)
この配列のintの値は「ARGB(各8bit)」になっており、配列の長さが「ビットマップの幅×高さ」になっています。
ちゃんとαチャンネルの値を保持できる辺りも嬉しい限りです。

この配列に対して、シフト演算子でARGBの値を使ってint型を作って、「幅×y座標 + x座標」みたいな感じでpixels配列にセットすればその部分のピクセルの色が変わる、というある種の方々には大変直観的な設計になっています。

が、タダの配列とはいえ、細々とアクセスをしていると「?」となるくらい遅くなる時がありました。
そこで、モノは試しで「ダブルバッファ」をやってみたのがこのサンプルです。

Silverlight3 + WriteableBitmapのダブルバッファサンプル
(※動作にはSilverlight3が必要です)

ソースコードはコチラ
(要Visual Studio 2008 + Silverlight3 SDK)

やっている事は「600×400ピクセルのWriteableBitmapに同じ色をセットする」という処理なのですが、二通りの方法でテストしています。
まず、通常(赤)と書いてある方が、ループでピクセル(赤)をセットする方法です。
そしてダブルバッファ(緑)という方が
・pixelsと同サイズのint型の配列を作る
・その配列に対して同じくint型のピクセル(緑)をセット
・配列の「CopyTo()」を使って、pixelsに一気にCopy
という手順を行っています。
どちらも画面更新(Invalidate())のタイミングに違いはありません。

見た眼は死ぬほど地味(色は派手)ですので、興味が無い人には全くもってアピールのないサンプルですが、注目して頂きたいのはそれぞれの処理を行っている時のフレームレートです。

私の環境では、
・通常(赤) : 150fps前後
・ダブルバッファ(緑) : 180~190fps前後
となっています。
一見余計な手順を踏んでいる後者の方が、30~40fps(20~25%)ほど速いのです。

一応、弊社内の色々なPCで試してみましたが、大体
・緑の方が速い
・赤と緑で差が無い
というケースに分かれ、(本来そうなりそうなものなのですが)少なくとも緑の方が遅くなる、というケースは見受けられませんでした。
皆様の環境での差も教えて頂きたいところです。

なぜこのような差が発生するのか理由は不明ですが、「pixelsってアクセス時に何がしかのチェックロジックが走る」という事なのでしょうか…?
なんにせよ「やっておくと多少速くなる『かも』」なテクニックとして試して頂ければと思います。

なお、今回のサンプルコードでは、フレームレート処理部分にblog.sph62.net様の「SilverlightでFlash的なパーティクル(サンプル)」という記事からコードを拝借いたしました。

それでは失礼いたします。

コメントはまだありません »

コメントはまだありません。

このコメント欄の RSS フィード トラックバック URL

コメントをどうぞ

HTML convert time: 0.325 sec. Powered by WordPress
Copyright (C) 2007 fmfmsoft corp.