トップページ > 記事閲覧
SetWaitVSyncFlag()とWaitVSync()について+α
名前:そめ 日時: 2021/06/30 03:24

お世話になっております Android版においてのみ、SetWaitVSyncFlag()を使うとメインループの回転速度が上がってしまう現象が発生しています 下記のコードにおいて使い方を間違っていている部分があるか見ていただきたいです 確認はVC++版とAndroid版(Debug x86 emu)で行っております タイトルとは別件になりますが現在高速化と最適化を行っておりVSync周りを触るなど色々やっておりまして とりあえずVC++版で成功し、Android版のみ上手く行かずずっとその検証に難航している状態でして その中でもうひとつ不可解な現象に合っています SetDrawScreen( DX_SCREEN_BACK ) ; を現在すでにDX_SCREEN_BACKが指定されている状態でさらに呼ぶとAndroid版のみ描画が行われなくなる現象が同作業中に発現してしまいました こちらにつきましては最小化したサンプルで再発できずソースを提示できないのですが、 もし何かやりがちなミスまたはバグの可能性が簡単に分かりそうでしたら確認いただけないでしょうか バグが起こるプロジェクトのソースをピンポイントで抜き出すとこうなります SetDrawScreen(DX_SCREEN_BACK);//一回目 SetDrawScreen(DX_SCREEN_BACK);//二回目※これをコメントアウトしないとAndroidのみ不具合を起こす DrawBox(0, 0, 3000, 3000, 0xff000020, true);//適当に塗りつぶし 以上となります よろしくお願いいたします #include "DxLib.h" #if defined(_WINDOWS) int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode(TRUE); SetAlwaysRunFlag(TRUE); int window_w = 1000; int window_h = 600; SetGraphMode( window_w, window_h , 32 ) ; SetWindowSize( window_w, window_h ) ; #else int android_main( void ) { #endif int GrHandle ; bool isManualVSyncWait = true;//VSync待ち マニュアル化 if(isManualVSyncWait){ SetWaitVSyncFlag(FALSE);//VSync待ち マニュアル化 } // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) { // エラーが起きたら直ちに終了 return -1 ; } // BMP画像の読み込み GrHandle = LoadGraph( "test1.bmp" ) ; // 描画先を裏画面に変更 SetDrawScreen( DX_SCREEN_BACK ) ; // 背景色をグレーに変更 SetBackgroundColor( 128, 128, 128 ) ; int mainLoopCount = 0; // メインループ while( ProcessMessage() == 0 ) { mainLoopCount++; // 画面をクリア ClearDrawScreen() ; // BMP画像の描画 DrawGraph( mainLoopCount%300, 0, GrHandle, TRUE ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; if(isManualVSyncWait){ WaitVSync(1);//VSync待ち } } // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
メンテ

Page: 1 |

Re: SetWaitVSyncFlag()とWaitVSync()について+α ( No.1 )
名前:そめ 日時:2021/07/01 12:07

下記のコードで一部現象を再現できました やはりというか描画処理をサブスレッドに移動したのが原因でした VC++版では上手く動き、Android版では描画が崩れます DXライブラリがマルチスレッド動作未定義なのは承知の上で、描画、テクスチャ干渉、モデル干渉する処理を 並列にならないようにしてあるのですがやはり問題ある感じでしょうか? サブスレッドで描画する使い方が根本的に無理であれば ・描画をメインスレッドに ・ゲーム進行をサブスレッドに という具合に逆転させる変更を加えることになるのですが そうした場合でも後者の側で入力を受け取る処理がDXライブラリに依存しており DXライブラリの関数呼び出しが並列に走ることになるのですがそちらは問題ないでしょうか? (例えば具体的にはメインスレッドでMV1DrawModelがサブスレッドでGetTouchInputが同時に走ります) また少し気になったのですが SleepThread関数が Ver 3.22c = 無し Ver 3.22d = 有り となっており最近追加された痕跡があるのですが WaitTimerとなにか違いがありますか? よろしくお願いいたします #include "DxLib.h" #include <thread> int GrHandle ; bool isDrawRequested = false; bool isThreadKill = false; int mainLoopCount = 0; void draw_thread_func() { top: while(!isDrawRequested){//描画リクエストが来るまで待ち続ける if(isThreadKill){ return; } WaitTimer(1); } // 画面をクリア ClearDrawScreen() ; // BMP画像の描画 DrawGraph( mainLoopCount%300, 0, GrHandle, TRUE ) ; isDrawRequested = false;//描画完了 goto top; } #if defined(_WINDOWS) int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode(TRUE); SetAlwaysRunFlag(TRUE); int window_w = 1000; int window_h = 600; SetGraphMode( window_w, window_h , 32 ) ; SetWindowSize( window_w, window_h ) ; #else int android_main( void ) { #endif bool isManualVSyncWait = true;//VSync待ち マニュアル化 if(isManualVSyncWait){ SetWaitVSyncFlag(FALSE);//VSync待ち マニュアル化 } // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) { // エラーが起きたら直ちに終了 return -1 ; } // BMP画像の読み込み GrHandle = LoadGraph( "test1.bmp" ) ; // 描画先を裏画面に変更 SetDrawScreen( DX_SCREEN_BACK ) ; // 背景色をグレーに変更 SetBackgroundColor( 128, 128, 128 ) ; std::thread std_thread(draw_thread_func);//描画スレッド // メインループ while( ProcessMessage() == 0 ) { mainLoopCount++; isDrawRequested = true;//描画スレッド起動リクエスト while(isDrawRequested){//描画スレッドの仕事が終わるまで待つ WaitTimer(1); } // 裏画面の内容を表画面に反映 ScreenFlip() ; if(isManualVSyncWait){ WaitVSync(1);//VSync待ち } } //スレッド終了処理 isThreadKill = true; std_thread.join(); // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
メンテ
Re: SetWaitVSyncFlag()とWaitVSync()について+α ( No.2 )
名前:管理人 日時:2021/07/02 01:04

> DXライブラリがマルチスレッド動作未定義なのは承知の上で、描画、テクスチャ干渉、モデル干渉する処理を > 並列にならないようにしてあるのですがやはり問題ある感じでしょうか? マルチスレッドでの動作は保証していませんので、問題が発生したとのことでしたら、問題があるということなのだと思います > そうした場合でも後者の側で入力を受け取る処理がDXライブラリに依存しており > DXライブラリの関数呼び出しが並列に走ることになるのですがそちらは問題ないでしょうか? すみません、入力と描画であれば大丈夫なような気がしますが、私にも問題があるかは分かりません > SleepThread関数が > Ver 3.22c = 無し > Ver 3.22d = 有り > となっており最近追加された痕跡があるのですが > WaitTimerとなにか違いがありますか? WaitTimer は『指定の時間、待つ』で SleepThread は『指定の時間スレッドを止める』の違いがあります WaitTimer は指定された時間を正確に待つ処理を行うので、 スレッドを休ませる( スレッドを休ませて他のスレッドにCPUリソースを渡す )効果の保証はありません なので、スレッドを止めて他のスレッドにCPUリソースを渡したい場合は WaitTimer ではなく SleepThread を 使用する必要があります( 最近 WaitTimer が他スレッドにCPUリソースを渡すことに使えないことにが分かり、 SleepThread を追加しました )
メンテ
Re: SetWaitVSyncFlag()とWaitVSync()について+α ( No.3 )
名前:そめ 日時:2021/07/02 04:17

解説ありがとうございます もろもろ了解いたしました 念の為描画も入力もメインスレッドに持っていき本当にプライベートな処理だけサブスレッドへ移すように手術していきたいと思います 一件目のサンプルコードの 『Android版においてのみ、SetWaitVSyncFlag()を使うとメインループの回転速度が上がってしまう現象』 こちらについても回答をお待ちしております こちらはマルチスレッドとは無関係の問題となっております よろしくお願いいたします
メンテ
Re: SetWaitVSyncFlag()とWaitVSync()について+α ( No.4 )
名前:管理人 日時:2021/07/06 01:42

> 一件目のサンプルコードの > 『Android版においてのみ、SetWaitVSyncFlag()を使うとメインループの回転速度が上がってしまう現象』 > こちらについても回答をお待ちしております すみません、スレッドの方の話に気を取られて失念していました Android版、iOS版は WaitVSync は非対応となっていますので、 例えば WaitVSync( 100 ); を実行しても、関数から一瞬で処理が戻ってきてしまいます なので、Windows環境以外では WaitVSync は使用しないようにしてください m(_ _)m
メンテ
Re: SetWaitVSyncFlag()とWaitVSync()について+α ( No.5 )
名前:そめ(解決済) 日時:2021/07/06 02:14

回答ありがとうございます リファレンスに非対応の旨記載があるのを見落としていました 大変申し訳有りません ありがとうございました
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存