C#+WPFチューニング戦記

C#とWPFで高速なコードと最適なシステムを書くためにやってきたいろいろな事を書いてみます。.NET Frameworkのソースコードを読み解きましょう。なお、ここに書かれているのは個人の見解であって何らかの団体や企業の見解を代表するものではありません。

透過率の変更コストをご存知ですか?

DrawingContextに対する描画では、いろいろコストを考えなければいけないところがあります。
例えば、下記のコードは同じような描画を期待できそうですが、速いのはどちらでしょうか。

こちらは、同じTransformのものをまとめています。

DrawingContext dc;
for(int idx1=0 ; idx1<100 ; idx1++) {
    dc.PushTransform(transform);
    for(int idx2=0 ; idx2<100 ; idx2++) {
        dc.PushOpacity(alpha);
        // 描画処理
        dc.Pop();
    }
    dc.Pop();
}

こちらは、同じ透過率のものをまとめています。

DrawingContext dc;
for(int idx1=0 ; idx1<100 ; idx1++) {
    dc.PushOpacity(alpha);
    for(int idx2=0 ; idx2<100 ; idx2++) {
        dc.PushTransform(transform);
        // 描画処理
        dc.Pop();
    }
    dc.Pop();
}

大抵の場合、10倍以上の違いで後者が高速です*1
一見計算処理が多そうなPushTransformより、グラフィックアクセラレーターに対するFlush処理を行う可能性が高いPushOpacityの方が、計算量を超えた負荷になるのです。
Direct3DOpenGLに馴染みのある人にはごく普通に理解できることと思いますが。

もちろん描画順序から透過率の変更を避けられない状況はあります。しかし、透過率の変更を減らす方向に処理を整理する方が負荷は低いことが多くなります。

*1:ハードウェアレンダリングの支援が受けられない場合は例外ですが