aboutsummaryrefslogtreecommitdiffstats
path: root/src/profiling.c
blob: 6b073ed09d0b524feaaff66e71761506ae13161b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
// Profiling macros.
//

#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,
} ProfType;

char *prof_type_str[PROF_NUM] = {
    "INPUT  ",
    "UPDATE ",
    "RENDER ",
    "FLIPBUF",
    "SCRFILL",
};

u32 prof_frame_time  = 0;
u32 prof_frame_count = 0;
u32 prof_frame_avg  = -1;
u32 prof_frame_time_max  = 0;
u32 prof_times[PROF_NUM] = {0};
u32 prof_count[PROF_NUM] = {0};
u32 prof_avg[PROF_NUM] = {0};
u32 prof_max[PROF_NUM] = {0};
u32 prof_min[PROF_NUM] = {0};

bool prof_reset_minmax = PROF_RESET_MINMAX;
bool prof_show = true;

#define PROF_INIT() do { \
    for (size_t i = 0; i < PROF_NUM; 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++;\
        prof_frame_time_max = MAX(prof_frame_time_max, profile_measure());\
        prof_frame_time += profile_stop();\
        if (prof_show) { \
            draw_filled_rect(0, 0, SCREEN_WIDTH - 1, 8 * (PROF_NUM + 1), 0); \
            txt_drawf_small("FRAME TIME/FPS: %.9l/%.2l", 0, 0, COL_FG, \
                    prof_frame_avg, \
                    (u32)((u64)280896 * 60 / (prof_frame_avg + 1)));\
            txt_drawf_small("MAX: %.9l/%l", 8 * 19, 0, COL_FG, \
                    prof_frame_time_max,280896);\
            for (size_t idx = 0; idx < PROF_NUM; idx++) { \
                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]);\
            }; \
        } \
        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)

#else

// No profiling.
#define PROF_INIT()
#define PROF(F,VAR) do {F;} while(0)
#define FRAME_START()
#define FRAME_END()
#define PROF_SHOW()
#endif