#経緯
DXライブラーの方々から、複数の画像を1つのファイルにまとめると描画高速化処理が働いて早くなると聞いて、どのくらい早くなるのか気になったので検証しました
詳しくは下記の記事参照、DirectXの仕様が絡むみたい
画像前処理で描画速度とメンテナンス性を両立する
#検証方法
- 画像を1ループで4回描画(画像3と比較するための4回)
- それを10万回を1セット
- 計10セット行った平均を処理時間とする
画像は適当に作ったこの3つを使います。
・画像1
・画像2
・画像3
画像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;