/* * Copyright (c) Camden Dixie O'Brien * SPDX-License-Identifier: AGPL-3.0-only */ #include "engine_hooks.h" #include #include #include #include #define FRAMERATE 60 #define INTERVAL (1000 / FRAMERATE) #define VT100_CURSORTOPLEFT "\33[H" #define VT100_CLEAR "\33[2J" typedef struct { double freq; uint64_t start, evt, update, render; } perf_t; int main(int argc, char *argv[]) { int err = SDL_Init(SDL_INIT_VIDEO); assert(0 == err); SDL_Window *window = SDL_CreateWindow( game_conf.win.title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, game_conf.win.w, game_conf.win.h, 0); assert(NULL != window); SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); assert(NULL != renderer); void *gamemem = calloc(1, game_conf.memsize); game_init(argc, argv, gamemem, renderer); perf_t perf = { .freq = SDL_GetPerformanceFrequency() / 1000000.0 }; uint64_t frame = 0, prevt = SDL_GetTicks64(); while (1) { const uint64_t t = SDL_GetTicks64(); const uint64_t dt = t - prevt; if (dt >= INTERVAL) { perf.start = SDL_GetPerformanceCounter(); // Handle all events currently in queue SDL_Event evt; while (SDL_PollEvent(&evt)) { if (game_evthandle(gamemem, &evt) != GAMESTATUS_OK) goto quit; } perf.evt = SDL_GetPerformanceCounter(); // Update game state if (game_update(gamemem, INTERVAL) != GAMESTATUS_OK) goto quit; perf.update = SDL_GetPerformanceCounter(); // Render frame SDL_RenderClear(renderer); game_render(gamemem, renderer, t); SDL_RenderPresent(renderer); perf.render = SDL_GetPerformanceCounter(); // Print performance analysis every 16 frames if ((frame & 15) == 0) { const double evt = (perf.evt - perf.start) / perf.freq; const double update = (perf.update - perf.evt) / perf.freq; const double render = (perf.render - perf.update) / perf.freq; const double total = (perf.render - perf.start) / perf.freq; const double total_pc = (100 * total / (1000 * INTERVAL)); printf( VT100_CLEAR VT100_CURSORTOPLEFT "evt\t%10.3f μs\nupdate\t%10.3f μs\nrender\t" "%10.3f μs\ntotal\t%10.3f μs (%05.2f%%)\n", evt, update, render, total, total_pc); } // Increment frame counter and update time ++frame; prevt = t; } SDL_Delay(INTERVAL / 8); } quit: game_teardown(gamemem); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); }