mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-31 12:13:16 +00:00
Merge branch 'finish-update-optimize' into 'master'
Interpolation optimization See merge request KartKrew/Kart!566
This commit is contained in:
commit
5db877ab35
14 changed files with 360 additions and 171 deletions
|
|
@ -5149,7 +5149,7 @@ boolean TryRunTics(tic_t realtics)
|
|||
|
||||
if (demo.playback)
|
||||
{
|
||||
neededtic = gametic + realtics * (gamestate == GS_LEVEL ? cv_playbackspeed.value : 1);
|
||||
neededtic = gametic + realtics;
|
||||
// start a game after a demo
|
||||
maketic += realtics;
|
||||
firstticstosend = maketic;
|
||||
|
|
@ -5199,7 +5199,6 @@ boolean TryRunTics(tic_t realtics)
|
|||
while (neededtic > gametic)
|
||||
{
|
||||
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
|
||||
prev_tics = I_GetTime();
|
||||
|
||||
ps_tictime = I_GetPreciseTime();
|
||||
|
||||
|
|
|
|||
166
src/d_main.c
166
src/d_main.c
|
|
@ -679,6 +679,29 @@ static void D_Display(void)
|
|||
}
|
||||
}
|
||||
|
||||
static boolean D_CheckFrameCap(void)
|
||||
{
|
||||
static boolean init = false;
|
||||
static precise_t startCap = 0;
|
||||
precise_t endCap = 0;
|
||||
|
||||
endCap = I_GetPreciseTime();
|
||||
|
||||
if (init == false)
|
||||
{
|
||||
startCap = endCap;
|
||||
init = true;
|
||||
}
|
||||
else if (I_CheckFrameCap(startCap, endCap))
|
||||
{
|
||||
// Framerate should be capped.
|
||||
return true;
|
||||
}
|
||||
|
||||
startCap = endCap;
|
||||
return false;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// D_SRB2Loop
|
||||
// =========================================================================
|
||||
|
|
@ -689,6 +712,8 @@ void D_SRB2Loop(void)
|
|||
{
|
||||
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
|
||||
boolean ticked;
|
||||
boolean interp;
|
||||
boolean doDisplay = false;
|
||||
|
||||
if (dedicated)
|
||||
server = true;
|
||||
|
|
@ -754,14 +779,25 @@ void D_SRB2Loop(void)
|
|||
|
||||
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||
|
||||
if (demo.playback && gamestate == GS_LEVEL)
|
||||
{
|
||||
// Nicer place to put this.
|
||||
realtics = realtics * cv_playbackspeed.value;
|
||||
}
|
||||
|
||||
#ifdef DEBUGFILE
|
||||
if (!realtics)
|
||||
if (debugload)
|
||||
debugload--;
|
||||
#endif
|
||||
|
||||
if (!realtics && !singletics && cv_frameinterpolation.value != 1)
|
||||
interp = R_UsingFrameInterpolation();
|
||||
doDisplay = false;
|
||||
ticked = false;
|
||||
|
||||
if (!realtics && !singletics && !interp)
|
||||
{
|
||||
// Non-interp sleep
|
||||
I_Sleep();
|
||||
continue;
|
||||
}
|
||||
|
|
@ -770,73 +806,100 @@ void D_SRB2Loop(void)
|
|||
HW3S_BeginFrameUpdate();
|
||||
#endif
|
||||
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
ticked = TryRunTics(realtics);
|
||||
|
||||
if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause()))
|
||||
if (realtics > 0 || singletics)
|
||||
{
|
||||
static float tictime;
|
||||
// don't skip more than 10 frames at a time
|
||||
// (fadein / fadeout cause massive frame skip!)
|
||||
if (realtics > 8)
|
||||
realtics = 1;
|
||||
|
||||
// process tics (but maybe not if realtic == 0)
|
||||
ticked = TryRunTics(realtics);
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
|
||||
doDisplay = true;
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
{
|
||||
doDisplay = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (interp)
|
||||
{
|
||||
static float tictime = 0.0f;
|
||||
static float prevtime = 0.0f;
|
||||
float entertime = I_GetTimeFrac();
|
||||
|
||||
fixed_t entertimefrac;
|
||||
fixed_t entertimefrac = FRACUNIT;
|
||||
|
||||
if (ticked)
|
||||
{
|
||||
tictime = entertime;
|
||||
}
|
||||
|
||||
if (aproxfps < 35.0)
|
||||
entertimefrac = FRACUNIT;
|
||||
else
|
||||
entertimefrac = FLOAT_TO_FIXED(entertime - tictime);
|
||||
// Handle interp sleep / framerate cap here.
|
||||
// TryRunTics needs ran if possible to prevent lagged map changes,
|
||||
// (and if that runs, the code above needs to also run)
|
||||
// so this is done here after TryRunTics.
|
||||
if (D_CheckFrameCap())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
if (entertimefrac > rendertimefrac)
|
||||
renderdeltatics += entertimefrac - rendertimefrac;
|
||||
else
|
||||
renderdeltatics -= rendertimefrac - entertimefrac;
|
||||
if (!(paused || P_AutoPause()))
|
||||
{
|
||||
#if 0
|
||||
CONS_Printf("prevtime = %f\n", prevtime);
|
||||
CONS_Printf("entertime = %f\n", entertime);
|
||||
CONS_Printf("tictime = %f\n", tictime);
|
||||
CONS_Printf("entertime - prevtime = %f\n", entertime - prevtime);
|
||||
CONS_Printf("entertime - tictime = %f\n", entertime - tictime);
|
||||
CONS_Printf("========\n");
|
||||
#endif
|
||||
|
||||
rendertimefrac = entertimefrac;
|
||||
if (entertime - prevtime >= 1.0f)
|
||||
{
|
||||
// Lagged for more frames than a gametic...
|
||||
// No need for interpolation.
|
||||
entertimefrac = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
entertimefrac = min(FRACUNIT, FLOAT_TO_FIXED(entertime - tictime));
|
||||
}
|
||||
|
||||
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
if (entertimefrac > rendertimefrac)
|
||||
renderdeltatics += entertimefrac - rendertimefrac;
|
||||
else
|
||||
renderdeltatics -= rendertimefrac - entertimefrac;
|
||||
|
||||
rendertimefrac = entertimefrac;
|
||||
}
|
||||
|
||||
prevtime = entertime;
|
||||
}
|
||||
else
|
||||
{
|
||||
rendertimefrac = FRACUNIT;
|
||||
renderdeltatics = realtics * FRACUNIT;
|
||||
rendertimefrac = FRACUNIT;
|
||||
}
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
if (interp || doDisplay)
|
||||
{
|
||||
D_Display();
|
||||
}
|
||||
|
||||
if (lastdraw || singletics || gametic > rendergametic)
|
||||
{
|
||||
rendergametic = gametic;
|
||||
rendertimeout = entertic+TICRATE/17;
|
||||
|
||||
// Update display, next frame, with current state.
|
||||
// (Only display if not already done for frame interp)
|
||||
cv_frameinterpolation.value == 0 ? D_Display() : (void)0;
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
}
|
||||
else if (rendertimeout < entertic) // in case the server hang or netsplit
|
||||
{
|
||||
// (Only display if not already done for frame interp)
|
||||
cv_frameinterpolation.value == 0 ? D_Display() : (void)0;
|
||||
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
}
|
||||
if (moviemode)
|
||||
M_SaveFrame();
|
||||
if (takescreenshot) // Only take screenshots after drawing.
|
||||
M_DoScreenShot();
|
||||
|
||||
// consoleplayer -> displayplayers (hear sounds from viewpoint)
|
||||
S_UpdateSounds(); // move positional sounds
|
||||
|
|
@ -854,6 +917,11 @@ void D_SRB2Loop(void)
|
|||
Discord_RunCallbacks();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Moved to here from I_FinishUpdate.
|
||||
// It doesn't track fades properly anymore by being here (might be easy fix),
|
||||
// but it's a little more accurate for actual game logic when its here.
|
||||
SCR_CalculateFPS();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2
|
|||
|
||||
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t sleeping_cons_t[] = {{-1, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
|
||||
static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ int I_PreciseToMicros(precise_t d);
|
|||
*/
|
||||
void I_Sleep(void);
|
||||
|
||||
boolean I_CheckFrameCap(precise_t start, precise_t end);
|
||||
|
||||
/** \brief Get events
|
||||
|
||||
Called by D_SRB2Loop,
|
||||
|
|
|
|||
|
|
@ -151,4 +151,6 @@ void I_BeginRead(void);
|
|||
*/
|
||||
void I_EndRead(void);
|
||||
|
||||
UINT32 I_GetRefreshRate(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
15
src/m_menu.c
15
src/m_menu.c
|
|
@ -63,6 +63,7 @@
|
|||
#include "d_player.h" // KITEM_ constants
|
||||
#include "k_color.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
#include "i_joy.h" // for joystick menu controls
|
||||
|
||||
|
|
@ -1260,18 +1261,18 @@ static menuitem_t OP_VideoOptionsMenu[] =
|
|||
{IT_STRING|IT_CVAR, NULL, "Fullscreen", {.cvar = &cv_fullscreen}, 20},
|
||||
#endif
|
||||
#ifdef HWRENDER
|
||||
{IT_STRING | IT_CVAR, NULL, "Renderer", {.cvar = &cv_renderer}, 30},
|
||||
{IT_STRING | IT_CVAR, NULL, "Renderer", {.cvar = &cv_renderer}, 30},
|
||||
#else
|
||||
{IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", {.cvar = &cv_renderer}, 30},
|
||||
{IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", {.cvar = &cv_renderer}, 30},
|
||||
#endif
|
||||
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
|
||||
NULL, "Gamma", {.cvar = &cv_globalgamma}, 50},
|
||||
NULL, "Gamma", {.cvar = &cv_globalgamma}, 50},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show FPS", {.cvar = &cv_ticrate}, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "Vertical Sync", {.cvar = &cv_vidwait}, 70},
|
||||
{IT_STRING | IT_CVAR, NULL, "Show FPS", {.cvar = &cv_ticrate}, 60},
|
||||
{IT_STRING | IT_CVAR, NULL, "FPS Cap", {.cvar = &cv_fpscap}, 70},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Draw Distance", {.cvar = &cv_drawdist}, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Weather Draw Distance", {.cvar = &cv_drawdist_precip}, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Draw Distance", {.cvar = &cv_drawdist}, 90},
|
||||
{IT_STRING | IT_CVAR, NULL, "Weather Draw Distance", {.cvar = &cv_drawdist_precip}, 100},
|
||||
{IT_STRING | IT_CVAR, NULL, "Skyboxes", {.cvar = &cv_skybox}, 110},
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
|
|||
46
src/r_fps.c
46
src/r_fps.c
|
|
@ -20,10 +20,52 @@
|
|||
#include "r_plane.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_state.h"
|
||||
#include "console.h" // con_startup_loadprogress
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h" // for cv_glshearing
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t fpscap_cons_t[] = {
|
||||
{-1, "Match refresh rate"},
|
||||
{0, "Unlimited"},
|
||||
#ifdef DEVELOP
|
||||
// Lower values are actually pretty useful for debugging interp problems!
|
||||
{1, "One Singular Frame"},
|
||||
{10, "10"},
|
||||
{20, "20"},
|
||||
{25, "25"},
|
||||
{30, "30"},
|
||||
#endif
|
||||
{35, "35"},
|
||||
{50, "50"},
|
||||
{60, "60"},
|
||||
{70, "70"},
|
||||
{75, "75"},
|
||||
{90, "90"},
|
||||
{100, "100"},
|
||||
{120, "120"},
|
||||
{144, "144"},
|
||||
{200, "200"},
|
||||
{240, "240"},
|
||||
{0, NULL}
|
||||
};
|
||||
consvar_t cv_fpscap = CVAR_INIT ("fpscap", "Match refresh rate", CV_SAVE, fpscap_cons_t, NULL);
|
||||
|
||||
UINT32 R_GetFramerateCap(void)
|
||||
{
|
||||
if (cv_fpscap.value < 0)
|
||||
{
|
||||
return I_GetRefreshRate();
|
||||
}
|
||||
|
||||
return cv_fpscap.value;
|
||||
}
|
||||
|
||||
boolean R_UsingFrameInterpolation(void)
|
||||
{
|
||||
return (R_GetFramerateCap() != TICRATE); // maybe use ">" instead?
|
||||
}
|
||||
|
||||
static viewvars_t pview_old[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t pview_new[MAXSPLITSCREENPLAYERS];
|
||||
static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS];
|
||||
|
|
@ -156,7 +198,7 @@ void R_SetViewContext(enum viewcontext_e _viewcontext)
|
|||
|
||||
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
|
||||
{
|
||||
if (cv_frameinterpolation.value == 0)
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
|
@ -166,7 +208,7 @@ fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
|
|||
|
||||
angle_t R_InterpolateAngle(angle_t from, angle_t to)
|
||||
{
|
||||
if (cv_frameinterpolation.value == 0)
|
||||
if (!R_UsingFrameInterpolation())
|
||||
{
|
||||
return to;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@
|
|||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
|
||||
extern consvar_t cv_fpscap;
|
||||
|
||||
UINT32 R_GetFramerateCap(void);
|
||||
boolean R_UsingFrameInterpolation(void);
|
||||
|
||||
enum viewcontext_e
|
||||
{
|
||||
VIEWCONTEXT_PLAYER1 = 0,
|
||||
|
|
|
|||
|
|
@ -104,9 +104,6 @@ lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
|
|||
lighttable_t *scalelightfixed[MAXLIGHTSCALE];
|
||||
lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
|
||||
|
||||
// Frame interpolation/uncapped
|
||||
tic_t prev_tics;
|
||||
|
||||
// Hack to support extra boom colormaps.
|
||||
extracolormap_t *extra_colormaps = NULL;
|
||||
|
||||
|
|
@ -175,9 +172,6 @@ consvar_t cv_fov[MAXSPLITSCREENPLAYERS] = {
|
|||
CVAR_INIT ("fov4", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange)
|
||||
};
|
||||
|
||||
// Frame interpolation/uncapped
|
||||
consvar_t cv_frameinterpolation = CVAR_INIT ("frameinterpolation", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
// Okay, whoever said homremoval causes a performance hit should be shot.
|
||||
consvar_t cv_homremoval = CVAR_INIT ("homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL);
|
||||
|
||||
|
|
@ -1678,5 +1672,5 @@ void R_RegisterEngineStuff(void)
|
|||
CV_RegisterVar(&cv_movebob);
|
||||
|
||||
// Frame interpolation/uncapped
|
||||
CV_RegisterVar(&cv_frameinterpolation);
|
||||
CV_RegisterVar(&cv_fpscap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,10 +116,6 @@ extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS];
|
|||
extern consvar_t cv_skybox;
|
||||
extern consvar_t cv_tailspickup;
|
||||
|
||||
// Frame interpolation (uncapped framerate)
|
||||
extern tic_t prev_tics;
|
||||
extern consvar_t cv_frameinterpolation;
|
||||
|
||||
// Called by startup code.
|
||||
void R_Init(void);
|
||||
|
||||
|
|
|
|||
154
src/screen.c
154
src/screen.c
|
|
@ -33,12 +33,15 @@
|
|||
#include "s_sound.h" // ditto
|
||||
#include "g_game.h" // ditto
|
||||
#include "p_local.h" // P_AutoPause()
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_main.h"
|
||||
#include "hardware/hw_light.h"
|
||||
#include "hardware/hw_model.h"
|
||||
#endif
|
||||
|
||||
// SRB2Kart
|
||||
#include "r_fps.h" // R_GetFramerateCap
|
||||
|
||||
#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
|
||||
#define RUSEASM //MSC.NET can't patch itself
|
||||
|
|
@ -68,16 +71,17 @@ viddef_t vid;
|
|||
INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1)
|
||||
UINT8 setrenderneeded = 0;
|
||||
|
||||
static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}};
|
||||
|
||||
static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}};
|
||||
|
||||
//added : 03-02-98: default screen mode, as loaded/saved in config
|
||||
consvar_t cv_scr_width = CVAR_INIT ("scr_width", "640", CV_SAVE, CV_Unsigned, NULL);
|
||||
consvar_t cv_scr_height = CVAR_INIT ("scr_height", "400", CV_SAVE, CV_Unsigned, NULL);
|
||||
|
||||
static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}};
|
||||
consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL);
|
||||
|
||||
consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL);
|
||||
consvar_t cv_vhseffect = CVAR_INIT ("vhspause", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}};
|
||||
consvar_t cv_shittyscreen = CVAR_INIT ("televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL);
|
||||
|
||||
CV_PossibleValue_t cv_renderer_t[] = {
|
||||
|
|
@ -518,104 +522,96 @@ boolean SCR_IsAspectCorrect(INT32 width, INT32 height)
|
|||
);
|
||||
}
|
||||
|
||||
// XMOD FPS display
|
||||
// moved out of os-specific code for consistency
|
||||
static boolean ticsgraph[TICRATE];
|
||||
static tic_t lasttic;
|
||||
double averageFPS = 0.0f;
|
||||
|
||||
static UINT32 fpstime = 0;
|
||||
static UINT32 lastupdatetime = 0;
|
||||
#define FPS_SAMPLE_RATE (50000) // How often to update FPS samples, in microseconds
|
||||
#define NUM_FPS_SAMPLES 16 // Number of samples to store
|
||||
|
||||
#define FPSUPDATERATE 1/20 // What fraction of a second to update at. The fraction will not simplify to 0, trust me.
|
||||
#define FPSMAXSAMPLES 16
|
||||
static double fps_samples[NUM_FPS_SAMPLES];
|
||||
|
||||
static UINT32 fpssamples[FPSMAXSAMPLES];
|
||||
static UINT32 fpssampleslen = 0;
|
||||
static UINT32 fpssum = 0;
|
||||
double aproxfps = 0.0f;
|
||||
|
||||
void SCR_CalcAproxFps(void)
|
||||
void SCR_CalculateFPS(void)
|
||||
{
|
||||
tic_t i = 0;
|
||||
if (I_PreciseToMicros(fpstime - lastupdatetime) > 1000000 * FPSUPDATERATE)
|
||||
static boolean init = false;
|
||||
|
||||
static precise_t startTime = 0;
|
||||
precise_t endTime = 0;
|
||||
|
||||
static precise_t updateTime = 0;
|
||||
int updateElapsed = 0;
|
||||
int i;
|
||||
|
||||
endTime = I_GetPreciseTime();
|
||||
|
||||
if (init == false)
|
||||
{
|
||||
if (fpssampleslen == FPSMAXSAMPLES)
|
||||
{
|
||||
fpssum -= fpssamples[0];
|
||||
|
||||
for (i = 1; i < fpssampleslen; i++)
|
||||
fpssamples[i-1] = fpssamples[i];
|
||||
}
|
||||
else
|
||||
fpssampleslen++;
|
||||
|
||||
fpssamples[fpssampleslen-1] = I_GetPreciseTime() - fpstime;
|
||||
fpssum += fpssamples[fpssampleslen-1];
|
||||
|
||||
aproxfps = 1000000 / (I_PreciseToMicros(fpssum) / (double)fpssampleslen);
|
||||
|
||||
lastupdatetime = I_GetPreciseTime();
|
||||
startTime = updateTime = endTime;
|
||||
init = true;
|
||||
return;
|
||||
}
|
||||
|
||||
fpstime = I_GetPreciseTime();
|
||||
updateElapsed = I_PreciseToMicros(endTime - updateTime);
|
||||
|
||||
if (updateElapsed >= FPS_SAMPLE_RATE)
|
||||
{
|
||||
static int sampleIndex = 0;
|
||||
int frameElapsed = I_PreciseToMicros(endTime - startTime);
|
||||
|
||||
fps_samples[sampleIndex] = frameElapsed / 1000.0f;
|
||||
|
||||
sampleIndex++;
|
||||
if (sampleIndex >= NUM_FPS_SAMPLES)
|
||||
sampleIndex = 0;
|
||||
|
||||
averageFPS = 0.0f;
|
||||
for (i = 0; i < NUM_FPS_SAMPLES; i++)
|
||||
{
|
||||
averageFPS += fps_samples[i];
|
||||
}
|
||||
averageFPS = 1000.0f / (averageFPS / NUM_FPS_SAMPLES);
|
||||
|
||||
updateTime = endTime;
|
||||
}
|
||||
|
||||
startTime = endTime;
|
||||
}
|
||||
|
||||
void SCR_DisplayTicRate(void)
|
||||
{
|
||||
tic_t i;
|
||||
tic_t ontic = I_GetTime();
|
||||
tic_t totaltics = 0;
|
||||
const UINT8 *ticcntcolor = NULL;
|
||||
|
||||
for (i = lasttic + 1; i < TICRATE+lasttic && i < ontic; ++i)
|
||||
ticsgraph[i % TICRATE] = false;
|
||||
|
||||
ticsgraph[ontic % TICRATE] = true;
|
||||
|
||||
for (i = 0;i < TICRATE;++i)
|
||||
if (ticsgraph[i])
|
||||
++totaltics;
|
||||
UINT32 cap = R_GetFramerateCap();
|
||||
UINT32 benchmark = (cap == 0) ? I_GetRefreshRate() : cap;
|
||||
INT32 x = 318;
|
||||
double fps = ceil(averageFPS);
|
||||
|
||||
// draw "FPS"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 183<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, framecounter, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE));
|
||||
|
||||
if (cv_frameinterpolation.value == 1)
|
||||
{
|
||||
if (aproxfps <= 15.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
else if (aproxfps >= 60.0f) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
if (fps > (benchmark - 5))
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
else if (fps < 20)
|
||||
ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
|
||||
/*
|
||||
if (cv_fpscap.value != 0)
|
||||
{
|
||||
// draw total frame:
|
||||
//V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cv_fpscap.value, ticcntcolor);
|
||||
// draw "/"
|
||||
//V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, aproxfps, ticcntcolor);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, aproxfps, ticcntcolor);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (cap != 0)
|
||||
{
|
||||
if (totaltics <= 15) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE);
|
||||
else if (totaltics >= TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE);
|
||||
UINT32 digits = 1;
|
||||
UINT32 c2 = cap;
|
||||
|
||||
while (c2 > 0)
|
||||
{
|
||||
c2 = c2 / 10;
|
||||
digits++;
|
||||
}
|
||||
|
||||
// draw total frame:
|
||||
V_DrawPingNum(318, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, TICRATE, ticcntcolor);
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, cap, ticcntcolor);
|
||||
x -= digits * 4;
|
||||
|
||||
// draw "/"
|
||||
V_DrawFixedPatch(306<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(306, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, totaltics, ticcntcolor);
|
||||
V_DrawFixedPatch(x<<FRACBITS, 190<<FRACBITS, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, frameslash, ticcntcolor);
|
||||
}
|
||||
|
||||
|
||||
lasttic = ontic;
|
||||
// draw our actual framerate
|
||||
V_DrawPingNum(x, 190, V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS, fps, ticcntcolor);
|
||||
}
|
||||
|
||||
// SCR_DisplayLocalPing
|
||||
|
|
|
|||
|
|
@ -191,7 +191,8 @@ extern boolean R_SSE2;
|
|||
extern viddef_t vid;
|
||||
extern INT32 setmodeneeded; // mode number to set if needed, or 0
|
||||
extern UINT8 setrenderneeded;
|
||||
extern double aproxfps;
|
||||
|
||||
extern double averageFPS;
|
||||
|
||||
void SCR_ChangeRenderer(void);
|
||||
|
||||
|
|
@ -231,7 +232,7 @@ void SCR_CheckDefaultMode(void);
|
|||
// Set the mode number which is saved in the config
|
||||
void SCR_SetDefaultMode(void);
|
||||
|
||||
void SCR_CalcAproxFps(void);
|
||||
void SCR_CalculateFPS(void);
|
||||
|
||||
FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height);
|
||||
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ static char returnWadPath[256];
|
|||
#include "../d_net.h"
|
||||
#include "../g_game.h"
|
||||
#include "../filesrch.h"
|
||||
#include "../k_pwrlv.h"
|
||||
#include "endtxt.h"
|
||||
#include "sdlmain.h"
|
||||
|
||||
|
|
@ -181,7 +180,10 @@ static char returnWadPath[256];
|
|||
|
||||
#include "../m_argv.h"
|
||||
|
||||
// SRB2Kart
|
||||
#include "../k_pwrlv.h"
|
||||
#include "../r_main.h" // Frame interpolation/uncapped
|
||||
#include "../r_fps.h"
|
||||
|
||||
#ifdef MAC_ALERT
|
||||
#include "macosx/mac_alert.h"
|
||||
|
|
@ -1699,6 +1701,57 @@ void I_Sleep(void)
|
|||
SDL_Delay(cv_sleep.value);
|
||||
}
|
||||
|
||||
boolean I_CheckFrameCap(precise_t start, precise_t end)
|
||||
{
|
||||
UINT32 capFrames = R_GetFramerateCap();
|
||||
int capMicros = 0;
|
||||
|
||||
int elapsed;
|
||||
|
||||
if (capFrames == 0)
|
||||
{
|
||||
// We don't want to cap.
|
||||
return false;
|
||||
}
|
||||
|
||||
elapsed = I_PreciseToMicros(end - start);
|
||||
capMicros = 1000000 / capFrames;
|
||||
|
||||
if (elapsed < capMicros)
|
||||
{
|
||||
// Wait to draw the next frame.
|
||||
UINT32 wait = ((capMicros - elapsed) / 1000);
|
||||
|
||||
if (cv_sleep.value > 1)
|
||||
{
|
||||
// 1 is the default, and in non-interpolated mode is just the bare minimum wait.
|
||||
// Since we're already adding some wait with an FPS cap, only apply when it's above 1.
|
||||
wait += cv_sleep.value - 1;
|
||||
}
|
||||
|
||||
// If the wait's greater than our granularity value,
|
||||
// we'll just burn the couple extra cycles in the main loop
|
||||
// in order to get to the next frame.
|
||||
// This makes us get to the exact FPS cap more often.
|
||||
|
||||
// Higher values have more wasted CPU cycles, but the in-game frame performance is better.
|
||||
// 10ms is the average clock tick of most OS scheduling.
|
||||
// 15ms is a little more than that, for leniency on slow machines. (This helps mine reach a stable 60, at least!)
|
||||
// (https://www.libsdl.org/release/SDL-1.2.15/docs/html/sdldelay.html)
|
||||
#define DELAY_GRANULARITY 15
|
||||
if (wait >= DELAY_GRANULARITY)
|
||||
{
|
||||
SDL_Delay(wait);
|
||||
}
|
||||
#undef DELAY_GRANULARITY
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Waited enough to draw again.
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef NEWSIGNALHANDLER
|
||||
static void newsignalhandler_Warn(const char *pr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1256,12 +1256,15 @@ void I_UpdateNoBlit(void)
|
|||
// from PrBoom's src/SDL/i_video.c
|
||||
static inline boolean I_SkipFrame(void)
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
// While I fixed the FPS counter bugging out with this,
|
||||
// I actually really like being able to pause and
|
||||
// use perfstats to measure rendering performance
|
||||
// without game logic changes.
|
||||
return false;
|
||||
#else
|
||||
static boolean skip = false;
|
||||
|
||||
if (rendermode != render_soft)
|
||||
return false;
|
||||
|
||||
skip = !skip;
|
||||
|
||||
switch (gamestate)
|
||||
|
|
@ -1276,12 +1279,13 @@ static inline boolean I_SkipFrame(void)
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// I_FinishUpdate
|
||||
//
|
||||
static SDL_Rect src_rect = { 0, 0, 0, 0 };
|
||||
|
||||
void I_FinishUpdate(void)
|
||||
{
|
||||
int player;
|
||||
|
|
@ -1289,11 +1293,11 @@ void I_FinishUpdate(void)
|
|||
if (rendermode == render_none)
|
||||
return; //Alam: No software or OpenGl surface
|
||||
|
||||
//SCR_CalculateFPS(); // Moved to main loop
|
||||
|
||||
if (I_SkipFrame())
|
||||
return;
|
||||
|
||||
SCR_CalcAproxFps();
|
||||
|
||||
if (st_overlay)
|
||||
{
|
||||
if (cv_ticrate.value)
|
||||
|
|
@ -1338,27 +1342,22 @@ void I_FinishUpdate(void)
|
|||
|
||||
if (rendermode == render_soft && screens[0])
|
||||
{
|
||||
SDL_Rect rect;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.w = vid.width;
|
||||
rect.h = vid.height;
|
||||
|
||||
if (!bufSurface) //Double-Check
|
||||
{
|
||||
Impl_VideoSetupSDLBuffer();
|
||||
}
|
||||
|
||||
if (bufSurface)
|
||||
{
|
||||
SDL_BlitSurface(bufSurface, NULL, vidSurface, &rect);
|
||||
SDL_BlitSurface(bufSurface, &src_rect, vidSurface, &src_rect);
|
||||
// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
|
||||
SDL_LockSurface(vidSurface);
|
||||
SDL_UpdateTexture(texture, &rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UpdateTexture(texture, &src_rect, vidSurface->pixels, vidSurface->pitch);
|
||||
SDL_UnlockSurface(vidSurface);
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderCopy(renderer, texture, &src_rect, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
#ifdef HWRENDER
|
||||
|
|
@ -1367,6 +1366,7 @@ void I_FinishUpdate(void)
|
|||
OglSdlFinishUpdate(cv_vidwait.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
exposevideo = SDL_FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1583,8 +1583,15 @@ static SDL_bool Impl_CreateContext(void)
|
|||
int flags = 0; // Use this to set SDL_RENDERER_* flags now
|
||||
if (usesdl2soft)
|
||||
flags |= SDL_RENDERER_SOFTWARE;
|
||||
#if 0
|
||||
// This shit is BROKEN.
|
||||
// - The version of SDL we're using cannot toggle VSync at runtime. We'll need a new SDL version implemented to have this work properly.
|
||||
// - cv_vidwait is initialized before config is loaded, so it's forced to default value at runtime, and forced off when switching. The config loading code would need restructured.
|
||||
// - With both this & frame interpolation on, I_FinishUpdate takes x10 longer. At this point, it is simpler to use a standard FPS cap.
|
||||
// So you can probably guess why I'm kinda over this, I'm just disabling it.
|
||||
else if (cv_vidwait.value)
|
||||
flags |= SDL_RENDERER_PRESENTVSYNC;
|
||||
#endif
|
||||
|
||||
if (!renderer)
|
||||
renderer = SDL_CreateRenderer(window, -1, flags);
|
||||
|
|
@ -1719,6 +1726,9 @@ INT32 VID_SetMode(INT32 modeNum)
|
|||
vid.height = windowedModes[modeNum][1];
|
||||
vid.modenum = modeNum;
|
||||
|
||||
src_rect.w = vid.width;
|
||||
src_rect.h = vid.height;
|
||||
|
||||
//Impl_SetWindowName("SRB2Kart "VERSIONSTRING);
|
||||
VID_CheckRenderer();
|
||||
return SDL_TRUE;
|
||||
|
|
@ -2061,3 +2071,23 @@ void I_ShutdownGraphics(void)
|
|||
framebuffer = SDL_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
UINT32 I_GetRefreshRate(void)
|
||||
{
|
||||
int index = SDL_GetWindowDisplayIndex(window);
|
||||
SDL_DisplayMode m;
|
||||
|
||||
if (SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
{
|
||||
// Video not init yet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SDL_GetDesktopDisplayMode(index, &m) != 0)
|
||||
{
|
||||
// Error has occurred.
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m.refresh_rate;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue