mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-13 07:58:04 +00:00
Add a profiling option to the 'demo' OSD command.
See the comment in source/osdcmds.c for instructions on its usage. git-svn-id: https://svn.eduke32.com/eduke32@3021 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
6389874b5d
commit
95d11b9703
5 changed files with 217 additions and 16 deletions
|
@ -825,7 +825,6 @@ void sampletimer(void)
|
||||||
int32_t n;
|
int32_t n;
|
||||||
|
|
||||||
if (!timerfreq) return;
|
if (!timerfreq) return;
|
||||||
|
|
||||||
i = SDL_GetTicks();
|
i = SDL_GetTicks();
|
||||||
n = (int32_t)(i * timerticspersec / timerfreq) - timerlastsample;
|
n = (int32_t)(i * timerticspersec / timerfreq) - timerlastsample;
|
||||||
if (n>0)
|
if (n>0)
|
||||||
|
|
|
@ -227,10 +227,13 @@ error_wopen_demo:
|
||||||
g_demo_cnt = 1;
|
g_demo_cnt = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t g_demo_playFirstFlag = 0;
|
// demo_profile: < 0: prepare
|
||||||
void Demo_PlayFirst(void)
|
static int32_t g_demo_playFirstFlag, g_demo_profile, g_demo_stopProfile;
|
||||||
|
void Demo_PlayFirst(int32_t prof)
|
||||||
{
|
{
|
||||||
g_demo_playFirstFlag = 1;
|
g_demo_playFirstFlag = 1;
|
||||||
|
Bassert(prof >= 0);
|
||||||
|
g_demo_profile = -prof; // prepare
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,6 +358,106 @@ static int32_t Demo_ReadSync(int32_t errcode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////// DEMO PROFILING (TIMEDEMO MODE) //////////
|
||||||
|
static struct {
|
||||||
|
int32_t numtics, numframes;
|
||||||
|
double totalgamems;
|
||||||
|
double totalroomsdrawms, totalrestdrawms;
|
||||||
|
double starthitickms;
|
||||||
|
} g_prof;
|
||||||
|
|
||||||
|
int32_t Demo_IsProfiling(void)
|
||||||
|
{
|
||||||
|
return (g_demo_profile > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Demo_StopProfiling(void)
|
||||||
|
{
|
||||||
|
g_demo_stopProfile = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Demo_GToc(double t)
|
||||||
|
{
|
||||||
|
g_prof.numtics++;
|
||||||
|
g_prof.totalgamems += gethitickms()-t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Demo_RToc(double t1, double t2)
|
||||||
|
{
|
||||||
|
g_prof.numframes++;
|
||||||
|
g_prof.totalroomsdrawms += t2-t1;
|
||||||
|
g_prof.totalrestdrawms += gethitickms()-t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Demo_DisplayProfStatus(void)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
static int32_t lastpercent=-1;
|
||||||
|
int32_t percent = (100*g_demo_cnt)/g_demo_totalCnt;
|
||||||
|
|
||||||
|
if (lastpercent == percent)
|
||||||
|
return;
|
||||||
|
lastpercent = percent;
|
||||||
|
|
||||||
|
clearallviews(0);
|
||||||
|
Bsnprintf(buf, sizeof(buf), "timing... %d/%d game tics (%d %%)",
|
||||||
|
g_demo_cnt, g_demo_totalCnt, percent);
|
||||||
|
gametext(160,60, buf, 0, 2+8+16);
|
||||||
|
nextpage();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Demo_SetupProfile(void)
|
||||||
|
{
|
||||||
|
g_demo_profile *= -1; // now >0: profile for real
|
||||||
|
|
||||||
|
g_demo_soundToggle = ud.config.SoundToggle;
|
||||||
|
ud.config.SoundToggle = 0; // restored by Demo_FinishProfile()
|
||||||
|
|
||||||
|
Bmemset(&g_prof, 0, sizeof(g_prof));
|
||||||
|
|
||||||
|
g_prof.starthitickms = gethitickms();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Demo_FinishProfile(void)
|
||||||
|
{
|
||||||
|
if (Demo_IsProfiling())
|
||||||
|
{
|
||||||
|
int32_t dn=g_whichDemo-1;
|
||||||
|
int32_t nt=g_prof.numtics, nf=g_prof.numframes;
|
||||||
|
double gms=g_prof.totalgamems;
|
||||||
|
double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms;
|
||||||
|
|
||||||
|
ud.config.SoundToggle = g_demo_soundToggle;
|
||||||
|
|
||||||
|
if (nt > 0)
|
||||||
|
{
|
||||||
|
OSD_Printf("== demo %d: %d gametics\n", dn, nt);
|
||||||
|
OSD_Printf("== demo %d game times: %.03f ms (%.03f us/gametic)\n",
|
||||||
|
dn, gms, (gms*1000.0)/nt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nf > 0)
|
||||||
|
{
|
||||||
|
OSD_Printf("== demo %d: %d frames (%d frames/gametic)\n", dn, nf, g_demo_profile-1);
|
||||||
|
OSD_Printf("== demo %d drawrooms times: %.03f s (%.03f ms/frame)\n",
|
||||||
|
dn, dms1/1000.0, dms1/nf);
|
||||||
|
OSD_Printf("== demo %d drawrest times: %.03f s (%.03f ms/frame)\n",
|
||||||
|
dn, dms2/1000.0, dms2/nf);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
double totalprofms = gms+dms1+dms2;
|
||||||
|
double totalms = gethitickms()-g_prof.starthitickms;
|
||||||
|
OSD_Printf("== demo %d: non-profiled time overhead: %.02f %%\n",
|
||||||
|
dn, 100.0*totalms/totalprofms - 100.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_demo_profile = 0;
|
||||||
|
g_demo_stopProfile = 0;
|
||||||
|
}
|
||||||
|
////////////////////
|
||||||
|
|
||||||
int32_t G_PlaybackDemo(void)
|
int32_t G_PlaybackDemo(void)
|
||||||
{
|
{
|
||||||
|
@ -366,6 +469,8 @@ int32_t G_PlaybackDemo(void)
|
||||||
if (ready2send)
|
if (ready2send)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
g_demo_profile = 0;
|
||||||
|
|
||||||
RECHECK:
|
RECHECK:
|
||||||
|
|
||||||
#if KRANDDEBUG
|
#if KRANDDEBUG
|
||||||
|
@ -421,6 +526,10 @@ RECHECK:
|
||||||
#if KRANDDEBUG
|
#if KRANDDEBUG
|
||||||
krd_enable(2);
|
krd_enable(2);
|
||||||
#endif
|
#endif
|
||||||
|
if (g_demo_profile < 0)
|
||||||
|
{
|
||||||
|
Demo_SetupProfile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundemo == 0 || in_menu || I_CheckAllInput() || numplayers > 1)
|
if (foundemo == 0 || in_menu || I_CheckAllInput() || numplayers > 1)
|
||||||
|
@ -447,6 +556,7 @@ RECHECK:
|
||||||
{
|
{
|
||||||
g_demo_playFirstFlag = 0;
|
g_demo_playFirstFlag = 0;
|
||||||
g_whichDemo = 1; // force g_firstDemoFile[]
|
g_whichDemo = 1; // force g_firstDemoFile[]
|
||||||
|
g_demo_paused = 0;
|
||||||
goto nextdemo_nomenu;
|
goto nextdemo_nomenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,6 +603,9 @@ RECHECK:
|
||||||
Demo_RestoreModes(menu);
|
Demo_RestoreModes(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_demo_stopProfile)
|
||||||
|
Demo_FinishProfile();
|
||||||
|
|
||||||
while (totalclock >= (lockclock+TICSPERFRAME)
|
while (totalclock >= (lockclock+TICSPERFRAME)
|
||||||
// || (ud.reccnt > REALGAMETICSPERSEC*2 && ud.pause_on)
|
// || (ud.reccnt > REALGAMETICSPERSEC*2 && ud.pause_on)
|
||||||
|| (g_demo_goalCnt>0 && g_demo_cnt<g_demo_goalCnt))
|
|| (g_demo_goalCnt>0 && g_demo_cnt<g_demo_goalCnt))
|
||||||
|
@ -576,6 +689,8 @@ nextdemo_nomenu:
|
||||||
ud.config.SoundToggle = g_demo_soundToggle;
|
ud.config.SoundToggle = g_demo_soundToggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Demo_IsProfiling()) // don't reset g_demo_profile if it's < 0
|
||||||
|
Demo_FinishProfile();
|
||||||
goto RECHECK;
|
goto RECHECK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,15 +707,25 @@ nextdemo_nomenu:
|
||||||
|
|
||||||
g_demo_cnt++;
|
g_demo_cnt++;
|
||||||
|
|
||||||
if (!g_demo_paused)
|
if (Demo_IsProfiling())
|
||||||
|
{
|
||||||
|
int32_t t = gethitickms();
|
||||||
|
G_DoMoveThings();
|
||||||
|
Demo_GToc(t);
|
||||||
|
}
|
||||||
|
else if (!g_demo_paused)
|
||||||
{
|
{
|
||||||
// assumption that ud.multimode doesn't change in a demo may not be true
|
// assumption that ud.multimode doesn't change in a demo may not be true
|
||||||
// sometime in the future v v v v v v v v v
|
// sometime in the future v v v v v v v v v
|
||||||
if (g_demo_goalCnt==0 || !demo_hasdiffs || ud.reccnt/ud.multimode>=g_demo_goalCnt-g_demo_cnt)
|
if (g_demo_goalCnt==0 || !demo_hasdiffs || ud.reccnt/ud.multimode>=g_demo_goalCnt-g_demo_cnt)
|
||||||
|
{
|
||||||
G_DoMoveThings(); // increases lockclock by TICSPERFRAME
|
G_DoMoveThings(); // increases lockclock by TICSPERFRAME
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
lockclock += TICSPERFRAME;
|
lockclock += TICSPERFRAME;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int32_t k = ud.config.SoundToggle;
|
int32_t k = ud.config.SoundToggle;
|
||||||
|
@ -631,6 +756,9 @@ nextdemo_nomenu:
|
||||||
totalclock = lockclock;
|
totalclock = lockclock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Demo_IsProfiling())
|
||||||
|
totalclock += TICSPERFRAME;
|
||||||
|
|
||||||
if (foundemo == 0)
|
if (foundemo == 0)
|
||||||
{
|
{
|
||||||
G_DrawBackground();
|
G_DrawBackground();
|
||||||
|
@ -640,6 +768,9 @@ nextdemo_nomenu:
|
||||||
static uint32_t nextrender = 0, framewaiting = 0;
|
static uint32_t nextrender = 0, framewaiting = 0;
|
||||||
uint32_t tt;
|
uint32_t tt;
|
||||||
|
|
||||||
|
// NOTE: currently, no key/mouse events will be seen while
|
||||||
|
// demo-profiling because we need 'totalclock' for ourselves.
|
||||||
|
// And handleevents() -> sampletimer() would mess that up.
|
||||||
G_HandleLocalKeys();
|
G_HandleLocalKeys();
|
||||||
|
|
||||||
if (framewaiting)
|
if (framewaiting)
|
||||||
|
@ -657,7 +788,41 @@ nextdemo_nomenu:
|
||||||
|
|
||||||
tt = getticks();
|
tt = getticks();
|
||||||
|
|
||||||
if (r_maxfps == 0 || tt >= nextrender)
|
// Render one frame (potentially many if profiling)
|
||||||
|
if (Demo_IsProfiling())
|
||||||
|
{
|
||||||
|
int32_t i, num = g_demo_profile-1;
|
||||||
|
|
||||||
|
Bassert(totalclock-ototalclock==4);
|
||||||
|
|
||||||
|
for (i=0; i<num; i++)
|
||||||
|
{
|
||||||
|
double t1 = gethitickms(), t2;
|
||||||
|
|
||||||
|
// initprintf("t=%d, o=%d, t-o = %d\n", totalclock,
|
||||||
|
// ototalclock, totalclock-ototalclock);
|
||||||
|
|
||||||
|
// NOTE: G_DrawRooms() calculates smoothratio inside and
|
||||||
|
// ignores the function argument, so we set totalclock
|
||||||
|
// accordingly.
|
||||||
|
j = (i<<16)/num;
|
||||||
|
totalclock = ototalclock + (j>>16);
|
||||||
|
|
||||||
|
G_DrawRooms(screenpeek,j);
|
||||||
|
|
||||||
|
t2 = gethitickms();
|
||||||
|
|
||||||
|
G_DisplayRest(j);
|
||||||
|
|
||||||
|
Demo_RToc(t1, t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalclock = ototalclock+4;
|
||||||
|
|
||||||
|
// draw status
|
||||||
|
Demo_DisplayProfStatus();
|
||||||
|
}
|
||||||
|
else if (r_maxfps == 0 || tt >= nextrender)
|
||||||
{
|
{
|
||||||
if (tt > nextrender+g_frameDelay)
|
if (tt > nextrender+g_frameDelay)
|
||||||
nextrender = tt;
|
nextrender = tt;
|
||||||
|
@ -674,7 +839,7 @@ nextdemo_nomenu:
|
||||||
framewaiting++;
|
framewaiting++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
|
if (!Demo_IsProfiling() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
|
||||||
{
|
{
|
||||||
if (demoplay_showsync && outofsync)
|
if (demoplay_showsync && outofsync)
|
||||||
gametext(160,100,"OUT OF SYNC",0,2+8+16);
|
gametext(160,100,"OUT OF SYNC",0,2+8+16);
|
||||||
|
@ -717,7 +882,10 @@ nextdemo_nomenu:
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL))
|
if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL))
|
||||||
|
{
|
||||||
|
Demo_FinishProfile();
|
||||||
goto RECHECK;
|
goto RECHECK;
|
||||||
|
}
|
||||||
|
|
||||||
if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0)
|
if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0)
|
||||||
{
|
{
|
||||||
|
@ -729,7 +897,12 @@ nextdemo_nomenu:
|
||||||
S_MenuSound();
|
S_MenuSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
if (Demo_IsProfiling())
|
||||||
|
{
|
||||||
|
// Do nothing: sampletimer() is reached from M_DisplayMenus() ->
|
||||||
|
// Net_GetPackets() else.
|
||||||
|
}
|
||||||
|
else if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
||||||
{
|
{
|
||||||
Net_EnterMessage();
|
Net_EnterMessage();
|
||||||
|
|
||||||
|
@ -756,6 +929,7 @@ nextdemo_nomenu:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Demo_IsProfiling())
|
||||||
G_PrintGameQuotes(screenpeek);
|
G_PrintGameQuotes(screenpeek);
|
||||||
|
|
||||||
if (ud.last_camsprite != ud.camerasprite)
|
if (ud.last_camsprite != ud.camerasprite)
|
||||||
|
@ -770,6 +944,9 @@ nextdemo_nomenu:
|
||||||
rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
|
rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: We must prevent handleevents() and Net_GetPackets() from
|
||||||
|
// updating totalclock when profiling (both via sampletimer()):
|
||||||
|
if (!Demo_IsProfiling())
|
||||||
G_HandleAsync();
|
G_HandleAsync();
|
||||||
|
|
||||||
if (ud.recstat==0)
|
if (ud.recstat==0)
|
||||||
|
@ -794,6 +971,8 @@ nextdemo_nomenu:
|
||||||
ud.multimode = numplayers; // fixes 2 infinite loops after watching demo
|
ud.multimode = numplayers; // fixes 2 infinite loops after watching demo
|
||||||
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
|
kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
|
||||||
|
|
||||||
|
Demo_FinishProfile();
|
||||||
|
|
||||||
// if we're in the menu, try next demo immediately
|
// if we're in the menu, try next demo immediately
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_MENU)
|
if (g_player[myconnectindex].ps->gm&MODE_MENU)
|
||||||
goto RECHECK;
|
goto RECHECK;
|
||||||
|
|
|
@ -48,7 +48,10 @@ void G_CloseDemoWrite(void);
|
||||||
void G_DemoRecord(void);
|
void G_DemoRecord(void);
|
||||||
void G_OpenDemoWrite(void);
|
void G_OpenDemoWrite(void);
|
||||||
|
|
||||||
void Demo_PlayFirst(void);
|
void Demo_PlayFirst(int32_t prof);
|
||||||
|
|
||||||
|
int32_t Demo_IsProfiling(void);
|
||||||
|
void Demo_StopProfiling(void);
|
||||||
|
|
||||||
#if KRANDDEBUG
|
#if KRANDDEBUG
|
||||||
int32_t krd_print(const char *filename);
|
int32_t krd_print(const char *filename);
|
||||||
|
|
|
@ -3021,10 +3021,13 @@ void G_DisplayRest(int32_t smoothratio)
|
||||||
rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
|
rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Demo_IsProfiling())
|
||||||
|
{
|
||||||
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
if (g_player[myconnectindex].ps->gm&MODE_TYPE)
|
||||||
Net_EnterMessage();
|
Net_EnterMessage();
|
||||||
else
|
else
|
||||||
M_DisplayMenus();
|
M_DisplayMenus();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
static int32_t applied = 0;
|
static int32_t applied = 0;
|
||||||
|
|
|
@ -287,6 +287,22 @@ static int32_t osdcmd_map(const osdfuncparm_t *parm)
|
||||||
return OSDCMD_OK;
|
return OSDCMD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// demo <demonum or demofn> [<prof>]
|
||||||
|
//
|
||||||
|
// To profile a demo ("timedemo mode"), <prof> can be given in the range 0-8,
|
||||||
|
// which will start to replay it as fast as possible, rendering <prof> frames
|
||||||
|
// for each gametic.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// * The demos should be recorded with demorec_diffs set to 0, so that the
|
||||||
|
// game state updates are actually computed.
|
||||||
|
// * There's currently no way to abort the profiling.
|
||||||
|
// * With <prof> greater than 1, interpolation should be calculated properly,
|
||||||
|
// though this has not been verified by looking at the frames.
|
||||||
|
// * When testing whether a change in the source has an effect on performance,
|
||||||
|
// the variance of the run times MUST be taken into account (that is, the
|
||||||
|
// replaying must be performed multiple times for the old and new versions,
|
||||||
|
// etc.)
|
||||||
static int32_t osdcmd_demo(const osdfuncparm_t *parm)
|
static int32_t osdcmd_demo(const osdfuncparm_t *parm)
|
||||||
{
|
{
|
||||||
if (numplayers > 1)
|
if (numplayers > 1)
|
||||||
|
@ -301,20 +317,21 @@ static int32_t osdcmd_demo(const osdfuncparm_t *parm)
|
||||||
return OSDCMD_OK;
|
return OSDCMD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parm->numparms != 1)
|
if (parm->numparms != 1 && parm->numparms != 2)
|
||||||
return OSDCMD_SHOWHELP;
|
return OSDCMD_SHOWHELP;
|
||||||
|
|
||||||
{
|
{
|
||||||
char *tailptr;
|
char *tailptr;
|
||||||
const char *demostr = parm->parms[0];
|
const char *demostr = parm->parms[0];
|
||||||
int32_t i = Bstrtol(demostr, &tailptr, 10);
|
int32_t i = Bstrtol(demostr, &tailptr, 10);
|
||||||
|
int32_t prof = parm->numparms==2 ? Batoi(parm->parms[1]) : -1;
|
||||||
|
|
||||||
if (tailptr!=demostr && i>=0 && i<=999) // demo number passed
|
if (tailptr!=demostr && i>=0 && i<=999) // demo number passed
|
||||||
Bsprintf(g_firstDemoFile, "edemo%03d.edm", i);
|
Bsprintf(g_firstDemoFile, "edemo%03d.edm", i);
|
||||||
else // demo file name passed
|
else // demo file name passed
|
||||||
maybe_append_ext(g_firstDemoFile, sizeof(g_firstDemoFile), parm->parms[0], ".edm");
|
maybe_append_ext(g_firstDemoFile, sizeof(g_firstDemoFile), parm->parms[0], ".edm");
|
||||||
|
|
||||||
Demo_PlayFirst();
|
Demo_PlayFirst(clamp(prof, -1, 8)+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OSDCMD_OK;
|
return OSDCMD_OK;
|
||||||
|
|
Loading…
Reference in a new issue