Gerenciamento de Memória em um Jogo
Poderiamos usar o método de alocar memória dinamicamente conforme o jogo vai acontecendo.
É comum entre vários devs usar new
e delete
para alocar/desalocar a memória do heap.
Contudo, há outra maneira.
Podemos alocar todo o espaço necessário quando o jogo se inicia e trabalhar nesse pool
disponivel.
Primeiro alocamos a memória na platform-layer e passamos no game_update
para ser particionado/fragmentado nas ocasiões que o game necessitar.
A struct é definida com um tamanho de memória para dados permanentes (persistente) e dados transients.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Game_Memory
{
bool initialized;
void *permanent;
u64 permanent_size;
void *transient;
u64 transient_size;
};
//
// Visible only Game Layer
//
struct Game_State
{
int tone_hz;
int xo;
int yo;
};
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
game_update(Game_Memory *memory, Game_Back_Buffer *buffer, Game_Input *input)
{
// garantimos que o espaço do estado sempre caiba no storage.
ASSERT(sizeof(Game_State) <= memory->permanent_size);
// Casting para usarmos a memória baseada na struct
Game_State *game_state = (Game_State *)memory->permanent;
// atribui valores padrões e garante que já foi iniciado a memória.
if (!memory->initialized) {
game_state->tone_hz = 256;
game_state->xo = 0;
game_state->yo = 0;
memory->initialized = true;
}
// ... code
// atualiza o estado do jogo (permanente)
game_state->xo += (int) (4.0f * controller->stick_avg_x);
game_state->tone_hz = 256 + (int) (128.0f * controller->stick_avg_x);
update_gradient(buffer, game_state->xo, game_state->yo);
}
E para alocar, vamos usar o VirtualAlloc
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Game_Memory game_memory = {};
game_memory.permanent_size = MEGA_BYTES(64);
game_memory.transient_size = GIGA_BYTES(4);
#if INTERNAL
// Se for em desenv. vamos alocar um endereço base.
// Isso ajudará futuramente para conseguirmos fazer um live code
// e gravar em disco os estados do jogo (screen record)
LPVOID base_address = (LPVOID) TERA_BYTES(2);
#else
LPVOID base_address = 0;
#endif
// 4gb + 64mb será o total da memória.
u64 total_size = game_memory.permanent_size + game_memory.transient_size;
game_memory.permanent = VirtualAlloc(base_address, (size_t) total_size,
MEM_RESERVE|MEM_COMMIT,
PAGE_READWRITE);
// O espaço transient iniciará a partir do espaço permanente.
// faremos o casting para 1 byte.
game_memory.transient = ((u8 *) game_memory.permanent + game_memory.permanent_size);
Esta postagem está licenciada sob
CC BY 4.0
pelo autor.