Taxa de Quadros e Tempo Gasto no Jogo
Para descobrir o tempo gasto no programa primeiro vamos encontrar quantos ticks ocorreram em um frame.
Calculando milisegundos por frame
Antes do main loop definimos o QueryPerformanceCounter(&last_counter);
e no final do loop o valor end.
1
2
3
4
5
6
7
8
9
10
// antes do main loop
LARGE_INTEGER last_counter;
QueryPerformanceCounter(&last_counter);
// no fim do main loop
LARGE_INTEGER end_counter;
QueryPerformanceCounter(&end_counter);
int64 counter_elapsed = end_counter.QuadPart - last_counter.QuadPart;
Agora, sabendo quantos ticks ocorreram dentro de um frame.
Precisamos saber qual é a frequência da CPU em segundos, ou seja, quantos ticks a CPU consegue fazer dentro de 1 segundo.
Dessa forma, descobriremos quanto tempo passou em um frame MSPF - milisegundos por frame.
O valor que a CPU pode contabilizar é um valor que pode ser cacheado (leia-se global) no começo do programa logo após a função main. Exemplo de valor capturado: (10_000_000).
1
2
3
4
// contagem por segundo
LARGE_INTEGER perf_count_frequency_result;
QueryPerformanceFrequency(&perf_count_frequency_result);
int64 perf_count_frequency = perf_count_frequency_result.QuadPart;
Agora, podemos dividir a frequência pela quantidade de ticks para descobrir o seu valor (em segundos).
Contudo, vamos transformar primeiro em milisegundos para que o número não seja truncado por ser muito grande.
1
2
3
4
5
6
/*
count count count sec sec
===== * ===== = ===== / ===== = =====
1 sec 1 count 1
*/
double mspf = (1000.0 * (double) counter_elapsed) / (double) perf_count_frequency;
Calculando mega ciclos por frame
Vamos calcular quantos megaciclos a CPU faz em cada frame. É semelhante ao cálculo de milisegundos por frame.
No início do programa:
1
uint64 end_cycle_count = __rdtsc();
__rdtsc()
é uma function intrinsic
de acesso ao processador e retornará o timestamp de hora e hora do processador - read timestamp counter.
1
2
uint64 end_cycle_count = __rdtsc();
uint64 cycles_elapsed = end_cycle_count - last_cycle_count;
Agora vamos descobrir o valor de mega ciclos por frame.
1
int32 mcpf = (int32) cycles_elapsed / (1000 * 1000); // transforma em mega
Calculando frames por segundos - FPS
1
int32 fps = 1 / mspf * 1000;
Invertendo o operador para divisão, conseguimos encontrar o frames por segundo a partir do segundos por frame.
NOTE: Multiplicando
mc * fps
encontramos o valor que o nosso processador está trabalhando no momento.
Imprimindo valores formatados
Vamos usar um buffer com wsprintf:
1
2
3
4
5
6
7
8
9
10
char buffer[256];
// MC * FPS = Velocidade do processador (2,4ghz)
// wsprintf não suporte float point
// https://youtu.be/UuZi437EzxU - explicado porque float é 2x mais rapido de double
wsprintf(buffer, "ms/f: %d, fps: %d, MC/f: %d\n", ms_per_frame, fps, mcpf);
// MC * FPS = Velocidade do processador (2,4ghz)
OutputDebugStringA(buffer);