DXライブラリのScreenFlip();の反映タイミングについて

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

DXライブラリのScreenFlip();の反映タイミングについて

#1

投稿記事 by yoshihingis » 13年前

いつもお世話になります。DXライブラリ初心者です。

DXライブラリのScreenFlip();のコマンドが反映されるタイミングについて質問がありますので、ご存知でしたら教えてください。

コード:

//ScreenFilpの垂直同期Wait(on/off)
SetWaitVsyncFlag(1);

// DXライブラリの初期化
if( DxLib_Init() < 0 ) return -1;

//描画処理の繰り返し
For(i = 0;i<10000;i++){

//描画処理
//ここで何かしらの描画データ作成

//描画データ作成終了
//垂直同期信号のWait
WaitVsync(2);

//裏画面を描画画面に反映
ScreenFlip();

//初期化
InitGraph() ;
}//__For


 上記のようなコードを作成したとします。SetWaitVsyncFLAG(1)なので、ScreenFlip();は、垂直同期を待って、裏画面を描画画面に反映されることになります。

 描画データを作成した後、まずWaitVsync(2);があるので、まずは、垂直同期信号を2つ待ってから、ScreenFlip();命令が発せられると事になると思います。
このとき、ScreenFlip();は、垂直同期信号を待つので、描画データ作成後のWaitVsync(2);があるので、タイミングとして描画データ作成後、3つ目の垂直同期信号で裏画面データを描画画面に切り替えることになるのでしょうか?

 WaitVsync(2);で2つの垂直同期信号を待った後、ScreenFlip();がさらに1垂直同期信号を待つとすれば、最初のSetWaitVsyncFlag(1);をSetWaitVsyncFlag(0);とすれば、WaitVsync(2);の後、ただちにScreenFlip();が反映されて、描画作成データ終了後、2垂直同期信号の直後で裏画面が描画画面となるので、SetWaitVsyncFlag(1);と設定した場合と、フレームレートが変わってくると思ったのですが、Frapsというフリーソフトで、フレームレートを測定したところ、SetWaitVsyncFlag()を0,1どちらに設定しても30FPSでした。

 描画処理は、数msec程度のものであり、30FPSのフレームレートに影響を与えないほど短いものです。

 私のScreenFlip();の反映タイミングの考え方に間違いがあれば、ご指摘頂きたく、投稿させて頂きました。
 どなたか、ご存じの方がいましたら、ご教授いただければ幸いです。

初歩的質問で申し訳ありませんが、よろしくお願いいたします。

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

Re: DXライブラリのScreenFlip();の反映タイミングについて

#2

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

とりあえずコードがコンパイル出来て実行できるものを投稿していていただけますでしょうか? こちらでも検証しています。
それとGetNowCount();で時間計測して表示するようにしたほうが良いと思います。

下記コードのを参考にしてSleepをなくせば周期が明確になると思いますので、組み込んでみて下さい。
「3.14章 特定のFPSで動作させる方法」
http://dixq.net/g/03_14.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: DXライブラリのScreenFlip();の反映タイミングについて

#3

投稿記事 by h2so5 » 13年前

そもそもFrapsの測定結果が正確かどうかがよく分かりませんね。
(スクリーンキャプチャの差分でFPSを測定している?)

単体で動くちゃんとした再現コードがほしいです。

yoshihingis

Re: DXライブラリのScreenFlip();の反映タイミングについて

#4

投稿記事 by yoshihingis » 13年前

softya様、h2so5様 >アドバイスありがとうございます。再現性のあるコードを投稿したいと思いますので、しばらくお待ちください。なお、Frapsの測定結果もフリーソフトであるため完全に信じてはおりませんが、ScreenFlip();が2垂直同期信号目か、3垂直信号目で反映されるか、でフレームレートの数値が変わるくらいの信頼性は過去の使用経験からあると思い目安として使用しております。
 softya様ご指摘のコードも組み込んで実験したいと思います。
 以上よろしくお願いいたします。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: DXライブラリのScreenFlip();の反映タイミングについて

#5

投稿記事 by ISLe » 13年前

垂直同期信号は、垂直帰線期間に入る瞬間に発生するハードウェア割り込みですが、そもそもDirectXで取得できるのは垂直同期信号ではなく、垂直帰線期間かどうか、です。

WaitVsyncは、垂直帰線期間ではない状態から垂直帰線期間である状態になるのを一回とカウントしているのでしょう。
その後も垂直帰線期間は続くので、その間にScreenFlipを呼び出すことで即座に画面切り替えが行われていると考えられます。

yoshihingis

Re: DXライブラリのScreenFlip();の反映タイミングについて

#6

投稿記事 by yoshihingis » 13年前

ISle様、アドバイスありがとうございます。

Frapsだけでなく下記のサイトで紹介されているWindows SDK for Windows7のPerformance Tool KitのGPUView.exeでログを見てみましたが、SetWaitVsyncFlag()の設定にかかわらず、やはり30FPSで表示されていました。
http://mundania.org/diary/?date=20090119

下記にテストに使用したコードを記載します。
なお、ドライブFはSSDですので720X480pixelsのRGBのBMPファイルを読み込み時間は2,3msecしか、かかっておりません。
FドライブにWhiteAngel00000.bmp-WhiteAngel6524.bmpという名前のの連番静止画BMPファイルを置いて、読みだしております。

ISel様のご指摘のような動作をDXライブラリのScrennFlip();は行なっていると考えてよさそうです。

コード:

#include "DxLib.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int WindowWidth = 1280;
int WindowHeight = 800;

int LOOP;
int START = 0;
int END   = 6524;

int inwidth = 720;
int inheight = 480;

int Color;

int cno =0;

int StartTime0,StartTime1,EndTime0,EndTime1,EndTime2,Endtime3 = 0;


char ch1[512] ;
char st1[25],st2[25];
char c_zero[6] = "00000";
char no[10];


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	int handle1 ;
	

//LCD表示初期設定

	//ScreenFlipのVsync同期(ON/OFF)
	 SetWaitVSyncFlag( 0 ) ;

	// DXライブラリの初期化
	if( DxLib_Init() < 0 ) return -1;

	 

	//描画Windowsのサイズ設定
	SetGraphMode( WindowWidth , WindowHeight , 32 ) ;


	ChangeWindowMode(TRUE); // ウィンドウモードに設定

	
	SetDrawScreen( DX_SCREEN_BACK ); //描画先を表画面に設定


	// 白色の値を取得
	Color = GetColor( 255 , 255 , 255 ) ;

 //最初の同期合わせ	
    WaitVSync(1) ;
	

for(LOOP = START;LOOP <= END;LOOP++){


	ClearDrawScreen();//ScreenのClear


	StartTime0 = GetNowCount() ;



//入力画像データFILE名作成

	 sprintf(no,"%d",LOOP);
	cno = (int)(strlen(no));
		
	strcpy(ch1,"F:\\White_Angel/");
	strcat(ch1,"WhiteAngel");
	strncat(ch1,c_zero,5 -cno);
	strcat(ch1,no);
	strcat(ch1,".bmp");




//画像データ(BMP)読み込み
	
	handle1 = LoadGraph(ch1) ;

	DrawGraph( 0, 0, handle1, TRUE ); // データハンドルを使って画像を描画

	
	 EndTime0 = GetNowCount() ;

 
 //FILE名、計測時間の表示
	 DrawString( 20 ,500 , ch1 , Color );
	 DrawFormatString( 20, 520 , Color, "描画準備時間:%d[msec]\n",EndTime0-StartTime0 ) ;
	
		 
	 WaitVSync(2);

	ScreenFlip(); //裏画面を表画面に反映
	
	//メモリ読み込んだ画像を消去する。
	//これを入れないと、多数の静止画を読み込んだ時、メモリが更新されなくなる。
	InitGraph() ;

	
	}

// 使い終わっったハンドルを解放
	DeleteSoftImage( handle1 ) ;

	// キー入力待ち
	WaitKey();
	

	// DXライブラリの後始末
	DxLib_End();

	// ソフトの終了
	return 0;
}

閉鎖

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