mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-06-01 09:17:15 -04:00
Use Limiter class in waitForTick (#330)
This uses the existing `Limiter` class (stolen from Metaforce) in `JFWDisplay::waitForTick`. The limiter also now uses `SDL_DelayPrecise` internally on non-Windows platforms. On Windows, the existing `NanoSleep` logic is untouched, as it appears to provide a more stable framerate for the folks testing it on Windows than `SDL_DelayPrecise` does. On Linux, however, `SDL_DelayPrecise` is plenty accurate.
This commit is contained in:
+3
-5
@@ -15,12 +15,10 @@
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#endif
|
||||
|
||||
#include "dusk/logging.h"
|
||||
|
||||
constexpr auto DUSK_FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::duration<double>(1001.0 / 30000.0));
|
||||
|
||||
class Limiter {
|
||||
using delta_clock = std::chrono::high_resolution_clock;
|
||||
using duration_t = std::chrono::nanoseconds;
|
||||
@@ -101,7 +99,7 @@ private:
|
||||
} while (current.QuadPart - start.QuadPart < ticksToWait);
|
||||
}
|
||||
#else
|
||||
void NanoSleep(const duration_t duration) { std::this_thread::sleep_for(duration); }
|
||||
void NanoSleep(const duration_t duration) { SDL_DelayPrecise(duration.count()); }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
#include "JSystem/JSystem.h" // IWYU pragma: keep
|
||||
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/vi.h>
|
||||
#include <gx.h>
|
||||
#include <stdint.h>
|
||||
#include <vi.h>
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
|
||||
#include "JSystem/JFramework/JFWDisplay.h"
|
||||
#include "JSystem/J2DGraph/J2DOrthoGraph.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "JSystem/JUtility/JUTAssert.h"
|
||||
#include "JSystem/JUtility/JUTConsole.h"
|
||||
#include "JSystem/JUtility/JUTDbPrint.h"
|
||||
#include "JSystem/JUtility/JUTProcBar.h"
|
||||
#include "aurora/aurora.h"
|
||||
#include <gx.h>
|
||||
#include <vi.h>
|
||||
#include "global.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef TARGET_PC
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/gx_helper.h"
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "global.h"
|
||||
#include "dusk/time.h"
|
||||
|
||||
#include "SDL3/SDL_timer.h"
|
||||
#include "tracy/Tracy.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
void JFWDisplay::ctor_subroutine(bool enableAlpha) {
|
||||
mEnableAlpha = enableAlpha;
|
||||
mClamp = GX_CLAMP_TOP | GX_CLAMP_BOTTOM;
|
||||
@@ -377,6 +381,19 @@ void JFWDisplay::waitBlanking(int param_0) {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
constexpr auto FRAME_PERIOD = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::duration<double>(1001.0 / 30000.0));
|
||||
constexpr auto RETRACE_PERIOD = FRAME_PERIOD / 2;
|
||||
|
||||
static void waitPrecise(Limiter& limiter, Uint64 targetNs) {
|
||||
const auto sleepTime = limiter.SleepTime(std::chrono::nanoseconds(targetNs));
|
||||
dusk::frameUsagePct =
|
||||
100.0f * (1.0f - static_cast<float>(sleepTime.count()) / static_cast<float>(targetNs));
|
||||
limiter.Sleep(std::chrono::nanoseconds(targetNs));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void waitForTick(u32 p1, u16 p2) {
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
@@ -385,44 +402,42 @@ static void waitForTick(u32 p1, u16 p2) {
|
||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
p1 = OS_TIMER_CLOCK / 120;
|
||||
}
|
||||
ZoneScopedC(tracy::Color::DimGray);
|
||||
#endif
|
||||
|
||||
ZoneScopedC(tracy::Color::DimGray);
|
||||
if (p1 != 0)
|
||||
{
|
||||
if (p1 != 0) {
|
||||
#if TARGET_PC
|
||||
static Limiter limiter;
|
||||
waitPrecise(limiter, static_cast<Uint64>(OSTicksToMicroseconds(p1)) * 1000ULL);
|
||||
#else
|
||||
static OSTime nextTick = OSGetTime();
|
||||
OSTime time = OSGetTime();
|
||||
OSTime waitTime = (nextTick > time) ? (nextTick - time) : 0;
|
||||
while (time < nextTick) {
|
||||
JFWDisplay::getManager()->threadSleep((nextTick - time));
|
||||
time = OSGetTime();
|
||||
}
|
||||
dusk::frameUsagePct = 100.0f * (1.0f - (float)waitTime / (float)p1);
|
||||
nextTick = time + p1;
|
||||
#endif
|
||||
} else {
|
||||
static u32 nextCount = VIGetRetraceCount();
|
||||
u32 uVar1 = (p2 == 0) ? 1 : p2;
|
||||
#if TARGET_PC
|
||||
static Limiter limiter;
|
||||
waitPrecise(limiter, static_cast<Uint64>((RETRACE_PERIOD * uVar1).count()));
|
||||
#else
|
||||
static u32 nextCount = VIGetRetraceCount();
|
||||
OSMessage msg;
|
||||
do {
|
||||
if (!OSReceiveMessage(JUTVideo::getManager()->getMessageQueue(), &msg,
|
||||
OS_MESSAGE_BLOCK))
|
||||
{
|
||||
OS_MESSAGE_BLOCK)) {
|
||||
msg = 0;
|
||||
}
|
||||
} while (((intptr_t)msg - (intptr_t)nextCount) < 0);
|
||||
dusk::frameUsagePct = 100.0f;
|
||||
nextCount = (intptr_t)msg + uVar1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
JSUList<JFWAlarm> JFWAlarm::sList(false);
|
||||
|
||||
#if TARGET_PC
|
||||
void JFWDisplay::threadSleep(s64 time) {
|
||||
SDL_DelayNS(OSTicksToMicroseconds(time) * 1'000);
|
||||
}
|
||||
#else
|
||||
|
||||
static void JFWThreadAlarmHandler(OSAlarm* p_alarm, OSContext* p_ctx) {
|
||||
JFWAlarm* alarm = static_cast<JFWAlarm*>(p_alarm);
|
||||
alarm->removeLink();
|
||||
@@ -440,7 +455,6 @@ void JFWDisplay::threadSleep(s64 time) {
|
||||
OSSuspendThread(alarm.getThread());
|
||||
OSRestoreInterrupts(status);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dummy() {
|
||||
JUTXfb::getManager()->setDisplayingXfbIndex(0);
|
||||
@@ -480,7 +494,7 @@ void JFWDisplay::clearEfb(GXColor color) {
|
||||
|
||||
void JFWDisplay::clearEfb(int param_0, int param_1, int param_2, int param_3, GXColor color) {
|
||||
STUB_RET();
|
||||
|
||||
|
||||
u16 width;
|
||||
u16 height;
|
||||
Mtx44 mtx;
|
||||
|
||||
@@ -182,7 +182,9 @@ void JUTVideo::postRetraceProc(u32 retrace_count) {
|
||||
sManager->mPostCallback(retrace_count);
|
||||
}
|
||||
|
||||
#ifndef TARGET_PC // Not read by JFWDisplay waitForTick
|
||||
OSSendMessage(&sManager->mMessageQueue, (OSMessage)(uintptr_t)VIGetRetraceCount(), OS_MESSAGE_NOBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
void JUTVideo::setRenderMode(GXRenderModeObj const* pObj) {
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "version.h"
|
||||
#include "dusk/time.h"
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <aurora/event.h>
|
||||
|
||||
Reference in New Issue
Block a user