Merge branch 'perfstats-thinkframes' into 'next'

Implement perfstats options for LUAh_PreThinkFrame and LUAh_PostThinkFrame

See merge request STJr/SRB2!1932
This commit is contained in:
Logan Aerl Arias 2024-01-01 04:05:16 +00:00
commit 37a917df49
6 changed files with 162 additions and 30 deletions

View file

@ -126,7 +126,9 @@ int LUA_HookPlayer(player_t *, int hook);
int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook);
int LUA_HookKey(event_t *event, int hook); // Hooks for key events
void LUA_HookPreThinkFrame(void);
void LUA_HookThinkFrame(void);
void LUA_HookPostThinkFrame(void);
int LUA_HookMobjLineCollide(mobj_t *, line_t *);
int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher);
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);

View file

@ -671,10 +671,8 @@ void LUA_HookHUD(int hook_type, huddrawlist_h list)
SPECIALIZED HOOKS
========================================================================= */
void LUA_HookThinkFrame(void)
static void hook_think_frame(int type)
{
const int type = HOOK(ThinkFrame);
// variables used by perf stats
int hook_index = 0;
precise_t time_taken = 0;
@ -692,7 +690,7 @@ void LUA_HookThinkFrame(void)
{
get_hook(&hook, map->ids, k);
if (cv_perfstats.value == 3)
if (cv_perfstats.value >= 3)
{
lua_pushvalue(gL, -1);/* need the function again */
time_taken = I_GetPreciseTime();
@ -700,12 +698,18 @@ void LUA_HookThinkFrame(void)
call_single_hook(&hook);
if (cv_perfstats.value == 3)
if (cv_perfstats.value >= 3)
{
lua_Debug ar;
time_taken = I_GetPreciseTime() - time_taken;
lua_getinfo(gL, ">S", &ar);
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
if (type == 4) // sorry for magic numbers
PS_SetPreThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
else if (type == 5)
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
else if (type == 6)
PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
hook_index++;
}
}
@ -714,6 +718,21 @@ void LUA_HookThinkFrame(void)
}
}
void LUA_HookPreThinkFrame(void)
{
hook_think_frame(HOOK(PreThinkFrame));
}
void LUA_HookThinkFrame(void)
{
hook_think_frame(HOOK(ThinkFrame));
}
void LUA_HookPostThinkFrame(void)
{
hook_think_frame(HOOK(PostThinkFrame));
}
int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line)
{
Hook_State hook;

View file

@ -65,7 +65,10 @@ static ps_metric_t ps_removecount = {0};
ps_metric_t ps_checkposition_calls = {0};
ps_metric_t ps_lua_prethinkframe_time = {0};
ps_metric_t ps_lua_thinkframe_time = {0};
ps_metric_t ps_lua_postthinkframe_time = {0};
ps_metric_t ps_lua_mobjhooks = {0};
ps_metric_t ps_otherlogictime = {0};
@ -157,7 +160,9 @@ perfstatrow_t gamelogic_rows[] = {
{" mobjs ", " Mobjs: ", &ps_thlist_times[THINK_MOBJ], PS_TIME|PS_LEVEL},
{" dynslop", " Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE], PS_TIME|PS_LEVEL},
{" precip ", " Precipitation: ", &ps_thlist_times[THINK_PRECIP], PS_TIME|PS_LEVEL},
{" lprethinkf", " LUAh_PreThinkFrame:", &ps_lua_prethinkframe_time, PS_TIME|PS_LEVEL},
{" lthinkf", " LUAh_ThinkFrame:", &ps_lua_thinkframe_time, PS_TIME|PS_LEVEL},
{" lpostthinkf", " LUAh_PostThinkFrame:", &ps_lua_postthinkframe_time, PS_TIME|PS_LEVEL},
{" other ", " Other: ", &ps_otherlogictime, PS_TIME|PS_LEVEL},
{0}
};
@ -192,10 +197,43 @@ int ps_frame_index = 0;
int ps_tick_index = 0;
// dynamically allocated resizeable array for thinkframe hook stats
ps_hookinfo_t *prethinkframe_hooks = NULL;
int prethinkframe_hooks_length = 0;
int prethinkframe_hooks_capacity = 16;
ps_hookinfo_t *thinkframe_hooks = NULL;
int thinkframe_hooks_length = 0;
int thinkframe_hooks_capacity = 16;
ps_hookinfo_t *postthinkframe_hooks = NULL;
int postthinkframe_hooks_length = 0;
int postthinkframe_hooks_capacity = 16;
void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
{
if (!prethinkframe_hooks)
{
// array needs to be initialized
prethinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity, PU_STATIC, NULL);
}
if (index >= prethinkframe_hooks_capacity)
{
// array needs more space, realloc with double size
int new_capacity = prethinkframe_hooks_capacity * 2;
prethinkframe_hooks = Z_Realloc(prethinkframe_hooks,
sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL);
// initialize new memory with zeros so the pointers in the structs are null
memset(&prethinkframe_hooks[prethinkframe_hooks_capacity], 0,
sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity);
prethinkframe_hooks_capacity = new_capacity;
}
prethinkframe_hooks[index].time_taken.value.p = time_taken;
memcpy(prethinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
// since the values are set sequentially from begin to end, the last call should leave
// the correct value to this variable
prethinkframe_hooks_length = index + 1;
}
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
{
if (!thinkframe_hooks)
@ -221,6 +259,31 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
thinkframe_hooks_length = index + 1;
}
void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
{
if (!postthinkframe_hooks)
{
// array needs to be initialized
postthinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity, PU_STATIC, NULL);
}
if (index >= postthinkframe_hooks_capacity)
{
// array needs more space, realloc with double size
int new_capacity = postthinkframe_hooks_capacity * 2;
postthinkframe_hooks = Z_Realloc(postthinkframe_hooks,
sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL);
// initialize new memory with zeros so the pointers in the structs are null
memset(&postthinkframe_hooks[postthinkframe_hooks_capacity], 0,
sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity);
postthinkframe_hooks_capacity = new_capacity;
}
postthinkframe_hooks[index].time_taken.value.p = time_taken;
memcpy(postthinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
// since the values are set sequentially from begin to end, the last call should leave
// the correct value to this variable
postthinkframe_hooks_length = index + 1;
}
static boolean PS_HighResolution(void)
{
return (vid.width >= 640 && vid.height >= 400);
@ -564,7 +627,9 @@ void PS_UpdateTickStats(void)
ps_tictime.value.p -
ps_playerthink_time.value.p -
ps_thinkertime.value.p -
ps_lua_thinkframe_time.value.p;
ps_lua_prethinkframe_time.value.p -
ps_lua_thinkframe_time.value.p -
ps_lua_postthinkframe_time.value.p;
PS_CountThinkers();
}
@ -576,21 +641,35 @@ void PS_UpdateTickStats(void)
PS_UpdateRowHistories(misc_calls_rows, false);
}
}
if (cv_perfstats.value == 3 && cv_ps_samplesize.value > 1 && PS_IsLevelActive())
if (cv_ps_samplesize.value > 1)
{
int i;
for (i = 0; i < thinkframe_hooks_length; i++)
if(cv_perfstats.value >= 3 && PS_IsLevelActive())
{
PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false);
int i;
if (cv_perfstats.value == 3)
{
for (i = 0; i < thinkframe_hooks_length; i++)
PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false);
}
else if (cv_perfstats.value == 4)
{
for (i = 0; i < prethinkframe_hooks_length; i++)
PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false, false);
}
else if (cv_perfstats.value == 5)
{
for (i = 0; i < postthinkframe_hooks_length; i++)
PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false, false);
}
}
if (cv_perfstats.value)
{
ps_tick_index++;
if (ps_tick_index >= cv_ps_samplesize.value)
ps_tick_index = 0;
if (ps_tick_samples_left)
ps_tick_samples_left--;
}
}
if (cv_perfstats.value && cv_ps_samplesize.value > 1)
{
ps_tick_index++;
if (ps_tick_index >= cv_ps_samplesize.value)
ps_tick_index = 0;
if (ps_tick_samples_left)
ps_tick_samples_left--;
}
}
@ -610,7 +689,7 @@ static void PS_DrawDescriptorHeader(void)
int samples_left = max(ps_frame_samples_left, ps_tick_samples_left);
int x, y;
if (cv_perfstats.value == 3)
if (cv_perfstats.value >= 3)
{
x = 2;
y = 0;
@ -697,7 +776,7 @@ static void PS_DrawGameLogicStats(void)
PS_DrawPerfRows(x, y, V_PURPLEMAP, misc_calls_rows);
}
static void PS_DrawThinkFrameStats(void)
static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook)
{
char s[100];
int i;
@ -711,7 +790,7 @@ static void PS_DrawThinkFrameStats(void)
PS_DrawDescriptorHeader();
for (i = 0; i < thinkframe_hooks_length; i++)
for (i = 0; i < hook_length; i++)
{
#define NEXT_ROW() \
@ -724,7 +803,7 @@ if (y > 192) \
break; \
}
char* str = thinkframe_hooks[i].short_src;
char* str = hook[i].short_src;
char* tempstr = tempbuffer;
int len = (int)strlen(str);
char* str_ptr;
@ -771,7 +850,7 @@ if (y > 192) \
if (len > 20)
str += len - 20;
snprintf(s, sizeof s - 1, "%20s: %d", str,
PS_GetMetricScreenValue(&thinkframe_hooks[i].time_taken, true));
PS_GetMetricScreenValue(&hook[i].time_taken, true));
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s);
NEXT_ROW()
@ -780,6 +859,21 @@ if (y > 192) \
}
}
static void PS_DrawPreThinkFrameStats(void)
{
draw_think_frame_stats(prethinkframe_hooks_length, prethinkframe_hooks);
}
static void PS_DrawThinkFrameStats(void)
{
draw_think_frame_stats(thinkframe_hooks_length, thinkframe_hooks);
}
static void PS_DrawPostThinkFrameStats(void)
{
draw_think_frame_stats(postthinkframe_hooks_length, postthinkframe_hooks);
}
void M_DrawPerfStats(void)
{
if (cv_perfstats.value == 1) // rendering
@ -793,7 +887,7 @@ void M_DrawPerfStats(void)
// tics when frame skips happen
PS_DrawGameLogicStats();
}
else if (cv_perfstats.value == 3) // lua thinkframe
else if (cv_perfstats.value >= 3) // lua thinkframe
{
if (!PS_IsLevelActive())
return;
@ -802,13 +896,22 @@ void M_DrawPerfStats(void)
// Low resolutions can't really use V_DrawSmallString that is used by thinkframe stats.
// A low-res version using V_DrawThinString could be implemented,
// but it would have much less space for information.
V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Perfstats 3 is not available");
V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Lua Perfstats is not available");
V_DrawThinString(80, 100, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "for resolutions below 640x400.");
return;
}
else
if (cv_perfstats.value == 3)
{
PS_DrawThinkFrameStats();
}
else if (cv_perfstats.value == 4)
{
PS_DrawPreThinkFrameStats();
}
else if (cv_perfstats.value == 5)
{
PS_DrawPostThinkFrameStats();
}
}
}

View file

@ -43,12 +43,16 @@ extern ps_metric_t ps_thlist_times[];
extern ps_metric_t ps_checkposition_calls;
extern ps_metric_t ps_lua_prethinkframe_time;
extern ps_metric_t ps_lua_thinkframe_time;
extern ps_metric_t ps_lua_postthinkframe_time;
extern ps_metric_t ps_lua_mobjhooks;
extern ps_metric_t ps_otherlogictime;
void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void PS_UpdateTickStats(void);

View file

@ -380,7 +380,7 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_
consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL);
static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {4, "PreThinkFrame"}, {5, "PostThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange);
static CV_PossibleValue_t ps_samplesize_cons_t[] = {
{1, "MIN"}, {1000, "MAX"}, {0, NULL}};

View file

@ -769,7 +769,9 @@ void P_Ticker(boolean run)
ps_lua_mobjhooks.value.i = 0;
ps_checkposition_calls.value.i = 0;
LUA_HOOK(PreThinkFrame);
PS_START_TIMING(ps_lua_prethinkframe_time);
LUA_HookPreThinkFrame();
PS_STOP_TIMING(ps_lua_prethinkframe_time);
PS_START_TIMING(ps_playerthink_time);
for (i = 0; i < MAXPLAYERS; i++)
@ -867,7 +869,9 @@ void P_Ticker(boolean run)
if (modeattacking)
G_GhostTicker();
LUA_HOOK(PostThinkFrame);
PS_START_TIMING(ps_lua_postthinkframe_time);
LUA_HookPostThinkFrame();
PS_STOP_TIMING(ps_lua_postthinkframe_time);
}
if (run)