処理落ちについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
コレジャナイ

処理落ちについて

#1

投稿記事 by コレジャナイ » 14年前

おはようございます。

今まで処理落ちした事が無かったため、何ら対策を練る事なく過ごしてきたのですが、この度初めて処理落ちが起こってしまい困っております。
通常時ですとFPSは60を維持しているのですが、メニュー画面を開いた時のみFPSが40前後となってしまいます。

メニューを開いている状態での1フレーム当たりのループしている箇所を調べた所7か所ありました。
しかしたかが7か所のループ(しかも0~50までくらいのもの)で処理落ちが発生しているとは考えにくいため、メニュー画面を開いた状態も含めて描画が原因かなと考えておりました。(絵自体は26kbあります。

そして絵の描画を止めては見たのですが、FPSに改善は見られず(ループ処理もいくつか止めてみましたが効果はありませんでした)何が原因か皆目見当がつきませんorz

その処理ではポインタを多用し、合計15個ほど(それぞれ別々の関数にですが)関数の引数に用いてますが、これが原因なのでしょうか?

動作自体は全く問題ないためデバッグ作業の仕様がなく・・・こうした問題を解決するにはどのようにすれば宜しいのでしょうか?

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 処理落ちについて

#2

投稿記事 by beatle » 14年前

まず、メインループ内の各部の処理時間を計測してください。
  • whileループの内側全体の時間を計測してみる。(ScreenFlipは除外する)
  • もし、whileループの内側全体の時間が1/60秒より十分小さいなら、原因はコレジャナイさんのプログラム以外かも。
  • whileループの内側全体の時間が確かに処理落ちするレベルの時間なら、今度はwhileループの前半と後半の時間を計測する。
  • 前半と後半のどちらに主な原因があるかを調べ、その主原因の方を更に半分に分けて計測する。
  • 原因を絞り込めるまで分割&計測を繰り返す。
こんな感じだと思います。

時間計測はGetNowCount()で処理の前後をはさみ、その差を処理時間とすればいいでしょう。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#3

投稿記事 by softya(ソフト屋) » 14年前

描画自体が1/60秒を超えている可能性もあります。
その場合は処理時間を計測して合計しても1/60秒を超えていないはずでScreenFlipで遅延します。

【補足】
解説しておくとプログラムで書かれている処理はCPUの処理ですが、描画自体はGPUで行われます。
DrawGrpah()を呼び出しても、その時点で描画されるわけではなく描画が予約されるだけで実際にはScreenFlipを起点に裏画面への描画がスタートします。
この描画処理はGPUで独立して並行処理で行われるのでCPUの処理とは干渉しません。
なので、CPUの処理だけで遅延することもありますし、GPUの処理だけで遅延することもありえます。
処理遅延を調べるときは両方を考慮する必要が出てきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#4

投稿記事 by コレジャナイ » 14年前

通常時が16~17
メニュー表示時が24
でした。
printf("%d\n",GetNowCount());
と表記して出力された数値の差を取ったのですが、この方法で間違っていませんよね?

値にあまり変化が出なかったので・・・。

コレジャナイ

Re: 処理落ちについて

#5

投稿記事 by コレジャナイ » 14年前

失礼
上記の値はScreenFlip();表示中です(そうしないとメニュー画面が開けないので・・・

ScreenFlip();をコメントアウトしても値は16と変化はありませんでした

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#6

投稿記事 by softya(ソフト屋) » 14年前

それは何処から何処の範囲の時間の計測結果でしょうか?
計測するならScreenFlip()直後からScreenFlip()直前までの時間を計測して下さい。
あと多数の場所にScreenFlip()があると言う悪い組み方はしていませんか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#7

投稿記事 by コレジャナイ » 14年前

ループ内の計測でした

今ScreenFlip()の直前と直後で試したところ

差分は 約4、14
を交互に繰り返してました。

ScreenFlip()はメインループに一つしかありません。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#8

投稿記事 by softya(ソフト屋) » 14年前

直前と直後ではなく、逆の直後から直前までの時間を教えて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#9

投稿記事 by コレジャナイ » 14年前

通常時だと3もしくは4
メニュー表示中だと23前後

でした

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#10

投稿記事 by softya(ソフト屋) » 14年前

コレジャナイ さんが書きました:通常時だと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;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#11

投稿記事 by コレジャナイ » 14年前

通常時が1か2
メニュー表示中だと28前後でした。
やり方は合ってた・・・はず・・・。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#12

投稿記事 by softya(ソフト屋) » 14年前

コレジャナイ さんが書きました:通常時が1か2
メニュー表示中だと28前後でした。
やり方は合ってた・・・はず・・・。
メニュー表示中が重すぎます。
1/60秒は16.666・・・msですので確実にメニュー処理で1/60秒を超えています。
メニュー表示の中で何が悪さをしているのかbeatleさんの書きこみに従って調査してみて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#13

投稿記事 by コレジャナイ » 14年前

コード:

//メインループ
	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: 処理落ちについて

#14

投稿記事 by コレジャナイ » 14年前

あ、了解です。

一つの関数で3,4ms越えてるものがあったのですが、これもやはりおかしいですよね?

メニュー表示してない時の処理合計が1か2msな訳ですし・・・・。

コレジャナイ

Re: 処理落ちについて

#15

投稿記事 by コレジャナイ » 14年前

解決しました!
どうやらフォントや書体、文字のサイズを設定させていた関数の呼び出しが原因だったようです。

しかしこれほど重くなるとは・・・。
ノーベルゲーなど書体がころころ変わるゲームだと大変そうですね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 処理落ちについて

#16

投稿記事 by softya(ソフト屋) » 14年前

コレジャナイ さんが書きました:解決しました!
どうやらフォントや書体、文字のサイズを設定させていた関数の呼び出しが原因だったようです。

しかしこれほど重くなるとは・・・。
ノーベルゲーなど書体がころころ変わるゲームだと大変そうですね。
最初にハンドルを全部用意しておいて切り替えるだけならさほど重くないです。
DrawStringToHandle()などと言った関数を使います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

コレジャナイ

Re: 処理落ちについて

#17

投稿記事 by コレジャナイ » 14年前

有難う御座います

自分の場合 値がよく変動するものを描画していたので、DeleteFontToHandleだと描画するものを自由に変えれない(先に書いておく必要がある?)ため使ってませんでした。

しかし便利ですね。
感謝ですm(_ _)m

閉鎖

“C言語何でも質問掲示板” へ戻る