#gamedev

Medindo o Tempo com Alta Precisão no MacOS

Durante o desenvolvimento de um jogo precisamos de alguma forma medir o tempo percorrido dentro de um quadro. Isso é importante para conseguir fixar taxas de quadros como 60 FPS (frames por segundo) 30 FPS e assim por diante.

Aqui no macOS temos algumas funções nativas do sistema - precisamente no kernel - que nos retornam os ticks de alto desempenho para trabalhar.

Tempo absoluto

A função que vamos usar é a mach_absolute_time. Essa função retorna unidades de tiques, de maneira incremental.

Ou seja, conseguimos recuperar o clock de alta resolução e sua unidade de medida não é nem segundo e nem milisegundos. É uma unidade que precisa ser convertida, logo, é uma unidade abstrata do sistema (ticks).

Com isso, vamos precisar de mais uma carinha para nos ajudar a converter em nano segundos ou segundos.

Buscando fração de alta escala

A função que vamos usr é a mach_timebase_info. Essa função irá fornecer para uma struct mach_timebase_info_data_t os valores de numerador e denominador como resposta.

Esses valores permitem o sistema armazenar em escala maior a frequência ao qual os ticks ocorrem.

Geralmente definimos no início do programa (cache) para que possamos usá-lo quando necessário para efetuar a conversão.

mach_timebase_info_data_t tb;
kern_return_t ret = mach_timebase_info(&tb);
if(ret != KERN_SUCCESS) exit(1);

u64 frequency = (u64) tb.numer / (u64) tb.denom;

Convertendo ticks em Segundos

Agora, com essas informações podemos buscar o tempo na unidade de medida que conhecemos como nano segundos.

u64 last_counter = mach_absolute_time();

while (!should_quit) {
        u64 end_counter = mach_absolute_time();
        u64 elapsed_counter = end_counter - last_counter;
        u64 elapsed_ns = elapsed_counter * frequency;

        printf("MSPF %f, %d FPS\n",
                   elapsed_ns / 1000000.0f,
                   (u32)(1000000000.0f / elapsed_ns));

        // code..

        last_counter = end_counter;
 }