LoginSignup
12
8

More than 3 years have passed since last update.

DXライブラリの描画高速化が意外と無視できないレベルで早かった件

Last updated at Posted at 2019-07-26

経緯

DXライブラーの方々から、複数の画像を1つのファイルにまとめると描画高速化処理が働いて早くなると聞いて、どのくらい早くなるのか気になったので検証しました

詳しくは下記の記事参照、DirectXの仕様が絡むみたい
画像前処理で描画速度とメンテナンス性を両立する

検証方法

  1. 画像を1ループで4回描画(画像3と比較するための4回)
  2. それを10万回を1セット
  3. 計10セット行った平均を処理時間とする

画像は適当に作ったこの3つを使います。

・画像1
TestImg1.png
・画像2
TestImg2.png
・画像3
TestImg4.png
画像1と2はLoadGraphで読みこむ。
画像3はLoadGraphからのDerivationGraphとか、LoadDivGraphで読み込む。

検証結果

先に結果

内容 環境1[ms] 環境2[ms]
画像1を4回 372.8 126.0
画像1と2を交互に2回 692.0 736.6
画像1を毎回ALPHA指定で4回 309.7 25.3
画像1をALPHAとADDを交互に4回 656.0 480.5
画像1をADD指定で4回描画 263.5 25.1
DerivationGraph画像を交互に2回 377.4 95.6
LoadDivGraph画像を4回 345.5 118.6

下記の環境で確認しました。

  • 環境1

    • Windows 10 Pro 64-bit
    • Intel(R) Core(TM) i7-6500
    • 16GB RAM
    • Intel(R) HD Graphics 520
  • 環境2

    • Windows 10 Home 64-bit
    • Intel(R) Core(TM) i7-2700K
    • 16GB RAM
    • Nvidia Geforce GTX 560

感想

意外と無視できないレベルで早くなる。
特に弾幕ゲーとか作るときには弾の画像を大量に描画するからより恩地を得られると思う。

画像前処理で描画速度とメンテナンス性を両立する
でも書かれてましたが、画像のメンテナンス性が絶望的に悪いのでうまくフォローしないと危ない。

各検証の詳細

測定はstd::chronoを使用しました。

画像1を4回 : 372.8ms

一番高速かと思いきやLoadDivGraphの画像の方が早かった。

    img1    = LoadGraph( "data\\TestImg1.png" );
    const bool trans = false; 
    SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        DrawGraph( 100, 100, img1, trans );
        DrawGraph( 100, 200, img1, trans );
        DrawGraph( 100, 300, img1, trans );
        DrawGraph( 100, 400, img1, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

画像1と2を交互に2回 : 692.0ms

描画する画像が変わると高速化が切れる途端に遅くなる。わかりやすい

    img1    = LoadGraph( "data\\TestImg1.png" );
    img2    = LoadGraph( "data\\TestImg2.png" );
    const bool trans = false; 
    SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        DrawGraph( 100, 100, img1, trans );
        DrawGraph( 100, 200, img2, trans );
        DrawGraph( 100, 300, img1, trans );
        DrawGraph( 100, 400, img2, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

画像1を毎回ALPHA指定で4回 : 309.7ms

毎回ALPHA指定して上げたほうが何故か早い・・・謎

    img1    = LoadGraph( "data\\TestImg1.png" );
    const bool trans = false; 
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
        DrawGraph( 100, 100, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
        DrawGraph( 100, 200, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
        DrawGraph( 100, 300, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
        DrawGraph( 100, 400, img1, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

画像1をALPHAとADDを交互に4回 : 656.0ms

BlendModeを切り替えても高速化が切れるという分かりやすい例

    img1    = LoadGraph( "data\\TestImg1.png" );
    const bool trans = false; 
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
        DrawGraph( 100, 100, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ADD, 200 );
        DrawGraph( 100, 200, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA, 150 );
        DrawGraph( 100, 300, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ADD, 100 );
        DrawGraph( 100, 400, img1, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

画像1をADD指定で4回描画 : 263.5ms

単純にALPHAよりADDの方が早い

    img1    = LoadGraph( "data\\TestImg1.png" );
    const bool trans = false; 
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        SetDrawBlendMode( DX_BLENDMODE_ADD, 255 );
        DrawGraph( 100, 100, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ADD, 255 );
        DrawGraph( 100, 200, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ADD, 255 );
        DrawGraph( 100, 300, img1, trans );
        SetDrawBlendMode( DX_BLENDMODE_ADD, 255 );
        DrawGraph( 100, 400, img1, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

DerivationGraph画像を交互に2回 : 377.4ms

同じ画像ファイルなので画像を変えても高速化が切れない

    img3    = LoadGraph( "data\\TestImg4.png" );
    img3_1  = DerivationGraph( 0, 0, 64, 64, img3 );
    img3_2  = DerivationGraph( 64, 0, 64, 64, img3 );
    const bool trans = false; 
    SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        DrawGraph( 100, 100, img3_1, trans );
        DrawGraph( 100, 200, img3_2, trans );
        DrawGraph( 100, 300, img3_1, trans );
        DrawGraph( 100, 400, img3_2, trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;

LoadDivGraph画像を4回 : 345.5ms

同じ画像ファイルなので画像を変えても高速化が切れない
DerivationGraphより早い

    LoadDivGraph( "data\\TestImg4.png", 4, 4, 1, 64, 64, imgs );
    const bool trans = false; 
    SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255 );
    //ここから測定開始
    auto st = std::chrono::system_clock::now();
    for( int i=0 ; i<Loops ; i++ )
    {
        DrawGraph( 100, 100, imgs[0], trans );
        DrawGraph( 100, 200, imgs[1], trans );
        DrawGraph( 100, 300, imgs[2], trans );
        DrawGraph( 100, 400, imgs[3], trans );
    }
    //測定完了
    auto now = std::chrono::system_clock::now() - st;
12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8