Post

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);
Esta postagem está licenciada sob CC BY 4.0 pelo autor.