mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-22 10:01:46 +00:00
Rewrote the core of how the game determines how quickly it should run at
Allows vsync to be enabled regardless of the monitor's refresh rate Automatically drops frames when it needs to The game no longer runs fast on 144hz monitors
This commit is contained in:
parent
10c6d1d33f
commit
667cac9831
4 changed files with 67 additions and 37 deletions
|
|
@ -42,6 +42,17 @@
|
|||
#define FRAME_INTERVAL_US_DENOMINATOR 6
|
||||
#endif
|
||||
|
||||
// TODO: figure out if this shit even works
|
||||
#ifdef VERSION_EU
|
||||
# define FRAMERATE 25
|
||||
#else
|
||||
# define FRAMERATE 30
|
||||
#endif
|
||||
// time between consequtive game frames
|
||||
static const f64 sFrameTime = 1.0 / (2.0 * FRAMERATE);
|
||||
static f64 sFrameTargetTime = 0;
|
||||
extern "C" f64 clock_elapsed_f64(void);
|
||||
|
||||
using namespace Microsoft::WRL; // For ComPtr
|
||||
|
||||
static bool inTextInput = false;
|
||||
|
|
@ -395,7 +406,8 @@ static uint64_t qpc_to_us(uint64_t qpc) {
|
|||
}
|
||||
|
||||
static bool gfx_dxgi_start_frame(void) {
|
||||
DXGI_FRAME_STATISTICS stats;
|
||||
// HACK: all of this is too confusing to bother with right now
|
||||
/*DXGI_FRAME_STATISTICS stats;
|
||||
if (dxgi.swap_chain->GetFrameStatistics(&stats) == S_OK && (stats.SyncRefreshCount != 0 || stats.SyncQPCTime.QuadPart != 0ULL)) {
|
||||
{
|
||||
LARGE_INTEGER t0;
|
||||
|
|
@ -507,13 +519,36 @@ static bool gfx_dxgi_start_frame(void) {
|
|||
dxgi.length_in_vsync_frames = vsyncs_to_wait;
|
||||
} else {
|
||||
dxgi.length_in_vsync_frames = 2;
|
||||
}*/
|
||||
|
||||
dxgi.length_in_vsync_frames = configWindow.vsync;
|
||||
f64 curTime = clock_elapsed_f64();
|
||||
if (curTime > sFrameTargetTime) {
|
||||
sFrameTargetTime += sFrameTime;
|
||||
if (curTime > sFrameTargetTime + sFrameTime * 3) {
|
||||
sFrameTargetTime = curTime;
|
||||
}
|
||||
dxgi.dropped_frame = true;
|
||||
return false;
|
||||
}
|
||||
dxgi.dropped_frame = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sync_framerate_with_timer(void) {
|
||||
f64 curTime = clock_elapsed_f64();
|
||||
if (curTime < sFrameTargetTime) {
|
||||
u32 delayMs = (sFrameTargetTime - curTime) * 1000.0;
|
||||
if (delayMs > 0) {
|
||||
Sleep(delayMs);
|
||||
}
|
||||
}
|
||||
sFrameTargetTime += sFrameTime;
|
||||
}
|
||||
|
||||
static void gfx_dxgi_swap_buffers_begin(void) {
|
||||
//dxgi.length_in_vsync_frames = 1;
|
||||
sync_framerate_with_timer();
|
||||
ThrowIfFailed(dxgi.swap_chain->Present(dxgi.length_in_vsync_frames, 0));
|
||||
UINT this_present_id;
|
||||
if (dxgi.swap_chain->GetLastPresentCount(&this_present_id) == S_OK) {
|
||||
|
|
@ -527,12 +562,12 @@ static void gfx_dxgi_swap_buffers_end(void) {
|
|||
QueryPerformanceCounter(&t0);
|
||||
QueryPerformanceCounter(&t1);
|
||||
|
||||
if (!dxgi.dropped_frame) {
|
||||
/*if (!dxgi.dropped_frame) {
|
||||
if (dxgi.waitable_object != nullptr) {
|
||||
WaitForSingleObject(dxgi.waitable_object, INFINITE);
|
||||
}
|
||||
// else TODO: maybe sleep until some estimated time the frame will be shown to reduce lag
|
||||
}
|
||||
}*/
|
||||
|
||||
DXGI_FRAME_STATISTICS stats;
|
||||
dxgi.swap_chain->GetFrameStatistics(&stats);
|
||||
|
|
|
|||
|
|
@ -35,12 +35,17 @@
|
|||
|
||||
#include "src/pc/controller/controller_keyboard.h"
|
||||
|
||||
#include "pc/utils/misc.h"
|
||||
|
||||
// TODO: figure out if this shit even works
|
||||
#ifdef VERSION_EU
|
||||
# define FRAMERATE 25
|
||||
#else
|
||||
# define FRAMERATE 30
|
||||
#endif
|
||||
// time between consequtive game frames
|
||||
static const f64 sFrameTime = 1.0 / (2.0 * FRAMERATE);
|
||||
static f64 sFrameTargetTime = 0;
|
||||
|
||||
static SDL_Window *wnd;
|
||||
static SDL_GLContext ctx = NULL;
|
||||
|
|
@ -51,11 +56,6 @@ static kb_callback_t kb_key_up = NULL;
|
|||
static void (*kb_all_keys_up)(void) = NULL;
|
||||
static void (*kb_text_input)(char*) = NULL;
|
||||
|
||||
// whether to use timer for frame control
|
||||
static bool use_timer = true;
|
||||
// time between consequtive game frames
|
||||
static const int frame_time = 1000 / (2 * FRAMERATE);
|
||||
|
||||
const SDL_Scancode windows_scancode_table[] = {
|
||||
/* 0 1 2 3 4 5 6 7 */
|
||||
/* 8 9 A B C D E F */
|
||||
|
|
@ -140,26 +140,7 @@ int test_vsync(void) {
|
|||
}
|
||||
|
||||
static inline void gfx_sdl_set_vsync(const bool enabled) {
|
||||
if (enabled) {
|
||||
// try to detect refresh rate
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
int vblanks = test_vsync();
|
||||
if (vblanks & 1)
|
||||
vblanks = 0; // not divisible by 60, fuck that
|
||||
else
|
||||
vblanks /= 2;
|
||||
if (vblanks) {
|
||||
printf("determined swap interval: %d\n", vblanks);
|
||||
SDL_GL_SetSwapInterval(vblanks);
|
||||
use_timer = false;
|
||||
return;
|
||||
} else {
|
||||
printf("could not determine swap interval, falling back to timer sync\n");
|
||||
}
|
||||
}
|
||||
|
||||
use_timer = true;
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
SDL_GL_SetSwapInterval(enabled);
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_fullscreen(void) {
|
||||
|
|
@ -334,21 +315,30 @@ static void gfx_sdl_set_keyboard_callbacks(kb_callback_t on_key_down, kb_callbac
|
|||
}
|
||||
|
||||
static bool gfx_sdl_start_frame(void) {
|
||||
f64 curTime = clock_elapsed_f64();
|
||||
if (curTime > sFrameTargetTime) {
|
||||
sFrameTargetTime += sFrameTime;
|
||||
if (curTime > sFrameTargetTime + sFrameTime * 3) {
|
||||
sFrameTargetTime = curTime;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void sync_framerate_with_timer(void) {
|
||||
static Uint32 last_time = 0;
|
||||
// get base timestamp on the first frame (might be different from 0)
|
||||
if (last_time == 0) last_time = SDL_GetTicks();
|
||||
const int elapsed = SDL_GetTicks() - last_time;
|
||||
if (elapsed < frame_time)
|
||||
SDL_Delay(frame_time - elapsed);
|
||||
last_time += frame_time;
|
||||
f64 curTime = clock_elapsed_f64();
|
||||
if (curTime < sFrameTargetTime) {
|
||||
u32 delayMs = (sFrameTargetTime - curTime) * 1000.0;
|
||||
if (delayMs > 0) {
|
||||
SDL_Delay(delayMs);
|
||||
}
|
||||
}
|
||||
sFrameTargetTime += sFrameTime;
|
||||
}
|
||||
|
||||
static void gfx_sdl_swap_buffers_begin(void) {
|
||||
if (use_timer) sync_framerate_with_timer();
|
||||
sync_framerate_with_timer();
|
||||
SDL_GL_SwapWindow(wnd);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ f32 clock_elapsed(void) {
|
|||
return (clock_elapsed_ns() / 1000000000.0f);
|
||||
}
|
||||
|
||||
f64 clock_elapsed_f64(void) {
|
||||
return (clock_elapsed_ns() / 1000000000.0);
|
||||
}
|
||||
|
||||
u32 clock_elapsed_ticks(void) {
|
||||
return (clock_elapsed_ns() * 3 / 100000000);
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
float smoothstep(float edge0, float edge1, float x);
|
||||
void update_all_mario_stars(void);
|
||||
f32 clock_elapsed(void);
|
||||
f64 clock_elapsed_f64(void);
|
||||
u32 clock_elapsed_ticks(void);
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue