Day 18 done. FPS enforcing.
This commit is contained in:
+53
-20
@@ -19,6 +19,14 @@
|
||||
|
||||
global bool GlobalRunning;
|
||||
|
||||
global U64 GlobalPerfCountFrequency;
|
||||
|
||||
#define CONTROLLER_LEFT_THUMB_DEADZONE 8000
|
||||
#define MAX_CONTROLLERS 4
|
||||
SDL_GameController *ControllerHandles[MAX_CONTROLLERS];
|
||||
|
||||
global offscreen_buffer GlobalBackbuffer;
|
||||
|
||||
internal U32 SafeTruncateUInt64(U64 Value)
|
||||
{
|
||||
Assert(Value <= 0xFFFFFFFF);
|
||||
@@ -105,12 +113,6 @@ sdl_window_dimension SDLGetWindowDimension(SDL_Window *Window)
|
||||
return Dimension;
|
||||
}
|
||||
|
||||
#define CONTROLLER_LEFT_THUMB_DEADZONE 8000
|
||||
#define MAX_CONTROLLERS 4
|
||||
SDL_GameController *ControllerHandles[MAX_CONTROLLERS];
|
||||
|
||||
global offscreen_buffer GlobalBackbuffer;
|
||||
|
||||
internal void SDLResizeTexture(offscreen_buffer *Buffer, SDL_Renderer *Renderer, int Width, int Height)
|
||||
{
|
||||
if(Buffer->Texture)
|
||||
@@ -295,21 +297,30 @@ internal F32 SDLProcessInputStickValue(F32 Value, S32 DeadZoneThreshold)
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define DEFAULT_REFRESH_RATE 60
|
||||
internal S32 SDLGetWindowRefreshRate(SDL_Window *Window)
|
||||
{
|
||||
SDL_DisplayMode Mode;
|
||||
int DisplayIndex = SDL_GetWindowDisplayIndex(Window);
|
||||
// If we can't find the refresh rate, we'll return this:
|
||||
int DefaultRefreshRate = 60;
|
||||
SDL_DisplayMode Mode;
|
||||
|
||||
if(SDL_GetDesktopDisplayMode(DisplayIndex, &Mode) != 0)
|
||||
return DefaultRefreshRate;
|
||||
return DEFAULT_REFRESH_RATE;
|
||||
if(Mode.refresh_rate == 0)
|
||||
return DefaultRefreshRate;
|
||||
return DEFAULT_REFRESH_RATE;
|
||||
return Mode.refresh_rate;
|
||||
}
|
||||
|
||||
internal U64 SDLGetWallClock()
|
||||
{
|
||||
return SDL_GetPerformanceCounter();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
internal F32 SDLGetSecondsElapsed(U64 Start, U64 End)
|
||||
{
|
||||
return (F32)(End - Start) / (F32)GlobalPerfCountFrequency;
|
||||
}
|
||||
|
||||
S32 main(int argc, char *argv[])
|
||||
{
|
||||
if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_GAMECONTROLLER|SDL_INIT_AUDIO)) {
|
||||
/* TODO: This didn't work . . . */
|
||||
@@ -320,7 +331,8 @@ int main(int argc, char *argv[])
|
||||
SDL_Window *Window = SDL_CreateWindow("Handmade Hero", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 500, SDL_WINDOW_RESIZABLE);
|
||||
|
||||
if(Window) {
|
||||
SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, 0);
|
||||
//SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, 0);
|
||||
SDL_Renderer *Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_PRESENTVSYNC);
|
||||
// "Wayland needs an event loop and rendering or it won't function." https://github.com/libsdl-org/SDL/issues/7699#issuecomment-1545684792
|
||||
// NOTE: This means that we need to readraw to even resize the window, otherwise the window frame will appear outdated to its actual size.
|
||||
// SDL_RenderPresent(Renderer) is enough to display the window.
|
||||
@@ -368,18 +380,24 @@ int main(int argc, char *argv[])
|
||||
game_input *OldInput = &Input[1];
|
||||
memset(&Input, 0, sizeof(Input));
|
||||
|
||||
U64 PerfCountFrequency = SDL_GetPerformanceFrequency();
|
||||
GlobalPerfCountFrequency = SDL_GetPerformanceFrequency();
|
||||
|
||||
U64 LastCounter;
|
||||
#if ARCH_X64 || ARCH_X86
|
||||
U64 LastCycleCount;
|
||||
#endif
|
||||
|
||||
while(GlobalRunning) {
|
||||
LastCounter = SDL_GetPerformanceCounter();
|
||||
LastCounter = SDLGetWallClock();
|
||||
|
||||
#if ARCH_X64 || ARCH_X86
|
||||
LastCycleCount = __rdtsc(); // NOTE: rdtsc reports clock cylces, however it is not meant for really precise profiler work as the value returned is varied.
|
||||
#endif // Also, __rdtsc is not available on MacOS ARM; I have not checked MacOS x64.
|
||||
|
||||
S32 MonitorRefreshHz = SDLGetWindowRefreshRate(Window);
|
||||
S32 GameUpdateHz = MonitorRefreshHz;
|
||||
F32 TargetSecondsPerFrame = 1.0f / (F32)GameUpdateHz;
|
||||
|
||||
game_controller_input *OldKeyboardController = GetController(OldInput, 0);
|
||||
game_controller_input *NewKeyboardController = GetController(NewInput, 0);
|
||||
game_controller_input ZeroController = {0};
|
||||
@@ -466,12 +484,28 @@ int main(int argc, char *argv[])
|
||||
GameUpdateAndRender(&GameMemory, NewInput, &Buffer, &SoundBuffer);
|
||||
SDLFillSoundBuffer(&SoundOutput, BytesToWrite);
|
||||
|
||||
U64 WorkCounter = SDLGetWallClock();
|
||||
F32 WorkSecondsElapsed = SDLGetSecondsElapsed(LastCounter, WorkCounter);
|
||||
|
||||
F32 SecondsElapsedForFrame = WorkSecondsElapsed;
|
||||
if(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
while(SecondsElapsedForFrame < TargetSecondsPerFrame) {
|
||||
SecondsElapsedForFrame = SDLGetSecondsElapsed(LastCounter, SDLGetWallClock());
|
||||
SDL_Delay((U32)((TargetSecondsPerFrame - SecondsElapsedForFrame) * 1000.0f));
|
||||
}
|
||||
} else {
|
||||
// TODO: Missed frame rate!
|
||||
// TODO: Logging.
|
||||
}
|
||||
|
||||
U64 EndCounter = SDLGetWallClock();
|
||||
|
||||
SDLDisplayBufferInWindow(GlobalBackbuffer, Window, Renderer);
|
||||
|
||||
U64 EndCounter = SDL_GetPerformanceCounter();
|
||||
U64 CounterElapsed = EndCounter - LastCounter;
|
||||
F64 MSPerFrame = (((1000.0f * (F64)CounterElapsed) / (F64)PerfCountFrequency));
|
||||
F64 FPS = (F64)PerfCountFrequency / (F64)CounterElapsed;
|
||||
F64 MSPerFrame = 1000.0f * SDLGetSecondsElapsed(LastCounter, EndCounter);
|
||||
F64 FPS = 0.0f;
|
||||
|
||||
LastCounter = EndCounter;
|
||||
|
||||
#if ARCH_X64 || ARCH_X86
|
||||
U64 EndCycleCount = __rdtsc();
|
||||
@@ -482,7 +516,6 @@ int main(int argc, char *argv[])
|
||||
#else
|
||||
fprintf(stderr, "%.02f ms/f, %.02f/s\n", MSPerFrame, FPS);
|
||||
#endif
|
||||
LastCounter = EndCounter;
|
||||
|
||||
Swap(game_input *, NewInput, OldInput);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user