// // Profiling macros. // // NOTE: Profiling uses the last two timers to count cycles, and thus can't be // used for measuring applications that use them. #ifndef PROF_ENABLE #define PROF_ENABLE 0 #endif #if PROF_ENABLE > 0 #ifndef PROF_RESET_MINMAX #define PROF_RESET_MINMAX false #endif // Maximum number of profiling to monitor. typedef enum ProfType { PROF_INPUT, PROF_UPDATE, PROF_RENDER, PROF_FLIP, PROF_FILL, PROF_NUM, PROF_END, } ProfType; char *prof_type_str[PROF_END] = { "INPUT ", "UPDATE ", "RENDER ", "FLIPBUF ", "SCRFILL ", }; u32 prof_frame_time = 0; u32 prof_frame_count = 0; u32 prof_frame_avg = 0; u32 prof_frame_time_max = 0; u32 prof_times[PROF_END] = {0}; u32 prof_count[PROF_END] = {0}; u32 prof_avg[PROF_END] = {0}; u32 prof_max[PROF_END] = {0}; u32 prof_min[PROF_END] = {0}; bool prof_reset_minmax = PROF_RESET_MINMAX; bool prof_show = true; u8 prof_detail_level = 2; #define PROF_INIT() do { \ for (size_t i = 0; i < PROF_END; i++) { \ prof_min[i] = -1; \ } \ } while(0); #define PROF(func, idx) do { \ u32 time_before = profile_measure(); \ (func); \ u32 time_after = profile_measure(); \ u32 time_current = time_after - time_before; \ prof_times[idx] += time_current; \ prof_count[idx]++; \ prof_max[idx] = MAX(time_current, prof_max[idx]);\ prof_min[idx] = MIN(time_current, prof_min[idx]);\ } while(0); #define FRAME_START() do { \ profile_start();\ } while(0) #define FRAME_END() do { \ prof_frame_count++;\ u32 frame_time = profile_measure();\ prof_frame_time_max = MAX(prof_frame_time_max, frame_time);\ prof_frame_time += profile_stop();\ if (prof_show) { \ u32 fps = (u64)280896 * 60 / (prof_frame_avg + 1); \ if (prof_frame_avg == 0) { \ fps = 0; \ } \ if (prof_detail_level > 0) {\ draw_filled_rect(0, 0, SCREEN_WIDTH - 1, 8, 2); \ txt_drawf_small("AVG/MAX/VDRAW: %.9l/%.9l/%l FPS: %.3l CPU: %.3l", 0, 0, COL_FG, \ prof_frame_avg, prof_frame_time_max, 280896, fps, (u64)prof_frame_avg * 100 / 280896);\ } else { \ draw_filled_rect(8 * 25 + 4, 0, SCREEN_WIDTH - 1, 8, 2); \ txt_drawf_small("CPU: %.3l", 8 * 25 + 4, 0, COL_FG, \ (u64)prof_frame_avg * 100 / 280896);\ } \ if (prof_detail_level >= 3) {\ draw_filled_rect(0, 8, SCREEN_WIDTH - 1, 8 * (PROF_NUM + 1), 2); \ } else if (prof_detail_level >= 2) {\ draw_filled_rect(0, 8, 8 * 15, 8 * (PROF_NUM + 1), 2); \ } \ for (size_t idx = 0; idx < PROF_NUM; idx++) { \ if (prof_detail_level >= 3) {\ txt_drawf_small("%s %.9l (%.9l %.9l) %08x:%08x", 0, 8 * (idx + 1), COL_FG, \ prof_type_str[idx], \ prof_avg[idx], \ prof_min[idx], \ prof_max[idx], \ prof_avg[idx], \ prof_max[idx]);\ } else if (prof_detail_level >= 2) {\ txt_drawf_small("%s %.9l/%.9l", 0, 8 * (idx + 1), COL_FG, \ prof_type_str[idx], \ prof_avg[idx], \ prof_max[idx]);\ }\ }; \ } \ if (prof_frame_count >= PROF_ENABLE) { \ for (size_t idx = 0; idx < PROF_NUM; idx++) { \ prof_avg[idx] = prof_times[idx] / prof_frame_count; \ if (prof_reset_minmax) { \ prof_min[idx] = -1; \ prof_max[idx] = 0; \ } \ prof_times[idx] = 0; \ prof_count[idx] = 0; \ }; \ prof_frame_avg = prof_frame_time / prof_frame_count; \ prof_frame_count = 0; \ prof_frame_time = 0; \ } \ } while(0) #define PROF_SHOW() do { \ prof_show ^= 1; \ } while(0) #define PROF_DETAIL(N) do { \ prof_detail_level = (N); \ } while(0) #else // No profiling. #define PROF_INIT() #define PROF(F,VAR) do {F;} while(0) #define FRAME_START() #define FRAME_END() #define PROF_SHOW() #define PROF_DETAIL(N) #endif