[Feature] Option to override the display refresh rate

This adds a per-game graphics option, `DisplayRefreshRate`, to override the display refresh rate.

It defaults to 60 Hz, and is located in Dev tools.

Games using variable timesteps benefit from higher refresh rates.

Closes #19319
This commit is contained in:
Nabile Rahmani 2024-07-13 15:04:20 +02:00
parent 630cae9616
commit 7af15c73bc
No known key found for this signature in database
8 changed files with 15 additions and 7 deletions

View file

@ -684,7 +684,7 @@ bool StartVRRender() {
vrCompat[VR_COMPAT_SKYPLANE] = PSP_CoreParameter().compat.vrCompat().Skyplane;
// Set customizations
__DisplaySetFramerate(g_Config.bForce72Hz ? 72 : 60);
g_Config.iDisplayRefreshRate = g_Config.bForce72Hz ? 72 : 60;
VR_SetConfigFloat(VR_CONFIG_CANVAS_DISTANCE, vrScene && (appMode == VR_GAME_MODE) ? g_Config.fCanvas3DDistance : g_Config.fCanvasDistance);
VR_SetConfig(VR_CONFIG_PASSTHROUGH, g_Config.bPassthrough);
return true;

View file

@ -693,6 +693,8 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("UberShaderVertex", &g_Config.bUberShaderVertex, true, CfgFlag::DEFAULT),
ConfigSetting("UberShaderFragment", &g_Config.bUberShaderFragment, true, CfgFlag::DEFAULT),
ConfigSetting("DisplayRefreshRate", &g_Config.iDisplayRefreshRate, 60, CfgFlag::PER_GAME),
};
static const ConfigSetting soundSettings[] = {

View file

@ -160,6 +160,7 @@ public:
std::string sMicDevice;
bool bCameraMirrorHorizontal;
int iDisplayFramerateMode; // enum DisplayFramerateMode. Android-only.
int iDisplayRefreshRate;
bool bSoftwareRendering;
bool bSoftwareRenderingJit;

View file

@ -106,7 +106,7 @@ static int height;
static bool wasPaused;
static bool flippedThisFrame;
static int framerate = 60;
static int framerate = g_Config.iDisplayRefreshRate;
// 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have.
static double timePerVblank = 1.001 / framerate;
@ -152,6 +152,7 @@ void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId);
void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId);
void __DisplayFlip(int cyclesLate);
static void __DisplaySetFramerate(int value);
static bool UseLagSync() {
return g_Config.bForceLagSync && !g_Config.bAutoFrameSkip;
@ -562,6 +563,9 @@ static void NotifyUserIfSlow() {
}
void __DisplayFlip(int cyclesLate) {
if (g_Config.iDisplayRefreshRate != framerate)
__DisplaySetFramerate(g_Config.iDisplayRefreshRate);
flippedThisFrame = true;
// We flip only if the framebuffer was dirty. This eliminates flicker when using
// non-buffered rendering. The interaction with frame skipping seems to need
@ -1126,7 +1130,7 @@ void Register_sceDisplay_driver() {
RegisterModule("sceDisplay_driver", ARRAY_SIZE(sceDisplay), sceDisplay);
}
void __DisplaySetFramerate(int value) {
static void __DisplaySetFramerate(int value) {
framerate = value;
timePerVblank = 1.001 / (double)framerate;
frameMs = 1001.0 / (double)framerate;

View file

@ -34,5 +34,3 @@ void __DisplaySetWasPaused();
void Register_sceDisplay_driver();
void __DisplayWaitForVblanks(const char* reason, int vblanks, bool callbacks = false);
void __DisplaySetFramerate(int value);

View file

@ -78,7 +78,7 @@ static void CalculateFPS() {
actualFps = (float)(actualFlips - lastActualFlips);
fps = frames / (now - lastFpsTime);
flips = (float)(60.0 * (double)(gpuStats.numFlips - lastNumFlips) / frames);
flips = (float)(g_Config.iDisplayRefreshRate * (double)(gpuStats.numFlips - lastNumFlips) / frames);
lastFpsFrame = numVBlanks;
lastNumFlips = gpuStats.numFlips;

View file

@ -437,7 +437,7 @@ void DrawFPS(UIContext *ctx, const Bounds &bounds) {
char fpsbuf[256]{};
if (g_Config.iShowStatusFlags == ((int)ShowStatusFlags::FPS_COUNTER | (int)ShowStatusFlags::SPEED_COUNTER)) {
snprintf(fpsbuf, sizeof(fpsbuf), "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (59.94f / 100.0f));
snprintf(fpsbuf, sizeof(fpsbuf), "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (g_Config.iDisplayRefreshRate / 100.0f));
} else {
if (g_Config.iShowStatusFlags & (int)ShowStatusFlags::FPS_COUNTER) {
snprintf(fpsbuf, sizeof(fpsbuf), "FPS: %0.1f", actual_fps);

View file

@ -1888,6 +1888,9 @@ void DeveloperToolsScreen::CreateViews() {
ffMode->SetEnabledFunc([]() { return !g_Config.bVSync; });
ffMode->HideChoice(1); // not used
auto displayRefreshRate = list->Add(new PopupSliderChoice(&g_Config.iDisplayRefreshRate, 60, 1000, 60, dev->T("Display refresh rate"), 1, screenManager()));
displayRefreshRate->SetFormat(dev->T("%d Hz"));
Draw::DrawContext *draw = screenManager()->getDrawContext();
list->Add(new ItemHeader(dev->T("Ubershaders")));