ページ 1 / 1
処理落ちについて
Posted: 2012年4月03日(火) 09:26
by コレジャナイ
おはようございます。
今まで処理落ちした事が無かったため、何ら対策を練る事なく過ごしてきたのですが、この度初めて処理落ちが起こってしまい困っております。
通常時ですとFPSは60を維持しているのですが、メニュー画面を開いた時のみFPSが40前後となってしまいます。
メニューを開いている状態での1フレーム当たりのループしている箇所を調べた所7か所ありました。
しかしたかが7か所のループ(しかも0~50までくらいのもの)で処理落ちが発生しているとは考えにくいため、メニュー画面を開いた状態も含めて描画が原因かなと考えておりました。(絵自体は26kbあります。
そして絵の描画を止めては見たのですが、FPSに改善は見られず(ループ処理もいくつか止めてみましたが効果はありませんでした)何が原因か皆目見当がつきませんorz
その処理ではポインタを多用し、合計15個ほど(それぞれ別々の関数にですが)関数の引数に用いてますが、これが原因なのでしょうか?
動作自体は全く問題ないためデバッグ作業の仕様がなく・・・こうした問題を解決するにはどのようにすれば宜しいのでしょうか?
Re: 処理落ちについて
Posted: 2012年4月03日(火) 09:36
by beatle
まず、メインループ内の各部の処理時間を計測してください。
- whileループの内側全体の時間を計測してみる。(ScreenFlipは除外する)
- もし、whileループの内側全体の時間が1/60秒より十分小さいなら、原因はコレジャナイさんのプログラム以外かも。
- whileループの内側全体の時間が確かに処理落ちするレベルの時間なら、今度はwhileループの前半と後半の時間を計測する。
- 前半と後半のどちらに主な原因があるかを調べ、その主原因の方を更に半分に分けて計測する。
- 原因を絞り込めるまで分割&計測を繰り返す。
こんな感じだと思います。
時間計測はGetNowCount()で処理の前後をはさみ、その差を処理時間とすればいいでしょう。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:24
by softya(ソフト屋)
描画自体が1/60秒を超えている可能性もあります。
その場合は処理時間を計測して合計しても1/60秒を超えていないはずでScreenFlipで遅延します。
【補足】
解説しておくとプログラムで書かれている処理はCPUの処理ですが、描画自体はGPUで行われます。
DrawGrpah()を呼び出しても、その時点で描画されるわけではなく描画が予約されるだけで実際にはScreenFlipを起点に裏画面への描画がスタートします。
この描画処理はGPUで独立して並行処理で行われるのでCPUの処理とは干渉しません。
なので、CPUの処理だけで遅延することもありますし、GPUの処理だけで遅延することもありえます。
処理遅延を調べるときは両方を考慮する必要が出てきます。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:44
by コレジャナイ
通常時が16~17
メニュー表示時が24
でした。
printf("%d\n",GetNowCount());
と表記して出力された数値の差を取ったのですが、この方法で間違っていませんよね?
値にあまり変化が出なかったので・・・。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:45
by コレジャナイ
失礼
上記の値はScreenFlip();表示中です(そうしないとメニュー画面が開けないので・・・
ScreenFlip();をコメントアウトしても値は16と変化はありませんでした
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:47
by softya(ソフト屋)
それは何処から何処の範囲の時間の計測結果でしょうか?
計測するならScreenFlip()直後からScreenFlip()直前までの時間を計測して下さい。
あと多数の場所にScreenFlip()があると言う悪い組み方はしていませんか?
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:51
by コレジャナイ
ループ内の計測でした
今ScreenFlip()の直前と直後で試したところ
差分は 約4、14
を交互に繰り返してました。
ScreenFlip()はメインループに一つしかありません。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:54
by softya(ソフト屋)
直前と直後ではなく、逆の直後から直前までの時間を教えて下さい。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 11:56
by コレジャナイ
通常時だと3もしくは4
メニュー表示中だと23前後
でした
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:03
by softya(ソフト屋)
コレジャナイ さんが書きました:通常時だと3もしくは4
メニュー表示中だと23前後
でした
うまく通じてない気がしてきたので、プログラムで例を書きます。
こんな感じで計測をおこなって下さい。
コード:
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
ChangeWindowMode( TRUE ), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
int x = 0;
int Handle; // 画像格納用ハンドル
Handle = LoadGraph( "画像/キャラクタ01.png" ); // 画像のロード
// while( 裏画面を表画面に反映, メッセージ処理, 画面クリア )
while( ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 ) {
int start = GetNowCount(); //開始時間
// いろんな処理
int end = = GetNowCount(); //終了時間
printfDx( "処理時間=%dms\n", end-start); //欲しいのはこの時間です。
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:11
by コレジャナイ
通常時が1か2
メニュー表示中だと28前後でした。
やり方は合ってた・・・はず・・・。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:15
by softya(ソフト屋)
コレジャナイ さんが書きました:通常時が1か2
メニュー表示中だと28前後でした。
やり方は合ってた・・・はず・・・。
メニュー表示中が重すぎます。
1/60秒は16.666・・・msですので確実にメニュー処理で1/60秒を超えています。
メニュー表示の中で何が悪さをしているのかbeatleさんの書きこみに従って調査してみて下さい。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:15
by コレジャナイ
コード:
//メインループ
while(ProcessLoop()==0){
int start = GetNowCount();
switch(game_state){
case INIT:
Draw_init();
Cell_data_init();
master_character_data_init();
game_state = GAME_MAIN;
break;
case GAME_MAIN:
Game_play();
Draw_regarding();
break;
}
fps_wait();//フレームの待機を計算
if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break; //エスケープが入力されたらブレイク
int end = GetNowCount(); //終了時間
printfDx( "処理時間=%dms\n", end-start);
ScreenFlip();//裏画面反映
}
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:17
by コレジャナイ
あ、了解です。
一つの関数で3,4ms越えてるものがあったのですが、これもやはりおかしいですよね?
メニュー表示してない時の処理合計が1か2msな訳ですし・・・・。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:48
by コレジャナイ
解決しました!
どうやらフォントや書体、文字のサイズを設定させていた関数の呼び出しが原因だったようです。
しかしこれほど重くなるとは・・・。
ノーベルゲーなど書体がころころ変わるゲームだと大変そうですね。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 12:51
by softya(ソフト屋)
コレジャナイ さんが書きました:解決しました!
どうやらフォントや書体、文字のサイズを設定させていた関数の呼び出しが原因だったようです。
しかしこれほど重くなるとは・・・。
ノーベルゲーなど書体がころころ変わるゲームだと大変そうですね。
最初にハンドルを全部用意しておいて切り替えるだけならさほど重くないです。
DrawStringToHandle()などと言った関数を使います。
Re: 処理落ちについて
Posted: 2012年4月03日(火) 13:09
by コレジャナイ
有難う御座います
自分の場合 値がよく変動するものを描画していたので、DeleteFontToHandleだと描画するものを自由に変えれない(先に書いておく必要がある?)ため使ってませんでした。
しかし便利ですね。
感謝ですm(_ _)m