トップページ > 過去ログ > 記事閲覧
LoadSoftImageについて
名前:だみあん 日時: 2009/02/18 14:39

はじめまして。 DxLibをつかわせていただいております。 LoadSoftImageについてなのですが、 描画専用のクラスを使用して、 staticな変数(描画リスト用の構造体内)にグラフィックハンドルを登録して 一括で表示〜というようなことをやっていまして、 表示の際に行うエフェクト処理の時に モザイクエフェクトなどピクセル単位の処理がいる場合 以前まではGraphLockを使ってロックしてから描画する形でやっていたのですが 速度面でやはりちょっと不満で(画面全体サイズだと30fps近くまで落ちる) 今回、CPU描画がライブラリでサポートされたので 喜んでソースを書き直しまして 動作面では画面全体でも60〜50fpsぐらいとほぼ遅延無しなかんじで 満足な感じにはなったのですが、エフェクトが終了して DeleteSoftImageでメモリを解放処理をしているのですが、 どうも、そのときにメモリの解放に失敗してリークが発生してしまっているようです・・・。 単一のルーチン内 void mozaiku() { int GHandle = LoadSoftImage(・・・); for( int Eff_count = 0; Eff_count < 255; Eff_count++ ){ //モザイク処理とか } DeleteSoftImage(GHandle); } ですと、普通にメモリは解放されているのですが 以下、かなり簡略化してみた概要ソース //一画面描画毎に呼び出される。 int Render::Effect() { //こんなかんじで描画リストから構造体読み込み(プライオリティ順にコールされてくる。リスト内要素はすべてstatic _rend_list = _REND_LIST[_rend_list._Priority]; //最初の一回目 if(_rend_list.effect == 0){ _rend_list._GHandle = LoadSoftImage(・・・); _rend_list.effect_f = 1; } //モザイク処理とか一回分 //エフェクト用パラメータインクリメント _rend_list.effect++; //エフェクト処理が最後までいってたら if(_rend_list.effect > 256){ if(_rend_list.effect_f == 1){ DeleteSoftImage(_rend_list._GHandle); _rend_list.effect_f = 0; } } _REND_LIST[_rend_list._Priority] = _rend_list; } デバッガでみると、 DeleteSoftImageの際のグラフィックハンドルの値(int)は 読み込んだときの数値と一致しているようですし、 ハンドルが存在していない場合は DeleteSoftImageはエラー(メモリエラーとかでデバッガでとまる)上、 ルーチン内でのLoadSoftImageで取得したハンドルでの描画も 出来ていますので、ハンドルは有効な状態で呼び出されているようなのです。 (きちんとDeleteSoftImage自体はコールされている) 毎回、間にLoadSoftImageとDeleteSoftImageを挟むと メモリはきちんと解放されますが、それでは毎回ファイルからの読み込みが発生するので 結局40〜50fpsぐらいとちょっと速度が落ち込んでしまいますし 一画面毎に画像へのファイルアクセスがあるのもちょっと気持ち悪いです。 ちなみに、通常のLoadGraphで呼び出された物については 同じようなルーチン内でもきちんと解放はされているようです。 (GetGraphNumでの数はきちんと減っているようですが、こちらはInitGraph()やDxLib_Endでも(?) 解放できるので、実際には解放出来てるのかわかりませんが タスクマネージャのメモリ使用量で見る限りでは、きちんと解放されて減っているっぽいです) LoadSoftImageのほうは、ハンドル(int)との関連が変になってしまってるのでしょうか?? ハンドルがstaticなのがいけないのか・・・。 解決策がありますでしょうか・・・。 よろしくお願いします。

Page: 1 |

Re: LoadSoftImageについて ( No.1 )
名前: 日時:2009/02/18 17:53

_REND_LISTも同様ですが_rend_listが クラス内変数かグローバルか分かりませんが、 他のところで変更されている可能性は ありませんか?
Re: LoadSoftImageについて ( No.2 )
名前:だみあん 日時:2009/02/19 04:56

すみません、自己解決しました・・・。 DeleteSoftImageの直前に DrawSoftImage(0,0,_rend_list._GHandle); ScreenFlip(); // キー入力待ち WaitKey(); などいれて、チェックしてみたのですが、画像もきちんと表示されるし どういう事だとしばらく悩んでいたのですが・・・ どうにも、きちんとメモリの解放が行われている場合と そうでない場合があるため、どういうときに起こるのか追ってみたところ、 エフェクト中に同一のプライオリティに描画リストが上書きされる場合にのみ 起こっている現象だとわかりました・・・。 スクリプトからは描画リストに登録するだけの丸投げ状態なので、 ぽちぽち高速でスクリプトを進めていったときに エフェクト中の同一プライオリティに・・・という限定した状況でのみ 起こる現象だったので、なかなか問題を見つけ出すのに時間がかかってしまいました。 通常の画像ですと、同一プライオリティへの上書きの際に元にあるグラフィックハンドルは 解放してからリストに登録するのですが、そこで CPU描画を使用している途中を示すフラグをリストに追加することで そこでもDeleteSoftImageをおこなうことで 解決しました・・・。 結局、 >他のところで変更されている可能性は ありませんか? という、凡ミスでした・・・(汗 しかし、現状では、該当エフェクト中にゲームをセーブなどした場合と ゲームをロード後の画像のリロードの際にも起こる状況だったりするので・・・。 CPU描画のメリットと煩雑さを秤にかけてしまいます・・・w CPU描画の際にはスクリプトのほうにに制御を戻さず、メモリ解放までループで回すというのが 一番楽なのでしょうけども、なんか負けた気がして嫌ですし(?) メモリを一時的に動的に確保する性質上 自前できちんと解放まで面倒みるのがスジなのでしかたのないことなのでしょうけども。 あと、ついでになのですが DeleteSoftImage なのですが、ハンドルが無効、もしくはハンドルの指定する先が存在しない(?)場合 −1を返すとなっておりますが、値を返す前にデバッガが停止して メモリのアクセス違反で止まってしまいます。 (vc2008EE使用) 試してみましたが GetPixelSoftImageなどもエラーを返さずに強制終了する模様です。
Re: LoadSoftImageについて ( No.3 )
名前:管理人 日時:2009/02/19 13:19

問題が解決したようで何よりです DeleteSoftImage に無効なハンドル値を渡した場合に停止するのは、仕様です すいません、リファレンスの内容の方が誤りですので、近日中に修正しておきます
Re: LoadSoftImageについて ( No.4 )
名前:だみあん 日時:2009/02/20 07:37

すると、LoadSoftImageToMem等の読み込み系の返値が−1なら 以降の描画系およびDeleteSoftImageを弾くようなのが必須っぽいですね・・・。 それでも、ハンドルの値(int)は残ってて 中身が無い・・・という状況もかんがえるとやはり ハンドルが有効かのチェック出来る関数があるとありがたいのですが。 単一のサブルーチン内で確保とセットで解放を行う完結した感じならともかく マルチタスク風の描画系ですと、その辺でチェック機構がないのは CPU画像使用時のゲームのセーブ&ロードなどをかんがえると、ちょっときついです・・・。 ライブラリレベルで隠蔽して InitGraphでまとめて消せて、描画の際に無効なら無視・・・ というのがベターなのですが・・・。
Re: LoadSoftImageについて ( No.5 )
名前:管理人 日時:2009/02/21 11:00

ハンドルを削除した時点でそのハンドル値を代入していた変数に -1 を代入して、 以後ハンドル値が -1 だったら処理をしない、という風にすることで 解決することはできないでしょうか? という議論はさておき、ソフトイメージハンドルだけ他のハンドルと扱いが違うというのは混乱の元なので、 他のハンドルと同じように無効なハンドルが渡されたら−1を返し、DxLib_End 時に解放されていなかった ソフトイメージハンドルを解放するように仕様を変更したバージョンをアップしました 宜しければお使い下さい m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい) グラフィックハンドルと違い SetGraphMode や ChangeWindowMode 等の関数を使用しても 解放はされないという仕様の違いがあるので、InitGraph ではソフトイメージは解放されません 代わりに int InitSoftImage( void ) ; という関数を追加しましたので、もし InitGraph を 使用しているところでソフトイメージも解放したい、という場合は InitGraph(); InitSoftImage(); というように InitSoftImage(); を書き加えてください
Re: LoadSoftImageについて ( No.6 )
名前:だみあん 日時:2009/02/23 05:52

通常のグラフィック系と同じ感覚で扱えるようになるのは 大変うれしいです。 ありがとうございました。 早速使わせていただきます〜

Page: 1 |